@forgeax/engine-render 0.1.7 → 0.1.20

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 (777) hide show
  1. package/README.md +140 -2
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/assembly/backend-contract.d.ts +12 -0
  4. package/dist/assembly/backend-contract.d.ts.map +1 -1
  5. package/dist/assembly/factory.d.ts +26 -5
  6. package/dist/assembly/factory.d.ts.map +1 -1
  7. package/dist/assembly/host-contract.d.ts +4 -0
  8. package/dist/assembly/host-contract.d.ts.map +1 -1
  9. package/dist/assembly/renderer-frame-transaction.d.ts +39 -0
  10. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -0
  11. package/dist/assembly/renderer-inspection.d.ts +22 -0
  12. package/dist/assembly/renderer-inspection.d.ts.map +1 -0
  13. package/dist/assembly/renderer-lifecycle.d.ts +4 -0
  14. package/dist/assembly/renderer-lifecycle.d.ts.map +1 -0
  15. package/dist/authoring.mjs +4 -2
  16. package/dist/authoring.mjs.map +1 -1
  17. package/dist/chunk-4XINDLAY.mjs +9404 -0
  18. package/dist/chunk-4XINDLAY.mjs.map +1 -0
  19. package/dist/chunk-CDTWTHZR.mjs +752 -0
  20. package/dist/chunk-CDTWTHZR.mjs.map +1 -0
  21. package/dist/chunk-FJ6P52EE.mjs +46 -0
  22. package/dist/chunk-FJ6P52EE.mjs.map +1 -0
  23. package/dist/chunk-JDWARUOI.mjs +44 -0
  24. package/dist/chunk-JDWARUOI.mjs.map +1 -0
  25. package/dist/chunk-M2MP4ZOU.mjs +73 -0
  26. package/dist/chunk-M2MP4ZOU.mjs.map +1 -0
  27. package/dist/chunk-PCHBPYML.mjs +385 -0
  28. package/dist/chunk-PCHBPYML.mjs.map +1 -0
  29. package/dist/chunk-RXZ3RGOU.mjs +53 -0
  30. package/dist/chunk-RXZ3RGOU.mjs.map +1 -0
  31. package/dist/{chunk-YEJIUW7D.mjs → chunk-TBQJOK2L.mjs} +356 -543
  32. package/dist/chunk-TBQJOK2L.mjs.map +1 -0
  33. package/dist/{chunk-CQXZC5XI.mjs → chunk-VFPLTKCU.mjs} +79 -69
  34. package/dist/chunk-VFPLTKCU.mjs.map +1 -0
  35. package/dist/components/atmosphere.d.ts +9 -0
  36. package/dist/components/atmosphere.d.ts.map +1 -0
  37. package/dist/components/camera.d.ts +2 -1
  38. package/dist/components/camera.d.ts.map +1 -1
  39. package/dist/components/fog.d.ts +8 -0
  40. package/dist/components/fog.d.ts.map +1 -0
  41. package/dist/components/index.d.ts +3 -0
  42. package/dist/components/index.d.ts.map +1 -1
  43. package/dist/components/light-helpers.d.ts.map +1 -1
  44. package/dist/components/motion-blur.d.ts +7 -0
  45. package/dist/components/motion-blur.d.ts.map +1 -0
  46. package/dist/components/spot-light.d.ts +12 -0
  47. package/dist/components/spot-light.d.ts.map +1 -1
  48. package/dist/construct-renderer.d.ts +2 -2
  49. package/dist/construct-renderer.d.ts.map +1 -1
  50. package/dist/construct-renderer.mjs +11146 -14507
  51. package/dist/construct-renderer.mjs.map +1 -1
  52. package/dist/device/device-scope.d.ts +4 -0
  53. package/dist/device/device-scope.d.ts.map +1 -1
  54. package/dist/device/gpu-residency.d.ts +19 -2
  55. package/dist/device/gpu-residency.d.ts.map +1 -1
  56. package/dist/environment/frame.d.ts +60 -0
  57. package/dist/environment/frame.d.ts.map +1 -0
  58. package/dist/environment/generation.d.ts +21 -0
  59. package/dist/environment/generation.d.ts.map +1 -0
  60. package/dist/environment/graph.d.ts +4 -0
  61. package/dist/environment/graph.d.ts.map +1 -0
  62. package/dist/environment/inspection.d.ts +48 -0
  63. package/dist/environment/inspection.d.ts.map +1 -0
  64. package/dist/environment/lifecycle.d.ts +39 -0
  65. package/dist/environment/lifecycle.d.ts.map +1 -0
  66. package/dist/environment/signature.d.ts +25 -0
  67. package/dist/environment/signature.d.ts.map +1 -0
  68. package/dist/errors/render.d.ts +204 -1
  69. package/dist/errors/render.d.ts.map +1 -1
  70. package/dist/extract/camera.d.ts +5 -0
  71. package/dist/extract/camera.d.ts.map +1 -0
  72. package/dist/extract/environment.d.ts +74 -0
  73. package/dist/extract/environment.d.ts.map +1 -0
  74. package/dist/extract/visibility.d.ts +1 -1
  75. package/dist/extract/visibility.d.ts.map +1 -1
  76. package/dist/features/host.d.ts +9 -2
  77. package/dist/features/host.d.ts.map +1 -1
  78. package/dist/features/motion-blur/motion-blur-feature.d.ts +16 -0
  79. package/dist/features/motion-blur/motion-blur-feature.d.ts.map +1 -0
  80. package/dist/features/motion-blur/motion-blur-params.d.ts +25 -0
  81. package/dist/features/motion-blur/motion-blur-params.d.ts.map +1 -0
  82. package/dist/features/plan.d.ts +17 -2
  83. package/dist/features/plan.d.ts.map +1 -1
  84. package/dist/features/prepared-gpu-work.d.ts +3 -1
  85. package/dist/features/prepared-gpu-work.d.ts.map +1 -1
  86. package/dist/features/prepared-graphics.d.ts +2 -1
  87. package/dist/features/prepared-graphics.d.ts.map +1 -1
  88. package/dist/features/render-graph-raster.d.ts +2 -1
  89. package/dist/features/render-graph-raster.d.ts.map +1 -1
  90. package/dist/features/targets.d.ts +3 -0
  91. package/dist/features/targets.d.ts.map +1 -1
  92. package/dist/features/types.d.ts +12 -0
  93. package/dist/features/types.d.ts.map +1 -1
  94. package/dist/fullscreen-post-process-pass.d.ts +7 -1
  95. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  96. package/dist/gpu-scene.d.ts +2 -0
  97. package/dist/gpu-scene.d.ts.map +1 -1
  98. package/dist/gpu-usage.d.ts +2 -0
  99. package/dist/gpu-usage.d.ts.map +1 -1
  100. package/dist/ibl/skylight-bind-group.d.ts +5 -6
  101. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  102. package/dist/index.d.ts +24 -7
  103. package/dist/index.d.ts.map +1 -1
  104. package/dist/index.mjs +6 -4
  105. package/dist/index.mjs.map +1 -1
  106. package/dist/inspection-types.d.ts +43 -1
  107. package/dist/inspection-types.d.ts.map +1 -1
  108. package/dist/internal.d.ts +2 -0
  109. package/dist/internal.d.ts.map +1 -1
  110. package/dist/internal.mjs +2 -0
  111. package/dist/light-buffer-layout.d.ts +20 -12
  112. package/dist/light-buffer-layout.d.ts.map +1 -1
  113. package/dist/materials.d.ts +22 -0
  114. package/dist/materials.d.ts.map +1 -1
  115. package/dist/pbr-pipeline.d.ts +16 -9
  116. package/dist/pbr-pipeline.d.ts.map +1 -1
  117. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  118. package/dist/pipeline/standard-pipeline.d.ts +3 -0
  119. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  120. package/dist/pipeline/standard-post.d.ts +48 -0
  121. package/dist/pipeline/standard-post.d.ts.map +1 -0
  122. package/dist/pipeline/standard-profile.d.ts +12 -2
  123. package/dist/pipeline/standard-profile.d.ts.map +1 -1
  124. package/dist/pipeline-builder.d.ts +18 -0
  125. package/dist/pipeline-builder.d.ts.map +1 -1
  126. package/dist/pipeline-spec.d.ts.map +1 -1
  127. package/dist/plugin.d.ts.map +1 -1
  128. package/dist/record/frame-lighting.d.ts +2 -0
  129. package/dist/record/frame-lighting.d.ts.map +1 -1
  130. package/dist/record/frame-snapshot.d.ts +137 -6
  131. package/dist/record/frame-snapshot.d.ts.map +1 -1
  132. package/dist/record/frame-targets.d.ts.map +1 -1
  133. package/dist/record/frame.d.ts +6 -3
  134. package/dist/record/frame.d.ts.map +1 -1
  135. package/dist/record/gpu-timing.d.ts +32 -0
  136. package/dist/record/gpu-timing.d.ts.map +1 -0
  137. package/dist/record/main-pass-geometry.d.ts +11 -0
  138. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  139. package/dist/record/main-pass-material.d.ts +9 -6
  140. package/dist/record/main-pass-material.d.ts.map +1 -1
  141. package/dist/record/main-pass-sprite-draws.d.ts +8 -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/mesh-ssbo.d.ts.map +1 -1
  146. package/dist/record/render-context.d.ts +81 -19
  147. package/dist/record/render-context.d.ts.map +1 -1
  148. package/dist/record/shadow-pass.d.ts.map +1 -1
  149. package/dist/record/skybox-post-pass.d.ts +1 -11
  150. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  151. package/dist/record/typed-frame-graph.d.ts +36 -4
  152. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  153. package/dist/record/view-ubo.d.ts +4 -1
  154. package/dist/record/view-ubo.d.ts.map +1 -1
  155. package/dist/render-contract.d.ts +157 -8
  156. package/dist/render-contract.d.ts.map +1 -1
  157. package/dist/render-data.d.ts +10 -6
  158. package/dist/render-data.d.ts.map +1 -1
  159. package/dist/render-graph-primitives.d.ts.map +1 -1
  160. package/dist/render-pipeline.d.ts +86 -6
  161. package/dist/render-pipeline.d.ts.map +1 -1
  162. package/dist/render-system-extract.d.ts +84 -8
  163. package/dist/render-system-extract.d.ts.map +1 -1
  164. package/dist/render-system.d.ts +30 -5
  165. package/dist/render-system.d.ts.map +1 -1
  166. package/dist/renderer-inspect.d.ts +29 -0
  167. package/dist/renderer-inspect.d.ts.map +1 -0
  168. package/dist/scene/render-scene.d.ts +36 -2
  169. package/dist/scene/render-scene.d.ts.map +1 -1
  170. package/dist/temporal/coverage.d.ts +42 -0
  171. package/dist/temporal/coverage.d.ts.map +1 -0
  172. package/dist/temporal/frame-coordinator.d.ts +99 -0
  173. package/dist/temporal/frame-coordinator.d.ts.map +1 -0
  174. package/dist/temporal/frame.d.ts +44 -0
  175. package/dist/temporal/frame.d.ts.map +1 -0
  176. package/dist/temporal/gpu.d.ts +39 -0
  177. package/dist/temporal/gpu.d.ts.map +1 -0
  178. package/dist/temporal/history.d.ts +37 -0
  179. package/dist/temporal/history.d.ts.map +1 -0
  180. package/dist/temporal/index.d.ts +7 -0
  181. package/dist/temporal/index.d.ts.map +1 -0
  182. package/dist/temporal/index.mjs +8 -0
  183. package/dist/temporal/index.mjs.map +1 -0
  184. package/dist/temporal/inspection.d.ts +36 -0
  185. package/dist/temporal/inspection.d.ts.map +1 -0
  186. package/dist/temporal/scene-data-catalog.d.ts +48 -0
  187. package/dist/temporal/scene-data-catalog.d.ts.map +1 -0
  188. package/dist/temporal/scene-data.d.ts +43 -0
  189. package/dist/temporal/scene-data.d.ts.map +1 -0
  190. package/dist/temporal/standard-scene-data.d.ts +61 -0
  191. package/dist/temporal/standard-scene-data.d.ts.map +1 -0
  192. package/dist/temporal/taa-history-resources.d.ts +22 -0
  193. package/dist/temporal/taa-history-resources.d.ts.map +1 -0
  194. package/dist/temporal/taa-history-store.d.ts +27 -0
  195. package/dist/temporal/taa-history-store.d.ts.map +1 -0
  196. package/dist/temporal/taa-resolve.d.ts +15 -0
  197. package/dist/temporal/taa-resolve.d.ts.map +1 -0
  198. package/dist/temporal/temporal-view.d.ts +40 -0
  199. package/dist/temporal/temporal-view.d.ts.map +1 -0
  200. package/dist/temporal/transaction.d.ts +9 -0
  201. package/dist/temporal/transaction.d.ts.map +1 -0
  202. package/dist/temporal/view.d.ts +56 -0
  203. package/dist/temporal/view.d.ts.map +1 -0
  204. package/dist/transmission/backdrop.d.ts +147 -0
  205. package/dist/transmission/backdrop.d.ts.map +1 -0
  206. package/dist/transmission/inspection.d.ts +57 -0
  207. package/dist/transmission/inspection.d.ts.map +1 -0
  208. package/dist/transmission/oracle.d.ts +42 -0
  209. package/dist/transmission/oracle.d.ts.map +1 -0
  210. package/dist/transmission/projection.d.ts +37 -0
  211. package/dist/transmission/projection.d.ts.map +1 -0
  212. package/dist/typed-render-graph-primitives.d.ts +30 -2
  213. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  214. package/dist/typed-shadow-atlas.d.ts +10 -0
  215. package/dist/typed-shadow-atlas.d.ts.map +1 -0
  216. package/dist/typed-shadow-passes.d.ts.map +1 -1
  217. package/dist/volume/capability.d.ts +57 -0
  218. package/dist/volume/capability.d.ts.map +1 -0
  219. package/dist/volume/component.d.ts +61 -0
  220. package/dist/volume/component.d.ts.map +1 -0
  221. package/dist/volume/extract.d.ts +11 -0
  222. package/dist/volume/extract.d.ts.map +1 -0
  223. package/dist/volume/inspection.d.ts +38 -0
  224. package/dist/volume/inspection.d.ts.map +1 -0
  225. package/dist/volume/passes.d.ts +38 -0
  226. package/dist/volume/passes.d.ts.map +1 -0
  227. package/dist/volume/recovery.d.ts +38 -0
  228. package/dist/volume/recovery.d.ts.map +1 -0
  229. package/dist/volume/resources.d.ts +57 -0
  230. package/dist/volume/resources.d.ts.map +1 -0
  231. package/dist/volume/temporal.d.ts +35 -0
  232. package/dist/volume/temporal.d.ts.map +1 -0
  233. package/package.json +24 -19
  234. package/src/__tests__/ai-user-cold-start.integration.test.ts +59 -0
  235. package/src/__tests__/ai-user-public-surface.test-d.ts +45 -0
  236. package/src/__tests__/bloom-exact-zero.unit.test.ts +202 -0
  237. package/src/__tests__/bloom-lifecycle.integration.test.ts +125 -0
  238. package/src/__tests__/construct-renderer-identity.unit.test.ts +4 -3
  239. package/src/__tests__/detached-inspection.integration.test.ts +177 -0
  240. package/src/__tests__/environment-fog-lanes.integration.test.ts +219 -0
  241. package/src/__tests__/environment-generation.integration.test.ts +141 -0
  242. package/src/__tests__/environment-selection.unit.test.ts +245 -0
  243. package/src/__tests__/factory-contract.integration.test.ts +1380 -9
  244. package/src/__tests__/frame-plan-contract.unit.test.ts +90 -0
  245. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +7 -0
  246. package/src/__tests__/gpu-driven-production.integration.test.ts +74 -22
  247. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +37 -0
  248. package/src/__tests__/gpu-scene.unit.test.ts +10 -0
  249. package/src/__tests__/injection-kind-owner.test-d.ts +2 -1
  250. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +14 -14
  251. package/src/__tests__/material-contract-inventory.unit.test.ts +62 -0
  252. package/src/__tests__/material-cooked-projection.unit.test.ts +18 -146
  253. package/src/__tests__/materials-transmission-validation.unit.test.ts +36 -0
  254. package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +1 -1
  255. package/src/__tests__/morph-feature-plan.unit.test.ts +7 -0
  256. package/src/__tests__/motion-blur.pixel.integration.test.ts +121 -0
  257. package/src/__tests__/public-surface.test-d.ts +15 -1
  258. package/src/__tests__/render-error-code-owner.test-d.ts +14 -0
  259. package/src/__tests__/render-error-detail-ssot.test-d.ts +11 -2
  260. package/src/__tests__/render-error-exhaustive.test-d.ts +3 -0
  261. package/src/__tests__/render-feature-errors.unit.test.ts +33 -3
  262. package/src/__tests__/render-feature-gpu-work.integration.test.ts +44 -0
  263. package/src/__tests__/render-feature-plan.test-d.ts +22 -89
  264. package/src/__tests__/render-scene-projection.unit.test.ts +28 -0
  265. package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +26 -0
  266. package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +21 -0
  267. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +423 -1
  268. package/src/__tests__/renderer-frame-transaction.integration.test.ts +405 -0
  269. package/src/__tests__/renderer-lifecycle.integration.test.ts +22 -0
  270. package/src/__tests__/scene-data-catalog.unit.test.ts +59 -0
  271. package/src/__tests__/scene-data-consumer.integration.test.ts +67 -0
  272. package/src/__tests__/scene-data-contract.test-d.ts +35 -0
  273. package/src/__tests__/scene-data-inspection.unit.test.ts +41 -0
  274. package/src/__tests__/scene-data-public-surface.test-d.ts +34 -0
  275. package/src/__tests__/shader-manifest-fixture.ts +111 -0
  276. package/src/__tests__/skinned-shadow-caster.test.ts +123 -0
  277. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +24 -3
  278. package/src/__tests__/standard-pipeline.dawn.test.ts +15 -0
  279. package/src/__tests__/standard-pipeline.integration.test.ts +543 -1
  280. package/src/__tests__/standard-profile-oracle.unit.test.ts +12 -2
  281. package/src/__tests__/standard-temporal-producer.integration.test.ts +35 -0
  282. package/src/__tests__/surface-configuration.unit.test.ts +211 -12
  283. package/src/__tests__/taa-transaction.integration.test.ts +30 -0
  284. package/src/__tests__/temporal-admission.integration.test.ts +40 -0
  285. package/src/__tests__/temporal-coverage.unit.test.ts +35 -0
  286. package/src/__tests__/temporal-demand.unit.test.ts +44 -0
  287. package/src/__tests__/temporal-frame-coordinator.unit.test.ts +64 -0
  288. package/src/__tests__/temporal-graph-topology.unit.test.ts +51 -0
  289. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +170 -0
  290. package/src/__tests__/temporal-performance.integration.test.ts +615 -0
  291. package/src/__tests__/temporal-reset-matrix.unit.test.ts +97 -0
  292. package/src/__tests__/temporal-transaction.integration.test.ts +60 -0
  293. package/src/__tests__/temporal-view.unit.test.ts +152 -0
  294. package/src/__tests__/transmission-prewarm.unit.test.ts +93 -0
  295. package/src/__tests__/typed-pipeline-topology.unit.test.ts +230 -1
  296. package/src/__tests__/urp-pipeline-targets.unit.test.ts +25 -1
  297. package/src/__tests__/urp-pipeline.unit.test.ts +4 -3
  298. package/src/__tests__/visibility-extract.integration.test.ts +27 -1
  299. package/src/__tests__/visibility-producer-matrix.integration.test.ts +10 -0
  300. package/src/__tests__/volume-optics-oracle.unit.test.ts +85 -0
  301. package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +655 -0
  302. package/src/__tests__/volumetric-fog-component.unit.test.ts +71 -0
  303. package/src/__tests__/volumetric-fog-composite-stage-readback.dawn.test.ts +376 -0
  304. package/src/__tests__/volumetric-fog-errors.unit.test.ts +51 -0
  305. package/src/__tests__/volumetric-fog-inspection.unit.test.ts +77 -0
  306. package/src/__tests__/volumetric-fog-light-capability.unit.test.ts +19 -0
  307. package/src/__tests__/volumetric-fog-light-consumers.integration.test.ts +18 -0
  308. package/src/__tests__/volumetric-fog-light-errors.unit.test.ts +17 -0
  309. package/src/__tests__/volumetric-fog-light-topology.unit.test.ts +21 -0
  310. package/src/__tests__/volumetric-fog-light-transaction.integration.test.ts +53 -0
  311. package/src/__tests__/volumetric-fog-m9-watcher.integration.test.ts +27 -0
  312. package/src/__tests__/volumetric-fog-point-light-owner.integration.test.ts +44 -0
  313. package/src/__tests__/volumetric-fog-point-spot-accumulation.integration.test.ts +49 -0
  314. package/src/__tests__/volumetric-fog-point-spot-contract.unit.test.ts +28 -0
  315. package/src/__tests__/volumetric-fog-point-spot-lkg.integration.test.ts +65 -0
  316. package/src/__tests__/volumetric-fog-point-spot-selection.integration.test.ts +49 -0
  317. package/src/__tests__/volumetric-fog-point-spot-temporal.unit.test.ts +55 -0
  318. package/src/__tests__/volumetric-fog-projector-contract.unit.test.ts +22 -0
  319. package/src/__tests__/volumetric-fog-projector-inspection.unit.test.ts +12 -0
  320. package/src/__tests__/volumetric-fog-projector-surface-volume.integration.test.ts +11 -0
  321. package/src/__tests__/volumetric-fog-projector-transaction.integration.test.ts +26 -0
  322. package/src/__tests__/volumetric-fog-recovery.integration.test.ts +47 -0
  323. package/src/__tests__/volumetric-fog-selected-light-resolution.integration.test.ts +63 -0
  324. package/src/__tests__/volumetric-fog-spot-closure.integration.test.ts +26 -0
  325. package/src/__tests__/volumetric-fog-spot-contract.test-d.ts +21 -0
  326. package/src/__tests__/volumetric-fog-spot-contract.unit.test.ts +27 -0
  327. package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +14 -0
  328. package/src/__tests__/volumetric-fog-spot-optics.integration.test.ts +29 -0
  329. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +550 -0
  330. package/src/__tests__/volumetric-fog-temporal-selected-light.unit.test.ts +33 -0
  331. package/src/__tests__/volumetric-fog-temporal.unit.test.ts +45 -0
  332. package/src/__tests__/volumetric-fog-topology.unit.test.ts +237 -0
  333. package/src/__tests__/volumetric-fog-transparent.integration.test.ts +27 -0
  334. package/src/assembly/backend-contract.ts +47 -1
  335. package/src/assembly/factory.ts +1480 -505
  336. package/src/assembly/host-contract.ts +4 -0
  337. package/src/assembly/renderer-frame-transaction.ts +75 -0
  338. package/src/assembly/renderer-inspection.ts +112 -0
  339. package/src/assembly/renderer-lifecycle.ts +6 -0
  340. package/src/components/__tests__/motion-blur.unit.test.ts +14 -0
  341. package/src/components/__tests__/schema-contract.unit.test.ts +6 -1
  342. package/src/components/atmosphere.ts +10 -0
  343. package/src/components/camera.ts +2 -1
  344. package/src/components/fog.ts +9 -0
  345. package/src/components/index.ts +3 -0
  346. package/src/components/light-helpers.ts +4 -0
  347. package/src/components/motion-blur.ts +8 -0
  348. package/src/components/spot-light.ts +22 -3
  349. package/src/construct-renderer.ts +40 -3
  350. package/src/device/device-scope.ts +15 -1
  351. package/src/device/gpu-residency.ts +168 -58
  352. package/src/environment/frame.ts +185 -0
  353. package/src/environment/generation.ts +23 -0
  354. package/src/environment/graph.ts +9 -0
  355. package/src/environment/inspection.ts +87 -0
  356. package/src/environment/lifecycle.ts +250 -0
  357. package/src/environment/signature.ts +55 -0
  358. package/src/errors/render.ts +404 -1
  359. package/src/extract/camera.ts +78 -0
  360. package/src/extract/environment.ts +171 -0
  361. package/src/extract/visibility.ts +38 -19
  362. package/src/features/host.ts +36 -5
  363. package/src/features/motion-blur/__tests__/motion-blur-feature.unit.test.ts +67 -0
  364. package/src/features/motion-blur/__tests__/motion-blur-params.unit.test.ts +53 -0
  365. package/src/features/motion-blur/motion-blur-feature.ts +119 -0
  366. package/src/features/motion-blur/motion-blur-params.ts +89 -0
  367. package/src/features/plan.ts +32 -3
  368. package/src/features/prepared-gpu-work.ts +21 -6
  369. package/src/features/prepared-graphics.ts +2 -1
  370. package/src/features/render-graph-raster.ts +2 -1
  371. package/src/features/targets.ts +24 -2
  372. package/src/features/types.ts +13 -0
  373. package/src/fullscreen-post-process-pass.ts +34 -4
  374. package/src/gpu-scene.ts +24 -0
  375. package/src/gpu-usage.ts +2 -0
  376. package/src/ibl/skylight-bind-group.ts +30 -38
  377. package/src/index.ts +104 -7
  378. package/src/inspection-types.ts +48 -0
  379. package/src/internal.ts +5 -0
  380. package/src/light-buffer-layout.ts +59 -26
  381. package/src/materials.ts +119 -24
  382. package/src/pbr-pipeline.ts +91 -29
  383. package/src/pipeline/standard-forward-lane.ts +178 -101
  384. package/src/pipeline/standard-pipeline.ts +176 -105
  385. package/src/pipeline/standard-post.ts +373 -0
  386. package/src/pipeline/standard-profile.ts +26 -3
  387. package/src/pipeline-builder.ts +102 -12
  388. package/src/pipeline-spec.ts +9 -0
  389. package/src/plugin.ts +2 -0
  390. package/src/record/__tests__/fullscreen-temporal-routing.unit.test.ts +25 -0
  391. package/src/record/__tests__/main-pass-geometry.unit.test.ts +47 -0
  392. package/src/record/__tests__/material-bg-cache.unit.test.ts +12 -1
  393. package/src/record/__tests__/material-pipeline-pending-cache.unit.test.ts +22 -0
  394. package/src/record/__tests__/sprite-material-abi.unit.test.ts +75 -0
  395. package/src/record/__tests__/standard-pbr-ubo-layout.unit.test.ts +67 -0
  396. package/src/record/__tests__/temporal-payload.unit.test.ts +164 -0
  397. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +127 -0
  398. package/src/record/frame-lighting.ts +103 -89
  399. package/src/record/frame-snapshot.ts +170 -6
  400. package/src/record/frame-targets.ts +21 -8
  401. package/src/record/frame.ts +1014 -7
  402. package/src/record/gpu-timing.ts +224 -0
  403. package/src/record/main-pass-geometry.ts +86 -40
  404. package/src/record/main-pass-material.ts +120 -68
  405. package/src/record/main-pass-sprite-draws.ts +78 -101
  406. package/src/record/main-pass.ts +77 -4
  407. package/src/record/mesh-ssbo.ts +22 -3
  408. package/src/record/render-context.ts +194 -23
  409. package/src/record/shadow-pass.ts +197 -58
  410. package/src/record/skybox-post-pass.ts +97 -41
  411. package/src/record/typed-frame-graph.ts +704 -30
  412. package/src/record/view-ubo.ts +52 -4
  413. package/src/render-contract.ts +181 -6
  414. package/src/render-data.ts +50 -22
  415. package/src/render-graph-primitives.ts +18 -1
  416. package/src/render-pipeline.ts +144 -27
  417. package/src/render-system-extract.ts +522 -72
  418. package/src/render-system.ts +561 -41
  419. package/src/renderer-inspect.ts +66 -0
  420. package/src/scene/render-scene.ts +252 -7
  421. package/src/temporal/__tests__/taa-history-resources.unit.test.ts +45 -0
  422. package/src/temporal/coverage.ts +76 -0
  423. package/src/temporal/frame-coordinator.ts +311 -0
  424. package/src/temporal/frame.ts +128 -0
  425. package/src/temporal/gpu.ts +287 -0
  426. package/src/temporal/history.ts +92 -0
  427. package/src/temporal/index.ts +6 -0
  428. package/src/temporal/inspection.ts +97 -0
  429. package/src/temporal/scene-data-catalog.ts +200 -0
  430. package/src/temporal/scene-data.ts +149 -0
  431. package/src/temporal/standard-scene-data.ts +182 -0
  432. package/src/temporal/taa-history-resources.ts +128 -0
  433. package/src/temporal/taa-history-store.ts +79 -0
  434. package/src/temporal/taa-resolve.ts +34 -0
  435. package/src/temporal/temporal-view.ts +169 -0
  436. package/src/temporal/transaction.ts +17 -0
  437. package/src/temporal/view.ts +161 -0
  438. package/src/transmission/__tests__/capability.unit.test.ts +83 -0
  439. package/src/transmission/__tests__/composition.integration.test.ts +161 -0
  440. package/src/transmission/__tests__/inspection.unit.test.ts +241 -0
  441. package/src/transmission/__tests__/lifecycle.integration.test.ts +96 -0
  442. package/src/transmission/__tests__/oracle.unit.test.ts +131 -0
  443. package/src/transmission/__tests__/projection.unit.test.ts +71 -0
  444. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +437 -0
  445. package/src/transmission/__tests__/transmission-backdrop-topology.unit.test.ts +109 -0
  446. package/src/transmission/__tests__/transmission-backdrop.dawn.test.ts +105 -0
  447. package/src/transmission/backdrop.ts +572 -0
  448. package/src/transmission/inspection.ts +190 -0
  449. package/src/transmission/oracle.ts +141 -0
  450. package/src/transmission/projection.ts +83 -0
  451. package/src/typed-render-graph-primitives.ts +194 -11
  452. package/src/typed-shadow-atlas.ts +17 -0
  453. package/src/typed-shadow-passes.ts +6 -5
  454. package/src/volume/capability.ts +173 -0
  455. package/src/volume/component.ts +110 -0
  456. package/src/volume/extract.ts +21 -0
  457. package/src/volume/inspection.ts +78 -0
  458. package/src/volume/passes.ts +680 -0
  459. package/src/volume/recovery.ts +86 -0
  460. package/src/volume/resources.ts +236 -0
  461. package/src/volume/temporal.ts +89 -0
  462. package/dist/__tests__/authoring-path.unit.test.d.ts +0 -2
  463. package/dist/__tests__/authoring-path.unit.test.d.ts.map +0 -1
  464. package/dist/__tests__/backend-selection-rhi-capture.test-d.d.ts +0 -2
  465. package/dist/__tests__/backend-selection-rhi-capture.test-d.d.ts.map +0 -1
  466. package/dist/__tests__/callback-inference.test-d.d.ts +0 -2
  467. package/dist/__tests__/callback-inference.test-d.d.ts.map +0 -1
  468. package/dist/__tests__/cluster-binner.test.d.ts +0 -2
  469. package/dist/__tests__/cluster-binner.test.d.ts.map +0 -1
  470. package/dist/__tests__/cluster-grid-default-surface.unit.test.d.ts +0 -2
  471. package/dist/__tests__/cluster-grid-default-surface.unit.test.d.ts.map +0 -1
  472. package/dist/__tests__/construct-renderer-identity.unit.test.d.ts +0 -2
  473. package/dist/__tests__/construct-renderer-identity.unit.test.d.ts.map +0 -1
  474. package/dist/__tests__/device-scope-lifecycle.unit.test.d.ts +0 -2
  475. package/dist/__tests__/device-scope-lifecycle.unit.test.d.ts.map +0 -1
  476. package/dist/__tests__/device-scope-stale-matrix.unit.test.d.ts +0 -2
  477. package/dist/__tests__/device-scope-stale-matrix.unit.test.d.ts.map +0 -1
  478. package/dist/__tests__/direct-extract-consumer-contract.test-d.d.ts +0 -2
  479. package/dist/__tests__/direct-extract-consumer-contract.test-d.d.ts.map +0 -1
  480. package/dist/__tests__/direct-light-snapshot.unit.test.d.ts +0 -2
  481. package/dist/__tests__/direct-light-snapshot.unit.test.d.ts.map +0 -1
  482. package/dist/__tests__/factory-contract.integration.test.d.ts +0 -2
  483. package/dist/__tests__/factory-contract.integration.test.d.ts.map +0 -1
  484. package/dist/__tests__/fallback-row-stride-surface.unit.test.d.ts +0 -2
  485. package/dist/__tests__/fallback-row-stride-surface.unit.test.d.ts.map +0 -1
  486. package/dist/__tests__/frame-observation.contract.test.d.ts +0 -2
  487. package/dist/__tests__/frame-observation.contract.test.d.ts.map +0 -1
  488. package/dist/__tests__/fullscreen-feature-plan.unit.test.d.ts +0 -2
  489. package/dist/__tests__/fullscreen-feature-plan.unit.test.d.ts.map +0 -1
  490. package/dist/__tests__/glyph-text-layout-recovery.unit.test.d.ts +0 -2
  491. package/dist/__tests__/glyph-text-layout-recovery.unit.test.d.ts.map +0 -1
  492. package/dist/__tests__/gpu-driven-indirect-raster-evidence.d.ts +0 -6
  493. package/dist/__tests__/gpu-driven-indirect-raster-evidence.d.ts.map +0 -1
  494. package/dist/__tests__/gpu-driven-indirect-raster.browser.test.d.ts +0 -2
  495. package/dist/__tests__/gpu-driven-indirect-raster.browser.test.d.ts.map +0 -1
  496. package/dist/__tests__/gpu-driven-indirect-raster.dawn.test.d.ts +0 -2
  497. package/dist/__tests__/gpu-driven-indirect-raster.dawn.test.d.ts.map +0 -1
  498. package/dist/__tests__/gpu-driven-production.integration.test.d.ts +0 -2
  499. package/dist/__tests__/gpu-driven-production.integration.test.d.ts.map +0 -1
  500. package/dist/__tests__/gpu-driven-scaling.unit.test.d.ts +0 -2
  501. package/dist/__tests__/gpu-driven-scaling.unit.test.d.ts.map +0 -1
  502. package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts +0 -18
  503. package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts.map +0 -1
  504. package/dist/__tests__/gpu-driven-view-graph.integration.test.d.ts +0 -2
  505. package/dist/__tests__/gpu-driven-view-graph.integration.test.d.ts.map +0 -1
  506. package/dist/__tests__/gpu-driven-view-reference.d.ts +0 -15
  507. package/dist/__tests__/gpu-driven-view-reference.d.ts.map +0 -1
  508. package/dist/__tests__/gpu-driven-view.browser.test.d.ts +0 -2
  509. package/dist/__tests__/gpu-driven-view.browser.test.d.ts.map +0 -1
  510. package/dist/__tests__/gpu-driven-view.dawn.test.d.ts +0 -2
  511. package/dist/__tests__/gpu-driven-view.dawn.test.d.ts.map +0 -1
  512. package/dist/__tests__/gpu-driven-view.unit.test.d.ts +0 -2
  513. package/dist/__tests__/gpu-driven-view.unit.test.d.ts.map +0 -1
  514. package/dist/__tests__/gpu-resource-store-stride.unit.test.d.ts +0 -2
  515. package/dist/__tests__/gpu-resource-store-stride.unit.test.d.ts.map +0 -1
  516. package/dist/__tests__/gpu-scene-render-graph-gpu.d.ts +0 -7
  517. package/dist/__tests__/gpu-scene-render-graph-gpu.d.ts.map +0 -1
  518. package/dist/__tests__/gpu-scene-render-graph.browser.test.d.ts +0 -2
  519. package/dist/__tests__/gpu-scene-render-graph.browser.test.d.ts.map +0 -1
  520. package/dist/__tests__/gpu-scene-render-graph.dawn.test.d.ts +0 -2
  521. package/dist/__tests__/gpu-scene-render-graph.dawn.test.d.ts.map +0 -1
  522. package/dist/__tests__/gpu-scene-schema.unit.test.d.ts +0 -2
  523. package/dist/__tests__/gpu-scene-schema.unit.test.d.ts.map +0 -1
  524. package/dist/__tests__/gpu-scene.dawn.test.d.ts +0 -2
  525. package/dist/__tests__/gpu-scene.dawn.test.d.ts.map +0 -1
  526. package/dist/__tests__/gpu-scene.unit.test.d.ts +0 -2
  527. package/dist/__tests__/gpu-scene.unit.test.d.ts.map +0 -1
  528. package/dist/__tests__/ibl/face-uniforms.unit.test.d.ts +0 -2
  529. package/dist/__tests__/ibl/face-uniforms.unit.test.d.ts.map +0 -1
  530. package/dist/__tests__/infinite-grid-no-vertex-probe.unit.test.d.ts +0 -2
  531. package/dist/__tests__/infinite-grid-no-vertex-probe.unit.test.d.ts.map +0 -1
  532. package/dist/__tests__/injection-kind-owner.test-d.d.ts +0 -2
  533. package/dist/__tests__/injection-kind-owner.test-d.d.ts.map +0 -1
  534. package/dist/__tests__/ktx2-basis-gpu-consumer.dawn.test.d.ts +0 -2
  535. package/dist/__tests__/ktx2-basis-gpu-consumer.dawn.test.d.ts.map +0 -1
  536. package/dist/__tests__/light-buffer-layout.unit.test.d.ts +0 -2
  537. package/dist/__tests__/light-buffer-layout.unit.test.d.ts.map +0 -1
  538. package/dist/__tests__/material-contract-inventory.unit.test.d.ts +0 -2
  539. package/dist/__tests__/material-contract-inventory.unit.test.d.ts.map +0 -1
  540. package/dist/__tests__/material-cooked-projection.unit.test.d.ts +0 -2
  541. package/dist/__tests__/material-cooked-projection.unit.test.d.ts.map +0 -1
  542. package/dist/__tests__/material-snapshot-mutation.integration.test.d.ts +0 -2
  543. package/dist/__tests__/material-snapshot-mutation.integration.test.d.ts.map +0 -1
  544. package/dist/__tests__/material-static-dynamic-route.unit.test.d.ts +0 -2
  545. package/dist/__tests__/material-static-dynamic-route.unit.test.d.ts.map +0 -1
  546. package/dist/__tests__/material-stride-surface.unit.test.d.ts +0 -2
  547. package/dist/__tests__/material-stride-surface.unit.test.d.ts.map +0 -1
  548. package/dist/__tests__/mesh-buffer-usage-surface.unit.test.d.ts +0 -2
  549. package/dist/__tests__/mesh-buffer-usage-surface.unit.test.d.ts.map +0 -1
  550. package/dist/__tests__/mesh-material-bindings.unit.test.d.ts +0 -2
  551. package/dist/__tests__/mesh-material-bindings.unit.test.d.ts.map +0 -1
  552. package/dist/__tests__/mesh-stride-surface.unit.test.d.ts +0 -2
  553. package/dist/__tests__/mesh-stride-surface.unit.test.d.ts.map +0 -1
  554. package/dist/__tests__/morph-culling-reentry.dawn.test.d.ts +0 -2
  555. package/dist/__tests__/morph-culling-reentry.dawn.test.d.ts.map +0 -1
  556. package/dist/__tests__/morph-feature-gpu-work.integration.test.d.ts +0 -2
  557. package/dist/__tests__/morph-feature-gpu-work.integration.test.d.ts.map +0 -1
  558. package/dist/__tests__/morph-feature-plan.unit.test.d.ts +0 -2
  559. package/dist/__tests__/morph-feature-plan.unit.test.d.ts.map +0 -1
  560. package/dist/__tests__/morph-visual-evidence.integration.test.d.ts +0 -2
  561. package/dist/__tests__/morph-visual-evidence.integration.test.d.ts.map +0 -1
  562. package/dist/__tests__/nineslice-handle-surface.unit.test.d.ts +0 -2
  563. package/dist/__tests__/nineslice-handle-surface.unit.test.d.ts.map +0 -1
  564. package/dist/__tests__/post-process-error-policy-owner.unit.test.d.ts +0 -2
  565. package/dist/__tests__/post-process-error-policy-owner.unit.test.d.ts.map +0 -1
  566. package/dist/__tests__/prepared-buffer-kind-owner.test-d.d.ts +0 -2
  567. package/dist/__tests__/prepared-buffer-kind-owner.test-d.d.ts.map +0 -1
  568. package/dist/__tests__/prepared-graphics-capability.unit.test.d.ts +0 -2
  569. package/dist/__tests__/prepared-graphics-capability.unit.test.d.ts.map +0 -1
  570. package/dist/__tests__/prepared-graphics-generation.unit.test.d.ts +0 -2
  571. package/dist/__tests__/prepared-graphics-generation.unit.test.d.ts.map +0 -1
  572. package/dist/__tests__/prepared-graphics-lifecycle.unit.test.d.ts +0 -2
  573. package/dist/__tests__/prepared-graphics-lifecycle.unit.test.d.ts.map +0 -1
  574. package/dist/__tests__/prepared-graphics-pipeline-warmup.unit.test.d.ts +0 -2
  575. package/dist/__tests__/prepared-graphics-pipeline-warmup.unit.test.d.ts.map +0 -1
  576. package/dist/__tests__/prepared-graphics-resolver.unit.test.d.ts +0 -2
  577. package/dist/__tests__/prepared-graphics-resolver.unit.test.d.ts.map +0 -1
  578. package/dist/__tests__/prepared-graphics-snapshot.unit.test.d.ts +0 -2
  579. package/dist/__tests__/prepared-graphics-snapshot.unit.test.d.ts.map +0 -1
  580. package/dist/__tests__/prepared-graphics-store.unit.test.d.ts +0 -2
  581. package/dist/__tests__/prepared-graphics-store.unit.test.d.ts.map +0 -1
  582. package/dist/__tests__/prepared-graphics-validation.unit.test.d.ts +0 -2
  583. package/dist/__tests__/prepared-graphics-validation.unit.test.d.ts.map +0 -1
  584. package/dist/__tests__/profiler-default-off.test.d.ts +0 -2
  585. package/dist/__tests__/profiler-default-off.test.d.ts.map +0 -1
  586. package/dist/__tests__/profiler-phase-catalog.test.d.ts +0 -2
  587. package/dist/__tests__/profiler-phase-catalog.test.d.ts.map +0 -1
  588. package/dist/__tests__/profiler-phase-integration.test.d.ts +0 -2
  589. package/dist/__tests__/profiler-phase-integration.test.d.ts.map +0 -1
  590. package/dist/__tests__/profiler-phase-token.test.d.ts +0 -2
  591. package/dist/__tests__/profiler-phase-token.test.d.ts.map +0 -1
  592. package/dist/__tests__/public-surface.test-d.d.ts +0 -2
  593. package/dist/__tests__/public-surface.test-d.d.ts.map +0 -1
  594. package/dist/__tests__/recover-error-policy-owner.unit.test.d.ts +0 -2
  595. package/dist/__tests__/recover-error-policy-owner.unit.test.d.ts.map +0 -1
  596. package/dist/__tests__/render-error-code-owner.test-d.d.ts +0 -2
  597. package/dist/__tests__/render-error-code-owner.test-d.d.ts.map +0 -1
  598. package/dist/__tests__/render-error-detail-ssot.test-d.d.ts +0 -2
  599. package/dist/__tests__/render-error-detail-ssot.test-d.d.ts.map +0 -1
  600. package/dist/__tests__/render-error-exhaustive.test-d.d.ts +0 -2
  601. package/dist/__tests__/render-error-exhaustive.test-d.d.ts.map +0 -1
  602. package/dist/__tests__/render-feature-assembly.test-d.d.ts +0 -2
  603. package/dist/__tests__/render-feature-assembly.test-d.d.ts.map +0 -1
  604. package/dist/__tests__/render-feature-context.test-d.d.ts +0 -2
  605. package/dist/__tests__/render-feature-context.test-d.d.ts.map +0 -1
  606. package/dist/__tests__/render-feature-contract.test-d.d.ts +0 -2
  607. package/dist/__tests__/render-feature-contract.test-d.d.ts.map +0 -1
  608. package/dist/__tests__/render-feature-diagnostics.unit.test.d.ts +0 -2
  609. package/dist/__tests__/render-feature-diagnostics.unit.test.d.ts.map +0 -1
  610. package/dist/__tests__/render-feature-docs.unit.test.d.ts +0 -2
  611. package/dist/__tests__/render-feature-docs.unit.test.d.ts.map +0 -1
  612. package/dist/__tests__/render-feature-errors.unit.test.d.ts +0 -2
  613. package/dist/__tests__/render-feature-errors.unit.test.d.ts.map +0 -1
  614. package/dist/__tests__/render-feature-gpu-work.integration.test.d.ts +0 -2
  615. package/dist/__tests__/render-feature-gpu-work.integration.test.d.ts.map +0 -1
  616. package/dist/__tests__/render-feature-plan.test-d.d.ts +0 -2
  617. package/dist/__tests__/render-feature-plan.test-d.d.ts.map +0 -1
  618. package/dist/__tests__/render-feature-plan.unit.test.d.ts +0 -2
  619. package/dist/__tests__/render-feature-plan.unit.test.d.ts.map +0 -1
  620. package/dist/__tests__/render-feature-prepared-diagnostics.unit.test.d.ts +0 -2
  621. package/dist/__tests__/render-feature-prepared-diagnostics.unit.test.d.ts.map +0 -1
  622. package/dist/__tests__/render-feature-prepared-errors.test-d.d.ts +0 -2
  623. package/dist/__tests__/render-feature-prepared-errors.test-d.d.ts.map +0 -1
  624. package/dist/__tests__/render-feature-prepared-graphics-docs.unit.test.d.ts +0 -2
  625. package/dist/__tests__/render-feature-prepared-graphics-docs.unit.test.d.ts.map +0 -1
  626. package/dist/__tests__/render-feature-prepared-graphics-isolation.unit.test.d.ts +0 -2
  627. package/dist/__tests__/render-feature-prepared-graphics-isolation.unit.test.d.ts.map +0 -1
  628. package/dist/__tests__/render-feature-prepared-graphics-negative.test-d.d.ts +0 -2
  629. package/dist/__tests__/render-feature-prepared-graphics-negative.test-d.d.ts.map +0 -1
  630. package/dist/__tests__/render-feature-prepared-graphics.test-d.d.ts +0 -2
  631. package/dist/__tests__/render-feature-prepared-graphics.test-d.d.ts.map +0 -1
  632. package/dist/__tests__/render-feature-prepared-graphics.unit.test.d.ts +0 -2
  633. package/dist/__tests__/render-feature-prepared-graphics.unit.test.d.ts.map +0 -1
  634. package/dist/__tests__/render-feature-public-surface.test-d.d.ts +0 -2
  635. package/dist/__tests__/render-feature-public-surface.test-d.d.ts.map +0 -1
  636. package/dist/__tests__/render-feature-retry.unit.test.d.ts +0 -2
  637. package/dist/__tests__/render-feature-retry.unit.test.d.ts.map +0 -1
  638. package/dist/__tests__/render-feature-scheduling.unit.test.d.ts +0 -2
  639. package/dist/__tests__/render-feature-scheduling.unit.test.d.ts.map +0 -1
  640. package/dist/__tests__/render-feature-stage-failed-policy-owner.unit.test.d.ts +0 -2
  641. package/dist/__tests__/render-feature-stage-failed-policy-owner.unit.test.d.ts.map +0 -1
  642. package/dist/__tests__/render-feature-stage-fault-recovery.unit.test.d.ts +0 -2
  643. package/dist/__tests__/render-feature-stage-fault-recovery.unit.test.d.ts.map +0 -1
  644. package/dist/__tests__/render-feature-visibility-context.test-d.d.ts +0 -2
  645. package/dist/__tests__/render-feature-visibility-context.test-d.d.ts.map +0 -1
  646. package/dist/__tests__/render-feature-visibility-context.unit.test.d.ts +0 -2
  647. package/dist/__tests__/render-feature-visibility-context.unit.test.d.ts.map +0 -1
  648. package/dist/__tests__/render-feature-zero-work.unit.test.d.ts +0 -2
  649. package/dist/__tests__/render-feature-zero-work.unit.test.d.ts.map +0 -1
  650. package/dist/__tests__/render-graph-compute-raster-gpu.d.ts +0 -7
  651. package/dist/__tests__/render-graph-compute-raster-gpu.d.ts.map +0 -1
  652. package/dist/__tests__/render-graph-compute-raster.browser.test.d.ts +0 -2
  653. package/dist/__tests__/render-graph-compute-raster.browser.test.d.ts.map +0 -1
  654. package/dist/__tests__/render-graph-compute-raster.dawn.test.d.ts +0 -2
  655. package/dist/__tests__/render-graph-compute-raster.dawn.test.d.ts.map +0 -1
  656. package/dist/__tests__/render-graph-hzb-gpu.d.ts +0 -7
  657. package/dist/__tests__/render-graph-hzb-gpu.d.ts.map +0 -1
  658. package/dist/__tests__/render-graph-hzb.browser.test.d.ts +0 -2
  659. package/dist/__tests__/render-graph-hzb.browser.test.d.ts.map +0 -1
  660. package/dist/__tests__/render-graph-hzb.dawn.test.d.ts +0 -2
  661. package/dist/__tests__/render-graph-hzb.dawn.test.d.ts.map +0 -1
  662. package/dist/__tests__/render-graph-primitives.unit.test.d.ts +0 -2
  663. package/dist/__tests__/render-graph-primitives.unit.test.d.ts.map +0 -1
  664. package/dist/__tests__/render-graph-storage-indirect-gpu.d.ts +0 -12
  665. package/dist/__tests__/render-graph-storage-indirect-gpu.d.ts.map +0 -1
  666. package/dist/__tests__/render-graph-storage-indirect.browser.test.d.ts +0 -2
  667. package/dist/__tests__/render-graph-storage-indirect.browser.test.d.ts.map +0 -1
  668. package/dist/__tests__/render-graph-storage-indirect.dawn.test.d.ts +0 -2
  669. package/dist/__tests__/render-graph-storage-indirect.dawn.test.d.ts.map +0 -1
  670. package/dist/__tests__/render-scene-projection.unit.test.d.ts +0 -2
  671. package/dist/__tests__/render-scene-projection.unit.test.d.ts.map +0 -1
  672. package/dist/__tests__/renderer-factory-material-contract.unit.test.d.ts +0 -2
  673. package/dist/__tests__/renderer-factory-material-contract.unit.test.d.ts.map +0 -1
  674. package/dist/__tests__/renderer-lifecycle.integration.test.d.ts +0 -2
  675. package/dist/__tests__/renderer-lifecycle.integration.test.d.ts.map +0 -1
  676. package/dist/__tests__/rhi-backend-package-boundary.unit.test.d.ts +0 -2
  677. package/dist/__tests__/rhi-backend-package-boundary.unit.test.d.ts.map +0 -1
  678. package/dist/__tests__/scriptable-pack-consumer.test-d.d.ts +0 -2
  679. package/dist/__tests__/scriptable-pack-consumer.test-d.d.ts.map +0 -1
  680. package/dist/__tests__/shader-stage-surface.unit.test.d.ts +0 -2
  681. package/dist/__tests__/shader-stage-surface.unit.test.d.ts.map +0 -1
  682. package/dist/__tests__/ssao-config.unit.test.d.ts +0 -2
  683. package/dist/__tests__/ssao-config.unit.test.d.ts.map +0 -1
  684. package/dist/__tests__/ssao-kernel-surface.unit.test.d.ts +0 -2
  685. package/dist/__tests__/ssao-kernel-surface.unit.test.d.ts.map +0 -1
  686. package/dist/__tests__/standard-clustered-pipeline.unit.test.d.ts +0 -2
  687. package/dist/__tests__/standard-clustered-pipeline.unit.test.d.ts.map +0 -1
  688. package/dist/__tests__/standard-descriptors.test-d.d.ts +0 -2
  689. package/dist/__tests__/standard-descriptors.test-d.d.ts.map +0 -1
  690. package/dist/__tests__/standard-pipeline.dawn.test.d.ts +0 -2
  691. package/dist/__tests__/standard-pipeline.dawn.test.d.ts.map +0 -1
  692. package/dist/__tests__/standard-pipeline.integration.test.d.ts +0 -2
  693. package/dist/__tests__/standard-pipeline.integration.test.d.ts.map +0 -1
  694. package/dist/__tests__/standard-profile-oracle.unit.test.d.ts +0 -2
  695. package/dist/__tests__/standard-profile-oracle.unit.test.d.ts.map +0 -1
  696. package/dist/__tests__/surface-configuration.unit.test.d.ts +0 -2
  697. package/dist/__tests__/surface-configuration.unit.test.d.ts.map +0 -1
  698. package/dist/__tests__/texture-usage-surface.unit.test.d.ts +0 -2
  699. package/dist/__tests__/texture-usage-surface.unit.test.d.ts.map +0 -1
  700. package/dist/__tests__/typed-pipeline-topology.unit.test.d.ts +0 -2
  701. package/dist/__tests__/typed-pipeline-topology.unit.test.d.ts.map +0 -1
  702. package/dist/__tests__/urp-pipeline-targets.unit.test.d.ts +0 -2
  703. package/dist/__tests__/urp-pipeline-targets.unit.test.d.ts.map +0 -1
  704. package/dist/__tests__/urp-pipeline.unit.test.d.ts +0 -2
  705. package/dist/__tests__/urp-pipeline.unit.test.d.ts.map +0 -1
  706. package/dist/__tests__/vertex-color-pipeline.unit.test.d.ts +0 -2
  707. package/dist/__tests__/vertex-color-pipeline.unit.test.d.ts.map +0 -1
  708. package/dist/__tests__/vertex-layout-consumer.unit.test.d.ts +0 -2
  709. package/dist/__tests__/vertex-layout-consumer.unit.test.d.ts.map +0 -1
  710. package/dist/__tests__/visibility-diagnostics.integration.test.d.ts +0 -2
  711. package/dist/__tests__/visibility-diagnostics.integration.test.d.ts.map +0 -1
  712. package/dist/__tests__/visibility-extract.integration.test.d.ts +0 -2
  713. package/dist/__tests__/visibility-extract.integration.test.d.ts.map +0 -1
  714. package/dist/__tests__/visibility-extract.perf.test.d.ts +0 -2
  715. package/dist/__tests__/visibility-extract.perf.test.d.ts.map +0 -1
  716. package/dist/__tests__/visibility-feature-dedup.integration.test.d.ts +0 -2
  717. package/dist/__tests__/visibility-feature-dedup.integration.test.d.ts.map +0 -1
  718. package/dist/__tests__/visibility-hidden-report.unit.test.d.ts +0 -2
  719. package/dist/__tests__/visibility-hidden-report.unit.test.d.ts.map +0 -1
  720. package/dist/__tests__/visibility-instances.integration.test.d.ts +0 -2
  721. package/dist/__tests__/visibility-instances.integration.test.d.ts.map +0 -1
  722. package/dist/__tests__/visibility-multi-world.integration.test.d.ts +0 -2
  723. package/dist/__tests__/visibility-multi-world.integration.test.d.ts.map +0 -1
  724. package/dist/__tests__/visibility-producer-matrix.integration.test.d.ts +0 -2
  725. package/dist/__tests__/visibility-producer-matrix.integration.test.d.ts.map +0 -1
  726. package/dist/__tests__/visibility-producer-matrix.unit.test.d.ts +0 -2
  727. package/dist/__tests__/visibility-producer-matrix.unit.test.d.ts.map +0 -1
  728. package/dist/__tests__/visibility-public-surface.test-d.d.ts +0 -2
  729. package/dist/__tests__/visibility-public-surface.test-d.d.ts.map +0 -1
  730. package/dist/__tests__/visibility-resolver.unit.test.d.ts +0 -2
  731. package/dist/__tests__/visibility-resolver.unit.test.d.ts.map +0 -1
  732. package/dist/__tests__/visibility-resource-short-circuit.unit.test.d.ts +0 -2
  733. package/dist/__tests__/visibility-resource-short-circuit.unit.test.d.ts.map +0 -1
  734. package/dist/__tests__/visibility-snapshot-contract.unit.test.d.ts +0 -2
  735. package/dist/__tests__/visibility-snapshot-contract.unit.test.d.ts.map +0 -1
  736. package/dist/__tests__/vocabulary.unit.test.d.ts +0 -2
  737. package/dist/__tests__/vocabulary.unit.test.d.ts.map +0 -1
  738. package/dist/chunk-CQXZC5XI.mjs.map +0 -1
  739. package/dist/chunk-HCOGPHKS.mjs +0 -93
  740. package/dist/chunk-HCOGPHKS.mjs.map +0 -1
  741. package/dist/chunk-YEJIUW7D.mjs.map +0 -1
  742. package/dist/components/__tests__/points-lines-admission.unit.test.d.ts +0 -2
  743. package/dist/components/__tests__/points-lines-admission.unit.test.d.ts.map +0 -1
  744. package/dist/components/__tests__/points-lines-schema.unit.test.d.ts +0 -2
  745. package/dist/components/__tests__/points-lines-schema.unit.test.d.ts.map +0 -1
  746. package/dist/components/__tests__/schema-contract.unit.test.d.ts +0 -2
  747. package/dist/components/__tests__/schema-contract.unit.test.d.ts.map +0 -1
  748. package/dist/components/__tests__/schema-parity.unit.test.d.ts +0 -2
  749. package/dist/components/__tests__/schema-parity.unit.test.d.ts.map +0 -1
  750. package/dist/components/__tests__/visibility-schema.unit.test.d.ts +0 -2
  751. package/dist/components/__tests__/visibility-schema.unit.test.d.ts.map +0 -1
  752. package/dist/points-lines/__tests__/bounds.unit.test.d.ts +0 -2
  753. package/dist/points-lines/__tests__/bounds.unit.test.d.ts.map +0 -1
  754. package/dist/points-lines/__tests__/cache-recovery.unit.test.d.ts +0 -2
  755. package/dist/points-lines/__tests__/cache-recovery.unit.test.d.ts.map +0 -1
  756. package/dist/points-lines/__tests__/inspection-lanes.integration.test.d.ts +0 -2
  757. package/dist/points-lines/__tests__/inspection-lanes.integration.test.d.ts.map +0 -1
  758. package/dist/points-lines/__tests__/inspection.unit.test.d.ts +0 -2
  759. package/dist/points-lines/__tests__/inspection.unit.test.d.ts.map +0 -1
  760. package/dist/points-lines/__tests__/lane-structural.integration.test.d.ts +0 -2
  761. package/dist/points-lines/__tests__/lane-structural.integration.test.d.ts.map +0 -1
  762. package/dist/points-lines/__tests__/points-lines.bench.d.ts +0 -2
  763. package/dist/points-lines/__tests__/points-lines.bench.d.ts.map +0 -1
  764. package/dist/points-lines/__tests__/raster-lane.integration.test.d.ts +0 -2
  765. package/dist/points-lines/__tests__/raster-lane.integration.test.d.ts.map +0 -1
  766. package/dist/points-lines/__tests__/snapshot.unit.test.d.ts +0 -2
  767. package/dist/points-lines/__tests__/snapshot.unit.test.d.ts.map +0 -1
  768. package/dist/points-lines/__tests__/view-ubo.unit.test.d.ts +0 -2
  769. package/dist/points-lines/__tests__/view-ubo.unit.test.d.ts.map +0 -1
  770. package/dist/record/__tests__/material-bg-cache.unit.test.d.ts +0 -2
  771. package/dist/record/__tests__/material-bg-cache.unit.test.d.ts.map +0 -1
  772. package/dist/record/__tests__/material-slot-plan.unit.test.d.ts +0 -2
  773. package/dist/record/__tests__/material-slot-plan.unit.test.d.ts.map +0 -1
  774. package/dist/record/__tests__/typed-frame-graph-plan.unit.test.d.ts +0 -2
  775. package/dist/record/__tests__/typed-frame-graph-plan.unit.test.d.ts.map +0 -1
  776. package/dist/record/__tests__/video-texture-view.unit.test.d.ts +0 -2
  777. package/dist/record/__tests__/video-texture-view.unit.test.d.ts.map +0 -1
@@ -102,7 +102,7 @@ import {
102
102
  resolveAssetHandle,
103
103
  walkMaterialPassesOverSharedRefs,
104
104
  } from '@forgeax/engine-assets-runtime';
105
- import type { Component, ComponentSchema, EntityHandle, World } from '@forgeax/engine-ecs';
105
+ import type { Component, ComponentSchema, EntityHandle, Query, World } from '@forgeax/engine-ecs';
106
106
  import {
107
107
  InstanceTransformsStrideMismatchError,
108
108
  readRenderArrayView,
@@ -142,6 +142,7 @@ import type {
142
142
  ParamSchemaEntry,
143
143
  PrimitiveTopology,
144
144
  SkeletonAsset,
145
+ TextureAsset,
145
146
  } from '@forgeax/engine-types';
146
147
  import {
147
148
  ASSET_ERROR_HINTS,
@@ -152,11 +153,9 @@ import {
152
153
  toShared,
153
154
  } from '@forgeax/engine-types';
154
155
  import {
155
- antialiasFromF32,
156
- bloomEnabledFromF32,
157
- Camera,
158
- cameraProjectionFromF32,
156
+ Atmosphere,
159
157
  DirectionalLight,
158
+ Fog,
160
159
  Instances,
161
160
  Layer,
162
161
  Lines,
@@ -173,16 +172,23 @@ import {
173
172
  SpotLight,
174
173
  SpriteInstances,
175
174
  SpriteRegionOverride,
176
- tonemapFromF32,
177
175
  tonemapToU32,
178
176
  } from './components';
179
177
  import { GlyphText } from './components/glyph-text';
180
178
  import { computeInvRangeSquared, degToCos } from './components/light-helpers';
179
+ import { selectEnvironment } from './environment/frame';
181
180
  import {
182
181
  MaterialSkinAttrMissingError,
183
182
  ShadowInvalidConfigError,
184
183
  SkinMaterialMismatchError,
185
184
  } from './errors/render';
185
+ import { extractCameraSnapshots } from './extract/camera';
186
+ import type {
187
+ EnvironmentCandidate,
188
+ EnvironmentFrame,
189
+ FogCandidate,
190
+ FogFrame,
191
+ } from './extract/environment';
186
192
  import { resolveVisibility, type VisibilitySnapshot } from './extract/visibility';
187
193
  import type {
188
194
  RenderFeatureHiddenEntityReport,
@@ -197,11 +203,22 @@ import {
197
203
  import { isStandardPbrMaterialShader } from './pbr-pipeline';
198
204
  import { expandPointsLinesBounds } from './points-lines/bounds';
199
205
  import type { PointsLinesRetainedSnapshot, PointsLinesStyle } from './points-lines/snapshot';
200
- import { type CameraSnapshot, STANDARD_TONEMAP_FEATURE_ID } from './render-contract';
201
- import { getActiveCamera, selectActiveCameraIndex } from './systems/active-camera';
206
+ import { type CameraSnapshot, STANDARD_OUTPUT_TRANSFORM_FEATURE_ID } from './render-contract';
202
207
  import { selectPasses } from './systems/pass-selector';
208
+
209
+ export { extractCameraSnapshots } from './extract/camera';
210
+
203
211
  import type { SkinPaletteAllocator } from './systems/skin-palette-allocator';
204
212
  import type { SkinPaletteSlice } from './systems/skin-palette-types';
213
+ import { resolveSelectedVolumetricLight } from './volume/capability';
214
+ import {
215
+ type ValidatedVolumetricFog,
216
+ type VolumeDensityBinding,
217
+ VolumetricFog,
218
+ type VolumetricFogAuthoring,
219
+ } from './volume/component';
220
+ import { extractVolumetricFog } from './volume/extract';
221
+ import type { VolumeProjectorTuple } from './volume/temporal';
205
222
 
206
223
  /**
207
224
  * DirectionalLightSnapshot — sun-like infinite light variant of the
@@ -214,6 +231,7 @@ import type { SkinPaletteSlice } from './systems/skin-palette-types';
214
231
  */
215
232
  export interface DirectionalLightSnapshot {
216
233
  readonly kind: 'directional';
234
+ readonly entity?: EntityHandle;
217
235
  readonly direction: Vec3;
218
236
  readonly color: Vec3;
219
237
  readonly intensity: number;
@@ -227,6 +245,7 @@ export interface DirectionalLightSnapshot {
227
245
  */
228
246
  export interface PointLightSnapshot {
229
247
  readonly kind: 'point';
248
+ readonly entity?: EntityHandle | number;
230
249
  readonly position: Vec3;
231
250
  readonly color: Vec3;
232
251
  readonly intensity: number;
@@ -310,10 +329,15 @@ export interface PointShadowSnapshot {
310
329
  * is false, dir degenerates, or the light is clipped). shadowAtlasTile
311
330
  * (i32 sentinel -1) is the allocated tile index 0..3 or -1 for unassigned
312
331
  * (plan-strategy D-4). mapSize / nearPlane / farPlane are the source
313
- * component shadow parameters carried through to the record stage.
332
+ * component shadow parameters carried through to the record stage. The
333
+ * author-facing `shadowIntensity` remains in [0,1] and is copied unchanged;
334
+ * shader consumers apply it only to shadow visibility, never to candela
335
+ * radiance.
314
336
  */
315
337
  export interface SpotLightSnapshot {
316
338
  readonly kind: 'spot';
339
+ /** Entity identity is branded in extracted frames; numeric fixtures remain compatible. */
340
+ readonly entity?: EntityHandle | number;
317
341
  readonly position: Vec3;
318
342
  readonly direction: Vec3;
319
343
  readonly color: Vec3;
@@ -328,6 +352,17 @@ export interface SpotLightSnapshot {
328
352
  readonly nearPlane: number;
329
353
  readonly farPlane: number;
330
354
  readonly shadowAtlasTile: number;
355
+ /** Fraction of sampled shadow visibility to retain; 1 = fully opaque shadow. */
356
+ readonly shadowIntensity?: number;
357
+ readonly depthBias?: number;
358
+ readonly normalBias?: number;
359
+ readonly pcfKernelSize?: number;
360
+ /** Authoritative TextureAsset projector resolved from the SpotLight handle. */
361
+ readonly projectorHandle?: Handle<'TextureAsset', 'shared'>;
362
+ readonly projectorAsset?: TextureAsset;
363
+ readonly projectorGuid?: string;
364
+ readonly projectorGeneration?: number;
365
+ readonly projectorRevision?: number;
331
366
  }
332
367
 
333
368
  /**
@@ -498,6 +533,37 @@ export interface SkyboxSnapshot {
498
533
  readonly entityHandle: number;
499
534
  }
500
535
 
536
+ /**
537
+ * Resource-owner projection for the single ECS VolumetricFog singleton.
538
+ *
539
+ * The renderer carries the validated authoring facts and the source POD all
540
+ * the way to the record stage. No profile flag or source/catalog byte is
541
+ * allowed to enable the graph: `status: 'available'` is produced only after
542
+ * the ECS component, its shared TextureAsset, and the volume validator all
543
+ * agree on one linear 3D density owner.
544
+ */
545
+ export interface ExtractedVolumetricFog {
546
+ readonly status: 'off' | 'available' | 'degraded';
547
+ readonly fog?: ValidatedVolumetricFog;
548
+ readonly densityHandle?: Handle<'TextureAsset', 'shared'>;
549
+ readonly densityAsset?: TextureAsset;
550
+ readonly guid?: string;
551
+ readonly generation?: number;
552
+ readonly digest?: string;
553
+ readonly worldId?: number;
554
+ /** Required same-World light selected by the authoring component. */
555
+ readonly lightEntity?: EntityHandle;
556
+ readonly lightKind?: 'directional' | 'point' | 'spot';
557
+ /** Optional Point+Spot pair identities consumed by the volume integrator. */
558
+ readonly pointLightEntity?: EntityHandle;
559
+ readonly spotLightEntity?: EntityHandle;
560
+ /** Accepted projector tuple shared by surface and volume when authored. */
561
+ readonly projector?: VolumeProjectorTuple;
562
+ /** The resolved projector payload shared with the surface light snapshot. */
563
+ readonly projectorHandle?: Handle<'TextureAsset', 'shared'>;
564
+ readonly projectorAsset?: TextureAsset;
565
+ }
566
+
501
567
  export interface RenderableSnapshot {
502
568
  readonly assetHandle: number;
503
569
  readonly transform: TransformSnapshot;
@@ -604,10 +670,32 @@ export interface RenderableSnapshot {
604
670
  * deltas and the record stage only receives this frozen POD snapshot.
605
671
  */
606
672
  readonly morph?: MorphSnapshot;
673
+ /** Renderer-owned previous-frame facts attached during temporal projection. */
674
+ readonly temporal?: RenderableTemporalSnapshot;
607
675
  /** Detached M2 authoring facts for the optional Points/Lines projection. */
608
676
  readonly pointsLines?: PointsLinesRetainedSnapshot;
609
677
  }
610
678
 
679
+ export type RenderablePreviousSource = 'last-submitted' | 'current-seed';
680
+ export type RenderableReactiveReason =
681
+ | 'new-slot'
682
+ | 'generation-reuse'
683
+ | 'reentered'
684
+ | 'geometry-revision'
685
+ | 'material-revision'
686
+ | 'skinning-deformation'
687
+ | 'morph-deformation';
688
+ export interface RenderableTemporalSnapshot {
689
+ readonly previousEpoch: number | undefined;
690
+ readonly previousSource: RenderablePreviousSource;
691
+ readonly reactive: boolean;
692
+ readonly reactiveReasons: readonly RenderableReactiveReason[];
693
+ readonly previousTransform: TransformSnapshot;
694
+ readonly previousInstances: InstancesSnapshot | undefined;
695
+ readonly previousSkin: SkinPaletteSlice | undefined;
696
+ readonly previousMorphWeights: Float32Array | undefined;
697
+ }
698
+
611
699
  export interface MorphSnapshot {
612
700
  readonly weights: Float32Array;
613
701
  readonly targetCount: number;
@@ -758,9 +846,9 @@ export interface MaterialSnapshot {
758
846
  *
759
847
  * Populated by iterating `textureFieldNames`; absent keys mean the
760
848
  * paramValue was missing / mis-typed (record falls back to default white).
761
- * `emissiveTexture` / `occlusionTexture` are NOT here they live in the
762
- * engine-injection lightmap region (their named fields below feed
763
- * `appendInjection('lightmap')`, not the user-region).
849
+ * `emissiveTexture` / `occlusionTexture` are included here as ordinary
850
+ * Standard user-region fields; the production layout does not duplicate
851
+ * them in a lightmap injection region.
764
852
  */
765
853
  readonly textureHandles?: ReadonlyMap<string, Handle<'TextureAsset', 'shared'>> | undefined;
766
854
  /**
@@ -973,6 +1061,12 @@ function appendMaterialDispatchEntries(
973
1061
  export interface ExtractedFrame {
974
1062
  readonly cameras: CameraSnapshot[];
975
1063
  readonly lights: ExtractedLights;
1064
+ /** Resource-owner environment facts selected once at the extract boundary. */
1065
+ readonly environment: EnvironmentFrame | undefined;
1066
+ /** False when the resource-owner world failed environment/fog selection. */
1067
+ readonly environmentReady: boolean;
1068
+ /** One resource-owner volume projection; absent means no authored fog. */
1069
+ readonly volumetricFog?: ExtractedVolumetricFog;
976
1070
  readonly renderables: RenderableSnapshot[];
977
1071
  /**
978
1072
  * Single dispatch list sorted by queue value (ascending, stable sort).
@@ -984,6 +1078,8 @@ export interface ExtractedFrame {
984
1078
  readonly skylightCount: number;
985
1079
  readonly skybox: SkyboxSnapshot | undefined;
986
1080
  readonly skyboxCount: number;
1081
+ /** Resource-owner Fog facts selected once at the frame boundary. */
1082
+ readonly fog: FogFrame | undefined;
987
1083
  /**
988
1084
  * feat-20260528-frustum-culling M3 / w11: frustum culling statistics
989
1085
  * collected during the extract phase. `total` is the count of entities
@@ -1062,6 +1158,10 @@ const BUILTIN_USER_REGION_TEXTURE_FIELDS: readonly string[] = [
1062
1158
  'metallicRoughnessTexture',
1063
1159
  'normalTexture',
1064
1160
  'specularTintTexture',
1161
+ 'emissiveTexture',
1162
+ 'occlusionTexture',
1163
+ 'transmissionTexture',
1164
+ 'thicknessTexture',
1065
1165
  ];
1066
1166
  const BUILTIN_USER_REGION_TEXTURE_FIELD_SET = new Set(BUILTIN_USER_REGION_TEXTURE_FIELDS);
1067
1167
  const BUILTIN_BASE_COLOR_TEXTURE_FIELD_SET = new Set(['baseColorTexture']);
@@ -1350,11 +1450,11 @@ function collectMaterialTextureSamplers(
1350
1450
  * `AssetRegistry.materialShaderTextureFieldNames`). Each declared texture
1351
1451
  * field whose paramValue resolves to a handle lands in the returned map keyed
1352
1452
  * by field name; this is the single path through which an arbitrary number of user-region
1353
- * textures (4 standard or 5+ custom, e.g. parallax `heightTexture`) flow.
1453
+ * textures (8 Standard or 9+ custom, e.g. parallax `heightTexture`) flow.
1354
1454
  *
1355
- * When the shader is not registered the built-in 4-field set is used so
1356
- * standard materials still resolve. `emissiveTexture` / `occlusionTexture`
1357
- * are engine-injection (lightmap) textures and are NOT part of this set.
1455
+ * When the shader is not registered the built-in Standard field set is used
1456
+ * so standard materials still resolve. Emissive and occlusion are ordinary
1457
+ * schema-driven user-region textures in that set.
1358
1458
  *
1359
1459
  * feat-20260623-world-space-video-asset M4 / w14 (D-5): a field whose paramValue
1360
1460
  * catalogues to a VideoAsset is routed into `videoOut` (a VideoAsset-branded
@@ -1665,8 +1765,7 @@ export function resolveMaterialSnapshot(
1665
1765
  // feat-20260621-learn-render-5-5-parallax M2 / w7 (D-3): iterate the
1666
1766
  // shader's derive(paramSchema).textureFieldNames SSOT instead of a hardcoded
1667
1767
  // user-region field list, so an Nth texture (e.g. parallax heightTexture)
1668
- // resolves through the same path. emissive/occlusion are engine-injection
1669
- // (lightmap) textures, NOT in textureFieldNames, so they keep named reads.
1768
+ // resolves through the same path, including emissive/occlusion fields.
1670
1769
  const videoTextureFields = new Map<string, Handle<'VideoAsset', 'shared'>>();
1671
1770
  const textureHandles = collectUserRegionTextureHandles(
1672
1771
  pv,
@@ -2192,59 +2291,15 @@ export interface PreparedExtractContext {
2192
2291
  readonly assets: AssetRegistry | null | undefined;
2193
2292
  readonly pipelineState: ExtractPipelineSurface | null | undefined;
2194
2293
  readonly materialSnapshotCache: MaterialSnapshotCache | undefined;
2294
+ /** `undefined` keeps direct extractFrame's local Fog semantics; `null` means
2295
+ * the frame owner already selected that no Fog is present for this world. */
2296
+ readonly resourceOwnerFog: FogFrame | null | undefined;
2195
2297
  readonly cull: 'self' | 'none' | 'external';
2196
2298
  readonly cullCameras: readonly CameraSnapshot[] | undefined;
2197
2299
  readonly hierarchy: SceneHierarchySnapshot;
2198
2300
  readonly visibility: VisibilitySnapshot;
2199
2301
  }
2200
2302
 
2201
- export function extractCameraSnapshots(world: World): CameraSnapshot[] {
2202
- const worldInternal = createWorldInternalView(world);
2203
- const cameras: CameraSnapshot[] = [];
2204
- const cameraEntities: number[] = [];
2205
- const cameraQuery = world.query({ read: [Camera], with: [Transform] }).unwrap();
2206
- for (const row of cameraQuery) {
2207
- const cam = row.get(Camera);
2208
- const entity = row.entity;
2209
- const view = worldInternal._getArrayView(entity, Transform, 'world');
2210
- if (view === undefined) continue;
2211
- const worldMat = new Float32Array(view);
2212
- cameras.push({
2213
- entityKey: entity as number,
2214
- position: mat4.getTranslation(vec3.create(), worldMat),
2215
- world: worldMat,
2216
- fov: cam.fov,
2217
- aspect: cam.aspect,
2218
- near: cam.near,
2219
- far: cam.far,
2220
- projection: cameraProjectionFromF32(cam.projection),
2221
- orthoLeft: cam.left,
2222
- orthoRight: cam.right,
2223
- orthoBottom: cam.bottom,
2224
- orthoTop: cam.top,
2225
- tonemap: tonemapFromF32(cam.tonemap),
2226
- exposure: cam.exposure,
2227
- whitePoint: cam.whitePoint,
2228
- antialias: antialiasFromF32(cam.antialias),
2229
- bloom: bloomEnabledFromF32(cam.bloom),
2230
- bloomThreshold: cam.bloomThreshold,
2231
- bloomIntensity: cam.bloomIntensity,
2232
- bloomBlurRadius: cam.bloomBlurRadius,
2233
- clearColor: [
2234
- cam.clearColor[0] ?? 0,
2235
- cam.clearColor[1] ?? 0,
2236
- cam.clearColor[2] ?? 0,
2237
- cam.clearColor[3] ?? 1,
2238
- ],
2239
- });
2240
- cameraEntities.push(entity as number);
2241
- }
2242
- const activeCameraIndex = selectActiveCameraIndex(cameraEntities, getActiveCamera(world)?.entity);
2243
- if (activeCameraIndex < 0) return cameras;
2244
- const selected = cameras[activeCameraIndex];
2245
- return selected === undefined ? cameras : [selected];
2246
- }
2247
-
2248
2303
  function tonemapParams(camera: CameraSnapshot): Uint8Array {
2249
2304
  const bytes = new ArrayBuffer(16);
2250
2305
  const floats = new Float32Array(bytes);
@@ -2261,6 +2316,7 @@ export function prepareExtractContext(
2261
2316
  readonly assets?: AssetRegistry | null;
2262
2317
  readonly pipelineState?: ExtractPipelineSurface | null;
2263
2318
  readonly materialSnapshotCache?: MaterialSnapshotCache;
2319
+ readonly resourceOwnerFog?: FogFrame | null;
2264
2320
  readonly cull?: 'self' | 'none' | 'external';
2265
2321
  readonly cullCameras?: readonly CameraSnapshot[];
2266
2322
  } = {},
@@ -2270,6 +2326,7 @@ export function prepareExtractContext(
2270
2326
  assets: options.assets,
2271
2327
  pipelineState: options.pipelineState,
2272
2328
  materialSnapshotCache: options.materialSnapshotCache,
2329
+ resourceOwnerFog: options.resourceOwnerFog,
2273
2330
  cull: options.cull ?? 'self',
2274
2331
  cullCameras: options.cullCameras,
2275
2332
  hierarchy,
@@ -2277,6 +2334,213 @@ export function prepareExtractContext(
2277
2334
  };
2278
2335
  }
2279
2336
 
2337
+ const fogQueries = new WeakMap<World, Query<readonly [typeof Fog]>>();
2338
+
2339
+ function selectFogFrame(world: World): FogFrame | undefined {
2340
+ // Query compilation is owned once per World; Query refreshes its matched
2341
+ // tables when the ECS structure changes, while iteration reads current Fog
2342
+ // values. This keeps the frame boundary free of repeated descriptor work.
2343
+ const fogCandidates: FogCandidate[] = [];
2344
+ let fogQuery = fogQueries.get(world);
2345
+ if (fogQuery === undefined) {
2346
+ fogQuery = world.query({ read: [Fog] }).unwrap();
2347
+ fogQueries.set(world, fogQuery);
2348
+ }
2349
+ for (const row of fogQuery) {
2350
+ const value = row.get(Fog);
2351
+ fogCandidates.push({
2352
+ entityKey: row.entity,
2353
+ color: [value.color[0] ?? 0, value.color[1] ?? 0, value.color[2] ?? 0],
2354
+ density: value.density,
2355
+ heightFalloff: value.heightFalloff,
2356
+ maxOpacity: value.maxOpacity,
2357
+ });
2358
+ }
2359
+ const fogSelection = selectEnvironment({
2360
+ environments: [],
2361
+ fogs: fogCandidates,
2362
+ suns: [],
2363
+ lane: 'direct',
2364
+ });
2365
+ if (fogSelection.ok) return fogSelection.value.fog;
2366
+ routeWorldError(world, fogSelection.error, {
2367
+ systemName: 'RenderSystem.extract (fog-selection)',
2368
+ });
2369
+ throw fogSelection.error;
2370
+ }
2371
+
2372
+ function textureDigest(texture: TextureAsset): string {
2373
+ // The render inspection needs a stable identity token, not a second byte
2374
+ // store. FNV-1a is deterministic, synchronous, and deliberately labelled
2375
+ // as a non-cryptographic digest so it cannot be mistaken for Catalog proof.
2376
+ let hash = 2166136261;
2377
+ for (const byte of texture.data) hash = Math.imul(hash ^ byte, 16777619) >>> 0;
2378
+ return `fnv1a:${hash.toString(16).padStart(8, '0')}`;
2379
+ }
2380
+
2381
+ function extractVolumeSnapshot(
2382
+ world: World,
2383
+ assets: AssetRegistry | null | undefined,
2384
+ worldInternal: WorldInternalView,
2385
+ ): ExtractedVolumetricFog | undefined {
2386
+ const query = world.query({ read: [VolumetricFog] }).unwrap();
2387
+ const authorings: VolumetricFogAuthoring[] = [];
2388
+ let selectedLight:
2389
+ | {
2390
+ readonly entity: EntityHandle;
2391
+ readonly kind: 'directional' | 'point' | 'spot';
2392
+ readonly pointLightEntity?: EntityHandle;
2393
+ readonly spotLightEntity?: EntityHandle;
2394
+ }
2395
+ | undefined;
2396
+ let first:
2397
+ | {
2398
+ readonly densityHandle: Handle<'TextureAsset', 'shared'>;
2399
+ readonly densityAsset: TextureAsset;
2400
+ readonly guid: string;
2401
+ }
2402
+ | undefined;
2403
+
2404
+ for (const row of query) {
2405
+ const source = row.get(VolumetricFog);
2406
+ if (source.light === null) continue;
2407
+ const selected = resolveSelectedVolumetricLight(world, source.light);
2408
+ if (selected.status === 'available') {
2409
+ const pairSpot = source.spotLight === null ? undefined : source.spotLight;
2410
+ selectedLight ??= {
2411
+ entity: selected.entity,
2412
+ kind: selected.kind,
2413
+ ...(selected.kind === 'point' ? { pointLightEntity: selected.entity } : {}),
2414
+ ...(pairSpot === undefined ? {} : { spotLightEntity: pairSpot }),
2415
+ };
2416
+ }
2417
+ const densityHandle = toShared<'TextureAsset'>(Math.round(Number(source.density)));
2418
+ const resolved = resolveAssetHandle<TextureAsset>(world, densityHandle);
2419
+ if (!resolved.ok || resolved.value.kind !== 'texture') {
2420
+ worldInternal._routeError(
2421
+ resolved.ok
2422
+ ? new RhiError({
2423
+ code: 'asset-not-registered',
2424
+ expected: 'VolumetricFog.density resolves to a TextureAsset',
2425
+ hint: 'load a TextureAsset before assigning it to VolumetricFog.density',
2426
+ detail: { assetHandle: Number(densityHandle) },
2427
+ })
2428
+ : resolved.error,
2429
+ { severity: Severity.Error, systemName: 'RenderSystem.extract (volumetric-density)' },
2430
+ );
2431
+ return { status: 'degraded' };
2432
+ }
2433
+ const densityAsset = resolved.value;
2434
+ const guid = assets?.guidOf(densityAsset) ?? `handle:${Number(densityHandle)}`;
2435
+ const shape = densityAsset.shape;
2436
+ const density: VolumeDensityBinding =
2437
+ shape.viewDimension === '3d'
2438
+ ? {
2439
+ guid,
2440
+ generation: 1,
2441
+ shape: {
2442
+ viewDimension: '3d',
2443
+ extent: {
2444
+ width: shape.extent.width,
2445
+ height: shape.extent.height,
2446
+ depth: shape.extent.depth,
2447
+ },
2448
+ },
2449
+ format: densityAsset.format,
2450
+ colorSpace: densityAsset.colorSpace,
2451
+ }
2452
+ : {
2453
+ guid,
2454
+ generation: 1,
2455
+ shape: {
2456
+ viewDimension: shape.viewDimension,
2457
+ extent:
2458
+ shape.viewDimension === '2d-array'
2459
+ ? {
2460
+ width: shape.extent.width,
2461
+ height: shape.extent.height,
2462
+ layers: shape.extent.layers,
2463
+ }
2464
+ : { width: shape.extent.width, height: shape.extent.height },
2465
+ },
2466
+ format: densityAsset.format,
2467
+ colorSpace: densityAsset.colorSpace,
2468
+ };
2469
+ const authoring: VolumetricFogAuthoring = {
2470
+ light: source.light,
2471
+ density,
2472
+ bounds: {
2473
+ min: [source.boundsMin[0] ?? 0, source.boundsMin[1] ?? 0, source.boundsMin[2] ?? 0],
2474
+ max: [source.boundsMax[0] ?? 0, source.boundsMax[1] ?? 0, source.boundsMax[2] ?? 0],
2475
+ },
2476
+ extinction: [source.extinction[0] ?? 0, source.extinction[1] ?? 0, source.extinction[2] ?? 0],
2477
+ albedo: [source.albedo[0] ?? 0, source.albedo[1] ?? 0, source.albedo[2] ?? 0],
2478
+ emission: [source.emission[0] ?? 0, source.emission[1] ?? 0, source.emission[2] ?? 0],
2479
+ anisotropy: source.anisotropy,
2480
+ maxDistance: source.maxDistance,
2481
+ };
2482
+ authorings.push(authoring);
2483
+ first ??= { densityHandle, densityAsset, guid };
2484
+ }
2485
+
2486
+ if (authorings.length === 0) return undefined;
2487
+ const extracted = extractVolumetricFog(authorings);
2488
+ if (!extracted.ok) {
2489
+ worldInternal._routeError(extracted.error, {
2490
+ severity: Severity.Error,
2491
+ systemName: 'RenderSystem.extract (volumetric-fog)',
2492
+ });
2493
+ return {
2494
+ status: 'degraded',
2495
+ ...(first === undefined
2496
+ ? {}
2497
+ : {
2498
+ densityHandle: first.densityHandle,
2499
+ densityAsset: first.densityAsset,
2500
+ guid: first.guid,
2501
+ generation: 1,
2502
+ digest: textureDigest(first.densityAsset),
2503
+ ...(selectedLight === undefined
2504
+ ? {}
2505
+ : {
2506
+ lightEntity: selectedLight.entity,
2507
+ lightKind: selectedLight.kind,
2508
+ ...(selectedLight.pointLightEntity === undefined
2509
+ ? {}
2510
+ : { pointLightEntity: selectedLight.pointLightEntity }),
2511
+ ...(selectedLight.spotLightEntity === undefined
2512
+ ? {}
2513
+ : { spotLightEntity: selectedLight.spotLightEntity }),
2514
+ }),
2515
+ }),
2516
+ };
2517
+ }
2518
+ if (extracted.value.status === 'off' || first === undefined) return { status: 'off' };
2519
+ const selectedLightFields =
2520
+ selectedLight === undefined
2521
+ ? {}
2522
+ : {
2523
+ lightEntity: selectedLight.entity,
2524
+ lightKind: selectedLight.kind,
2525
+ ...(selectedLight.pointLightEntity === undefined
2526
+ ? {}
2527
+ : { pointLightEntity: selectedLight.pointLightEntity }),
2528
+ ...(selectedLight.spotLightEntity === undefined
2529
+ ? {}
2530
+ : { spotLightEntity: selectedLight.spotLightEntity }),
2531
+ };
2532
+ return {
2533
+ status: 'available',
2534
+ fog: extracted.value.fog,
2535
+ densityHandle: first.densityHandle,
2536
+ densityAsset: first.densityAsset,
2537
+ guid: first.guid,
2538
+ generation: 1,
2539
+ digest: textureDigest(first.densityAsset),
2540
+ ...selectedLightFields,
2541
+ };
2542
+ }
2543
+
2280
2544
  export function extractFrames(
2281
2545
  worlds: readonly World[],
2282
2546
  owner: number | ExtractFramesOwner,
@@ -2304,6 +2568,12 @@ export function extractFrames(
2304
2568
  }
2305
2569
 
2306
2570
  const failedWorlds = new Set<World>();
2571
+ // Resource-owner selection is a frame-level concern. Select Fog once before
2572
+ // per-world extraction so non-owner worlds do not scan their ECS tables for
2573
+ // a value that the merge layer will discard.
2574
+ const resourceOwnerWorld = worlds[resourceOwner];
2575
+ const resourceOwnerFog =
2576
+ resourceOwnerWorld === undefined ? null : (selectFogFrame(resourceOwnerWorld) ?? null);
2307
2577
  // ── D-2: per-world extract with error isolation ────────────────────────
2308
2578
  //
2309
2579
  // Each world runs extractFrame over the final state published by
@@ -2334,6 +2604,7 @@ export function extractFrames(
2334
2604
  const prepared = prepareExtractContext(world, {
2335
2605
  ...(assets !== undefined ? { assets } : {}),
2336
2606
  ...(pipelineState !== undefined ? { pipelineState } : {}),
2607
+ resourceOwnerFog: wi === resourceOwner ? resourceOwnerFog : null,
2337
2608
  ...(materialSnapshotCachesByWorld === undefined
2338
2609
  ? {}
2339
2610
  : {
@@ -2527,10 +2798,13 @@ export function extractFrames(
2527
2798
  directionalCsmConfig,
2528
2799
  directionalCsmDirection,
2529
2800
  };
2801
+ const volumetricFog = resourceOwnerFrame?.volumetricFog;
2530
2802
  const skylight = resourceOwnerFrame?.skylight;
2531
2803
  const skylightCount = resourceOwnerFrame?.skylightCount ?? 0;
2532
2804
  const skybox = resourceOwnerFrame?.skybox;
2533
2805
  const skyboxCount = resourceOwnerFrame?.skyboxCount ?? 0;
2806
+ const fog = resourceOwnerFrame?.fog;
2807
+ const environment = resourceOwnerFrame?.environment;
2534
2808
  // User-authored PostProcessParams entities are singleton scene resources, so
2535
2809
  // they come from the resourceOwner world (holistic snapshot selection).
2536
2810
  const postProcessParams = new Map(resourceOwnerFrame?.postProcessParams);
@@ -2549,16 +2823,16 @@ export function extractFrames(
2549
2823
  // cameraOwner === resourceOwner this is a no-op (identical entry). The 'na'
2550
2824
  // Standard tonemap identity mirrors the engine provider key set at the
2551
2825
  // bottom of extractFrame (SSOT: same identity, same 16B layout).
2552
- const TONEMAP_PARAM_KEY = STANDARD_TONEMAP_FEATURE_ID;
2553
- const cameraTonemapParam = cameraOwnerFrame?.postProcessParams.get(TONEMAP_PARAM_KEY);
2826
+ const OUTPUT_TRANSFORM_PARAM_KEY = STANDARD_OUTPUT_TRANSFORM_FEATURE_ID;
2827
+ const cameraTonemapParam = cameraOwnerFrame?.postProcessParams.get(OUTPUT_TRANSFORM_PARAM_KEY);
2554
2828
  if (cameraTonemapParam !== undefined) {
2555
- postProcessParams.set(TONEMAP_PARAM_KEY, cameraTonemapParam);
2829
+ postProcessParams.set(OUTPUT_TRANSFORM_PARAM_KEY, cameraTonemapParam);
2556
2830
  } else {
2557
2831
  // The camera-owner world produced no tonemap param (no Camera surfaced
2558
2832
  // there this frame); do not leave a stale resource-owner entry that would
2559
2833
  // apply a foreign camera's exposure. Removing it lets the tonemap pass fall
2560
2834
  // back to its param-less zero path only when genuinely no camera exists.
2561
- postProcessParams.delete(TONEMAP_PARAM_KEY);
2835
+ postProcessParams.delete(OUTPUT_TRANSFORM_PARAM_KEY);
2562
2836
  }
2563
2837
 
2564
2838
  // D-3: frustumStats — culled/total summed across worlds.
@@ -2573,12 +2847,18 @@ export function extractFrames(
2573
2847
  return {
2574
2848
  cameras,
2575
2849
  lights,
2850
+ ...(volumetricFog === undefined
2851
+ ? {}
2852
+ : { volumetricFog: { ...volumetricFog, worldId: resourceOwner } }),
2576
2853
  renderables,
2577
2854
  dispatch: dispatchEntries,
2578
2855
  skylight,
2579
2856
  skylightCount,
2580
2857
  skybox,
2581
2858
  skyboxCount,
2859
+ fog,
2860
+ environment,
2861
+ environmentReady: resourceOwnerFrame !== undefined && environment !== undefined,
2582
2862
  frustumStats,
2583
2863
  visibilityStats,
2584
2864
  postProcessParams,
@@ -2666,7 +2946,12 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
2666
2946
  pipelineState,
2667
2947
  materialSnapshotCache: persistentMaterialSnapshotCache,
2668
2948
  cull: cullMode,
2949
+ resourceOwnerFog,
2669
2950
  } = context;
2951
+ // Environment reads are owned by the retained resource projection and are
2952
+ // established at the frame boundary; record never revisits World state.
2953
+ const fog =
2954
+ resourceOwnerFog === undefined ? selectFogFrame(world) : (resourceOwnerFog ?? undefined);
2670
2955
  const visibility = context.visibility.hasAnyHiddenIntent ? context.visibility : undefined;
2671
2956
  const skinPaletteAllocator = pipelineState?.skinPaletteAllocator ?? null;
2672
2957
 
@@ -2684,6 +2969,7 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
2684
2969
  // `row.get(X) !== undefined`); K-3 invariant preserved (`_getArrayView`
2685
2970
  // calls survive untouched, only the entity source changes).
2686
2971
  const worldInternal = createWorldInternalView(world);
2972
+ let volumetricFog = extractVolumeSnapshot(world, assets, worldInternal);
2687
2973
 
2688
2974
  const cameras = extractCameraSnapshots(world);
2689
2975
 
@@ -2715,6 +3001,7 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
2715
3001
  const intensity = l.intensity;
2716
3002
  const snapshot: DirectionalLightSnapshot = {
2717
3003
  kind: 'directional',
3004
+ entity: row.entity,
2718
3005
  direction: vec3.create(l.direction[0] ?? 0, l.direction[1] ?? -1, l.direction[2] ?? 0),
2719
3006
  color: vec3.create(
2720
3007
  (l.color[0] ?? 1) * intensity,
@@ -2770,6 +3057,7 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
2770
3057
  worldMat !== undefined ? mat4.getTranslation(vec3.create(), worldMat) : vec3.create(0, 0, 0);
2771
3058
  pointSnapshots.push({
2772
3059
  kind: 'point',
3060
+ entity: entityId,
2773
3061
  position,
2774
3062
  color: vec3.create(
2775
3063
  (p.color[0] ?? 1) * intensity,
@@ -2841,11 +3129,20 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
2841
3129
  const sMapSize = s.mapSize;
2842
3130
  const sNearPlane = s.nearPlane;
2843
3131
  const sFarPlane = s.farPlane;
3132
+ const shadowIntensity = s.shadowIntensity;
3133
+ // `shared<T>` columns are u32-backed and zero-filled when the optional
3134
+ // field is absent. Treat only a positive handle as an authored projector;
3135
+ // checking nullish values alone would turn the zero sentinel into a
3136
+ // phantom projector matrix and an avoidable asset-not-found diagnostic.
3137
+ const hasProjector = Number(s.projector) > 0;
2844
3138
 
2845
3139
  let lightViewProj: Float32Array | undefined;
2846
3140
  let shadowAtlasTile = -1;
2847
3141
 
2848
- if (castShadow && hasValidDirection) {
3142
+ // A projector needs the same perspective transform even when its SpotLight
3143
+ // has no shadow atlas tile. The matrix remains a derived light fact; the
3144
+ // shadow tile stays -1 so shadow visibility is still independently gated.
3145
+ if ((castShadow || hasProjector) && hasValidDirection) {
2849
3146
  const target = vec3.create(
2850
3147
  (position[0] ?? 0) + (dirN[0] ?? 0),
2851
3148
  (position[1] ?? 0) + (dirN[1] ?? 0),
@@ -2864,14 +3161,40 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
2864
3161
  mat4.multiply(lightViewProj as Mat4, proj, view);
2865
3162
 
2866
3163
  // D-4: allocate tile 0..3; 5th+ = -1 sentinel.
2867
- if (spotTileNext < 4) {
3164
+ if (castShadow && spotTileNext < 4) {
2868
3165
  shadowAtlasTile = spotTileNext;
2869
3166
  spotTileNext += 1;
2870
3167
  }
2871
3168
  }
2872
3169
 
3170
+ let projectorHandle: Handle<'TextureAsset', 'shared'> | undefined;
3171
+ let projectorAsset: TextureAsset | undefined;
3172
+ let projectorGuid: string | undefined;
3173
+ if (hasProjector) {
3174
+ const candidate = toShared<'TextureAsset'>(Math.round(Number(s.projector)));
3175
+ const resolvedProjector = resolveAssetHandle<TextureAsset>(world, candidate);
3176
+ if (!resolvedProjector.ok || resolvedProjector.value.kind !== 'texture') {
3177
+ worldInternal._routeError(
3178
+ resolvedProjector.ok
3179
+ ? new RhiError({
3180
+ code: 'asset-not-registered',
3181
+ expected: 'SpotLight.projector resolves to a TextureAsset',
3182
+ hint: 'load the authored projector TextureAsset before assigning SpotLight.projector',
3183
+ detail: { assetHandle: Number(candidate) },
3184
+ })
3185
+ : resolvedProjector.error,
3186
+ { severity: Severity.Error, systemName: 'RenderSystem.extract (spot-projector)' },
3187
+ );
3188
+ } else {
3189
+ projectorHandle = candidate;
3190
+ projectorAsset = resolvedProjector.value;
3191
+ projectorGuid = assets?.guidOf(projectorAsset) ?? `handle:${Number(candidate)}`;
3192
+ }
3193
+ }
3194
+
2873
3195
  spotSnapshots.push({
2874
3196
  kind: 'spot',
3197
+ entity: row.entity,
2875
3198
  // D-6: position reflects world transform; direction stays sourced
2876
3199
  // from SpotLight.direction (NOT rotated by the parent).
2877
3200
  position,
@@ -2892,9 +3215,59 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
2892
3215
  nearPlane: sNearPlane,
2893
3216
  farPlane: sFarPlane,
2894
3217
  shadowAtlasTile,
3218
+ shadowIntensity,
3219
+ depthBias: s.depthBias,
3220
+ normalBias: s.normalBias,
3221
+ pcfKernelSize: s.pcfKernelSize,
3222
+ ...(projectorHandle === undefined ||
3223
+ projectorAsset === undefined ||
3224
+ projectorGuid === undefined
3225
+ ? {}
3226
+ : {
3227
+ projectorHandle,
3228
+ projectorAsset,
3229
+ projectorGuid,
3230
+ projectorGeneration: 1,
3231
+ projectorRevision: 1,
3232
+ }),
2895
3233
  });
2896
3234
  }
2897
3235
 
3236
+ // The SpotLight is the sole projector owner. Once all light snapshots have
3237
+ // been extracted, publish its accepted TextureAsset tuple on the volume
3238
+ // snapshot so surface and volume consume the same identity and revision.
3239
+ let volumeSpot: SpotLightSnapshot | undefined;
3240
+ const extractedFog = volumetricFog;
3241
+ if (extractedFog !== undefined) {
3242
+ if (extractedFog.spotLightEntity !== undefined) {
3243
+ volumeSpot = spotSnapshots.find((light) => light.entity === extractedFog.spotLightEntity);
3244
+ } else if (extractedFog.lightKind === 'spot') {
3245
+ volumeSpot = spotSnapshots.find((light) => light.entity === extractedFog.lightEntity);
3246
+ }
3247
+ }
3248
+ if (
3249
+ volumetricFog !== undefined &&
3250
+ volumetricFog.status === 'available' &&
3251
+ volumeSpot?.projectorAsset !== undefined &&
3252
+ volumeSpot.projectorHandle !== undefined
3253
+ ) {
3254
+ const projectorHandle = volumeSpot.projectorHandle;
3255
+ const projectorAsset = volumeSpot.projectorAsset;
3256
+ volumetricFog = {
3257
+ ...volumetricFog,
3258
+ projector: {
3259
+ guid: volumeSpot.projectorGuid ?? `handle:${Number(volumeSpot.projectorHandle)}`,
3260
+ generation: volumeSpot.projectorGeneration ?? 1,
3261
+ view: '2d',
3262
+ sampler: 'linear-clamp-to-edge',
3263
+ projection: 'spot-projection',
3264
+ revision: volumeSpot.projectorRevision ?? 1,
3265
+ },
3266
+ projectorHandle,
3267
+ projectorAsset,
3268
+ };
3269
+ }
3270
+
2898
3271
  // bug-20260710-editor-cross-world-shadow: CSM matrices are computed by the
2899
3272
  // shared pure {@link computeDirectionalCsm}, called here per-world with THIS
2900
3273
  // world's own `cameras[0]`. In a single-world app the light and camera share
@@ -3144,6 +3517,79 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
3144
3517
  }
3145
3518
  }
3146
3519
 
3520
+ const environmentCandidates: EnvironmentCandidate[] = [];
3521
+ const imageEnvironment =
3522
+ skylight?.equirectHandle !== undefined && skylight.equirectHandle > 0
3523
+ ? skylight
3524
+ : skybox?.equirectHandle !== undefined && skybox.equirectHandle > 0
3525
+ ? skybox
3526
+ : undefined;
3527
+ if (imageEnvironment !== undefined) {
3528
+ environmentCandidates.push({
3529
+ kind: 'image',
3530
+ entityKey: imageEnvironment.entityHandle,
3531
+ sourceKey: `equirect:${imageEnvironment.equirectHandle}`,
3532
+ });
3533
+ }
3534
+ const atmosphereQuery = world.query({ read: [Atmosphere] }).unwrap();
3535
+ for (const row of atmosphereQuery) {
3536
+ const value = row.get(Atmosphere);
3537
+ const atmosphere = {
3538
+ turbidity: value.turbidity,
3539
+ rayleigh: value.rayleigh,
3540
+ mieCoefficient: value.mieCoefficient,
3541
+ mieDirectionalG: value.mieDirectionalG,
3542
+ sunAngularRadius: value.sunAngularRadius,
3543
+ } as const;
3544
+ environmentCandidates.push({
3545
+ kind: 'atmosphere',
3546
+ entityKey: row.entity,
3547
+ sourceKey: `atmosphere:${row.entity}`,
3548
+ atmosphere,
3549
+ });
3550
+ }
3551
+ const directionalDirection = directional?.direction;
3552
+ const directionalLength =
3553
+ directionalDirection === undefined
3554
+ ? 0
3555
+ : Math.hypot(
3556
+ directionalDirection[0] ?? 0,
3557
+ directionalDirection[1] ?? 0,
3558
+ directionalDirection[2] ?? 0,
3559
+ );
3560
+ const sun =
3561
+ directional === undefined || directionalLength <= 1e-6
3562
+ ? []
3563
+ : [
3564
+ {
3565
+ entityKey: 0,
3566
+ direction: [
3567
+ -(directionalDirection?.[0] ?? 0) / directionalLength,
3568
+ -(directionalDirection?.[1] ?? 0) / directionalLength,
3569
+ -(directionalDirection?.[2] ?? 0) / directionalLength,
3570
+ ] as [number, number, number],
3571
+ color: [
3572
+ directional.color[0] ?? 0,
3573
+ directional.color[1] ?? 0,
3574
+ directional.color[2] ?? 0,
3575
+ ] as [number, number, number],
3576
+ intensity: directional.intensity,
3577
+ },
3578
+ ];
3579
+ const environmentSelection = selectEnvironment({
3580
+ environments: environmentCandidates,
3581
+ fogs: fog === undefined ? [] : [fog],
3582
+ suns: sun,
3583
+ lane: 'direct',
3584
+ });
3585
+ if (!environmentSelection.ok) {
3586
+ routeWorldError(world, environmentSelection.error, {
3587
+ systemName: 'RenderSystem.extract (environment-selection)',
3588
+ });
3589
+ throw environmentSelection.error;
3590
+ }
3591
+ const environment: EnvironmentFrame = environmentSelection.value;
3592
+
3147
3593
  // feat-20260528-frustum-culling M3 / w10: precompute per-camera frustum
3148
3594
  // planes so entities can be tested against all cameras in the inner loop.
3149
3595
  // Cameras with degenerate projection parameters (e.g. zero fov, zero aspect)
@@ -4541,18 +4987,22 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
4541
4987
  // recordFrame's `activeCameras[0]` selection.
4542
4988
  const tonemapCamera = cameras[0];
4543
4989
  if (tonemapCamera !== undefined) {
4544
- postProcessParams.set(STANDARD_TONEMAP_FEATURE_ID, tonemapParams(tonemapCamera));
4990
+ postProcessParams.set(STANDARD_OUTPUT_TRANSFORM_FEATURE_ID, tonemapParams(tonemapCamera));
4545
4991
  }
4546
4992
 
4547
4993
  return {
4548
4994
  cameras,
4549
4995
  lights,
4996
+ environment,
4997
+ environmentReady: true,
4998
+ ...(volumetricFog === undefined ? {} : { volumetricFog }),
4550
4999
  renderables,
4551
5000
  dispatch,
4552
5001
  skylight,
4553
5002
  skylightCount,
4554
5003
  skybox,
4555
5004
  skyboxCount,
5005
+ fog,
4556
5006
  frustumStats: { culled: frustumCulled, total: frustumTotal },
4557
5007
  visibilityStats: { explicitlyHidden: explicitlyHidden.size },
4558
5008
  postProcessParams,