@forgeax/engine-render 0.1.27 → 0.1.29

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 (655) hide show
  1. package/README.md +842 -124
  2. package/dist/assembly/atmosphere-shader-prewarm.d.ts +6 -0
  3. package/dist/assembly/atmosphere-shader-prewarm.d.ts.map +1 -0
  4. package/dist/assembly/dynamic-geometry-host.d.ts +52 -0
  5. package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -0
  6. package/dist/assembly/dynamic-geometry-runtime.d.ts +20 -0
  7. package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -0
  8. package/dist/assembly/factory.d.ts +3 -1
  9. package/dist/assembly/factory.d.ts.map +1 -1
  10. package/dist/assembly/gpu-driven-owner.d.ts +10 -0
  11. package/dist/assembly/gpu-driven-owner.d.ts.map +1 -0
  12. package/dist/assembly/host-contract.d.ts +19 -0
  13. package/dist/assembly/host-contract.d.ts.map +1 -1
  14. package/dist/assembly/material/assembly.d.ts +7 -0
  15. package/dist/assembly/material/assembly.d.ts.map +1 -1
  16. package/dist/assembly/material-shader-policy.d.ts +3 -1
  17. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  18. package/dist/assembly/recovery/failure-location.d.ts +12 -0
  19. package/dist/assembly/recovery/failure-location.d.ts.map +1 -0
  20. package/dist/assembly/recovery/renderer-recover.d.ts +6 -4
  21. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  22. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  23. package/dist/assembly/renderer-feature-inspection.d.ts +5 -0
  24. package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -0
  25. package/dist/assembly/renderer-frame-transaction.d.ts +19 -0
  26. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  27. package/dist/assembly/renderer-helpers.d.ts +3 -0
  28. package/dist/assembly/renderer-helpers.d.ts.map +1 -1
  29. package/dist/assembly/renderer-inspection.d.ts +4 -0
  30. package/dist/assembly/renderer-inspection.d.ts.map +1 -1
  31. package/dist/assembly/shader-prewarm-policy.d.ts +6 -0
  32. package/dist/assembly/shader-prewarm-policy.d.ts.map +1 -1
  33. package/dist/assembly/skin-palette-owner.d.ts +8 -0
  34. package/dist/assembly/skin-palette-owner.d.ts.map +1 -0
  35. package/dist/assembly/ssr-shader-prewarm.d.ts +6 -0
  36. package/dist/assembly/ssr-shader-prewarm.d.ts.map +1 -0
  37. package/dist/assembly/webgpu-device-loss.d.ts +15 -0
  38. package/dist/assembly/webgpu-device-loss.d.ts.map +1 -0
  39. package/dist/assembly/webgpu-pbr-ready.d.ts +38 -0
  40. package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -0
  41. package/dist/assembly/webgpu-ready-mipmap.d.ts +11 -0
  42. package/dist/assembly/webgpu-ready-mipmap.d.ts.map +1 -0
  43. package/dist/assembly/webgpu-ready.d.ts +7 -3
  44. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  45. package/dist/assembly/webgpu-renderer-bootstrap.d.ts +10 -0
  46. package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -0
  47. package/dist/assembly/webgpu-renderer-contract.d.ts +62 -0
  48. package/dist/assembly/webgpu-renderer-contract.d.ts.map +1 -0
  49. package/dist/assembly/webgpu-renderer-guards.d.ts +9 -0
  50. package/dist/assembly/webgpu-renderer-guards.d.ts.map +1 -0
  51. package/dist/assembly/webgpu-renderer-observation.d.ts +6 -0
  52. package/dist/assembly/webgpu-renderer-observation.d.ts.map +1 -0
  53. package/dist/assembly/webgpu-renderer-recovery-failure.d.ts +12 -0
  54. package/dist/assembly/webgpu-renderer-recovery-failure.d.ts.map +1 -0
  55. package/dist/assembly/webgpu-renderer.d.ts +7 -141
  56. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  57. package/dist/assembly/webgpu-vertex-layouts.d.ts +28 -84
  58. package/dist/assembly/webgpu-vertex-layouts.d.ts.map +1 -1
  59. package/dist/authoring.mjs +3 -3
  60. package/dist/{chunk-ADHHVYLW.mjs → chunk-33XZFTQU.mjs} +245 -39
  61. package/dist/chunk-33XZFTQU.mjs.map +1 -0
  62. package/dist/{chunk-GF523LHF.mjs → chunk-BLXGONR2.mjs} +30 -12
  63. package/dist/chunk-BLXGONR2.mjs.map +1 -0
  64. package/dist/{chunk-KM2NOX2I.mjs → chunk-BQVQOQJH.mjs} +958 -254
  65. package/dist/chunk-BQVQOQJH.mjs.map +1 -0
  66. package/dist/{chunk-HKXTW355.mjs → chunk-BTWH7BP4.mjs} +386 -17
  67. package/dist/chunk-BTWH7BP4.mjs.map +1 -0
  68. package/dist/{chunk-TMIASV2N.mjs → chunk-FUODTTIA.mjs} +3934 -676
  69. package/dist/chunk-FUODTTIA.mjs.map +1 -0
  70. package/dist/{chunk-FJ6P52EE.mjs → chunk-ILQ5MEZF.mjs} +3 -17
  71. package/dist/chunk-ILQ5MEZF.mjs.map +1 -0
  72. package/dist/{chunk-E34VL5VI.mjs → chunk-JQTSEI3Z.mjs} +3 -3
  73. package/dist/{chunk-E34VL5VI.mjs.map → chunk-JQTSEI3Z.mjs.map} +1 -1
  74. package/dist/{chunk-GE3SDD72.mjs → chunk-NICXSHAT.mjs} +16 -38
  75. package/dist/chunk-NICXSHAT.mjs.map +1 -0
  76. package/dist/{chunk-ZZ4YQ474.mjs → chunk-NRNXBLIJ.mjs} +577 -7
  77. package/dist/chunk-NRNXBLIJ.mjs.map +1 -0
  78. package/dist/{chunk-JDWARUOI.mjs → chunk-PA5DRJNI.mjs} +17 -3
  79. package/dist/chunk-PA5DRJNI.mjs.map +1 -0
  80. package/dist/{chunk-XDP6XE5V.mjs → chunk-S4DNKQYQ.mjs} +1118 -446
  81. package/dist/chunk-S4DNKQYQ.mjs.map +1 -0
  82. package/dist/components/camera.d.ts +62 -2
  83. package/dist/components/camera.d.ts.map +1 -1
  84. package/dist/components/index.d.ts +1 -0
  85. package/dist/components/index.d.ts.map +1 -1
  86. package/dist/components/instances.d.ts +6 -20
  87. package/dist/components/instances.d.ts.map +1 -1
  88. package/dist/components/scene-instance.d.ts +2 -1
  89. package/dist/components/scene-instance.d.ts.map +1 -1
  90. package/dist/components/screen-space-reflection.d.ts +14 -0
  91. package/dist/components/screen-space-reflection.d.ts.map +1 -0
  92. package/dist/construct-renderer.mjs +13805 -7186
  93. package/dist/construct-renderer.mjs.map +1 -1
  94. package/dist/device/gpu-residency.d.ts +11 -17
  95. package/dist/device/gpu-residency.d.ts.map +1 -1
  96. package/dist/device/mesh-residency-lifetime.d.ts +21 -0
  97. package/dist/device/mesh-residency-lifetime.d.ts.map +1 -0
  98. package/dist/dynamic-geometry.d.ts +125 -0
  99. package/dist/dynamic-geometry.d.ts.map +1 -0
  100. package/dist/environment/background.d.ts +6 -0
  101. package/dist/environment/background.d.ts.map +1 -0
  102. package/dist/errors/gpu-driven.d.ts +6 -3
  103. package/dist/errors/gpu-driven.d.ts.map +1 -1
  104. package/dist/errors/render.d.ts +7 -4
  105. package/dist/errors/render.d.ts.map +1 -1
  106. package/dist/extract/camera.d.ts.map +1 -1
  107. package/dist/extract/gpu-driven.d.ts +33 -3
  108. package/dist/extract/gpu-driven.d.ts.map +1 -1
  109. package/dist/features/host.d.ts +23 -1
  110. package/dist/features/host.d.ts.map +1 -1
  111. package/dist/features/noise-texture.d.ts +17 -0
  112. package/dist/features/noise-texture.d.ts.map +1 -0
  113. package/dist/features/plan.d.ts +83 -2
  114. package/dist/features/plan.d.ts.map +1 -1
  115. package/dist/features/prepared-gpu-work.d.ts +37 -4
  116. package/dist/features/prepared-gpu-work.d.ts.map +1 -1
  117. package/dist/features/prepared-graphics-store.d.ts.map +1 -1
  118. package/dist/features/prepared-graphics.d.ts +5 -0
  119. package/dist/features/prepared-graphics.d.ts.map +1 -1
  120. package/dist/features/render-graph-compute.d.ts +5 -3
  121. package/dist/features/render-graph-compute.d.ts.map +1 -1
  122. package/dist/features/render-graph-contribution.d.ts +11 -3
  123. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  124. package/dist/features/render-graph-raster.d.ts +19 -3
  125. package/dist/features/render-graph-raster.d.ts.map +1 -1
  126. package/dist/features/types.d.ts +11 -0
  127. package/dist/features/types.d.ts.map +1 -1
  128. package/dist/fullscreen-post-process-pass.d.ts +2 -0
  129. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  130. package/dist/gpu-driven/batch-topology.d.ts +34 -1
  131. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  132. package/dist/gpu-driven/pbr-program.d.ts +10 -0
  133. package/dist/gpu-driven/pbr-program.d.ts.map +1 -0
  134. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
  135. package/dist/gpu-driven/production-raster.d.ts +144 -23
  136. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  137. package/dist/gpu-driven/shadow-views.d.ts +126 -0
  138. package/dist/gpu-driven/shadow-views.d.ts.map +1 -0
  139. package/dist/gpu-driven/view-gpu.d.ts +18 -2
  140. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  141. package/dist/gpu-scene-schema.d.ts +2 -8
  142. package/dist/gpu-scene-schema.d.ts.map +1 -1
  143. package/dist/gpu-scene.d.ts +14 -0
  144. package/dist/gpu-scene.d.ts.map +1 -1
  145. package/dist/gpu-texture-usage.d.ts +1 -0
  146. package/dist/gpu-texture-usage.d.ts.map +1 -1
  147. package/dist/hdrp-buffers.d.ts +6 -0
  148. package/dist/hdrp-buffers.d.ts.map +1 -1
  149. package/dist/ibl/frame-resources.d.ts +8 -0
  150. package/dist/ibl/frame-resources.d.ts.map +1 -0
  151. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  152. package/dist/index.d.ts +21 -8
  153. package/dist/index.d.ts.map +1 -1
  154. package/dist/index.mjs +8 -7
  155. package/dist/index.mjs.map +1 -1
  156. package/dist/inspection-types.d.ts +164 -0
  157. package/dist/inspection-types.d.ts.map +1 -1
  158. package/dist/instances-derived-bounds.d.ts +11 -0
  159. package/dist/instances-derived-bounds.d.ts.map +1 -1
  160. package/dist/instances.d.ts +89 -44
  161. package/dist/instances.d.ts.map +1 -1
  162. package/dist/internal.d.ts +3 -0
  163. package/dist/internal.d.ts.map +1 -1
  164. package/dist/internal.mjs +118 -10
  165. package/dist/internal.mjs.map +1 -1
  166. package/dist/lifecycle.d.ts +2 -1
  167. package/dist/lifecycle.d.ts.map +1 -1
  168. package/dist/material-row.d.ts +5 -0
  169. package/dist/material-row.d.ts.map +1 -0
  170. package/dist/materials.d.ts +15 -0
  171. package/dist/materials.d.ts.map +1 -1
  172. package/dist/pbr-pipeline.d.ts +21 -5
  173. package/dist/pbr-pipeline.d.ts.map +1 -1
  174. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  175. package/dist/pipeline/standard-output/auto-exposure/capability.d.ts +12 -0
  176. package/dist/pipeline/standard-output/auto-exposure/capability.d.ts.map +1 -0
  177. package/dist/pipeline/standard-output/auto-exposure/gpu.d.ts +70 -0
  178. package/dist/pipeline/standard-output/auto-exposure/gpu.d.ts.map +1 -0
  179. package/dist/pipeline/standard-output/auto-exposure/graph.d.ts +75 -0
  180. package/dist/pipeline/standard-output/auto-exposure/graph.d.ts.map +1 -0
  181. package/dist/pipeline/standard-output/auto-exposure/inspection.d.ts +111 -0
  182. package/dist/pipeline/standard-output/auto-exposure/inspection.d.ts.map +1 -0
  183. package/dist/pipeline/standard-output/auto-exposure/oracle.d.ts +16 -0
  184. package/dist/pipeline/standard-output/auto-exposure/oracle.d.ts.map +1 -0
  185. package/dist/pipeline/standard-output/auto-exposure/preset.d.ts +14 -0
  186. package/dist/pipeline/standard-output/auto-exposure/preset.d.ts.map +1 -0
  187. package/dist/pipeline/standard-output/auto-exposure/state.d.ts +46 -0
  188. package/dist/pipeline/standard-output/auto-exposure/state.d.ts.map +1 -0
  189. package/dist/pipeline/standard-output/color-transform.d.ts +27 -0
  190. package/dist/pipeline/standard-output/color-transform.d.ts.map +1 -0
  191. package/dist/pipeline/standard-output/graph.d.ts +15 -0
  192. package/dist/pipeline/standard-output/graph.d.ts.map +1 -0
  193. package/dist/pipeline/standard-output/lut-admission.d.ts +29 -0
  194. package/dist/pipeline/standard-output/lut-admission.d.ts.map +1 -0
  195. package/dist/pipeline/standard-output/lut-gpu.d.ts +48 -0
  196. package/dist/pipeline/standard-output/lut-gpu.d.ts.map +1 -0
  197. package/dist/pipeline/standard-output/lut-state.d.ts +68 -0
  198. package/dist/pipeline/standard-output/lut-state.d.ts.map +1 -0
  199. package/dist/pipeline/standard-output/resources.d.ts +10 -0
  200. package/dist/pipeline/standard-output/resources.d.ts.map +1 -0
  201. package/dist/pipeline/standard-output/types.d.ts +39 -0
  202. package/dist/pipeline/standard-output/types.d.ts.map +1 -0
  203. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  204. package/dist/pipeline/standard-post.d.ts +2 -2
  205. package/dist/pipeline/standard-post.d.ts.map +1 -1
  206. package/dist/pipeline-builder.d.ts +2 -1
  207. package/dist/pipeline-builder.d.ts.map +1 -1
  208. package/dist/pipeline-spec-types.d.ts +4 -0
  209. package/dist/pipeline-spec-types.d.ts.map +1 -1
  210. package/dist/pipeline-spec.d.ts +1 -9
  211. package/dist/pipeline-spec.d.ts.map +1 -1
  212. package/dist/points-lines/standard-owner.d.ts +1 -1
  213. package/dist/points-lines/standard-owner.d.ts.map +1 -1
  214. package/dist/prepare/prepared-graphics-resolver.d.ts +6 -1
  215. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  216. package/dist/record/dynamic-geometry-consumption.d.ts +15 -0
  217. package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -0
  218. package/dist/record/frame-lighting.d.ts +3 -3
  219. package/dist/record/frame-lighting.d.ts.map +1 -1
  220. package/dist/record/frame-snapshot.d.ts +106 -5
  221. package/dist/record/frame-snapshot.d.ts.map +1 -1
  222. package/dist/record/frame-targets.d.ts.map +1 -1
  223. package/dist/record/frame.d.ts +39 -4
  224. package/dist/record/frame.d.ts.map +1 -1
  225. package/dist/record/main-pass-geometry.d.ts +7 -8
  226. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  227. package/dist/record/main-pass-material.d.ts +38 -1
  228. package/dist/record/main-pass-material.d.ts.map +1 -1
  229. package/dist/record/main-pass-sprite-draws.d.ts +2 -10
  230. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  231. package/dist/record/main-pass.d.ts +12 -2
  232. package/dist/record/main-pass.d.ts.map +1 -1
  233. package/dist/record/mesh-ssbo.d.ts +15 -6
  234. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  235. package/dist/record/prepared-material-bindings.d.ts +19 -0
  236. package/dist/record/prepared-material-bindings.d.ts.map +1 -0
  237. package/dist/record/recovery-pipeline.d.ts +2 -9
  238. package/dist/record/recovery-pipeline.d.ts.map +1 -1
  239. package/dist/record/render-context.d.ts +76 -26
  240. package/dist/record/render-context.d.ts.map +1 -1
  241. package/dist/record/shadow-pass.d.ts +62 -7
  242. package/dist/record/shadow-pass.d.ts.map +1 -1
  243. package/dist/record/skybox-post-pass.d.ts +1 -1
  244. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  245. package/dist/record/typed-frame-graph.d.ts +35 -7
  246. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  247. package/dist/record/view-ubo.d.ts +1 -0
  248. package/dist/record/view-ubo.d.ts.map +1 -1
  249. package/dist/recovery/render-system-candidate.d.ts +10 -2
  250. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  251. package/dist/recovery/render-system-roots.d.ts +11 -0
  252. package/dist/recovery/render-system-roots.d.ts.map +1 -0
  253. package/dist/recovery/types.d.ts +76 -0
  254. package/dist/recovery/types.d.ts.map +1 -0
  255. package/dist/reflection/record-owner.d.ts +0 -2
  256. package/dist/reflection/record-owner.d.ts.map +1 -1
  257. package/dist/render-contract.d.ts +185 -30
  258. package/dist/render-contract.d.ts.map +1 -1
  259. package/dist/render-graph-primitives.d.ts +1 -0
  260. package/dist/render-graph-primitives.d.ts.map +1 -1
  261. package/dist/render-pipeline.d.ts +64 -5
  262. package/dist/render-pipeline.d.ts.map +1 -1
  263. package/dist/render-system-extract-tail.d.ts +7 -5
  264. package/dist/render-system-extract-tail.d.ts.map +1 -1
  265. package/dist/render-system-extract.d.ts +101 -41
  266. package/dist/render-system-extract.d.ts.map +1 -1
  267. package/dist/render-system-projections.d.ts +22 -0
  268. package/dist/render-system-projections.d.ts.map +1 -0
  269. package/dist/render-system.d.ts +34 -77
  270. package/dist/render-system.d.ts.map +1 -1
  271. package/dist/scene/render-scene-types.d.ts +14 -7
  272. package/dist/scene/render-scene-types.d.ts.map +1 -1
  273. package/dist/scene/render-scene.d.ts +29 -11
  274. package/dist/scene/render-scene.d.ts.map +1 -1
  275. package/dist/scene/shadow-visibility.d.ts +5 -0
  276. package/dist/scene/shadow-visibility.d.ts.map +1 -0
  277. package/dist/ssr/admission.d.ts +70 -1
  278. package/dist/ssr/admission.d.ts.map +1 -1
  279. package/dist/ssr/compose.d.ts +13 -0
  280. package/dist/ssr/compose.d.ts.map +1 -0
  281. package/dist/ssr/errors.d.ts +35 -0
  282. package/dist/ssr/errors.d.ts.map +1 -1
  283. package/dist/ssr/graph.d.ts +60 -0
  284. package/dist/ssr/graph.d.ts.map +1 -0
  285. package/dist/ssr/history.d.ts +97 -0
  286. package/dist/ssr/history.d.ts.map +1 -0
  287. package/dist/ssr/hiz.d.ts +37 -0
  288. package/dist/ssr/hiz.d.ts.map +1 -0
  289. package/dist/ssr/inspection.d.ts +42 -0
  290. package/dist/ssr/inspection.d.ts.map +1 -0
  291. package/dist/ssr/resources.d.ts +58 -0
  292. package/dist/ssr/resources.d.ts.map +1 -0
  293. package/dist/ssr/temporal.d.ts +38 -0
  294. package/dist/ssr/temporal.d.ts.map +1 -0
  295. package/dist/systems/skin-palette-allocator.d.ts +32 -10
  296. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  297. package/dist/systems/skin-palette-types.d.ts +15 -0
  298. package/dist/systems/skin-palette-types.d.ts.map +1 -1
  299. package/dist/systems/transparent-dispatch.d.ts +9 -0
  300. package/dist/systems/transparent-dispatch.d.ts.map +1 -0
  301. package/dist/targets/material-source.d.ts +7 -0
  302. package/dist/targets/material-source.d.ts.map +1 -1
  303. package/dist/temporal/frame-coordinator.d.ts +7 -0
  304. package/dist/temporal/frame-coordinator.d.ts.map +1 -1
  305. package/dist/temporal/gpu.d.ts +8 -0
  306. package/dist/temporal/gpu.d.ts.map +1 -1
  307. package/dist/temporal/history.d.ts.map +1 -1
  308. package/dist/temporal/index.mjs +6 -6
  309. package/dist/temporal/inspection.d.ts.map +1 -1
  310. package/dist/temporal/standard-scene-data.d.ts +2 -1
  311. package/dist/temporal/standard-scene-data.d.ts.map +1 -1
  312. package/dist/temporal/temporal-view.d.ts +2 -0
  313. package/dist/temporal/temporal-view.d.ts.map +1 -1
  314. package/dist/typed-render-graph-primitives.d.ts +35 -1
  315. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  316. package/dist/typed-shadow-passes.d.ts +3 -1
  317. package/dist/typed-shadow-passes.d.ts.map +1 -1
  318. package/dist/volume/temporal.d.ts +6 -0
  319. package/dist/volume/temporal.d.ts.map +1 -1
  320. package/package.json +21 -20
  321. package/src/__tests__/auto-exposure-gpu-evidence.ts +291 -0
  322. package/src/__tests__/auto-exposure-inspection.unit.test.ts +80 -0
  323. package/src/__tests__/auto-exposure-transaction.integration.test.ts +99 -0
  324. package/src/__tests__/auto-exposure.browser.test.ts +33 -0
  325. package/src/__tests__/auto-exposure.dawn.test.ts +33 -0
  326. package/src/__tests__/detached-inspection.integration.test.ts +5 -0
  327. package/src/__tests__/device-scope-lifecycle.unit.test.ts +18 -0
  328. package/src/__tests__/device-scope-stale-matrix.unit.test.ts +18 -0
  329. package/src/__tests__/docs-gate-green.unit.test.ts +3 -3
  330. package/src/__tests__/dynamic-geometry-host.unit.test.ts +1123 -0
  331. package/src/__tests__/dynamic-geometry.unit.test.ts +233 -0
  332. package/src/__tests__/factory-contract.integration.test.ts +73 -22
  333. package/src/__tests__/fallback-row-stride-surface.unit.test.ts +19 -0
  334. package/src/__tests__/feature-depth-input.dawn.test.ts +121 -0
  335. package/src/__tests__/feature-noise.unit.test.ts +38 -0
  336. package/src/__tests__/fixtures/taa-resolve-pinned-baseline.wgsl +301 -0
  337. package/src/__tests__/frame-camera-selection.unit.test.ts +131 -0
  338. package/src/__tests__/frame-plan-contract.unit.test.ts +24 -0
  339. package/src/__tests__/frame-targets.unit.test.ts +24 -0
  340. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +3 -0
  341. package/src/__tests__/gpu-driven-baseline.characterization.test.ts +79 -0
  342. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +287 -6
  343. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +122 -142
  344. package/src/__tests__/gpu-driven-indirect-raster.browser.test.ts +10 -1
  345. package/src/__tests__/gpu-driven-lod-cache.unit.test.ts +264 -0
  346. package/src/__tests__/gpu-driven-mesh-world-identity.unit.test.ts +349 -0
  347. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +1417 -0
  348. package/src/__tests__/gpu-driven-pbr.integration.test.ts +21 -0
  349. package/src/__tests__/gpu-driven-production-fixture.ts +96 -0
  350. package/src/__tests__/gpu-driven-production.integration.test.ts +1075 -93
  351. package/src/__tests__/gpu-driven-scaling.unit.test.ts +1 -3
  352. package/src/__tests__/gpu-driven-shadow-views.browser.test.ts +63 -0
  353. package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +294 -0
  354. package/src/__tests__/gpu-driven-shadow-views.integration.test.ts +97 -0
  355. package/src/__tests__/gpu-driven-shadow-views.unit.test.ts +168 -0
  356. package/src/__tests__/gpu-driven-skin-contract.test-d.ts +11 -0
  357. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +72 -20
  358. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +30 -9
  359. package/src/__tests__/gpu-driven-view.unit.test.ts +159 -52
  360. package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -1
  361. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +42 -0
  362. package/src/__tests__/gpu-scene-render-graph-gpu.ts +19 -5
  363. package/src/__tests__/gpu-scene.dawn.test.ts +40 -13
  364. package/src/__tests__/gpu-scene.unit.test.ts +559 -33
  365. package/src/__tests__/instances-culling.integration.test.ts +36 -10
  366. package/src/__tests__/instances-derived-bounds.unit.test.ts +54 -0
  367. package/src/__tests__/instances-store.unit.test.ts +242 -39
  368. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +6 -0
  369. package/src/__tests__/lighting-scene-roundtrip.integration.test.ts +13 -16
  370. package/src/__tests__/lut-lkg-transaction.integration.test.ts +122 -0
  371. package/src/__tests__/material-contract-inventory.unit.test.ts +5 -6
  372. package/src/__tests__/material-dispatch-shader-id.unit.test.ts +51 -0
  373. package/src/__tests__/material-lane-selection.unit.test.ts +60 -0
  374. package/src/__tests__/material-numeric-upload.unit.test.ts +53 -0
  375. package/src/__tests__/material-texture-handles.unit.test.ts +18 -0
  376. package/src/__tests__/material-texture-source.unit.test.ts +87 -0
  377. package/src/__tests__/materials-authoring-validation.unit.test.ts +41 -0
  378. package/src/__tests__/materials-standard-contract.unit.test.ts +52 -2
  379. package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +4 -0
  380. package/src/__tests__/mesh-submission-lifetime.unit.test.ts +53 -0
  381. package/src/__tests__/normal-fallback.dawn.test.ts +122 -0
  382. package/src/__tests__/particle-material-input-layout.unit.test.ts +104 -0
  383. package/src/__tests__/physical-clearcoat.integration.test.ts +37 -3
  384. package/src/__tests__/pipeline-texture-specialization.unit.test.ts +138 -0
  385. package/src/__tests__/point-shadow-inspection.unit.test.ts +2 -0
  386. package/src/__tests__/prepared-gpu-driven-pbr-contract.test-d.ts +31 -0
  387. package/src/__tests__/prepared-gpu-driven-pbr-contract.unit.test.ts +39 -0
  388. package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +35 -4
  389. package/src/__tests__/prepared-graphics-capability.unit.test.ts +21 -0
  390. package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +6 -2
  391. package/src/__tests__/profiler-phase-catalog.test.ts +5 -0
  392. package/src/__tests__/public-surface.test-d.ts +3 -0
  393. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +30 -12
  394. package/src/__tests__/reflection-fallback-async-publication.unit.test.ts +104 -0
  395. package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +2 -1
  396. package/src/__tests__/render-error-code-owner.test-d.ts +4 -0
  397. package/src/__tests__/render-error-detail-ssot.test-d.ts +22 -0
  398. package/src/__tests__/render-error-exhaustive.test-d.ts +15 -0
  399. package/src/__tests__/render-feature-gpu-work.integration.test.ts +285 -2
  400. package/src/__tests__/render-feature-plan.unit.test.ts +245 -0
  401. package/src/__tests__/render-feature-shadow-order.unit.test.ts +228 -0
  402. package/src/__tests__/render-feature-zero-work.unit.test.ts +35 -1
  403. package/src/__tests__/render-graph-fallback.integration.test.ts +2 -2
  404. package/src/__tests__/render-owner-cohesion.unit.test.ts +55 -0
  405. package/src/__tests__/render-scene-mixed-updates.integration.test.ts +426 -0
  406. package/src/__tests__/render-scene-projection.unit.test.ts +914 -23
  407. package/src/__tests__/render-scene-resource-updates.integration.test.ts +214 -0
  408. package/src/__tests__/render-scene-skin-lifecycle.integration.test.ts +173 -0
  409. package/src/__tests__/render-scene-temporal-retry.unit.test.ts +133 -0
  410. package/src/__tests__/render-target-material-source.test-d.ts +27 -3
  411. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +61 -1
  412. package/src/__tests__/renderer-frame-transaction.integration.test.ts +923 -5
  413. package/src/__tests__/shader-manifest-fixture.ts +39 -0
  414. package/src/__tests__/skin-motion-regression.unit.test.ts +0 -33
  415. package/src/__tests__/skin-palette-persistent.integration.test.ts +28 -0
  416. package/src/__tests__/skin-palette-persistent.unit.test.ts +247 -0
  417. package/src/__tests__/skinned-shadow-caster.test.ts +118 -14
  418. package/src/__tests__/specular-environment-scale.dawn.test.ts +156 -0
  419. package/src/__tests__/ssr-admission-matrix.integration.test.ts +7 -1
  420. package/src/__tests__/ssr-confidence-compose.unit.test.ts +84 -0
  421. package/src/__tests__/ssr-coordinate-oracle.unit.test.ts +28 -0
  422. package/src/__tests__/ssr-format-probe-gating.integration.test.ts +82 -0
  423. package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +91 -0
  424. package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +112 -0
  425. package/src/__tests__/ssr-gpu-dispatch.ts +946 -0
  426. package/src/__tests__/ssr-graph-topology.unit.test.ts +104 -0
  427. package/src/__tests__/ssr-history-filter.dawn.test.ts +198 -0
  428. package/src/__tests__/ssr-hit-color.dawn.test.ts +273 -0
  429. package/src/__tests__/ssr-hiz-odd-reduction.dawn.test.ts +569 -0
  430. package/src/__tests__/ssr-hiz-rescue.dawn.test.ts +279 -0
  431. package/src/__tests__/ssr-hiz.browser.test.ts +150 -0
  432. package/src/__tests__/ssr-hiz.dawn.test.ts +150 -0
  433. package/src/__tests__/ssr-hiz.unit.test.ts +56 -0
  434. package/src/__tests__/ssr-inspection.unit.test.ts +105 -0
  435. package/src/__tests__/ssr-memory-budget.unit.test.ts +45 -0
  436. package/src/__tests__/ssr-performance-sequence-aggregation.unit.test.ts +15 -0
  437. package/src/__tests__/ssr-public-surface.test-d.ts +37 -0
  438. package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +387 -0
  439. package/src/__tests__/ssr-reflection-mip-reducer.dawn.test.ts +309 -0
  440. package/src/__tests__/ssr-reprojection-probe.ts +90 -0
  441. package/src/__tests__/ssr-roughness-mip.dawn.test.ts +163 -0
  442. package/src/__tests__/ssr-shader-prewarm.unit.test.ts +59 -0
  443. package/src/__tests__/ssr-spatial.integration.test.ts +141 -0
  444. package/src/__tests__/ssr-stable-lattice.dawn.test.ts +475 -0
  445. package/src/__tests__/ssr-temporal-history.unit.test.ts +202 -0
  446. package/src/__tests__/ssr-texel-crossing.dawn.test.ts +448 -0
  447. package/src/__tests__/ssr-zero-work.integration.test.ts +87 -0
  448. package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +44 -12
  449. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +29 -0
  450. package/src/__tests__/standard-output-chain-contract.unit.test.ts +99 -0
  451. package/src/__tests__/standard-output-chain.integration.test.ts +73 -0
  452. package/src/__tests__/standard-output-gpu-evidence.ts +205 -0
  453. package/src/__tests__/standard-output.browser.test.ts +15 -0
  454. package/src/__tests__/standard-output.dawn.test.ts +15 -0
  455. package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +38 -0
  456. package/src/__tests__/standard-pipeline.integration.test.ts +320 -3
  457. package/src/__tests__/standard-profile-oracle.unit.test.ts +22 -0
  458. package/src/__tests__/standard-surface-lighting.unit.test.ts +41 -0
  459. package/src/__tests__/standard-texture-specialization.dawn.test.ts +141 -0
  460. package/src/__tests__/surface-adjacent-regressions.integration.test.ts +6 -3
  461. package/src/__tests__/taa-coverage-edge.dawn.test.ts +193 -0
  462. package/src/__tests__/taa-history-clipping.dawn.test.ts +328 -0
  463. package/src/__tests__/taa-neighborhood-equivalence.dawn.test.ts +778 -0
  464. package/src/__tests__/taa-stability-feedback.browser.test.ts +23 -0
  465. package/src/__tests__/taa-stability-feedback.dawn.test.ts +68 -0
  466. package/src/__tests__/taa-stability-feedback.ts +341 -0
  467. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +49 -7
  468. package/src/__tests__/temporal-reset-matrix.unit.test.ts +9 -0
  469. package/src/__tests__/temporal-transaction.integration.test.ts +28 -0
  470. package/src/__tests__/texture-usage-surface.unit.test.ts +4 -2
  471. package/src/__tests__/typed-pipeline-topology.unit.test.ts +109 -4
  472. package/src/__tests__/typed-scene-pass-material-cache.integration.test.ts +126 -0
  473. package/src/__tests__/vertex-layouts-ssot.unit.test.ts +47 -0
  474. package/src/__tests__/visibility-extract.perf.test.ts +20 -8
  475. package/src/__tests__/visibility-instances.integration.test.ts +19 -7
  476. package/src/__tests__/visibility-producer-matrix.integration.test.ts +20 -9
  477. package/src/assembly/atmosphere-shader-prewarm.ts +38 -0
  478. package/src/assembly/dynamic-geometry-host.ts +887 -0
  479. package/src/assembly/dynamic-geometry-runtime.ts +71 -0
  480. package/src/assembly/factory.ts +4 -0
  481. package/src/assembly/gpu-driven-owner.ts +29 -0
  482. package/src/assembly/host-contract.ts +36 -0
  483. package/src/assembly/material/assembly.ts +38 -0
  484. package/src/assembly/material-shader-policy.ts +71 -28
  485. package/src/assembly/recovery/failure-location.ts +62 -0
  486. package/src/assembly/recovery/renderer-recover.ts +19 -17
  487. package/src/assembly/renderer-facade.ts +29 -0
  488. package/src/assembly/renderer-feature-inspection.ts +13 -0
  489. package/src/assembly/renderer-frame-transaction.ts +63 -0
  490. package/src/assembly/renderer-helpers.ts +26 -0
  491. package/src/assembly/renderer-inspection.ts +6 -0
  492. package/src/assembly/shader-prewarm-policy.ts +32 -0
  493. package/src/assembly/skin-palette-owner.ts +21 -0
  494. package/src/assembly/ssr-shader-prewarm.ts +41 -0
  495. package/src/assembly/webgpu-device-loss.ts +75 -0
  496. package/src/assembly/webgpu-pbr-ready.ts +232 -0
  497. package/src/assembly/webgpu-ready-mipmap.ts +26 -0
  498. package/src/assembly/webgpu-ready.ts +142 -121
  499. package/src/assembly/webgpu-renderer-bootstrap.ts +85 -0
  500. package/src/assembly/webgpu-renderer-contract.ts +69 -0
  501. package/src/assembly/webgpu-renderer-guards.ts +32 -0
  502. package/src/assembly/webgpu-renderer-observation.ts +43 -0
  503. package/src/assembly/webgpu-renderer-recovery-failure.ts +62 -0
  504. package/src/assembly/webgpu-renderer.ts +675 -614
  505. package/src/assembly/webgpu-vertex-layouts.ts +233 -87
  506. package/src/components/__tests__/camera-exposure.contract.unit.test.ts +153 -0
  507. package/src/components/camera.ts +287 -7
  508. package/src/components/index.ts +1 -0
  509. package/src/components/instances.ts +45 -18
  510. package/src/components/scene-instance.ts +2 -1
  511. package/src/components/screen-space-reflection.ts +21 -0
  512. package/src/components/sprite-animation.ts +3 -3
  513. package/src/components/sprite-instances.ts +1 -1
  514. package/src/device/gpu-residency.ts +96 -93
  515. package/src/device/mesh-residency-lifetime.ts +73 -0
  516. package/src/dynamic-geometry.ts +736 -0
  517. package/src/environment/background.ts +263 -0
  518. package/src/errors/gpu-driven.ts +39 -5
  519. package/src/errors/render.ts +27 -3
  520. package/src/extract/camera.ts +26 -1
  521. package/src/extract/gpu-driven.ts +185 -10
  522. package/src/features/host.ts +237 -19
  523. package/src/features/noise-texture.ts +91 -0
  524. package/src/features/plan.ts +553 -24
  525. package/src/features/prepared-gpu-work.ts +631 -49
  526. package/src/features/prepared-graphics-store.ts +31 -0
  527. package/src/features/prepared-graphics.ts +5 -0
  528. package/src/features/render-graph-compute.ts +41 -8
  529. package/src/features/render-graph-contribution.ts +141 -3
  530. package/src/features/render-graph-raster.ts +143 -30
  531. package/src/features/types.ts +11 -0
  532. package/src/fullscreen-post-process-pass.ts +3 -0
  533. package/src/gpu-driven/batch-topology.ts +424 -102
  534. package/src/gpu-driven/pbr-program.ts +31 -0
  535. package/src/gpu-driven/prepared-draw.ts +29 -4
  536. package/src/gpu-driven/production-raster.ts +2267 -694
  537. package/src/gpu-driven/shadow-views.ts +539 -0
  538. package/src/gpu-driven/view-gpu.ts +188 -41
  539. package/src/gpu-scene-schema.ts +52 -11
  540. package/src/gpu-scene.ts +186 -99
  541. package/src/gpu-texture-usage.ts +1 -0
  542. package/src/hdrp-buffers.ts +72 -36
  543. package/src/ibl/frame-resources.ts +38 -0
  544. package/src/ibl/skylight-bind-group.ts +5 -4
  545. package/src/index.ts +125 -1
  546. package/src/inspection-types.ts +191 -0
  547. package/src/instances-derived-bounds.ts +258 -34
  548. package/src/instances.ts +459 -150
  549. package/src/internal.ts +22 -0
  550. package/src/lifecycle.ts +2 -0
  551. package/src/material-row.ts +145 -0
  552. package/src/materials.ts +44 -8
  553. package/src/pbr-pipeline.ts +159 -17
  554. package/src/pipeline/standard-forward-lane.ts +52 -24
  555. package/src/pipeline/standard-output/__tests__/lut-admission.unit.test.ts +103 -0
  556. package/src/pipeline/standard-output/auto-exposure/__tests__/capability.unit.test.ts +40 -0
  557. package/src/pipeline/standard-output/auto-exposure/__tests__/gpu.contract.unit.test.ts +125 -0
  558. package/src/pipeline/standard-output/auto-exposure/__tests__/graph.contract.unit.test.ts +94 -0
  559. package/src/pipeline/standard-output/auto-exposure/__tests__/oracle.test.ts +108 -0
  560. package/src/pipeline/standard-output/auto-exposure/__tests__/preset.test.ts +26 -0
  561. package/src/pipeline/standard-output/auto-exposure/capability.ts +38 -0
  562. package/src/pipeline/standard-output/auto-exposure/gpu.ts +567 -0
  563. package/src/pipeline/standard-output/auto-exposure/graph.ts +221 -0
  564. package/src/pipeline/standard-output/auto-exposure/inspection.ts +231 -0
  565. package/src/pipeline/standard-output/auto-exposure/oracle.ts +291 -0
  566. package/src/pipeline/standard-output/auto-exposure/preset.ts +28 -0
  567. package/src/pipeline/standard-output/auto-exposure/state.ts +156 -0
  568. package/src/pipeline/standard-output/color-transform.ts +124 -0
  569. package/src/pipeline/standard-output/graph.ts +139 -0
  570. package/src/pipeline/standard-output/lut-admission.ts +121 -0
  571. package/src/pipeline/standard-output/lut-gpu.ts +399 -0
  572. package/src/pipeline/standard-output/lut-state.ts +176 -0
  573. package/src/pipeline/standard-output/resources.ts +121 -0
  574. package/src/pipeline/standard-output/types.ts +58 -0
  575. package/src/pipeline/standard-pipeline.ts +192 -59
  576. package/src/pipeline/standard-post.ts +186 -27
  577. package/src/pipeline-builder.ts +16 -6
  578. package/src/pipeline-spec-types.ts +4 -0
  579. package/src/pipeline-spec.ts +37 -29
  580. package/src/points-lines/standard-owner.ts +6 -14
  581. package/src/prepare/prepared-graphics-resolver.ts +9 -2
  582. package/src/record/__tests__/material-slot-plan.unit.test.ts +48 -0
  583. package/src/record/__tests__/mesh-ssbo.unit.test.ts +40 -1
  584. package/src/record/__tests__/recovery-pipeline.unit.test.ts +2 -29
  585. package/src/record/__tests__/sprite-material-abi.unit.test.ts +36 -5
  586. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +45 -0
  587. package/src/record/__tests__/view-ubo-layout.unit.test.ts +5 -0
  588. package/src/record/dynamic-geometry-consumption.ts +59 -0
  589. package/src/record/frame-lighting.ts +12 -11
  590. package/src/record/frame-snapshot.ts +133 -23
  591. package/src/record/frame-targets.ts +9 -0
  592. package/src/record/frame.ts +727 -133
  593. package/src/record/main-pass-geometry.ts +162 -98
  594. package/src/record/main-pass-material.ts +115 -26
  595. package/src/record/main-pass-sprite-draws.ts +18 -107
  596. package/src/record/main-pass.ts +78 -8
  597. package/src/record/material-uniforms.ts +1 -1
  598. package/src/record/mesh-ssbo.ts +59 -15
  599. package/src/record/prepared-material-bindings.ts +234 -0
  600. package/src/record/recovery-pipeline.ts +59 -136
  601. package/src/record/render-context.ts +92 -22
  602. package/src/record/shadow-pass.ts +1231 -209
  603. package/src/record/skybox-post-pass.ts +14 -3
  604. package/src/record/typed-frame-graph.ts +1006 -53
  605. package/src/record/view-ubo.ts +11 -0
  606. package/src/recovery/render-system-candidate.ts +90 -66
  607. package/src/recovery/render-system-roots.ts +113 -0
  608. package/src/recovery/types.ts +77 -0
  609. package/src/reflection/record-owner.ts +26 -54
  610. package/src/render-contract.ts +219 -25
  611. package/src/render-graph-primitives.ts +6 -2
  612. package/src/render-pipeline.ts +70 -1
  613. package/src/render-system-extract-tail.ts +409 -160
  614. package/src/render-system-extract.ts +376 -102
  615. package/src/render-system-projections.ts +241 -0
  616. package/src/render-system.ts +692 -791
  617. package/src/scene/render-scene-types.ts +13 -4
  618. package/src/scene/render-scene.ts +569 -355
  619. package/src/scene/shadow-visibility.ts +21 -0
  620. package/src/ssr/admission.ts +380 -14
  621. package/src/ssr/compose.ts +144 -0
  622. package/src/ssr/errors.ts +48 -0
  623. package/src/ssr/graph.ts +777 -0
  624. package/src/ssr/history.ts +436 -0
  625. package/src/ssr/hiz.ts +124 -0
  626. package/src/ssr/inspection.ts +124 -0
  627. package/src/ssr/resources.ts +202 -0
  628. package/src/ssr/temporal.ts +164 -0
  629. package/src/systems/skin-palette-allocator.ts +495 -148
  630. package/src/systems/skin-palette-types.ts +17 -0
  631. package/src/systems/transparent-dispatch.ts +90 -0
  632. package/src/targets/material-source.ts +34 -0
  633. package/src/temporal/coverage.ts +1 -1
  634. package/src/temporal/frame-coordinator.ts +23 -2
  635. package/src/temporal/gpu.ts +74 -12
  636. package/src/temporal/history.ts +3 -1
  637. package/src/temporal/inspection.ts +2 -1
  638. package/src/temporal/standard-scene-data.ts +3 -1
  639. package/src/temporal/temporal-view.ts +3 -0
  640. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +204 -139
  641. package/src/typed-render-graph-primitives.ts +266 -74
  642. package/src/typed-shadow-passes.ts +122 -12
  643. package/src/volume/temporal.ts +10 -0
  644. package/dist/chunk-ADHHVYLW.mjs.map +0 -1
  645. package/dist/chunk-FJ6P52EE.mjs.map +0 -1
  646. package/dist/chunk-GE3SDD72.mjs.map +0 -1
  647. package/dist/chunk-GF523LHF.mjs.map +0 -1
  648. package/dist/chunk-HKXTW355.mjs.map +0 -1
  649. package/dist/chunk-JDWARUOI.mjs.map +0 -1
  650. package/dist/chunk-KM2NOX2I.mjs.map +0 -1
  651. package/dist/chunk-TMIASV2N.mjs.map +0 -1
  652. package/dist/chunk-XDP6XE5V.mjs.map +0 -1
  653. package/dist/chunk-ZZ4YQ474.mjs.map +0 -1
  654. package/src/__tests__/instances-world-ownership.integration.test.ts +0 -62
  655. package/src/scene/__tests__/changed-block-summary.candidate.test.ts +0 -36
@@ -76,9 +76,18 @@ import type { MaterialCookProgramContext } from '@forgeax/engine-pack/material-c
76
76
  // `MeshFilter.assetHandle` dangling path
77
77
  // (charter proposition 5; AC-11).
78
78
  //
79
- // World owns explicit Instances transforms. Extraction makes a detached
80
- // per-renderer projection; GPU residents acknowledge complete snapshots only
81
- // after successful uploads. Reading a snapshot never changes author state.
79
+ // Renderer-owned Large Instances:
80
+ // `Instances { collectionId }` is an ECS association to the renderer's
81
+ // `InstanceCollectionStore`, not an ECS transform-array column. The extract
82
+ // tail resolves the identity against that store and snapshots canonical
83
+ // transforms together with collection revision, capacity, dirty ranges,
84
+ // and residency facts. Invalid or stale associations route the existing
85
+ // typed `InstanceCollectionError` through the World error boundary; the
86
+ // record stage owns GPU residency and upload decisions.
87
+ //
88
+ // `SpriteInstances` remains the separate ECS-owned array-view path. Its
89
+ // snapshot is intentionally independent from renderer-owned Large Instances,
90
+ // so the extract stage does not duplicate collection storage or GPU policy.
82
91
 
83
92
  import type { AssetRegistry } from '@forgeax/engine-assets-runtime';
84
93
  import {
@@ -94,9 +103,11 @@ import { AssetGuid, type AssetGuid as AssetGuidBytes } from '@forgeax/engine-pac
94
103
  import { RhiError } from '@forgeax/engine-rhi';
95
104
  import { GlobalTransform, Transform } from '@forgeax/engine-scene';
96
105
  import {
106
+ DEFAULT_STANDARD_PBR_PARAM_SCHEMA,
97
107
  DEFAULT_STANDARD_SURFACE_MODULE,
98
108
  type MaterialShaderArtifact,
99
109
  STANDARD_PIPELINE_PARAM_SCHEMA,
110
+ standardTextureMask,
100
111
  } from '@forgeax/engine-shader';
101
112
  import type {
102
113
  Asset,
@@ -110,7 +121,6 @@ import type {
110
121
  MaterialTextureValue,
111
122
  MeshLodLevel,
112
123
  ParamSchemaEntry,
113
- PrimitiveTopology,
114
124
  TextureAsset,
115
125
  } from '@forgeax/engine-types';
116
126
  import {
@@ -119,17 +129,21 @@ import {
119
129
  materialValuesToLinearRuntime,
120
130
  toShared,
121
131
  } from '@forgeax/engine-types';
132
+ import { buildCubeCameraFaceViews } from './capture/cube-views';
122
133
  import {
123
134
  antialiasFromF32,
124
135
  bloomEnabledFromF32,
136
+ CAMERA_EXPOSURE_MODE_MANUAL,
125
137
  Camera,
126
138
  CubeCamera,
139
+ cameraExposureFromColumns,
127
140
  cameraProjectionFromF32,
128
141
  cubeCameraUpdateIntentFromF32,
129
142
  Fog,
130
143
  MotionBlur,
131
144
  ReflectionProbe,
132
145
  reflectionProbeUpdateIntentFromF32,
146
+ ScreenSpaceReflection,
133
147
  tonemapFromF32,
134
148
  tonemapToU32,
135
149
  } from './components';
@@ -147,12 +161,13 @@ import type {
147
161
  FogFrame,
148
162
  FogSelectionFailure,
149
163
  } from './extract/environment';
164
+ import type { GpuDrivenDrawSnapshot } from './extract/gpu-driven';
150
165
  import { resolveVisibility, type VisibilitySnapshot } from './extract/visibility';
151
166
  import type {
152
167
  RenderFeatureHiddenEntityReport,
153
168
  RenderFeatureWorldVisibilitySnapshot,
154
169
  } from './features/types';
155
- import type { InstanceCollectionId, InstanceProjectionStore } from './instances';
170
+ import type { InstanceCollectionId, InstanceCollectionStore } from './instances';
156
171
  import type {
157
172
  MeshMaterialBindingDiagnostic,
158
173
  MeshMaterialBindingSource,
@@ -165,7 +180,7 @@ import { defaultMaterialSnapshot } from './render-system-extract-tail';
165
180
  import { getActiveCamera, selectActiveCameraIndex } from './systems/active-camera';
166
181
  import { selectPasses } from './systems/pass-selector';
167
182
  import type { SkinPaletteAllocator } from './systems/skin-palette-allocator';
168
- import type { SkinPaletteSlice } from './systems/skin-palette-types';
183
+ import type { SkinPaletteReceipt } from './systems/skin-palette-types';
169
184
  import type { RenderTarget, RenderTargetTextureSource } from './targets/contracts';
170
185
  import { resolveRenderTargetMaterialSource } from './targets/material-source';
171
186
  import { resolveSelectedVolumetricLight } from './volume/capability';
@@ -204,6 +219,8 @@ export interface DirectionalLightSnapshot {
204
219
  export interface PointLightSnapshot {
205
220
  readonly kind: 'point';
206
221
  readonly entity?: EntityHandle | number;
222
+ /** World identity stamped by the composited extract owner. */
223
+ readonly worldId?: number;
207
224
  readonly position: Vec3;
208
225
  readonly color: Vec3;
209
226
  readonly intensity: number;
@@ -257,12 +274,16 @@ export interface PointLightSnapshot {
257
274
  export interface PointShadowSnapshot {
258
275
  /** Spawning entity index (joins PointLight + PointLightShadow + Transform). */
259
276
  readonly entity: number;
277
+ /** World identity stamped by the composited extract owner. */
278
+ readonly worldId?: number;
260
279
  /** World-space light position (sourced from companion Transform). */
261
280
  readonly position: Vec3;
262
281
  /** PointLightShadow.mapSize (per-face cube square dimension; 512 default). */
263
282
  readonly mapSize: number;
264
283
  readonly nearPlane: number;
265
284
  readonly farPlane: number;
285
+ readonly depthBias: number;
286
+ readonly normalBias: number;
266
287
  /**
267
288
  * Atlas layer assigned by extract in spawn order while capacity remains.
268
289
  * Sentinel -1 is used for a request that cannot be admitted and is
@@ -298,6 +319,8 @@ export interface SpotLightSnapshot {
298
319
  readonly kind: 'spot';
299
320
  /** Entity identity is branded in extracted frames; numeric fixtures remain compatible. */
300
321
  readonly entity?: EntityHandle | number;
322
+ /** World identity stamped by the composited extract owner. */
323
+ readonly worldId?: number;
301
324
  readonly position: Vec3;
302
325
  readonly direction: Vec3;
303
326
  readonly color: Vec3;
@@ -586,6 +609,8 @@ export interface SkylightSnapshot {
586
609
  /** Local diffuse probe facts; specular remains owned by Skylight/ReflectionProbe. */
587
610
  export interface LightProbeSnapshot {
588
611
  readonly identity: string;
612
+ /** World identity stamped by the composited extract owner. */
613
+ readonly worldId?: number;
589
614
  readonly position: readonly [number, number, number];
590
615
  readonly radius: number;
591
616
  readonly irradiance: Float32Array;
@@ -646,6 +671,8 @@ export interface ExtractedVolumetricFog {
646
671
  }
647
672
 
648
673
  export interface RenderableSnapshot {
674
+ /** Authored hierarchical visibility; retained hidden rows remain addressable. */
675
+ readonly authorVisible?: boolean;
649
676
  readonly assetHandle: number;
650
677
  readonly transform: TransformSnapshot;
651
678
  /** Producer-authored lower-detail references projected from MeshAsset. */
@@ -683,8 +710,6 @@ export interface RenderableSnapshot {
683
710
  readonly materialBindingSources: readonly MeshMaterialBindingSource[];
684
711
  /** Active structured override diagnostics for this renderable. */
685
712
  readonly materialBindingDiagnostics?: readonly MeshMaterialBindingDiagnostic[];
686
- /** Effective authored visibility retained by the persistent scene owner. */
687
- readonly authorVisible?: boolean;
688
713
  /**
689
714
  * feat-20260708-composited-multi-world-rendering M1 / D-1: the worldId
690
715
  * of the world this renderable was extracted from. Defaults to 0 in
@@ -749,9 +774,14 @@ export interface RenderableSnapshot {
749
774
  * draw to `forgeax::pbr-skin` pipeline + set the palette dynamic offset.
750
775
  * Absent (`undefined`) means the entity is not skinned.
751
776
  */
752
- readonly skin?: SkinPaletteSlice;
753
- /** Joint entity identities used by the persistent skin dependency index. */
777
+ readonly skin?: SkinPaletteReceipt;
778
+ /** Joint identities consumed by the retained scene dependency index. */
754
779
  readonly skinJointEntities?: readonly number[];
780
+ /** Source pass ownership retained with the scene record across view changes. */
781
+ readonly shadowCasterPasses?: readonly Omit<
782
+ ShadowCasterMembership,
783
+ 'worldEntity' | 'renderableIndex'
784
+ >[];
755
785
  /**
756
786
  * ECS-owned morph weights. Presence selects the Standard Pipeline CPU
757
787
  * specialized deformation lane; the asset remains the source of target
@@ -782,7 +812,7 @@ export interface RenderableTemporalSnapshot {
782
812
  readonly reactiveReasons: readonly RenderableReactiveReason[];
783
813
  readonly previousTransform: TransformSnapshot;
784
814
  readonly previousInstances: InstancesSnapshot | undefined;
785
- readonly previousSkin: SkinPaletteSlice | undefined;
815
+ readonly previousSkin: SkinPaletteReceipt | undefined;
786
816
  readonly previousMorphWeights: Float32Array | undefined;
787
817
  }
788
818
 
@@ -791,26 +821,7 @@ export interface MorphSnapshot {
791
821
  readonly targetCount: number;
792
822
  }
793
823
 
794
- export interface GpuDrivenDrawSnapshot {
795
- readonly kind: 'indexed' | 'non-indexed';
796
- readonly first: number;
797
- readonly count: number;
798
- readonly baseVertex: number;
799
- readonly materialSlot: number;
800
- readonly topology: PrimitiveTopology;
801
- readonly pipelineClass: string;
802
- readonly materialResourceClass: string;
803
- /** Producer-owned prepared ABI facts used by the Standard PBR GPU lane. */
804
- readonly prepared?: import('./gpu-driven/prepared-draw').PreparedGpuDrivenDraw;
805
- /** Optional projected height supplied by direct GPU-view evidence/tests. */
806
- readonly projectedHeight?: number;
807
- /** Root plus lower-detail index/vertex ranges, in LOD order. */
808
- readonly lodRanges?: readonly {
809
- readonly first: number;
810
- readonly count: number;
811
- readonly baseVertex: number;
812
- }[];
813
- }
824
+ export type { GpuDrivenDrawSnapshot } from './extract/gpu-driven';
814
825
 
815
826
  export interface InstancesSnapshot {
816
827
  /** Renderer-owned collection identity. */
@@ -821,6 +832,13 @@ export interface InstancesSnapshot {
821
832
  readonly instanceCount: number;
822
833
  /** Collection revision captured by this detached frame snapshot. */
823
834
  readonly revision?: number;
835
+ /** Logical collection capacity at snapshot time. */
836
+ readonly capacity?: number;
837
+ /** Coalesced matrix ordinals dirtied since the previous authoring update. */
838
+ readonly dirtyRanges?: readonly {
839
+ readonly start: number;
840
+ readonly end: number;
841
+ }[];
824
842
  /** Stable per-entity GPU buffer cache key (the packed Entity u32). */
825
843
  readonly cacheKey: number;
826
844
  /**
@@ -935,6 +953,8 @@ export interface MaterialSnapshot {
935
953
  readonly paramSnapshot?: Readonly<Record<string, number | number[] | string>> | undefined;
936
954
  /** Effective MaterialAsset parameter contract used to lay out this snapshot. */
937
955
  readonly materialParamSchema?: readonly ParamSchemaEntry[] | undefined;
956
+ /** Authored texture presence, separate from the shared GPU layout schema. */
957
+ readonly standardTextureMask?: number | undefined;
938
958
  /** Authored per-slot UV set and KHR texture transform metadata. */
939
959
  readonly textureCoordinates?: ReadonlyMap<string, MaterialTextureCoordinates> | undefined;
940
960
  /**
@@ -954,6 +974,8 @@ export interface MaterialSnapshot {
954
974
  * them in a lightmap injection region.
955
975
  */
956
976
  readonly textureHandles?: ReadonlyMap<string, Handle<'TextureAsset', 'shared'>> | undefined;
977
+ /** Explicitly authored texture fields that must resolve before GPU admission. */
978
+ readonly authoredTextureFields?: ReadonlySet<string> | undefined;
957
979
  /** Renderer-local target sources; never projected as TextureAsset handles. */
958
980
  readonly textureSources?: ReadonlyMap<string, RenderTargetTextureSource> | undefined;
959
981
  /**
@@ -974,6 +996,8 @@ export interface MaterialSnapshot {
974
996
  readonly videoTextureFields?: ReadonlyMap<string, Handle<'VideoAsset', 'shared'>> | undefined;
975
997
  /** Authored sampler handles keyed by their matching texture parameter. */
976
998
  readonly samplerHandles?: ReadonlyMap<string, Handle<'SamplerAsset', 'shared'>> | undefined;
999
+ /** Explicitly authored sampler fields that must resolve before GPU admission. */
1000
+ readonly authoredSamplerFields?: ReadonlySet<string> | undefined;
977
1001
  readonly baseColorTexture?: Handle<'TextureAsset', 'shared'> | undefined;
978
1002
  /**
979
1003
  * PBR metallic-roughness texture handle (present for PBR/sprite/skin
@@ -1188,6 +1212,11 @@ export interface ExtractedFrame {
1188
1212
  * three-bucket model per plan-strategy D-3.
1189
1213
  */
1190
1214
  readonly dispatch: DispatchEntry[];
1215
+ readonly shadowCasterEntityKeys: ReadonlySet<number>;
1216
+ /** ShadowCaster ownership keyed by concrete draw item and pass. */
1217
+ readonly shadowCasterDrawKeys: ReadonlySet<string>;
1218
+ /** Structured ShadowCaster ownership facts retained for exact residual routing. */
1219
+ readonly shadowCasterMembership?: readonly ShadowCasterMembership[];
1191
1220
  readonly skylight: SkylightSnapshot | undefined;
1192
1221
  readonly skylightCount: number;
1193
1222
  /** World-local diffuse probe candidates; never a direct-light slot. */
@@ -1207,6 +1236,8 @@ export interface ExtractedFrame {
1207
1236
  readonly frustumStats: { readonly culled: number; readonly total: number };
1208
1237
  /** Candidate entities rejected by author visibility before resource parsing. */
1209
1238
  readonly visibilityStats: { readonly explicitlyHidden: number };
1239
+ /** Detached material-source probe accounting for this extraction. */
1240
+ readonly materialTextureSources?: MaterialTextureSourceStats;
1210
1241
  /**
1211
1242
  * Per-frame post-process params snapshot collected from PostProcessParams
1212
1243
  * entities (D-1: data-driven params channel). Maps shader id to the
@@ -1223,6 +1254,30 @@ export interface ExtractedFrame {
1223
1254
  readonly hiddenEntityReports: readonly RenderFeatureHiddenEntityReport[];
1224
1255
  }
1225
1256
 
1257
+ /** Extracted ownership fact for one concrete ShadowCaster pass. */
1258
+ export interface ShadowCasterMembership {
1259
+ readonly worldEntity: number;
1260
+ readonly renderableIndex: number;
1261
+ readonly drawItemIndex: number;
1262
+ readonly materialHandle: number;
1263
+ readonly passIndex: number;
1264
+ readonly materialShaderId?: string;
1265
+ readonly renderState?: MaterialRenderState;
1266
+ readonly cpuReason?: ShadowCasterCpuReason;
1267
+ }
1268
+
1269
+ /** Producer evidence for a concrete ShadowCaster pass that remains on CPU. */
1270
+ export type ShadowCasterCpuReason =
1271
+ | 'transparent'
1272
+ | 'morph'
1273
+ | 'unsupported-shader'
1274
+ | 'unsupported-render-state'
1275
+ | 'missing-skin-bounds'
1276
+ | 'missing-gpu-draw'
1277
+ | 'unprepared'
1278
+ | 'prepared-contract'
1279
+ | 'multi-pass';
1280
+
1226
1281
  export type CameraTargetUpdate = 'once' | 'on-demand' | 'continuous';
1227
1282
 
1228
1283
  export interface CameraTargetCandidate {
@@ -1376,6 +1431,52 @@ export function materialTextureFields(
1376
1431
  return fields;
1377
1432
  }
1378
1433
 
1434
+ function declaredMaterialTextureFields(
1435
+ shaderId: string | undefined,
1436
+ paramSchema: readonly ParamSchemaEntry[] | undefined,
1437
+ assets: AssetRegistry,
1438
+ ): ReadonlySet<string> | undefined {
1439
+ return materialTextureFields(
1440
+ shaderId,
1441
+ paramSchema !== undefined
1442
+ ? derive(paramSchema).textureFieldNames
1443
+ : shaderId !== undefined
1444
+ ? assets.materialShaderTextureFieldNames(shaderId)
1445
+ : undefined,
1446
+ );
1447
+ }
1448
+
1449
+ /** Preserve authored-vs-default intent for the GPU resource readiness gate. */
1450
+ export function collectAuthoredMaterialTextureFields(
1451
+ values: Readonly<Record<string, unknown>>,
1452
+ shaderId: string | undefined,
1453
+ paramSchema: readonly ParamSchemaEntry[] | undefined,
1454
+ assets: AssetRegistry,
1455
+ ): ReadonlySet<string> | undefined {
1456
+ const fields = declaredMaterialTextureFields(shaderId, paramSchema, assets);
1457
+ if (fields === undefined) return undefined;
1458
+ const authored = new Set<string>();
1459
+ for (const field of fields) {
1460
+ if (Object.hasOwn(values, field)) authored.add(field);
1461
+ }
1462
+ return authored.size === 0 ? undefined : authored;
1463
+ }
1464
+
1465
+ /** Preserve explicit sampler intent; omitted samplers use the default sampler. */
1466
+ export function collectAuthoredMaterialSamplerFields(
1467
+ values: Readonly<Record<string, unknown>>,
1468
+ textureFields: ReadonlySet<string> | undefined,
1469
+ ): ReadonlySet<string> | undefined {
1470
+ const authored = new Set<string>();
1471
+ for (const field of textureFields ?? []) {
1472
+ if (materialTextureValue(values[field])?.sampler !== undefined) authored.add(field);
1473
+ }
1474
+ if (Object.hasOwn(values, 'sampler') && values.sampler !== undefined) {
1475
+ authored.add('baseColorTexture');
1476
+ }
1477
+ return authored.size === 0 ? undefined : authored;
1478
+ }
1479
+
1379
1480
  /**
1380
1481
  * The authored material surface uses the module IDs declared by built-in WGSL
1381
1482
  * sources. Runtime pipeline caches still use the existing engine registration
@@ -1507,6 +1608,82 @@ export function pipelineRenderState(
1507
1608
  };
1508
1609
  }
1509
1610
 
1611
+ export function shadowCasterCpuReason(
1612
+ material: MaterialSnapshot,
1613
+ draw: GpuDrivenDrawSnapshot | undefined,
1614
+ shadowEntries: readonly DispatchEntry[],
1615
+ morph: MorphSnapshot | undefined,
1616
+ skin: SkinPaletteReceipt | undefined,
1617
+ ): ShadowCasterCpuReason | undefined {
1618
+ if (shadowEntries.length !== 1) return 'multi-pass';
1619
+ if (material.transparent === true || material.renderState?.blend !== undefined) {
1620
+ return 'transparent';
1621
+ }
1622
+ if (morph !== undefined) return 'morph';
1623
+ const isStandardPbr =
1624
+ material.materialShaderId === 'forgeax::default-standard-pbr' ||
1625
+ material.materialShaderId === 'forgeax::pbr-skin' ||
1626
+ material.materialShaderId === 'forgeax::default-standard-pbr-skin';
1627
+ if (!isStandardPbr) return 'unsupported-shader';
1628
+ const shadowEntry = shadowEntries[0];
1629
+ if (
1630
+ shadowEntry !== undefined &&
1631
+ shadowEntry.materialShaderId !== undefined &&
1632
+ shadowEntry.materialShaderId !== 'forgeax::default-shadow-caster'
1633
+ ) {
1634
+ return 'unsupported-shader';
1635
+ }
1636
+ if (shadowEntry?.renderState !== undefined) return 'unsupported-render-state';
1637
+ if (draw === undefined) return 'missing-gpu-draw';
1638
+ if (draw.prepared === undefined) return 'unprepared';
1639
+ const isSkinnedPbr =
1640
+ material.materialShaderId === 'forgeax::pbr-skin' ||
1641
+ material.materialShaderId === 'forgeax::default-standard-pbr-skin';
1642
+ const preparedMaterial = draw.prepared.identity.material;
1643
+ const preparedDeformation = draw.prepared.identity.deformation;
1644
+ const materialContractMatches =
1645
+ (material.materialShaderId === 'forgeax::default-standard-pbr' &&
1646
+ preparedMaterial === 'forgeax::default-standard-pbr') ||
1647
+ (isSkinnedPbr &&
1648
+ (preparedMaterial === 'forgeax::pbr-skin' ||
1649
+ preparedMaterial === 'forgeax::default-standard-pbr-skin'));
1650
+ const deformationContractMatches =
1651
+ (skin === undefined && preparedDeformation === 'rigid') ||
1652
+ (skin !== undefined && preparedDeformation === 'skin');
1653
+ if (!materialContractMatches || !deformationContractMatches) return 'prepared-contract';
1654
+ if (isSkinnedPbr && !hasFiniteOrderedSkinBounds(skin?.bounds)) {
1655
+ return 'missing-skin-bounds';
1656
+ }
1657
+ return undefined;
1658
+ }
1659
+
1660
+ function hasFiniteOrderedSkinBounds(bounds: Float32Array | undefined): bounds is Float32Array {
1661
+ if (bounds === undefined || bounds.length !== 6) return false;
1662
+ const minX = bounds[0];
1663
+ const minY = bounds[1];
1664
+ const minZ = bounds[2];
1665
+ const maxX = bounds[3];
1666
+ const maxY = bounds[4];
1667
+ const maxZ = bounds[5];
1668
+ return (
1669
+ minX !== undefined &&
1670
+ minY !== undefined &&
1671
+ minZ !== undefined &&
1672
+ maxX !== undefined &&
1673
+ maxY !== undefined &&
1674
+ maxZ !== undefined &&
1675
+ Number.isFinite(minX) &&
1676
+ Number.isFinite(minY) &&
1677
+ Number.isFinite(minZ) &&
1678
+ Number.isFinite(maxX) &&
1679
+ Number.isFinite(maxY) &&
1680
+ Number.isFinite(maxZ) &&
1681
+ minX <= maxX &&
1682
+ minY <= maxY &&
1683
+ minZ <= maxZ
1684
+ );
1685
+ }
1686
+
1510
1687
  /**
1511
1688
  * tweak-20260627-model-loading-smoke-build-perf M4: per-World intern cache for
1512
1689
  * the loadByGuid texture/sampler resolution path. A MaterialAsset's
@@ -1663,20 +1840,82 @@ export function collectMaterialTextureCoordinates(
1663
1840
  return out;
1664
1841
  }
1665
1842
 
1843
+ /**
1844
+ * Return the schema-owned fields that may carry a texture source handle.
1845
+ * Numeric material values are otherwise scalar parameters (roughness,
1846
+ * metallic, custom steps, ...), so probing them through SharedRefStore is
1847
+ * both wasted work and an accidental dependency on slot-number collisions.
1848
+ */
1849
+ export function materialTextureSourceFields(
1850
+ schema: readonly ParamSchemaEntry[] | undefined,
1851
+ ): ReadonlySet<string> | undefined {
1852
+ if (schema === undefined) return undefined;
1853
+ const fields = new Set<string>();
1854
+ for (const entry of schema) {
1855
+ if (entry.type.startsWith('texture')) fields.add(entry.name);
1856
+ }
1857
+ return fields;
1858
+ }
1859
+
1860
+ export interface MaterialTextureSourceStats {
1861
+ sourceFieldsVisited: number;
1862
+ numericSharedRefProbes: number;
1863
+ sourceCacheHits: number;
1864
+ sourceCacheMisses: number;
1865
+ producerRoutes: Record<string, number>;
1866
+ }
1867
+
1868
+ /**
1869
+ * Extract-local cache for numeric shared references. `null` is a deliberate
1870
+ * negative entry: a handle that is not a render-target source must not be
1871
+ * resolved repeatedly for every material field in the same frame.
1872
+ */
1873
+ export type MaterialTextureSourceCache = Map<number, RenderTargetTextureSource | null>;
1874
+
1666
1875
  export function collectMaterialTextureSources(
1667
1876
  values: Readonly<Record<string, unknown>>,
1668
1877
  world: World,
1878
+ textureFields?: ReadonlySet<string>,
1879
+ stats?: MaterialTextureSourceStats,
1880
+ cache?: MaterialTextureSourceCache,
1669
1881
  ): Map<string, RenderTargetTextureSource> {
1670
1882
  const out = new Map<string, RenderTargetTextureSource>();
1671
1883
  for (const [field, value] of Object.entries(values)) {
1672
- const reference = materialTextureRef(value);
1884
+ const structured = materialTextureValue(value);
1885
+ const schemaKnown = textureFields !== undefined;
1886
+ const schemaAdmitted = textureFields?.has(field) === true;
1887
+ // With a known schema, only producer-admitted texture fields may carry a
1888
+ // source handle. Without a schema, retain the historical numeric parse so
1889
+ // an older producer can still publish a direct shared-ref value; its
1890
+ // structured form is accepted on the same conservative path.
1891
+ if (schemaKnown && !schemaAdmitted) continue;
1892
+ const reference = structured?.texture ?? value;
1893
+ if (stats !== undefined) stats.sourceFieldsVisited += 1;
1673
1894
  if (typeof reference !== 'number') continue;
1674
- const resolved = world.sharedRefs.resolve<
1675
- 'RenderTargetTextureSource',
1676
- RenderTargetTextureSource
1677
- >(toShared<'RenderTargetTextureSource'>(reference));
1678
- if (!resolved.ok || resolveRenderTargetMaterialSource(resolved.value) === undefined) continue;
1679
- out.set(field, resolved.value);
1895
+ if (stats !== undefined) stats.numericSharedRefProbes += 1;
1896
+ let source: RenderTargetTextureSource | undefined;
1897
+ if (cache?.has(reference) === true) {
1898
+ if (stats !== undefined) stats.sourceCacheHits += 1;
1899
+ source = cache.get(reference) ?? undefined;
1900
+ } else {
1901
+ if (stats !== undefined) stats.sourceCacheMisses += 1;
1902
+ const resolved = world.sharedRefs.resolve<
1903
+ 'RenderTargetTextureSource',
1904
+ RenderTargetTextureSource
1905
+ >(toShared<'RenderTargetTextureSource'>(reference));
1906
+ if (!resolved.ok) {
1907
+ cache?.set(reference, null);
1908
+ } else {
1909
+ const binding = resolveRenderTargetMaterialSource(resolved.value);
1910
+ cache?.set(reference, binding === undefined ? null : resolved.value);
1911
+ source = binding === undefined ? undefined : resolved.value;
1912
+ }
1913
+ }
1914
+ if (source === undefined) continue;
1915
+ if (stats !== undefined) {
1916
+ stats.producerRoutes.renderTarget = (stats.producerRoutes.renderTarget ?? 0) + 1;
1917
+ }
1918
+ out.set(field, source);
1680
1919
  }
1681
1920
  return out;
1682
1921
  }
@@ -1764,6 +2003,27 @@ export function isEngineInjectedTextureField(
1764
2003
  return isStandardPbrMaterialShader(shaderId) && ENGINE_INJECTED_TEXTURE_FIELDS.has(fieldName);
1765
2004
  }
1766
2005
 
2006
+ export function materialStandardTextureMask(
2007
+ parameters: readonly MaterialParameter[] | undefined,
2008
+ shaderId: string | undefined,
2009
+ values: Readonly<Record<string, unknown>>,
2010
+ ): number | undefined {
2011
+ return isCanonicalStandardPbrMaterialShader(shaderId)
2012
+ ? standardTextureMask(
2013
+ // Canonical materials may provide values without redeclaring the root
2014
+ // schema. Pruning must agree with the texture binder in that route too.
2015
+ DEFAULT_STANDARD_PBR_PARAM_SCHEMA.filter(
2016
+ (entry) =>
2017
+ entry.type === 'texture2d' &&
2018
+ (values[entry.name] !== undefined ||
2019
+ parameters?.some(
2020
+ (parameter) => parameter.name === entry.name && parameter.default !== undefined,
2021
+ )),
2022
+ ),
2023
+ )
2024
+ : undefined;
2025
+ }
2026
+
1767
2027
  /**
1768
2028
  * Project one material's authoring parameters into the runtime ABI.
1769
2029
  *
@@ -1953,6 +2213,8 @@ export function resolveMaterialSnapshot(
1953
2213
  materialSnapshotCache?: MaterialSnapshotCache,
1954
2214
  persistentMaterialSnapshotCache?: MaterialSnapshotCache,
1955
2215
  materialContext?: MaterialCookProgramContext,
2216
+ materialTextureSourceStats?: MaterialTextureSourceStats,
2217
+ materialTextureSourceCache?: MaterialTextureSourceCache,
1956
2218
  ): MaterialSnapshot {
1957
2219
  if (handleRaw === 0) return defaultMaterialSnapshot(handleRaw);
1958
2220
  const cached = materialSnapshotCache?.get(handleRaw);
@@ -2054,7 +2316,13 @@ export function resolveMaterialSnapshot(
2054
2316
  const samplerHandles = collectMaterialTextureSamplers(pv, (value) =>
2055
2317
  resolveTexLike(materialTextureRef(value), 'SamplerAsset'),
2056
2318
  );
2057
- const textureSources = collectMaterialTextureSources(pv, world);
2319
+ const textureSources = collectMaterialTextureSources(
2320
+ pv,
2321
+ world,
2322
+ materialTextureSourceFields(materialParamSchema.length > 0 ? materialParamSchema : undefined),
2323
+ materialTextureSourceStats,
2324
+ materialTextureSourceCache,
2325
+ );
2058
2326
  const emissiveTextureHandle = resolveTexLike(
2059
2327
  materialTextureRef(pv.emissiveTexture),
2060
2328
  'TextureAsset',
@@ -2087,6 +2355,7 @@ export function resolveMaterialSnapshot(
2087
2355
  renderState: pipelineRenderState(allPasses[0]?.renderState),
2088
2356
  paramSnapshot: paramSnap,
2089
2357
  ...(materialParamSchema.length > 0 && { materialParamSchema }),
2358
+ standardTextureMask: materialStandardTextureMask(resolved.parameters, firstPassShader, pv),
2090
2359
  ...(textureCoordinates.size > 0 && { textureCoordinates }),
2091
2360
  ...(textureHandles.size > 0 && { textureHandles }),
2092
2361
  ...(textureSources.size > 0 && { textureSources }),
@@ -2289,41 +2558,15 @@ export function pssmSplit(
2289
2558
  // requirements §5.3): 6-face view-proj matrix table for one omnidirectional
2290
2559
  // shadow caster.
2291
2560
  //
2292
- // Face order matches WebGPU cube layer convention (also LearnOpenGL 5.3.2):
2293
- // 0 (+X) | look=(+1, 0, 0) | up=(0, -1, 0)
2294
- // 1 (-X) | look=(-1, 0, 0) | up=(0, -1, 0)
2295
- // 2 (+Y) | look=(0, +1, 0) | up=(0, 0, +1)
2296
- // 3 (-Y) | look=(0, -1, 0) | up=(0, 0, -1)
2297
- // 4 (+Z) | look=(0, 0, +1) | up=(0, -1, 0)
2298
- // 5 (-Z) | look=(0, 0, -1) | up=(0, -1, 0)
2299
- //
2300
- // Projection: WebGPU [0, 1] NDC perspective (mat4.perspective short name).
2301
- // fov=90deg, aspect=1, near/far from PointLightShadow component.
2302
- const POINT_SHADOW_FACE_LOOK: readonly Vec3[] = [
2303
- vec3.create(1, 0, 0),
2304
- vec3.create(-1, 0, 0),
2305
- vec3.create(0, 1, 0),
2306
- vec3.create(0, -1, 0),
2307
- vec3.create(0, 0, 1),
2308
- vec3.create(0, 0, -1),
2309
- ];
2310
- const POINT_SHADOW_FACE_UP: readonly Vec3[] = [
2311
- vec3.create(0, -1, 0),
2312
- vec3.create(0, -1, 0),
2313
- vec3.create(0, 0, 1),
2314
- vec3.create(0, 0, -1),
2315
- vec3.create(0, -1, 0),
2316
- vec3.create(0, -1, 0),
2317
- ];
2318
-
2319
2561
  /**
2320
2562
  * Build 6 face view-proj matrices for an omnidirectional shadow caster
2321
2563
  * (point-light cube map). Returns 6 mat4 (column-major 16-float each) in face
2322
- * order [+X, -X, +Y, -Y, +Z, -Z] matching WebGPU cube layer convention.
2564
+ * order [+X, -X, +Y, -Y, +Z, -Z] matching the WebGPU cube-camera layer
2565
+ * convention.
2323
2566
  *
2324
- * Each matrix is `proj * view` where:
2325
- * - `view = lookAt(lightPos, lightPos + faceLook[i], faceUp[i])`
2326
- * - `proj = perspective(PI/2, 1, near, far)` (WebGPU [0, 1] NDC short name)
2567
+ * Derive face directions from the shared CubeCamera owner, then reflect clip X
2568
+ * to match WebGPU cubemap texel orientation. The point-shadow raster lane
2569
+ * mirrors authored front-face winding when it uses these reflected matrices.
2327
2570
  *
2328
2571
  * The returned `Mat4[]` length is always exactly 6. Caller can flatten into a
2329
2572
  * 96-float (6 mat4) Float32Array for UBO upload (T-M1-7).
@@ -2333,29 +2576,10 @@ const POINT_SHADOW_FACE_UP: readonly Vec3[] = [
2333
2576
  * @param far far plane distance (PointLightShadow.farPlane)
2334
2577
  */
2335
2578
  export function buildPointShadowMatrices(lightPos: Vec3, near: number, far: number): Mat4[] {
2336
- const fovY = Math.PI / 2; // 90 deg
2337
- const aspect = 1;
2338
- const proj = mat4.create();
2339
- mat4.perspective(proj, fovY, aspect, near, far);
2340
-
2341
- const out: Mat4[] = [];
2342
- for (let i = 0; i < 6; i++) {
2343
- // biome-ignore lint/style/noNonNullAssertion: i in [0..6) and arrays are length-6 const
2344
- const look = POINT_SHADOW_FACE_LOOK[i]!;
2345
- // biome-ignore lint/style/noNonNullAssertion: i in [0..6) and arrays are length-6 const
2346
- const up = POINT_SHADOW_FACE_UP[i]!;
2347
- const target = vec3.create(
2348
- (lightPos[0] ?? 0) + (look[0] ?? 0),
2349
- (lightPos[1] ?? 0) + (look[1] ?? 0),
2350
- (lightPos[2] ?? 0) + (look[2] ?? 0),
2351
- );
2352
- const view = mat4.create();
2353
- mat4.lookAt(view, lightPos, target, up);
2354
- const vp = mat4.create();
2355
- mat4.multiply(vp, proj, view);
2356
- out.push(vp);
2357
- }
2358
- return out;
2579
+ return buildCubeCameraFaceViews({ position: lightPos, near, far }).map(({ viewProjection }) => {
2580
+ for (const offset of [0, 4, 8, 12]) viewProjection[offset] = -(viewProjection[offset] ?? 0);
2581
+ return viewProjection;
2582
+ });
2359
2583
  }
2360
2584
 
2361
2585
  /**
@@ -2581,6 +2805,8 @@ export function computeDirectionalCsm(
2581
2805
  export interface ExtractFramesOwner {
2582
2806
  readonly cameraOwner: number;
2583
2807
  readonly resourceOwner: number;
2808
+ /** Explicit display-camera entity selected by the frame owner. */
2809
+ readonly cameraEntityKey?: number;
2584
2810
  }
2585
2811
 
2586
2812
  export interface PreparedExtractContext {
@@ -2593,18 +2819,23 @@ export interface PreparedExtractContext {
2593
2819
  readonly resourceOwnerFog: FogFrame | null | undefined;
2594
2820
  readonly cull: 'self' | 'none' | 'external';
2595
2821
  readonly cullCameras: readonly CameraSnapshot[] | undefined;
2822
+ /** Explicit display-camera entity for this world's camera-owner extract. */
2823
+ readonly cameraEntityKey?: number;
2596
2824
  readonly renderables: 'full' | 'none';
2597
- /** Restrict renderable extraction to these entities while still reading frame resources. */
2598
2825
  readonly renderableEntities: ReadonlySet<number> | undefined;
2599
- /** Keep authored-hidden renderables in the persistent source projection. */
2600
2826
  readonly retainHidden: boolean;
2827
+ /** World identity used to form cross-world producer ownership keys. */
2828
+ readonly worldId: number;
2601
2829
  readonly visibility: VisibilitySnapshot;
2602
2830
  /** Producer-owned artifact lookup; extraction only, never record-time asset reads. */
2603
2831
  readonly getMaterialShaderArtifact:
2604
- | ((materialShaderId: string) => MaterialShaderArtifact | undefined)
2832
+ | ((
2833
+ materialShaderId: string,
2834
+ vertexColorAvailable?: boolean,
2835
+ ) => MaterialShaderArtifact | undefined)
2605
2836
  | undefined;
2606
2837
  /** Renderer-owned canonical source for explicit large instance collections. */
2607
- readonly instanceCollections: InstanceProjectionStore | undefined;
2838
+ readonly instanceCollections: InstanceCollectionStore | undefined;
2608
2839
  }
2609
2840
 
2610
2841
  const ALL_VISIBLE: VisibilitySnapshot = {
@@ -2619,16 +2850,37 @@ function collectCameraSnapshots(world: World): CameraSnapshot[] {
2619
2850
  const worldInternal = createWorldInternalView(world);
2620
2851
  const cameras: CameraSnapshot[] = [];
2621
2852
  const cameraQuery = world
2622
- .query({ read: [Camera], optional: [MotionBlur], with: [Transform, GlobalTransform] })
2853
+ .query({
2854
+ read: [Camera],
2855
+ optional: [MotionBlur, ScreenSpaceReflection],
2856
+ with: [Transform, GlobalTransform],
2857
+ })
2623
2858
  .unwrap();
2624
2859
  for (const row of cameraQuery) {
2625
2860
  const cam = row.get(Camera);
2626
2861
  const motionBlur = row.get(MotionBlur);
2862
+ const screenSpaceReflection = row.get(ScreenSpaceReflection);
2627
2863
  const entity = row.entity;
2628
2864
  const view = worldInternal._getArrayView(entity, GlobalTransform, 'world');
2629
2865
  if (view === undefined) continue;
2630
2866
  const worldMat = new Float32Array(view);
2631
2867
  const target = resolveCameraTarget(world, cam.target);
2868
+ const hasNonDefaultOutput =
2869
+ cam.exposureMode !== CAMERA_EXPOSURE_MODE_MANUAL ||
2870
+ cam.exposure !== 1 ||
2871
+ cam.temperature !== 6504 ||
2872
+ cam.tint !== 0 ||
2873
+ cam.colorLut !== 0 ||
2874
+ cam.colorLutStrength !== 0;
2875
+ const output = hasNonDefaultOutput
2876
+ ? {
2877
+ exposure: cameraExposureFromColumns(cam),
2878
+ temperature: cam.temperature,
2879
+ tint: cam.tint,
2880
+ colorLut: cam.colorLut,
2881
+ colorLutStrength: cam.colorLutStrength,
2882
+ }
2883
+ : undefined;
2632
2884
  cameras.push({
2633
2885
  entityKey: entity as number,
2634
2886
  ...(target === undefined ? {} : { target }),
@@ -2647,6 +2899,7 @@ function collectCameraSnapshots(world: World): CameraSnapshot[] {
2647
2899
  tonemap: tonemapFromF32(cam.tonemap),
2648
2900
  exposure: cam.exposure,
2649
2901
  whitePoint: cam.whitePoint,
2902
+ ...(output === undefined ? {} : { output }),
2650
2903
  antialias: antialiasFromF32(cam.antialias),
2651
2904
  bloom: bloomEnabledFromF32(cam.bloom),
2652
2905
  bloomThreshold: cam.bloomThreshold,
@@ -2667,6 +2920,15 @@ function collectCameraSnapshots(world: World): CameraSnapshot[] {
2667
2920
  sampleCount: motionBlur.sampleCount,
2668
2921
  },
2669
2922
  }),
2923
+ ...(screenSpaceReflection === undefined
2924
+ ? {}
2925
+ : {
2926
+ screenSpaceReflection: {
2927
+ maxDistance: screenSpaceReflection.maxDistance,
2928
+ thickness: screenSpaceReflection.thickness,
2929
+ maxRoughness: screenSpaceReflection.maxRoughness,
2930
+ },
2931
+ }),
2670
2932
  });
2671
2933
  }
2672
2934
  return cameras;
@@ -2733,16 +2995,23 @@ interface CameraRoleSelection {
2733
2995
  readonly auxiliary: readonly CameraSnapshot[];
2734
2996
  }
2735
2997
 
2736
- export function selectCameraRoles(world: World): CameraRoleSelection {
2998
+ export function selectCameraRoles(world: World, requestedEntityKey?: number): CameraRoleSelection {
2737
2999
  const cameras = collectCameraSnapshots(world);
2738
3000
  const displayEntities = cameras
2739
3001
  .filter((camera) => camera.target === undefined)
2740
3002
  .map((camera) => camera.entityKey ?? 0);
3003
+ const hasExplicitSelection = requestedEntityKey !== undefined;
2741
3004
  const activeCameraIndex = selectActiveCameraIndex(
2742
3005
  displayEntities,
2743
- getActiveCamera(world)?.entity,
3006
+ hasExplicitSelection ? requestedEntityKey : getActiveCamera(world)?.entity,
2744
3007
  );
2745
- const displayEntityKey = displayEntities[activeCameraIndex] ?? displayEntities[0];
3008
+ // An explicit FrameCamera selection is authoritative. If it does not name a
3009
+ // display camera, retain the existing no-camera error path instead of
3010
+ // silently selecting the first camera. ActiveCamera keeps its established
3011
+ // first-hit fallback when no explicit frame selection is supplied.
3012
+ const displayEntityKey = hasExplicitSelection
3013
+ ? displayEntities[activeCameraIndex]
3014
+ : (displayEntities[activeCameraIndex] ?? displayEntities[0]);
2746
3015
  const display =
2747
3016
  displayEntityKey === undefined
2748
3017
  ? []
@@ -2792,13 +3061,16 @@ export function prepareExtractContext(
2792
3061
  readonly resourceOwnerFog?: FogFrame | null;
2793
3062
  readonly cull?: 'self' | 'none' | 'external';
2794
3063
  readonly cullCameras?: readonly CameraSnapshot[];
3064
+ readonly cameraEntityKey?: number;
2795
3065
  readonly renderables?: 'full' | 'none';
2796
3066
  readonly renderableEntities?: ReadonlySet<number>;
2797
3067
  readonly retainHidden?: boolean;
3068
+ readonly worldId?: number;
2798
3069
  readonly getMaterialShaderArtifact?: (
2799
3070
  materialShaderId: string,
3071
+ vertexColorAvailable?: boolean,
2800
3072
  ) => MaterialShaderArtifact | undefined;
2801
- readonly instanceCollections?: InstanceProjectionStore;
3073
+ readonly instanceCollections?: InstanceCollectionStore;
2802
3074
  } = {},
2803
3075
  ): PreparedExtractContext {
2804
3076
  const renderables = options.renderables ?? 'full';
@@ -2810,7 +3082,9 @@ export function prepareExtractContext(
2810
3082
  resourceOwnerFog: options.resourceOwnerFog,
2811
3083
  cull: options.cull ?? 'self',
2812
3084
  cullCameras: options.cullCameras,
3085
+ ...(options.cameraEntityKey === undefined ? {} : { cameraEntityKey: options.cameraEntityKey }),
2813
3086
  renderables,
3087
+ worldId: options.worldId ?? 0,
2814
3088
  renderableEntities: options.renderableEntities,
2815
3089
  retainHidden: options.retainHidden ?? false,
2816
3090
  visibility: renderables === 'none' ? ALL_VISIBLE : resolveVisibility(world),