@forgeax/engine-render 0.1.32 → 0.1.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (624) hide show
  1. package/README.md +1374 -142
  2. package/dist/assembly/analytic-fog-registration.d.ts +3 -0
  3. package/dist/assembly/analytic-fog-registration.d.ts.map +1 -0
  4. package/dist/assembly/backend-contract.d.ts +2 -0
  5. package/dist/assembly/backend-contract.d.ts.map +1 -1
  6. package/dist/assembly/barrel-distortion-inspection.d.ts +3 -0
  7. package/dist/assembly/barrel-distortion-inspection.d.ts.map +1 -0
  8. package/dist/assembly/canvas-draw-guard.d.ts +3 -0
  9. package/dist/assembly/canvas-draw-guard.d.ts.map +1 -0
  10. package/dist/assembly/cloud-shadow-entry.d.ts +4 -0
  11. package/dist/assembly/cloud-shadow-entry.d.ts.map +1 -0
  12. package/dist/assembly/dynamic-geometry-host.d.ts +4 -1
  13. package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
  14. package/dist/assembly/dynamic-geometry-runtime.d.ts +1 -1
  15. package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -1
  16. package/dist/assembly/factory.d.ts +1 -1
  17. package/dist/assembly/factory.d.ts.map +1 -1
  18. package/dist/assembly/fxaa-registration.d.ts +4 -0
  19. package/dist/assembly/fxaa-registration.d.ts.map +1 -0
  20. package/dist/assembly/host-contract.d.ts +3 -3
  21. package/dist/assembly/host-contract.d.ts.map +1 -1
  22. package/dist/assembly/lod-observation.d.ts +4 -0
  23. package/dist/assembly/lod-observation.d.ts.map +1 -0
  24. package/dist/assembly/material/assembly.d.ts.map +1 -1
  25. package/dist/assembly/material/pipeline-helpers.d.ts +5 -0
  26. package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -1
  27. package/dist/assembly/material-shader-policy.d.ts +16 -2
  28. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  29. package/dist/assembly/material-shader-prewarm.d.ts.map +1 -1
  30. package/dist/assembly/motion-blur-registration.d.ts +3 -0
  31. package/dist/assembly/motion-blur-registration.d.ts.map +1 -0
  32. package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
  33. package/dist/assembly/recovery/renderer-recover.d.ts +2 -0
  34. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  35. package/dist/assembly/render-feature-post-processes.d.ts +6 -0
  36. package/dist/assembly/render-feature-post-processes.d.ts.map +1 -0
  37. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  38. package/dist/assembly/renderer-feature-inspection.d.ts +1 -1
  39. package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -1
  40. package/dist/assembly/renderer-frame-transaction.d.ts +12 -0
  41. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  42. package/dist/assembly/renderer-inspection.d.ts +11 -0
  43. package/dist/assembly/renderer-inspection.d.ts.map +1 -1
  44. package/dist/assembly/temporal-post-process-prewarm.d.ts +13 -0
  45. package/dist/assembly/temporal-post-process-prewarm.d.ts.map +1 -0
  46. package/dist/assembly/webgpu-pbr-ready.d.ts +1 -0
  47. package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -1
  48. package/dist/assembly/webgpu-ready-contract.d.ts +4 -3
  49. package/dist/assembly/webgpu-ready-contract.d.ts.map +1 -1
  50. package/dist/assembly/webgpu-ready-per-pass.d.ts +39 -0
  51. package/dist/assembly/webgpu-ready-per-pass.d.ts.map +1 -0
  52. package/dist/assembly/webgpu-ready.d.ts +2 -2
  53. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  54. package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -1
  55. package/dist/assembly/webgpu-renderer-observation-owner.d.ts +35 -0
  56. package/dist/assembly/webgpu-renderer-observation-owner.d.ts.map +1 -0
  57. package/dist/assembly/webgpu-renderer.d.ts +1 -1
  58. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  59. package/dist/authoring.mjs +1 -1
  60. package/dist/barrel-distortion.d.ts +47 -0
  61. package/dist/barrel-distortion.d.ts.map +1 -0
  62. package/dist/bloom-admission.d.ts +13 -0
  63. package/dist/bloom-admission.d.ts.map +1 -0
  64. package/dist/{chunk-PA5DRJNI.mjs → chunk-ELJFJ2BU.mjs} +2 -2
  65. package/dist/chunk-ELJFJ2BU.mjs.map +1 -0
  66. package/dist/{chunk-JCIRYQ4V.mjs → chunk-HEB564WF.mjs} +10 -4
  67. package/dist/chunk-HEB564WF.mjs.map +1 -0
  68. package/dist/{chunk-JRIPCMYC.mjs → chunk-MKDIT2EM.mjs} +1584 -375
  69. package/dist/chunk-MKDIT2EM.mjs.map +1 -0
  70. package/dist/{chunk-S665NJNF.mjs → chunk-OCDLEI6I.mjs} +3 -3
  71. package/dist/{chunk-S665NJNF.mjs.map → chunk-OCDLEI6I.mjs.map} +1 -1
  72. package/dist/chunk-ODZWR6JQ.mjs +4927 -0
  73. package/dist/chunk-ODZWR6JQ.mjs.map +1 -0
  74. package/dist/{chunk-DRR7D3KX.mjs → chunk-SHFUFJ5N.mjs} +192 -18
  75. package/dist/chunk-SHFUFJ5N.mjs.map +1 -0
  76. package/dist/{chunk-4NNZQCL3.mjs → chunk-UI5SFODX.mjs} +223 -277
  77. package/dist/chunk-UI5SFODX.mjs.map +1 -0
  78. package/dist/{chunk-GWCEMDVR.mjs → chunk-UINHLCZA.mjs} +787 -80
  79. package/dist/chunk-UINHLCZA.mjs.map +1 -0
  80. package/dist/{chunk-6TFBXLRJ.mjs → chunk-WEX45HKH.mjs} +222 -337
  81. package/dist/chunk-WEX45HKH.mjs.map +1 -0
  82. package/dist/cloud/density.d.ts +55 -0
  83. package/dist/cloud/density.d.ts.map +1 -0
  84. package/dist/cloud/extract.d.ts +25 -0
  85. package/dist/cloud/extract.d.ts.map +1 -0
  86. package/dist/cloud/feature.d.ts +57 -0
  87. package/dist/cloud/feature.d.ts.map +1 -0
  88. package/dist/cloud/frame-context.d.ts +8 -0
  89. package/dist/cloud/frame-context.d.ts.map +1 -0
  90. package/dist/cloud/inspection.d.ts +59 -0
  91. package/dist/cloud/inspection.d.ts.map +1 -0
  92. package/dist/cloud/optics.d.ts +56 -0
  93. package/dist/cloud/optics.d.ts.map +1 -0
  94. package/dist/cloud/parameters.d.ts +73 -0
  95. package/dist/cloud/parameters.d.ts.map +1 -0
  96. package/dist/cloud/resources.d.ts +60 -0
  97. package/dist/cloud/resources.d.ts.map +1 -0
  98. package/dist/cloud/shadow.d.ts +42 -0
  99. package/dist/cloud/shadow.d.ts.map +1 -0
  100. package/dist/cloud/temporal.d.ts +74 -0
  101. package/dist/cloud/temporal.d.ts.map +1 -0
  102. package/dist/components/atmosphere.d.ts +2 -0
  103. package/dist/components/atmosphere.d.ts.map +1 -1
  104. package/dist/components/barrel-distortion.d.ts +13 -0
  105. package/dist/components/barrel-distortion.d.ts.map +1 -0
  106. package/dist/components/camera.d.ts +20 -4
  107. package/dist/components/camera.d.ts.map +1 -1
  108. package/dist/components/cloud-layer.d.ts +29 -0
  109. package/dist/components/cloud-layer.d.ts.map +1 -0
  110. package/dist/components/index.d.ts +2 -0
  111. package/dist/components/index.d.ts.map +1 -1
  112. package/dist/components/instances.d.ts +20 -6
  113. package/dist/components/instances.d.ts.map +1 -1
  114. package/dist/components/mesh-filter.d.ts +6 -5
  115. package/dist/components/mesh-filter.d.ts.map +1 -1
  116. package/dist/components/motion-blur.d.ts +1 -0
  117. package/dist/components/motion-blur.d.ts.map +1 -1
  118. package/dist/construct-renderer.d.ts +1 -1
  119. package/dist/construct-renderer.d.ts.map +1 -1
  120. package/dist/construct-renderer.mjs +9751 -3528
  121. package/dist/construct-renderer.mjs.map +1 -1
  122. package/dist/device/gpu-residency.d.ts +6 -0
  123. package/dist/device/gpu-residency.d.ts.map +1 -1
  124. package/dist/dynamic-geometry.d.ts +5 -1
  125. package/dist/dynamic-geometry.d.ts.map +1 -1
  126. package/dist/environment/analytic-fog.d.ts +6 -0
  127. package/dist/environment/analytic-fog.d.ts.map +1 -0
  128. package/dist/errors/cloud.d.ts +59 -0
  129. package/dist/errors/cloud.d.ts.map +1 -0
  130. package/dist/errors/render.d.ts +23 -5
  131. package/dist/errors/render.d.ts.map +1 -1
  132. package/dist/examples/single-layer-medium-surface.d.ts +47 -0
  133. package/dist/examples/single-layer-medium-surface.d.ts.map +1 -0
  134. package/dist/extract/camera.d.ts.map +1 -1
  135. package/dist/extract/contracts.d.ts +12 -1
  136. package/dist/extract/contracts.d.ts.map +1 -1
  137. package/dist/extract/environment.d.ts +2 -0
  138. package/dist/extract/environment.d.ts.map +1 -1
  139. package/dist/features/barrel-distortion.d.ts +29 -0
  140. package/dist/features/barrel-distortion.d.ts.map +1 -0
  141. package/dist/features/error-reporting.d.ts +17 -0
  142. package/dist/features/error-reporting.d.ts.map +1 -0
  143. package/dist/features/host.d.ts +15 -0
  144. package/dist/features/host.d.ts.map +1 -1
  145. package/dist/features/motion-blur/motion-blur-feature.d.ts +20 -2
  146. package/dist/features/motion-blur/motion-blur-feature.d.ts.map +1 -1
  147. package/dist/features/motion-blur/motion-blur-params.d.ts +21 -0
  148. package/dist/features/motion-blur/motion-blur-params.d.ts.map +1 -1
  149. package/dist/features/motion-blur/motion-blur-runtime.d.ts +54 -0
  150. package/dist/features/motion-blur/motion-blur-runtime.d.ts.map +1 -0
  151. package/dist/features/plan.d.ts +15 -4
  152. package/dist/features/plan.d.ts.map +1 -1
  153. package/dist/features/prepared-gpu-work.d.ts +9 -5
  154. package/dist/features/prepared-gpu-work.d.ts.map +1 -1
  155. package/dist/features/render-graph-compute.d.ts.map +1 -1
  156. package/dist/features/render-graph-contribution.d.ts +5 -0
  157. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  158. package/dist/features/render-graph-raster.d.ts +1 -0
  159. package/dist/features/render-graph-raster.d.ts.map +1 -1
  160. package/dist/features/targets.d.ts +2 -0
  161. package/dist/features/targets.d.ts.map +1 -1
  162. package/dist/features/types.d.ts +44 -0
  163. package/dist/features/types.d.ts.map +1 -1
  164. package/dist/fullscreen-post-process-pass.d.ts +15 -7
  165. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  166. package/dist/gpu-dirty-ranges.d.ts +11 -0
  167. package/dist/gpu-dirty-ranges.d.ts.map +1 -0
  168. package/dist/gpu-driven/batch-topology.d.ts +17 -0
  169. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  170. package/dist/gpu-driven/material-artifacts.d.ts +6 -0
  171. package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
  172. package/dist/gpu-driven/prepared-draw.d.ts +7 -0
  173. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
  174. package/dist/gpu-driven/production-raster-material.d.ts +178 -0
  175. package/dist/gpu-driven/production-raster-material.d.ts.map +1 -0
  176. package/dist/gpu-driven/production-raster.d.ts +50 -4
  177. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  178. package/dist/gpu-driven/resource-allocation.d.ts +31 -0
  179. package/dist/gpu-driven/resource-allocation.d.ts.map +1 -0
  180. package/dist/gpu-driven/shadow-ownership.d.ts +14 -0
  181. package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -0
  182. package/dist/gpu-driven/view-gpu.d.ts +35 -2
  183. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  184. package/dist/gpu-scene.d.ts +11 -1
  185. package/dist/gpu-scene.d.ts.map +1 -1
  186. package/dist/hdrp-buffers.d.ts +2 -2
  187. package/dist/hdrp-buffers.d.ts.map +1 -1
  188. package/dist/ibl/skylight-bind-group.d.ts +10 -1
  189. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  190. package/dist/index.d.ts +31 -8
  191. package/dist/index.d.ts.map +1 -1
  192. package/dist/index.mjs +258 -8
  193. package/dist/index.mjs.map +1 -1
  194. package/dist/inspection-types.d.ts +178 -3
  195. package/dist/inspection-types.d.ts.map +1 -1
  196. package/dist/instance-buffer-cache.d.ts +4 -4
  197. package/dist/instance-buffer-cache.d.ts.map +1 -1
  198. package/dist/instances.d.ts +49 -94
  199. package/dist/instances.d.ts.map +1 -1
  200. package/dist/internal.mjs +7 -7
  201. package/dist/pbr-pipeline.d.ts +19 -1
  202. package/dist/pbr-pipeline.d.ts.map +1 -1
  203. package/dist/pipeline/single-layer-medium-passes.d.ts +73 -0
  204. package/dist/pipeline/single-layer-medium-passes.d.ts.map +1 -0
  205. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  206. package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
  207. package/dist/pipeline/standard-output/types.d.ts +4 -2
  208. package/dist/pipeline/standard-output/types.d.ts.map +1 -1
  209. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  210. package/dist/pipeline/standard-post.d.ts +28 -19
  211. package/dist/pipeline/standard-post.d.ts.map +1 -1
  212. package/dist/pipeline-builder.d.ts +1 -1
  213. package/dist/pipeline-builder.d.ts.map +1 -1
  214. package/dist/pipeline-spec.d.ts +2 -2
  215. package/dist/plugin.d.ts.map +1 -1
  216. package/dist/prepare/prepared-graphics-resolver.d.ts +2 -0
  217. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  218. package/dist/record/barrel-distortion-frame.d.ts +15 -0
  219. package/dist/record/barrel-distortion-frame.d.ts.map +1 -0
  220. package/dist/record/dynamic-geometry-consumption.d.ts +10 -2
  221. package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -1
  222. package/dist/record/fold-buckets.d.ts +95 -0
  223. package/dist/record/fold-buckets.d.ts.map +1 -0
  224. package/dist/record/fold-instance-buffer.d.ts +6 -0
  225. package/dist/record/fold-instance-buffer.d.ts.map +1 -0
  226. package/dist/record/frame-lighting.d.ts +1 -0
  227. package/dist/record/frame-lighting.d.ts.map +1 -1
  228. package/dist/record/frame-snapshot.d.ts +40 -3
  229. package/dist/record/frame-snapshot.d.ts.map +1 -1
  230. package/dist/record/frame-targets.d.ts.map +1 -1
  231. package/dist/record/frame.d.ts +14 -62
  232. package/dist/record/frame.d.ts.map +1 -1
  233. package/dist/record/gpu-draw-receipts.d.ts +11 -0
  234. package/dist/record/gpu-draw-receipts.d.ts.map +1 -0
  235. package/dist/record/gpu-timing.d.ts +8 -0
  236. package/dist/record/gpu-timing.d.ts.map +1 -1
  237. package/dist/record/main-pass-geometry.d.ts +21 -5
  238. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  239. package/dist/record/main-pass-material.d.ts +7 -1
  240. package/dist/record/main-pass-material.d.ts.map +1 -1
  241. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  242. package/dist/record/main-pass.d.ts +13 -2
  243. package/dist/record/main-pass.d.ts.map +1 -1
  244. package/dist/record/mesh-ssbo.d.ts +6 -5
  245. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  246. package/dist/record/motion-blur-receipt.d.ts +11 -0
  247. package/dist/record/motion-blur-receipt.d.ts.map +1 -0
  248. package/dist/record/probe-blend-buffer.d.ts +16 -0
  249. package/dist/record/probe-blend-buffer.d.ts.map +1 -0
  250. package/dist/record/recovery-pipeline.d.ts.map +1 -1
  251. package/dist/record/render-context.d.ts +34 -31
  252. package/dist/record/render-context.d.ts.map +1 -1
  253. package/dist/record/shadow-pass.d.ts +2 -0
  254. package/dist/record/shadow-pass.d.ts.map +1 -1
  255. package/dist/record/skybox-post-pass.d.ts +6 -4
  256. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  257. package/dist/record/typed-frame-graph.d.ts +22 -2
  258. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  259. package/dist/record/view-ubo.d.ts +11 -3
  260. package/dist/record/view-ubo.d.ts.map +1 -1
  261. package/dist/record/volume-params.d.ts +9 -0
  262. package/dist/record/volume-params.d.ts.map +1 -0
  263. package/dist/recovery/render-system-candidate.d.ts +10 -0
  264. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  265. package/dist/reflection/record-owner.d.ts.map +1 -1
  266. package/dist/render-contract.d.ts +66 -8
  267. package/dist/render-contract.d.ts.map +1 -1
  268. package/dist/render-graph-primitives.d.ts.map +1 -1
  269. package/dist/render-pipeline.d.ts +106 -3
  270. package/dist/render-pipeline.d.ts.map +1 -1
  271. package/dist/render-system-extract-tail.d.ts +3 -2
  272. package/dist/render-system-extract-tail.d.ts.map +1 -1
  273. package/dist/render-system-extract.d.ts +24 -10
  274. package/dist/render-system-extract.d.ts.map +1 -1
  275. package/dist/render-system-presentation.d.ts +23 -0
  276. package/dist/render-system-presentation.d.ts.map +1 -0
  277. package/dist/render-system-producer-roots.d.ts +10 -0
  278. package/dist/render-system-producer-roots.d.ts.map +1 -0
  279. package/dist/render-system-residency.d.ts +12 -0
  280. package/dist/render-system-residency.d.ts.map +1 -0
  281. package/dist/render-system.d.ts +26 -15
  282. package/dist/render-system.d.ts.map +1 -1
  283. package/dist/scene/probe-blend.d.ts +27 -0
  284. package/dist/scene/probe-blend.d.ts.map +1 -1
  285. package/dist/scene/render-scene.d.ts +14 -5
  286. package/dist/scene/render-scene.d.ts.map +1 -1
  287. package/dist/ssao-buffers.d.ts +9 -0
  288. package/dist/ssao-buffers.d.ts.map +1 -1
  289. package/dist/surface/dynamic-input.d.ts +133 -0
  290. package/dist/surface/dynamic-input.d.ts.map +1 -0
  291. package/dist/surface/gpu-driven.d.ts +41 -0
  292. package/dist/surface/gpu-driven.d.ts.map +1 -0
  293. package/dist/surface/submission-observation.d.ts +136 -0
  294. package/dist/surface/submission-observation.d.ts.map +1 -0
  295. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  296. package/dist/temporal/frame-coordinator.d.ts.map +1 -1
  297. package/dist/temporal/frame.d.ts +7 -0
  298. package/dist/temporal/frame.d.ts.map +1 -1
  299. package/dist/temporal/gpu.d.ts +13 -1
  300. package/dist/temporal/gpu.d.ts.map +1 -1
  301. package/dist/temporal/index.mjs +5 -5
  302. package/dist/temporal/inspection.d.ts.map +1 -1
  303. package/dist/temporal/standard-scene-data.d.ts.map +1 -1
  304. package/dist/temporal/target-coverage-attachment.d.ts.map +1 -1
  305. package/dist/temporal/view.d.ts +6 -1
  306. package/dist/temporal/view.d.ts.map +1 -1
  307. package/dist/transmission/single-layer-medium.d.ts +89 -0
  308. package/dist/transmission/single-layer-medium.d.ts.map +1 -0
  309. package/dist/typed-render-graph-primitives.d.ts +24 -9
  310. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  311. package/dist/volume/component.d.ts +9 -5
  312. package/dist/volume/component.d.ts.map +1 -1
  313. package/dist/volume/extract.d.ts +1 -1
  314. package/dist/volume/extract.d.ts.map +1 -1
  315. package/dist/volume/inspection.d.ts +2 -0
  316. package/dist/volume/inspection.d.ts.map +1 -1
  317. package/dist/volume/passes.d.ts +4 -1
  318. package/dist/volume/passes.d.ts.map +1 -1
  319. package/dist/volume/resources.d.ts.map +1 -1
  320. package/dist/volume/temporal.d.ts +3 -1
  321. package/dist/volume/temporal.d.ts.map +1 -1
  322. package/package.json +22 -21
  323. package/src/__tests__/analytic-fog-graph.unit.test.ts +199 -0
  324. package/src/__tests__/analytic-fog-optics.unit.test.ts +38 -0
  325. package/src/__tests__/atmosphere-daylight.dawn.test.ts +72 -0
  326. package/src/__tests__/barrel-distortion-lkg.integration.test.ts +353 -0
  327. package/src/__tests__/barrel-distortion.dawn.test.ts +41 -0
  328. package/src/__tests__/barrel-distortion.unit.test.ts +364 -0
  329. package/src/__tests__/bloom-exact-zero.unit.test.ts +112 -18
  330. package/src/__tests__/bloom-lifecycle.integration.test.ts +17 -4
  331. package/src/__tests__/construct-renderer-identity.unit.test.ts +49 -0
  332. package/src/__tests__/detached-recovery-graph.unit.test.ts +277 -0
  333. package/src/__tests__/device-loss-fanout.unit.test.ts +36 -1
  334. package/src/__tests__/docs-gate-green.unit.test.ts +112 -1
  335. package/src/__tests__/dynamic-resolution-plugin.integration.test.ts +20 -0
  336. package/src/__tests__/environment-fog-lanes.integration.test.ts +14 -0
  337. package/src/__tests__/environment-selection.unit.test.ts +12 -0
  338. package/src/__tests__/factory-contract.integration.test.ts +626 -113
  339. package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
  340. package/src/__tests__/frame-camera-selection.unit.test.ts +39 -1
  341. package/src/__tests__/frame-plan-contract.unit.test.ts +2 -0
  342. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +14 -3
  343. package/src/__tests__/gpu-dirty-ranges.unit.test.ts +22 -0
  344. package/src/__tests__/gpu-driven-baseline.characterization.test.ts +16 -3
  345. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +12 -0
  346. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +2 -1
  347. package/src/__tests__/gpu-driven-material-artifacts.unit.test.ts +143 -0
  348. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +2 -2
  349. package/src/__tests__/gpu-driven-production.integration.test.ts +482 -3
  350. package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +7 -6
  351. package/src/__tests__/gpu-driven-shadow-views.integration.test.ts +1 -1
  352. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +103 -4
  353. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +18 -2
  354. package/src/__tests__/gpu-driven-view.browser.test.ts +5 -8
  355. package/src/__tests__/gpu-driven-view.dawn.test.ts +6 -2
  356. package/src/__tests__/gpu-driven-view.unit.test.ts +1 -1
  357. package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +1 -0
  358. package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -4
  359. package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +1 -0
  360. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +12 -0
  361. package/src/__tests__/gpu-scene.unit.test.ts +210 -9
  362. package/src/__tests__/instance-allocation-failure.unit.test.ts +57 -0
  363. package/src/__tests__/instances-culling.integration.test.ts +10 -36
  364. package/src/__tests__/instances-store.unit.test.ts +105 -238
  365. package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
  366. package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +146 -0
  367. package/src/__tests__/material-shader-prewarm.unit.test.ts +59 -0
  368. package/src/__tests__/material-snapshot-mutation.integration.test.ts +39 -1
  369. package/src/__tests__/mesh-submission-lifetime.unit.test.ts +31 -0
  370. package/src/__tests__/morph-culling-reentry.dawn.test.ts +5 -5
  371. package/src/__tests__/morph-visual-evidence.integration.test.ts +8 -7
  372. package/src/__tests__/motion-blur-compute.dawn.test.ts +589 -0
  373. package/src/__tests__/motion-blur.pixel.integration.test.ts +2 -2
  374. package/src/__tests__/nineslice-handle-surface.unit.test.ts +4 -4
  375. package/src/__tests__/pbr-view-layout.unit.test.ts +9 -0
  376. package/src/__tests__/physical-clearcoat.integration.test.ts +58 -0
  377. package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +21 -0
  378. package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
  379. package/src/__tests__/prepared-graphics-lifecycle.unit.test.ts +86 -0
  380. package/src/__tests__/probe-bindings.unit.test.ts +582 -1
  381. package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
  382. package/src/__tests__/public-surface.test-d.ts +8 -0
  383. package/src/__tests__/receipt-observation-retirement.unit.test.ts +65 -0
  384. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +69 -0
  385. package/src/__tests__/render-error-code-owner.test-d.ts +9 -0
  386. package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
  387. package/src/__tests__/render-feature-error-reporting.unit.test.ts +44 -0
  388. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +10 -1
  389. package/src/__tests__/render-feature-retry.unit.test.ts +12 -1
  390. package/src/__tests__/render-feature-stage-fault-recovery.unit.test.ts +23 -0
  391. package/src/__tests__/render-scene-mixed-updates.integration.test.ts +145 -19
  392. package/src/__tests__/render-scene-projection.unit.test.ts +36 -11
  393. package/src/__tests__/render-scene-temporal-retry.unit.test.ts +37 -6
  394. package/src/__tests__/render-target-probe-soak.perf.test.ts +2 -2
  395. package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +3 -3
  396. package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +5 -2
  397. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +41 -7
  398. package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +16 -0
  399. package/src/__tests__/renderer-frame-transaction.integration.test.ts +33 -11
  400. package/src/__tests__/resource-allocation.unit.test.ts +123 -0
  401. package/src/__tests__/shader-manifest-fixture.ts +4 -4
  402. package/src/__tests__/single-layer-medium-passes.unit.test.ts +275 -0
  403. package/src/__tests__/skin-motion-regression.unit.test.ts +70 -1
  404. package/src/__tests__/skin-palette-recycling.dawn.test.ts +97 -0
  405. package/src/__tests__/skinned-shadow-caster.test.ts +17 -0
  406. package/src/__tests__/ssr-carrier-public-contract.unit.test.ts +21 -0
  407. package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +4 -4
  408. package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +2 -2
  409. package/src/__tests__/ssr-gpu-dispatch.ts +1 -1
  410. package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +6 -2
  411. package/src/__tests__/standard-lighting-write.unit.test.ts +2 -1
  412. package/src/__tests__/standard-output-chain-contract.unit.test.ts +28 -0
  413. package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +46 -1
  414. package/src/__tests__/standard-pipeline.dawn.test.ts +1 -1
  415. package/src/__tests__/standard-pipeline.integration.test.ts +200 -9
  416. package/src/__tests__/surface-dynamic-buffer-lifecycle.unit.test.ts +506 -0
  417. package/src/__tests__/surface-submission-observation.unit.test.ts +812 -0
  418. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +32 -0
  419. package/src/__tests__/temporal-performance.integration.test.ts +3 -3
  420. package/src/__tests__/temporal-reset-matrix.unit.test.ts +10 -0
  421. package/src/__tests__/temporal-view.unit.test.ts +2 -1
  422. package/src/__tests__/typed-pipeline-topology.unit.test.ts +20 -4
  423. package/src/__tests__/visibility-instances.integration.test.ts +7 -19
  424. package/src/__tests__/visibility-producer-matrix.integration.test.ts +9 -20
  425. package/src/__tests__/volume-optics-oracle.unit.test.ts +7 -3
  426. package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +189 -15
  427. package/src/__tests__/volumetric-fog-errors.unit.test.ts +4 -3
  428. package/src/__tests__/volumetric-fog-multiple.unit.test.ts +55 -0
  429. package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +1 -1
  430. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +558 -68
  431. package/src/__tests__/volumetric-fog-temporal.unit.test.ts +27 -0
  432. package/src/__tests__/volumetric-fog-topology.unit.test.ts +23 -5
  433. package/src/assembly/analytic-fog-registration.ts +14 -0
  434. package/src/assembly/backend-contract.ts +30 -0
  435. package/src/assembly/barrel-distortion-inspection.ts +22 -0
  436. package/src/assembly/canvas-draw-guard.ts +11 -0
  437. package/src/assembly/cloud-shadow-entry.ts +22 -0
  438. package/src/assembly/dynamic-geometry-host.ts +65 -37
  439. package/src/assembly/dynamic-geometry-runtime.ts +7 -1
  440. package/src/assembly/factory.ts +2 -30
  441. package/src/assembly/fxaa-registration.ts +17 -0
  442. package/src/assembly/host-contract.ts +3 -3
  443. package/src/assembly/lod-observation.ts +12 -0
  444. package/src/assembly/material/assembly.ts +25 -13
  445. package/src/assembly/material/pipeline-helpers.ts +53 -12
  446. package/src/assembly/material-shader-policy.ts +55 -0
  447. package/src/assembly/material-shader-prewarm.ts +21 -10
  448. package/src/assembly/motion-blur-registration.ts +17 -0
  449. package/src/assembly/recovery/device-loss-fanout.ts +13 -0
  450. package/src/assembly/recovery/renderer-recover.ts +41 -18
  451. package/src/assembly/render-feature-post-processes.ts +54 -0
  452. package/src/assembly/renderer-facade.ts +6 -1
  453. package/src/assembly/renderer-feature-inspection.ts +8 -2
  454. package/src/assembly/renderer-frame-transaction.ts +23 -0
  455. package/src/assembly/renderer-inspection.ts +28 -0
  456. package/src/assembly/skin-palette-owner.ts +1 -1
  457. package/src/assembly/temporal-post-process-prewarm.ts +40 -0
  458. package/src/assembly/webgpu-pbr-ready.ts +9 -1
  459. package/src/assembly/webgpu-ready-contract.ts +8 -3
  460. package/src/assembly/webgpu-ready-per-pass.ts +104 -0
  461. package/src/assembly/webgpu-ready.ts +296 -306
  462. package/src/assembly/webgpu-renderer-bootstrap.ts +0 -12
  463. package/src/assembly/webgpu-renderer-observation-owner.ts +222 -0
  464. package/src/assembly/webgpu-renderer.ts +228 -281
  465. package/src/assembly/webgpu-vertex-layouts.ts +1 -1
  466. package/src/barrel-distortion.ts +247 -0
  467. package/src/bloom-admission.ts +21 -0
  468. package/src/cloud/__tests__/cloud-density-parity.dawn.test.ts +173 -0
  469. package/src/cloud/__tests__/cloud-layer-framebuffer-y.dawn.test.ts +265 -0
  470. package/src/cloud/__tests__/cloud-layer.browser.test.ts +432 -0
  471. package/src/cloud/__tests__/cloud-layer.unit.test.ts +634 -0
  472. package/src/cloud/density.ts +600 -0
  473. package/src/cloud/extract.ts +110 -0
  474. package/src/cloud/feature.ts +1810 -0
  475. package/src/cloud/frame-context.ts +42 -0
  476. package/src/cloud/inspection.ts +130 -0
  477. package/src/cloud/optics.ts +285 -0
  478. package/src/cloud/parameters.ts +255 -0
  479. package/src/cloud/resources.ts +122 -0
  480. package/src/cloud/shadow.ts +167 -0
  481. package/src/cloud/temporal.ts +226 -0
  482. package/src/components/__tests__/motion-blur.unit.test.ts +1 -0
  483. package/src/components/atmosphere.ts +4 -0
  484. package/src/components/barrel-distortion.ts +46 -0
  485. package/src/components/camera.ts +66 -10
  486. package/src/components/cloud-layer.ts +47 -0
  487. package/src/components/index.ts +2 -0
  488. package/src/components/instances.ts +18 -45
  489. package/src/components/mesh-filter.ts +11 -9
  490. package/src/components/motion-blur.ts +1 -0
  491. package/src/components/sprite-instances.ts +1 -1
  492. package/src/construct-renderer.ts +1 -1
  493. package/src/device/gpu-residency.ts +56 -12
  494. package/src/dynamic-geometry.ts +12 -1
  495. package/src/environment/analytic-fog.ts +44 -0
  496. package/src/environment/background.ts +2 -2
  497. package/src/errors/cloud.ts +103 -0
  498. package/src/errors/render.ts +58 -8
  499. package/src/examples/single-layer-medium-surface.ts +59 -0
  500. package/src/extract/camera.ts +35 -8
  501. package/src/extract/contracts.ts +12 -0
  502. package/src/extract/environment.ts +4 -0
  503. package/src/features/barrel-distortion.ts +172 -0
  504. package/src/features/error-reporting.ts +98 -0
  505. package/src/features/host.ts +138 -24
  506. package/src/features/motion-blur/__tests__/motion-blur-feature.unit.test.ts +111 -1
  507. package/src/features/motion-blur/__tests__/motion-blur-params.unit.test.ts +58 -3
  508. package/src/features/motion-blur/motion-blur-feature.ts +1519 -15
  509. package/src/features/motion-blur/motion-blur-params.ts +70 -2
  510. package/src/features/motion-blur/motion-blur-runtime.ts +176 -0
  511. package/src/features/plan.ts +33 -8
  512. package/src/features/prepared-gpu-work.ts +86 -35
  513. package/src/features/render-graph-compute.ts +13 -5
  514. package/src/features/render-graph-contribution.ts +11 -0
  515. package/src/features/render-graph-raster.ts +45 -3
  516. package/src/features/targets.ts +66 -0
  517. package/src/features/types.ts +47 -0
  518. package/src/fullscreen-post-process-pass.ts +41 -9
  519. package/src/gpu-dirty-ranges.ts +48 -0
  520. package/src/gpu-driven/batch-topology.ts +53 -0
  521. package/src/gpu-driven/material-artifacts.ts +35 -32
  522. package/src/gpu-driven/prepared-draw.ts +27 -14
  523. package/src/gpu-driven/production-raster-material.ts +1894 -0
  524. package/src/gpu-driven/production-raster.ts +904 -787
  525. package/src/gpu-driven/resource-allocation.ts +142 -0
  526. package/src/gpu-driven/shadow-ownership.ts +71 -0
  527. package/src/gpu-driven/view-gpu.ts +181 -10
  528. package/src/gpu-scene.ts +259 -101
  529. package/src/hdrp-buffers.ts +4 -3
  530. package/src/ibl/skylight-bind-group.ts +49 -7
  531. package/src/index.ts +228 -9
  532. package/src/inspection-types.ts +222 -2
  533. package/src/instance-buffer-cache.ts +4 -4
  534. package/src/instances.ts +151 -492
  535. package/src/pbr-pipeline.ts +219 -13
  536. package/src/pipeline/single-layer-medium-passes.ts +267 -0
  537. package/src/pipeline/standard-forward-lane.ts +313 -57
  538. package/src/pipeline/standard-output/graph.ts +8 -2
  539. package/src/pipeline/standard-output/types.ts +12 -1
  540. package/src/pipeline/standard-pipeline.ts +291 -18
  541. package/src/pipeline/standard-post.ts +397 -102
  542. package/src/pipeline-builder.ts +1 -1
  543. package/src/pipeline-spec.ts +5 -5
  544. package/src/plugin.ts +4 -0
  545. package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
  546. package/src/points-lines/__tests__/view-ubo.unit.test.ts +2 -1
  547. package/src/prepare/prepared-graphics-resolver.ts +2 -0
  548. package/src/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
  549. package/src/record/__tests__/sprite-material-abi.unit.test.ts +1 -1
  550. package/src/record/__tests__/temporal-payload.unit.test.ts +3 -2
  551. package/src/record/__tests__/transparent-group2-selection.unit.test.ts +11 -0
  552. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -0
  553. package/src/record/__tests__/view-ubo-layout.unit.test.ts +4 -3
  554. package/src/record/barrel-distortion-frame.ts +110 -0
  555. package/src/record/dynamic-geometry-consumption.ts +39 -9
  556. package/src/record/fold-buckets.ts +852 -0
  557. package/src/record/fold-instance-buffer.ts +51 -0
  558. package/src/record/frame-lighting.ts +36 -2
  559. package/src/record/frame-snapshot.ts +44 -4
  560. package/src/record/frame-targets.ts +10 -6
  561. package/src/record/frame.ts +373 -1099
  562. package/src/record/gpu-draw-receipts.ts +38 -0
  563. package/src/record/gpu-timing.ts +48 -5
  564. package/src/record/main-pass-geometry.ts +281 -83
  565. package/src/record/main-pass-material.ts +66 -4
  566. package/src/record/main-pass-sprite-draws.ts +13 -66
  567. package/src/record/main-pass.ts +156 -20
  568. package/src/record/mesh-ssbo.ts +43 -6
  569. package/src/record/motion-blur-receipt.ts +91 -0
  570. package/src/record/probe-blend-buffer.ts +180 -0
  571. package/src/record/recovery-pipeline.ts +35 -3
  572. package/src/record/render-context.ts +51 -31
  573. package/src/record/shadow-pass.ts +36 -2
  574. package/src/record/skybox-post-pass.ts +150 -200
  575. package/src/record/typed-frame-graph.ts +824 -44
  576. package/src/record/view-ubo.ts +26 -3
  577. package/src/record/volume-params.ts +225 -0
  578. package/src/recovery/render-system-candidate.ts +257 -52
  579. package/src/reflection/record-owner.ts +7 -3
  580. package/src/render-contract.ts +71 -8
  581. package/src/render-graph-primitives.ts +7 -1
  582. package/src/render-pipeline.ts +136 -1
  583. package/src/render-system-extract-tail.ts +72 -60
  584. package/src/render-system-extract.ts +117 -87
  585. package/src/render-system-presentation.ts +56 -0
  586. package/src/render-system-producer-roots.ts +96 -0
  587. package/src/render-system-residency.ts +159 -0
  588. package/src/render-system.ts +601 -482
  589. package/src/scene/probe-blend.ts +96 -4
  590. package/src/scene/render-scene.ts +431 -281
  591. package/src/ssao-buffers.ts +95 -2
  592. package/src/surface/__tests__/dynamic-input.unit.test.ts +374 -0
  593. package/src/surface/__tests__/gpu-driven.unit.test.ts +87 -0
  594. package/src/surface/dynamic-input.ts +658 -0
  595. package/src/surface/gpu-driven.ts +147 -0
  596. package/src/surface/submission-observation.ts +517 -0
  597. package/src/systems/skin-palette-allocator.ts +4 -1
  598. package/src/temporal/__tests__/temporal-frame-transaction.unit.test.ts +36 -0
  599. package/src/temporal/frame-coordinator.ts +8 -1
  600. package/src/temporal/frame.ts +20 -0
  601. package/src/temporal/gpu.ts +101 -17
  602. package/src/temporal/inspection.ts +7 -1
  603. package/src/temporal/standard-scene-data.ts +5 -0
  604. package/src/temporal/target-coverage-attachment.ts +4 -0
  605. package/src/temporal/view.ts +13 -2
  606. package/src/transmission/__tests__/single-layer-medium.unit.test.ts +149 -0
  607. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +12 -11
  608. package/src/transmission/single-layer-medium.ts +322 -0
  609. package/src/typed-render-graph-primitives.ts +191 -50
  610. package/src/volume/component.ts +10 -10
  611. package/src/volume/extract.ts +11 -5
  612. package/src/volume/inspection.ts +3 -0
  613. package/src/volume/passes.ts +95 -8
  614. package/src/volume/resources.ts +2 -1
  615. package/src/volume/temporal.ts +11 -0
  616. package/dist/chunk-4NNZQCL3.mjs.map +0 -1
  617. package/dist/chunk-6TFBXLRJ.mjs.map +0 -1
  618. package/dist/chunk-DRR7D3KX.mjs.map +0 -1
  619. package/dist/chunk-GWCEMDVR.mjs.map +0 -1
  620. package/dist/chunk-JCIRYQ4V.mjs.map +0 -1
  621. package/dist/chunk-JRIPCMYC.mjs.map +0 -1
  622. package/dist/chunk-LULCA3OF.mjs +0 -1713
  623. package/dist/chunk-LULCA3OF.mjs.map +0 -1
  624. package/dist/chunk-PA5DRJNI.mjs.map +0 -1
@@ -75,7 +75,6 @@ import {
75
75
  type TextureAsset,
76
76
  type TextureShape,
77
77
  type MeshAsset as TypesMeshAsset,
78
- toShared,
79
78
  } from '@forgeax/engine-types';
80
79
  import { GpuBuffer, GpuTexture } from '../gpu-resource';
81
80
  import {
@@ -570,6 +569,12 @@ export class GpuResidencyCache {
570
569
  // equirect source always resolves to the same cubemap (idempotent, A2).
571
570
  private readonly cubemapIdempotentMap: Map<number, Handle<'EquirectAsset', 'shared'>> = new Map();
572
571
  private readonly meshGpuHandles: Map<string | number, MeshGpuHandles> = new Map();
572
+ /**
573
+ * Lower-detail POD identities packed into each resident mesh entry. The
574
+ * GPU entry only carries byte ranges; keeping the source identities beside
575
+ * it lets a later draw upgrade a root-only upload without hashing vertices.
576
+ */
577
+ private readonly meshLodAssets = new WeakMap<MeshGpuHandles, readonly TypesMeshAsset[]>();
573
578
  private readonly meshLifetimes = new WeakMap<MeshGpuHandles, MeshResidencyLifetime>();
574
579
  private readonly retiredMeshes = new Set<MeshGpuHandles>();
575
580
 
@@ -832,7 +837,7 @@ export class GpuResidencyCache {
832
837
  handle: Handle<'MeshAsset', 'shared'>,
833
838
  worldId: World | number = 0,
834
839
  ): { freed: number; errors: RhiError[] } {
835
- const id = this.worldKey(handleSlot(handle), worldId);
840
+ const id = this.worldKey(Number(handle), worldId);
836
841
  const entry = this.meshGpuHandles.get(id);
837
842
  if (entry === undefined) return { freed: 0, errors: [] };
838
843
 
@@ -1090,7 +1095,7 @@ export class GpuResidencyCache {
1090
1095
  handle: Handle<'MeshAsset', 'shared'>,
1091
1096
  worldId: World | number = 0,
1092
1097
  ): MeshGpuHandles | undefined {
1093
- return this.meshGpuHandles.get(this.worldKey(handleSlot(handle), worldId));
1098
+ return this.meshGpuHandles.get(this.worldKey(Number(handle), worldId));
1094
1099
  }
1095
1100
 
1096
1101
  /** Candidate leases retain the concrete allocation even after cache invalidation. */
@@ -1098,7 +1103,7 @@ export class GpuResidencyCache {
1098
1103
  handle: Handle<'MeshAsset', 'shared'>,
1099
1104
  worldId: World | number = 0,
1100
1105
  ): MeshResidencyLease | undefined {
1101
- const key = this.worldKey(handleSlot(handle), worldId);
1106
+ const key = this.worldKey(Number(handle), worldId);
1102
1107
  const entry = this.meshGpuHandles.get(key);
1103
1108
  return entry === undefined
1104
1109
  ? undefined
@@ -1110,7 +1115,7 @@ export class GpuResidencyCache {
1110
1115
 
1111
1116
  /** In-place author changes immediately miss the cache; old submissions keep their allocation. */
1112
1117
  invalidateMesh(handle: number, worldId: World | number = 0): void {
1113
- const key = this.worldKey(handleSlot(toShared<'MeshAsset'>(handle)), worldId);
1118
+ const key = this.worldKey(handle, worldId);
1114
1119
  const entry = this.meshGpuHandles.get(key);
1115
1120
  if (entry !== undefined) this.retireMeshEntry(key, entry);
1116
1121
  }
@@ -1156,9 +1161,32 @@ export class GpuResidencyCache {
1156
1161
  // path, not routed here).
1157
1162
  switch (pod.kind) {
1158
1163
  case 'mesh': {
1159
- const key = this.worldKey(id, worldId);
1164
+ // Recycled shared slots can coexist with an older GPU submission.
1165
+ // The generation is part of mesh residency identity, not only its slot.
1166
+ const key = this.worldKey(Number(handle), worldId);
1160
1167
  const existing = this.meshGpuHandles.get(key);
1161
- if (existing !== undefined) return ok(existing);
1168
+ if (existing !== undefined) {
1169
+ // A root mesh can become resident before its lower-detail assets are
1170
+ // available. Preserve the fast hit for the common case, but publish
1171
+ // a complete chain once the caller supplies one. Never downgrade a
1172
+ // resident chain when a later call has no lower assets yet.
1173
+ if (lodMeshes.length === 0) return ok(existing);
1174
+ const previousLodAssets = this.meshLodAssets.get(existing);
1175
+ const sameLodChain =
1176
+ previousLodAssets !== undefined &&
1177
+ previousLodAssets.length === lodMeshes.length &&
1178
+ previousLodAssets.every((asset, index) => asset === lodMeshes[index]);
1179
+ if (sameLodChain) return ok(existing);
1180
+
1181
+ const projected = deriveRenderDataMesh(pod);
1182
+ if (!projected.ok) return projected;
1183
+ const upgraded = this.uploadMeshById(key, pod, projected.value, lodMeshes);
1184
+ if (!upgraded.ok) return upgraded;
1185
+ // uploadMeshById publishes the new entry before this call so the
1186
+ // old allocation stays available to any already-recorded frame.
1187
+ this.retireMeshEntry(key, existing);
1188
+ return upgraded;
1189
+ }
1162
1190
  const projected = deriveRenderDataMesh(pod);
1163
1191
  if (!projected.ok) return projected;
1164
1192
  return this.uploadMeshById(key, pod, projected.value, lodMeshes);
@@ -1204,7 +1232,7 @@ export class GpuResidencyCache {
1204
1232
  ): Result<RecoveryResidencyPreparation, RhiError | AssetError | ImageError> {
1205
1233
  const id = handleSlot(handle);
1206
1234
  if (pod.kind === 'mesh') {
1207
- const key = this.worldKey(id, worldId);
1235
+ const key = this.worldKey(Number(handle), worldId);
1208
1236
  if (this.meshGpuHandles.has(key)) return ok({});
1209
1237
  const projected = deriveRenderDataMesh(pod);
1210
1238
  if (!projected.ok) return projected;
@@ -2035,6 +2063,10 @@ export class GpuResidencyCache {
2035
2063
  // Vertex-only mesh: skip the index buffer entirely. The indexed path below
2036
2064
  // is unchanged byte-for-byte when `indices` is present.
2037
2065
  let ibo: Buffer | null = null;
2066
+ const cleanupUpload = (): void => {
2067
+ if (ibo !== null) device.destroyBuffer(ibo);
2068
+ device.destroyBuffer(vbo);
2069
+ };
2038
2070
  if (indices !== undefined) {
2039
2071
  const iboResult = device.createBuffer({
2040
2072
  label: `mesh-${id}-ibo`,
@@ -2042,17 +2074,24 @@ export class GpuResidencyCache {
2042
2074
  usage: renderData.indexUsage,
2043
2075
  mappedAtCreation: false,
2044
2076
  });
2045
- if (!iboResult.ok) return iboResult;
2077
+ if (!iboResult.ok) {
2078
+ cleanupUpload();
2079
+ return iboResult;
2080
+ }
2046
2081
  ibo = iboResult.value;
2047
2082
  }
2048
2083
 
2049
2084
  const vboWriteResult = device.queue.writeBuffer(vbo, 0, vertices);
2050
- if (!vboWriteResult.ok) return err(vboWriteResult.error);
2085
+ if (!vboWriteResult.ok) {
2086
+ cleanupUpload();
2087
+ return err(vboWriteResult.error);
2088
+ }
2051
2089
 
2052
2090
  if (indices !== undefined) {
2053
2091
  const indexSrc = new Uint8Array(indexBytes);
2054
2092
  indexSrc.set(new Uint8Array(indices.buffer, indices.byteOffset, indexBytesUnpadded));
2055
- if (ibo === null)
2093
+ if (ibo === null) {
2094
+ cleanupUpload();
2056
2095
  return err(
2057
2096
  new RhiError({
2058
2097
  code: 'webgpu-runtime-error',
@@ -2060,8 +2099,12 @@ export class GpuResidencyCache {
2060
2099
  hint: 'the indexed mesh upload lost its RHI index-buffer owner',
2061
2100
  }),
2062
2101
  );
2102
+ }
2063
2103
  const iboWriteResult = device.queue.writeBuffer(ibo, 0, indexSrc);
2064
- if (!iboWriteResult.ok) return err(iboWriteResult.error);
2104
+ if (!iboWriteResult.ok) {
2105
+ cleanupUpload();
2106
+ return err(iboWriteResult.error);
2107
+ }
2065
2108
  }
2066
2109
 
2067
2110
  // The geometry projection already contains every packed attribute,
@@ -2085,6 +2128,7 @@ export class GpuResidencyCache {
2085
2128
  ...(lodRanges === undefined ? {} : { lodRanges }),
2086
2129
  };
2087
2130
  this.meshGpuHandles.set(id, entry);
2131
+ this.meshLodAssets.set(entry, lodMeshes);
2088
2132
  this.meshResidencyEpoch += 1;
2089
2133
  return ok(entry);
2090
2134
  }
@@ -53,6 +53,9 @@ export interface DynamicGeometryCandidate {
53
53
  readonly state: DynamicGeometryCandidateState;
54
54
  }
55
55
 
56
+ /** Record-stage lane that consumed a published dynamic-geometry candidate. */
57
+ export type DynamicGeometryRecordStageLane = 'cpu' | 'gpu' | 'mixed';
58
+
56
59
  /** Receipt that ties candidate publication to the sole Renderer FrameReceipt. */
57
60
  export interface DynamicGeometryReceipt {
58
61
  readonly candidateId: string;
@@ -69,6 +72,8 @@ export interface DynamicGeometryReceipt {
69
72
  };
70
73
  /** Whether the Renderer record stage consumed this candidate for this frame. */
71
74
  readonly recordStageConsumed: boolean;
75
+ /** Lane evidence from the exact submitted record stage, when attached. */
76
+ readonly recordStageLane?: DynamicGeometryRecordStageLane;
72
77
  /** Actual frame fixed step; may be newer than the preparation step. */
73
78
  readonly publicationFixedStep?: number;
74
79
  }
@@ -271,6 +276,9 @@ export interface DynamicGeometryLifecycle {
271
276
  worlds?: readonly object[],
272
277
  fixedStep?: number,
273
278
  canPublish?: (candidate: DynamicGeometryCandidate) => boolean,
279
+ recordStageLane?: (
280
+ candidate: DynamicGeometryCandidate,
281
+ ) => DynamicGeometryRecordStageLane | undefined,
274
282
  ): readonly DynamicGeometryReceipt[];
275
283
  invalidateWorld(world: object, completion?: Promise<unknown>): void;
276
284
  invalidateGeneration(generation: number): void;
@@ -610,7 +618,7 @@ export function createDynamicGeometryLifecycle(
610
618
  meshBytes = Math.max(0, meshBytes - record.candidate.meshBytes);
611
619
  return ok(undefined);
612
620
  },
613
- publishFrame(frame, worlds, fixedStep, canPublish) {
621
+ publishFrame(frame, worlds, fixedStep, canPublish, recordStageLane) {
614
622
  if (disposed || frame.deviceGeneration !== currentGeneration) return [];
615
623
  const receipts: DynamicGeometryReceipt[] = [];
616
624
  for (const record of records.values()) {
@@ -630,6 +638,8 @@ export function createDynamicGeometryLifecycle(
630
638
  continue;
631
639
  }
632
640
  if (canPublish !== undefined && !canPublish(record.candidate)) continue;
641
+ const consumedLane =
642
+ canPublish === undefined ? undefined : recordStageLane?.(record.candidate);
633
643
  record.candidate = Object.freeze({ ...record.candidate, state: 'published' as const });
634
644
  const receipt = Object.freeze({
635
645
  candidateId: record.candidate.candidateId,
@@ -642,6 +652,7 @@ export function createDynamicGeometryLifecycle(
642
652
  frameId: frame.frameId,
643
653
  deviceGeneration: frame.deviceGeneration,
644
654
  recordStageConsumed: canPublish !== undefined,
655
+ ...(consumedLane === undefined ? {} : { recordStageLane: consumedLane }),
645
656
  ...(fixedStep === undefined ? {} : { publicationFixedStep: fixedStep }),
646
657
  frame: Object.freeze({ ...frame }),
647
658
  });
@@ -0,0 +1,44 @@
1
+ import { mat4 } from '@forgeax/engine-math';
2
+ import type { FogFrame } from '../extract/environment';
3
+ import { computeProjectionMatrix, computeViewMatrix } from '../record/helpers';
4
+ import type { CameraSnapshot } from '../render-contract';
5
+
6
+ /** Numerical reference for the shader's closed-form height-density integral. */
7
+ export function analyticFogOpacity(
8
+ fog: Pick<FogFrame, 'density' | 'heightFalloff' | 'maxOpacity'>,
9
+ originY: number,
10
+ endY: number,
11
+ distance: number,
12
+ ): number {
13
+ const rho = fog.density * Math.exp(Math.max(-60, Math.min(60, -fog.heightFalloff * originY)));
14
+ const t = Math.max(-60, Math.min(60, fog.heightFalloff * (endY - originY)));
15
+ const integral = Math.abs(t) < 0.001 ? 1 - t / 2 + (t * t) / 6 : -Math.expm1(-t) / t;
16
+ return fog.maxOpacity * -Math.expm1(-Math.min(80, Math.max(0, rho * distance * integral)));
17
+ }
18
+
19
+ export function encodeAnalyticFogParams(fog: FogFrame, camera: CameraSnapshot): Uint8Array {
20
+ const projection = computeProjectionMatrix(camera);
21
+ // Match the scene depth's jittered projection before temporal resolve.
22
+ const jitter = camera.temporal?.currentJitterUv;
23
+ if (jitter !== undefined) {
24
+ for (let column = 0; column < 4; column++) {
25
+ projection[column * 4] =
26
+ (projection[column * 4] ?? 0) + jitter[0] * 2 * (projection[column * 4 + 3] ?? 0);
27
+ projection[column * 4 + 1] =
28
+ (projection[column * 4 + 1] ?? 0) - jitter[1] * 2 * (projection[column * 4 + 3] ?? 0);
29
+ }
30
+ }
31
+ const inverse = mat4.invert(
32
+ mat4.create(),
33
+ mat4.multiply(mat4.create(), projection, computeViewMatrix(camera)),
34
+ );
35
+ const data = new Float32Array(28);
36
+ data.set(inverse, 0);
37
+ data.set(camera.position, 16);
38
+ data.set([...fog.color, fog.density], 20);
39
+ data.set(
40
+ [fog.heightFalloff, fog.maxOpacity, camera.near, camera.projection === 'orthographic' ? 1 : 0],
41
+ 24,
42
+ );
43
+ return new Uint8Array(data.buffer);
44
+ }
@@ -88,8 +88,8 @@ export function addAtmosphereBackground(
88
88
  settings.mieDirectionalG,
89
89
  settings.sunAngularRadius,
90
90
  settings.sunAngularRadius > 0 ? 1 : 0,
91
- 0,
92
- 0,
91
+ settings.circumsolarStrength,
92
+ settings.circumsolarWidth,
93
93
  ]);
94
94
  frame.runtime.device.queue
95
95
  .writeBuffer(resources.buffer(params.value).unwrap(), 0, values)
@@ -0,0 +1,103 @@
1
+ /** Closed errors produced by the CloudLayer authoring and resource route. */
2
+
3
+ export interface CloudLayerInvalidParameterDetail {
4
+ readonly field: string;
5
+ readonly value: unknown;
6
+ readonly expected: string;
7
+ }
8
+
9
+ export class CloudLayerInvalidParameterError extends Error {
10
+ readonly code = 'cloud-layer-invalid-parameter' as const;
11
+ readonly expected: string;
12
+ readonly hint: string;
13
+ readonly detail: CloudLayerInvalidParameterDetail;
14
+
15
+ constructor(field: string, value: unknown, expected: string) {
16
+ super(`CloudLayer.${field} is invalid`);
17
+ this.name = 'CloudLayerInvalidParameterError';
18
+ this.expected = `CloudLayer.${field} must be ${expected}`;
19
+ this.hint = `set CloudLayer.${field} to ${expected}`;
20
+ this.detail = { field, value, expected };
21
+ }
22
+ }
23
+
24
+ export interface CloudLayerOwnerConflictDetail {
25
+ readonly count: number;
26
+ }
27
+
28
+ export class CloudLayerOwnerConflictError extends Error {
29
+ readonly code = 'cloud-layer-owner-conflict' as const;
30
+ readonly expected = 'at most one CloudLayer owns a World frame';
31
+ readonly hint = 'remove additional CloudLayer owners before extraction';
32
+ readonly detail: CloudLayerOwnerConflictDetail;
33
+
34
+ constructor(count: number) {
35
+ super(`CloudLayer owner cardinality is ${count}`);
36
+ this.name = 'CloudLayerOwnerConflictError';
37
+ this.detail = { count };
38
+ }
39
+ }
40
+
41
+ export interface CloudLayerCacheInvalidDetail {
42
+ readonly sourceKey: string;
43
+ readonly reason: string;
44
+ }
45
+
46
+ export class CloudLayerCacheInvalidError extends Error {
47
+ readonly code = 'cloud-layer-cache-invalid' as const;
48
+ readonly expected = 'the density cache payload matches its reconstructible source';
49
+ readonly hint = 'discard the derived cache and rebuild it from CloudLayer source facts';
50
+ readonly detail: CloudLayerCacheInvalidDetail;
51
+
52
+ constructor(sourceKey: string, reason: string) {
53
+ super(`CloudLayer cache is invalid: ${reason}`);
54
+ this.name = 'CloudLayerCacheInvalidError';
55
+ this.detail = { sourceKey, reason };
56
+ }
57
+ }
58
+
59
+ export interface CloudLayerCapabilityMissingDetail {
60
+ readonly capability: string;
61
+ }
62
+
63
+ export class CloudLayerCapabilityMissingError extends Error {
64
+ readonly code = 'cloud-layer-capability-missing' as const;
65
+ readonly expected = 'the selected backend exposes the capability required by the cloud lane';
66
+ readonly hint =
67
+ 'inspect the capability report, disable the cloud lane on this backend, or retry on a backend with the required capability';
68
+ readonly detail: CloudLayerCapabilityMissingDetail;
69
+
70
+ constructor(capability: string) {
71
+ super(`CloudLayer capability is unavailable: ${capability}`);
72
+ this.name = 'CloudLayerCapabilityMissingError';
73
+ this.detail = { capability };
74
+ }
75
+ }
76
+
77
+ export interface CloudLayerResourceFailureDetail {
78
+ readonly stage: 'cache' | 'shadow' | 'view' | 'history' | 'retire';
79
+ readonly generation: number;
80
+ readonly cause?: unknown;
81
+ }
82
+
83
+ export class CloudLayerResourceFailureError extends Error {
84
+ readonly code = 'cloud-layer-resource-failed' as const;
85
+ readonly expected = 'cloud resources are created, submitted and retired as one generation';
86
+ readonly hint = 'keep the last-known-good cloud generation and retry after recovery';
87
+ readonly detail: CloudLayerResourceFailureDetail;
88
+
89
+ constructor(detail: CloudLayerResourceFailureDetail) {
90
+ super(`CloudLayer ${detail.stage} resource failed at generation ${detail.generation}`);
91
+ this.name = 'CloudLayerResourceFailureError';
92
+ this.detail = detail;
93
+ }
94
+ }
95
+
96
+ export type CloudLayerError =
97
+ | CloudLayerInvalidParameterError
98
+ | CloudLayerOwnerConflictError
99
+ | CloudLayerCacheInvalidError
100
+ | CloudLayerCapabilityMissingError
101
+ | CloudLayerResourceFailureError;
102
+
103
+ export type CloudLayerErrorCode = CloudLayerError['code'];
@@ -19,6 +19,8 @@ import type {
19
19
  SurfaceFailureKind,
20
20
  } from '@forgeax/engine-render-graph';
21
21
  import type { DeviceResourceKind, DeviceScopeReceipt } from '../device/resource-types';
22
+ import type { SunCardinalityError } from '../environment/frame';
23
+ import type { MotionBlurValidationError } from '../features/motion-blur/motion-blur-params';
22
24
  import type {
23
25
  PreparedKind,
24
26
  RenderFeatureCapabilityKey,
@@ -28,6 +30,7 @@ import type {
28
30
  import type { AutoExposureError } from '../pipeline/standard-output/auto-exposure/inspection';
29
31
  import type { SceneDataLane, SceneDataSchemaId } from '../temporal/scene-data';
30
32
  import type { TransmissionCapabilityFact } from '../transmission/backdrop';
33
+ import type { CloudLayerError } from './cloud';
31
34
  import type { RecoveryOutcome, RecoveryPhase } from './recover';
32
35
 
33
36
  // Public render errors keep one machine-readable order: closed `code`,
@@ -783,6 +786,8 @@ export interface RenderFeatureStageFailedDetail {
783
786
  readonly stage: RenderFeatureStage;
784
787
  readonly recovery: RenderFeatureRecovery;
785
788
  readonly cleanupFailures?: readonly RenderFeatureCleanupFailure[];
789
+ /** Original stage exception when the feature did not return a RenderError. */
790
+ readonly cause?: unknown;
786
791
  }
787
792
 
788
793
  export interface RenderFeatureCapabilityMissingDetail {
@@ -947,6 +952,7 @@ export class RenderFeatureStageFailedError extends Error {
947
952
  order: number,
948
953
  stage: RenderFeatureStage,
949
954
  recovery: RenderFeatureRecovery,
955
+ cause?: unknown,
950
956
  ) {
951
957
  const expected = `feature '${featureIdentity}' completes its ${stage} stage without an error`;
952
958
  const hint = renderFeatureRecoveryHintByRecovery[recovery](featureIdentity, stage);
@@ -954,7 +960,13 @@ export class RenderFeatureStageFailedError extends Error {
954
960
  this.name = 'RenderFeatureStageFailedError';
955
961
  this.expected = expected;
956
962
  this.hint = hint;
957
- this.detail = { featureIdentity, order, stage, recovery };
963
+ this.detail = {
964
+ featureIdentity,
965
+ order,
966
+ stage,
967
+ recovery,
968
+ ...(cause === undefined ? {} : { cause }),
969
+ };
958
970
  }
959
971
  }
960
972
 
@@ -1381,6 +1393,27 @@ export type DynamicResolutionError =
1381
1393
  | DynamicResolutionRequiresTaaError
1382
1394
  | DynamicResolutionTimingUnavailableError;
1383
1395
 
1396
+ export interface BarrelDistortionInvalidParameterDetail {
1397
+ readonly field: 'width' | 'height' | 'strength' | 'centerX' | 'centerY';
1398
+ readonly value: number;
1399
+ readonly expected: string;
1400
+ }
1401
+
1402
+ export class BarrelDistortionInvalidParameterError extends Error {
1403
+ readonly code = 'barrel-distortion-invalid-parameter' as const;
1404
+ readonly expected: string;
1405
+ readonly hint: string;
1406
+ readonly detail: BarrelDistortionInvalidParameterDetail;
1407
+
1408
+ constructor(detail: BarrelDistortionInvalidParameterDetail) {
1409
+ super(`BarrelDistortion.${detail.field} is invalid`);
1410
+ this.name = 'BarrelDistortionInvalidParameterError';
1411
+ this.expected = `BarrelDistortion.${detail.field} must be ${detail.expected}`;
1412
+ this.hint = `set BarrelDistortion.${detail.field} to a value that is ${detail.expected}`;
1413
+ this.detail = detail;
1414
+ }
1415
+ }
1416
+
1384
1417
  export interface OwnerStageFailedDetail {
1385
1418
  readonly owner: 'environment' | 'temporal' | 'fog' | 'renderer';
1386
1419
  readonly stage: 'extract' | 'prepare' | 'record' | 'finish' | 'submit';
@@ -1828,8 +1861,8 @@ export interface VolumeOwnerConflictDetail {
1828
1861
 
1829
1862
  export class VolumeOwnerConflictError extends Error {
1830
1863
  readonly code = 'volume-owner-conflict' as const;
1831
- readonly expected = 'exactly one global VolumetricFog owner is authored';
1832
- readonly hint = 'remove additional VolumetricFog owners and retry extraction';
1864
+ readonly expected = 'at most eight local VolumetricFog owners per rendered World';
1865
+ readonly hint = 'reduce simultaneously visible volume owners and retry extraction';
1833
1866
  readonly detail: VolumeOwnerConflictDetail;
1834
1867
 
1835
1868
  constructor(ownerCount: number) {
@@ -1883,13 +1916,26 @@ export interface VolumeInvalidParametersDetail {
1883
1916
  export class VolumeInvalidParametersError extends Error {
1884
1917
  readonly code = 'volume-invalid-parameters' as const;
1885
1918
  readonly expected = 'volume parameters remain finite and inside their closed ranges';
1886
- readonly hint = 'repair extinction, albedo, emission, anisotropy, or maxDistance';
1919
+ readonly hint = 'repair extinction, albedo, emission, anisotropy, maxDistance, or sampling';
1887
1920
  readonly detail: VolumeInvalidParametersDetail;
1888
1921
 
1889
- constructor(input: { readonly maxDistance?: number; readonly anisotropy?: number }) {
1890
- const field =
1891
- input.maxDistance !== undefined && input.maxDistance <= 0 ? 'maxDistance' : 'parameters';
1892
- const value = field === 'maxDistance' ? input.maxDistance : input.anisotropy;
1922
+ constructor(input: {
1923
+ readonly maxDistance?: number;
1924
+ readonly anisotropy?: number;
1925
+ readonly sampling?: string;
1926
+ }) {
1927
+ const invalidSampling =
1928
+ input.sampling !== undefined && input.sampling !== 'noise' && input.sampling !== 'density';
1929
+ const field = invalidSampling
1930
+ ? 'sampling'
1931
+ : input.maxDistance !== undefined && input.maxDistance <= 0
1932
+ ? 'maxDistance'
1933
+ : 'parameters';
1934
+ const value = invalidSampling
1935
+ ? input.sampling
1936
+ : field === 'maxDistance'
1937
+ ? input.maxDistance
1938
+ : input.anisotropy;
1893
1939
  super(`volume-invalid-parameters: ${field} is outside the authored range`);
1894
1940
  this.name = 'VolumeInvalidParametersError';
1895
1941
  this.detail = { field, value };
@@ -1966,12 +2012,16 @@ export type RenderError =
1966
2012
  | RenderFeatureDrawRecordingFailedError
1967
2013
  | EnvironmentSourceConflictError
1968
2014
  | FogCardinalityError
2015
+ | SunCardinalityError
1969
2016
  | TaaCapsInsufficientError
1970
2017
  | EnvironmentGenerationFailedError
1971
2018
  | AtmosphereInvalidParameterError
2019
+ | BarrelDistortionInvalidParameterError
2020
+ | CloudLayerError
1972
2021
  | DynamicResolutionInvalidParameterError
1973
2022
  | DynamicResolutionRequiresTaaError
1974
2023
  | DynamicResolutionTimingUnavailableError
2024
+ | MotionBlurValidationError
1975
2025
  | OwnerStageFailedError
1976
2026
  | PointsLinesInvalidStyleError
1977
2027
  | PointsLinesTopologyMismatchError
@@ -0,0 +1,59 @@
1
+ import type { MaterialRootAsset } from '@forgeax/engine-types';
2
+
3
+ /**
4
+ * A public root asset showing the model declaration and its bounded input.
5
+ * The page is shared by every material instance; Render supplies the page
6
+ * bytes and each instance publishes its own range.
7
+ */
8
+ export const SINGLE_LAYER_MEDIUM_SURFACE_EXAMPLE = {
9
+ kind: 'material',
10
+ surface: {
11
+ model: 'single-layer-medium',
12
+ module: 'game::water_surface_a',
13
+ dynamicInput: {
14
+ name: 'waterEvents',
15
+ fields: [
16
+ { name: 'position', type: 'vec3<f32>' },
17
+ { name: 'time', type: 'f32' },
18
+ { name: 'eventId', type: 'u32' },
19
+ ],
20
+ maxRecords: 64,
21
+ maxDomains: 8,
22
+ maxPageBytes: 2048,
23
+ maxBindings: 1,
24
+ maxEventsPerSample: 8,
25
+ },
26
+ },
27
+ passes: [
28
+ {
29
+ name: 'color',
30
+ program: { module: 'forgeax::single-layer-medium' },
31
+ },
32
+ ],
33
+ parameters: [],
34
+ values: {},
35
+ } as const satisfies MaterialRootAsset;
36
+
37
+ /** Two different imported Surface implementations consuming one model ABI. */
38
+ export const SINGLE_LAYER_MEDIUM_SURFACE_EXAMPLES = [
39
+ {
40
+ module: 'game::water_surface_a',
41
+ source: `#define_import_path game::water_surface_a
42
+ #import forgeax_material::single_layer_medium_surface_v1::{SingleLayerMediumSurfaceInput, SingleLayerMediumSurfaceData}
43
+ fn evaluate_surface(input : SingleLayerMediumSurfaceInput) -> SingleLayerMediumSurfaceData {
44
+ let event = read_waterEvents(input.eventRangeStart);
45
+ let normal = normalize(input.geometricNormalWS + vec3<f32>(0.0, 0.0, event.time * 0.02));
46
+ return SingleLayerMediumSurfaceData(normal, 0.18, 1.0, 0.0, vec3<f32>(0.18, 0.06, 0.02), vec3<f32>(0.02, 0.04, 0.08), 1.333, 0.2, 1000.0);
47
+ }`,
48
+ },
49
+ {
50
+ module: 'game::water_surface_b',
51
+ source: `#define_import_path game::water_surface_b
52
+ #import forgeax_material::single_layer_medium_surface_v1::{SingleLayerMediumSurfaceInput, SingleLayerMediumSurfaceData}
53
+ fn evaluate_surface(input : SingleLayerMediumSurfaceInput) -> SingleLayerMediumSurfaceData {
54
+ let event = read_waterEvents(input.eventRangeStart);
55
+ let normal = normalize(input.geometricNormalWS + vec3<f32>(event.position.xy * 0.01, 0.0));
56
+ return SingleLayerMediumSurfaceData(normal, 0.32, 1.0, clamp(event.time * 0.1, 0.0, 1.0), vec3<f32>(0.04, 0.02, 0.01), vec3<f32>(0.08, 0.05, 0.02), 1.333, -0.1, 800.0);
57
+ }`,
58
+ },
59
+ ] as const;
@@ -2,13 +2,17 @@ import type { EntityHandle, World } from '@forgeax/engine-ecs';
2
2
  import { readRenderArrayView } from '@forgeax/engine-ecs/projection';
3
3
  import { mat4, vec3 } from '@forgeax/engine-math';
4
4
  import { GlobalTransform } from '@forgeax/engine-scene';
5
+ import {
6
+ BarrelDistortion,
7
+ validateBarrelDistortionParameters,
8
+ } from '../components/barrel-distortion';
5
9
  import {
6
10
  antialiasFromF32,
7
- bloomEnabledFromF32,
8
11
  Camera,
9
12
  cameraExposureFromColumns,
10
13
  cameraProjectionFromF32,
11
14
  tonemapFromF32,
15
+ validateCameraBloom,
12
16
  validateCameraColorGrading,
13
17
  } from '../components/camera';
14
18
  import { DepthOfField } from '../components/depth-of-field';
@@ -22,6 +26,7 @@ import {
22
26
  depthOfFieldRequestFailure,
23
27
  resolveDepthOfFieldParams,
24
28
  } from '../features/depth-of-field/depth-of-field-params';
29
+ import { resolveMotionBlurParams } from '../features/motion-blur/motion-blur-params';
25
30
  import type { CameraSnapshot } from '../render-contract';
26
31
  import { getActiveCamera, selectActiveCameraIndex } from '../systems/active-camera';
27
32
 
@@ -37,13 +42,23 @@ export function extractCameraSnapshots(world: World): CameraSnapshot[] {
37
42
  const cameraQuery = world
38
43
  .query({
39
44
  read: [Camera],
40
- optional: [MotionBlur, DynamicResolution, ScreenSpaceReflection, DepthOfField],
45
+ optional: [
46
+ MotionBlur,
47
+ DynamicResolution,
48
+ ScreenSpaceReflection,
49
+ DepthOfField,
50
+ BarrelDistortion,
51
+ ],
41
52
  with: [GlobalTransform],
42
53
  })
43
54
  .unwrap();
44
55
  for (const row of cameraQuery) {
45
56
  const cam = row.get(Camera);
46
57
  const motionBlur = row.get(MotionBlur);
58
+ const barrelDistortion = row.get(BarrelDistortion);
59
+ const motionBlurResult = resolveMotionBlurParams(motionBlur);
60
+ if (!motionBlurResult.ok) throw motionBlurResult.error;
61
+ const motionBlurParams = motionBlurResult.value;
47
62
  const depthOfField = row.get(DepthOfField);
48
63
  validateCameraColorGrading(cam.temperature, cam.tint, cam.colorLutStrength);
49
64
  const dynamicResolution = row.get(DynamicResolution);
@@ -58,12 +73,21 @@ export function extractCameraSnapshots(world: World): CameraSnapshot[] {
58
73
  ? undefined
59
74
  : depthOfFieldRequestFailure(depthOfFieldResult.error);
60
75
  const screenSpaceReflection = row.get(ScreenSpaceReflection);
76
+ const bloom = validateCameraBloom(
77
+ cam.bloom,
78
+ cam.bloomThreshold,
79
+ cam.bloomIntensity,
80
+ cam.bloomSoftKnee,
81
+ cam.bloomScatter,
82
+ );
61
83
  const entity = row.entity as EntityHandle;
62
84
  const worldMat = readWorldMatrix(world, entity);
63
85
  if (worldMat === undefined) continue;
64
86
  const antialias = antialiasFromF32(cam.antialias);
65
87
  const dynamicResolutionResult = validateDynamicResolutionCamera(dynamicResolution, antialias);
66
88
  if (!dynamicResolutionResult.ok) throw dynamicResolutionResult.error;
89
+ const barrelDistortionResult = validateBarrelDistortionParameters(barrelDistortion);
90
+ if (!barrelDistortionResult.ok) throw barrelDistortionResult.error;
67
91
  cameras.push({
68
92
  entityKey: entity as number,
69
93
  historyVersion: cam.historyVersion,
@@ -92,10 +116,11 @@ export function extractCameraSnapshots(world: World): CameraSnapshot[] {
92
116
  ...(dynamicResolutionResult.value === undefined
93
117
  ? {}
94
118
  : { dynamicResolution: dynamicResolutionResult.value }),
95
- bloom: bloomEnabledFromF32(cam.bloom),
119
+ bloom,
96
120
  bloomThreshold: cam.bloomThreshold,
97
121
  bloomIntensity: cam.bloomIntensity,
98
- bloomBlurRadius: cam.bloomBlurRadius,
122
+ bloomSoftKnee: cam.bloomSoftKnee,
123
+ bloomScatter: cam.bloomScatter,
99
124
  clearColor: [
100
125
  cam.clearColor[0] ?? 0,
101
126
  cam.clearColor[1] ?? 0,
@@ -106,15 +131,17 @@ export function extractCameraSnapshots(world: World): CameraSnapshot[] {
106
131
  ? { depthOfField: depthOfFieldResult.value }
107
132
  : {}),
108
133
  ...(depthOfFieldError === undefined ? {} : { depthOfFieldError }),
109
- ...(motionBlur === undefined
134
+ ...(motionBlurParams === undefined
110
135
  ? {}
111
136
  : {
112
137
  motionBlur: {
113
- shutterAngle: motionBlur.shutterAngle,
114
- maxRadiusPixels: motionBlur.maxRadiusPixels,
115
- sampleCount: motionBlur.sampleCount,
138
+ shutterAngle: motionBlurParams.shutterAngle,
139
+ maxRadiusPixels: motionBlurParams.maxRadiusPixels,
140
+ sampleCount: motionBlurParams.sampleCount,
141
+ targetFps: motionBlurParams.targetFps,
116
142
  },
117
143
  }),
144
+ ...(barrelDistortion === undefined ? {} : { barrelDistortion: barrelDistortionResult.value }),
118
145
  ...(screenSpaceReflection === undefined
119
146
  ? {}
120
147
  : {