@forgeax/engine-render 0.1.33 → 0.1.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (624) hide show
  1. package/README.md +1062 -127
  2. package/dist/assembly/backend-contract.d.ts +2 -0
  3. package/dist/assembly/backend-contract.d.ts.map +1 -1
  4. package/dist/assembly/barrel-distortion-inspection.d.ts +3 -0
  5. package/dist/assembly/barrel-distortion-inspection.d.ts.map +1 -0
  6. package/dist/assembly/canvas-draw-guard.d.ts +3 -0
  7. package/dist/assembly/canvas-draw-guard.d.ts.map +1 -0
  8. package/dist/assembly/cloud-shadow-entry.d.ts +4 -0
  9. package/dist/assembly/cloud-shadow-entry.d.ts.map +1 -0
  10. package/dist/assembly/device-feature-admission.d.ts +2 -2
  11. package/dist/assembly/dynamic-geometry-host.d.ts +4 -1
  12. package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
  13. package/dist/assembly/dynamic-geometry-runtime.d.ts +1 -1
  14. package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -1
  15. package/dist/assembly/factory.d.ts +1 -1
  16. package/dist/assembly/factory.d.ts.map +1 -1
  17. package/dist/assembly/host-contract.d.ts +6 -5
  18. package/dist/assembly/host-contract.d.ts.map +1 -1
  19. package/dist/assembly/material/assembly.d.ts.map +1 -1
  20. package/dist/assembly/material/pipeline-helpers.d.ts +5 -0
  21. package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -1
  22. package/dist/assembly/material-shader-policy.d.ts +16 -2
  23. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  24. package/dist/assembly/material-shader-prewarm.d.ts.map +1 -1
  25. package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
  26. package/dist/assembly/recovery/renderer-recover.d.ts +2 -0
  27. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  28. package/dist/assembly/render-feature-post-processes.d.ts +6 -0
  29. package/dist/assembly/render-feature-post-processes.d.ts.map +1 -0
  30. package/dist/assembly/render-target-host.d.ts +5 -0
  31. package/dist/assembly/render-target-host.d.ts.map +1 -1
  32. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  33. package/dist/assembly/renderer-feature-inspection.d.ts +1 -1
  34. package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -1
  35. package/dist/assembly/renderer-frame-transaction.d.ts +12 -0
  36. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  37. package/dist/assembly/renderer-inspection.d.ts +11 -0
  38. package/dist/assembly/renderer-inspection.d.ts.map +1 -1
  39. package/dist/assembly/webgpu-pbr-ready.d.ts +1 -0
  40. package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -1
  41. package/dist/assembly/webgpu-ready-per-pass.d.ts +39 -0
  42. package/dist/assembly/webgpu-ready-per-pass.d.ts.map +1 -0
  43. package/dist/assembly/webgpu-ready.d.ts +1 -1
  44. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  45. package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -1
  46. package/dist/assembly/webgpu-renderer-observation-owner.d.ts +35 -0
  47. package/dist/assembly/webgpu-renderer-observation-owner.d.ts.map +1 -0
  48. package/dist/assembly/webgpu-renderer.d.ts +2 -1
  49. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  50. package/dist/authoring.mjs +2 -4
  51. package/dist/authoring.mjs.map +1 -1
  52. package/dist/barrel-distortion.d.ts +47 -0
  53. package/dist/barrel-distortion.d.ts.map +1 -0
  54. package/dist/chunk-3XUBWRY2.mjs +1842 -0
  55. package/dist/chunk-3XUBWRY2.mjs.map +1 -0
  56. package/dist/{chunk-OO3DRYK7.mjs → chunk-G6HDNGY7.mjs} +2400 -1767
  57. package/dist/chunk-G6HDNGY7.mjs.map +1 -0
  58. package/dist/{chunk-ZDQWGQW7.mjs → chunk-LM5IE7GF.mjs} +4 -4
  59. package/dist/{chunk-ZDQWGQW7.mjs.map → chunk-LM5IE7GF.mjs.map} +1 -1
  60. package/dist/{chunk-VOZWDM3L.mjs → chunk-LNIUIKQ7.mjs} +1514 -498
  61. package/dist/chunk-LNIUIKQ7.mjs.map +1 -0
  62. package/dist/chunk-MXTWKZO4.mjs +3268 -0
  63. package/dist/chunk-MXTWKZO4.mjs.map +1 -0
  64. package/dist/chunk-MZ4C7EHF.mjs +6942 -0
  65. package/dist/chunk-MZ4C7EHF.mjs.map +1 -0
  66. package/dist/chunk-RIPAEGI6.mjs +48 -0
  67. package/dist/chunk-RIPAEGI6.mjs.map +1 -0
  68. package/dist/{chunk-LEAXOMYJ.mjs → chunk-SGPUJW3F.mjs} +117 -5
  69. package/dist/chunk-SGPUJW3F.mjs.map +1 -0
  70. package/dist/{chunk-PA5DRJNI.mjs → chunk-X2KA6WHM.mjs} +29 -4
  71. package/dist/chunk-X2KA6WHM.mjs.map +1 -0
  72. package/dist/{chunk-BLXGONR2.mjs → chunk-XSFB7XXQ.mjs} +51 -4
  73. package/dist/chunk-XSFB7XXQ.mjs.map +1 -0
  74. package/dist/cloud/density.d.ts +55 -0
  75. package/dist/cloud/density.d.ts.map +1 -0
  76. package/dist/cloud/extract.d.ts +25 -0
  77. package/dist/cloud/extract.d.ts.map +1 -0
  78. package/dist/cloud/feature.d.ts +57 -0
  79. package/dist/cloud/feature.d.ts.map +1 -0
  80. package/dist/cloud/frame-context.d.ts +8 -0
  81. package/dist/cloud/frame-context.d.ts.map +1 -0
  82. package/dist/cloud/inspection.d.ts +59 -0
  83. package/dist/cloud/inspection.d.ts.map +1 -0
  84. package/dist/cloud/optics.d.ts +56 -0
  85. package/dist/cloud/optics.d.ts.map +1 -0
  86. package/dist/cloud/parameters.d.ts +73 -0
  87. package/dist/cloud/parameters.d.ts.map +1 -0
  88. package/dist/cloud/resources.d.ts +60 -0
  89. package/dist/cloud/resources.d.ts.map +1 -0
  90. package/dist/cloud/shadow.d.ts +42 -0
  91. package/dist/cloud/shadow.d.ts.map +1 -0
  92. package/dist/cloud/temporal.d.ts +74 -0
  93. package/dist/cloud/temporal.d.ts.map +1 -0
  94. package/dist/components/barrel-distortion.d.ts +13 -0
  95. package/dist/components/barrel-distortion.d.ts.map +1 -0
  96. package/dist/components/cloud-layer.d.ts +29 -0
  97. package/dist/components/cloud-layer.d.ts.map +1 -0
  98. package/dist/components/index.d.ts +2 -0
  99. package/dist/components/index.d.ts.map +1 -1
  100. package/dist/components/instances.d.ts +20 -6
  101. package/dist/components/instances.d.ts.map +1 -1
  102. package/dist/construct-renderer.d.ts +1 -1
  103. package/dist/construct-renderer.d.ts.map +1 -1
  104. package/dist/construct-renderer.mjs +8406 -5785
  105. package/dist/construct-renderer.mjs.map +1 -1
  106. package/dist/device/gpu-residency.d.ts +19 -19
  107. package/dist/device/gpu-residency.d.ts.map +1 -1
  108. package/dist/dynamic-geometry.d.ts +5 -1
  109. package/dist/dynamic-geometry.d.ts.map +1 -1
  110. package/dist/errors/cloud.d.ts +59 -0
  111. package/dist/errors/cloud.d.ts.map +1 -0
  112. package/dist/errors/render.d.ts +20 -5
  113. package/dist/errors/render.d.ts.map +1 -1
  114. package/dist/examples/single-layer-medium-surface.d.ts +47 -0
  115. package/dist/examples/single-layer-medium-surface.d.ts.map +1 -0
  116. package/dist/extract/camera.d.ts.map +1 -1
  117. package/dist/extract/contracts.d.ts +5 -1
  118. package/dist/extract/contracts.d.ts.map +1 -1
  119. package/dist/extract/material-context.d.ts +7 -0
  120. package/dist/extract/material-context.d.ts.map +1 -0
  121. package/dist/features/barrel-distortion.d.ts +29 -0
  122. package/dist/features/barrel-distortion.d.ts.map +1 -0
  123. package/dist/features/error-reporting.d.ts +6 -2
  124. package/dist/features/error-reporting.d.ts.map +1 -1
  125. package/dist/features/host.d.ts +15 -0
  126. package/dist/features/host.d.ts.map +1 -1
  127. package/dist/features/plan.d.ts +10 -0
  128. package/dist/features/plan.d.ts.map +1 -1
  129. package/dist/features/render-graph-contribution.d.ts +5 -0
  130. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  131. package/dist/features/render-graph-raster.d.ts +1 -0
  132. package/dist/features/render-graph-raster.d.ts.map +1 -1
  133. package/dist/features/targets.d.ts +2 -0
  134. package/dist/features/targets.d.ts.map +1 -1
  135. package/dist/features/types.d.ts +48 -0
  136. package/dist/features/types.d.ts.map +1 -1
  137. package/dist/fullscreen-post-process-pass.d.ts +15 -7
  138. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  139. package/dist/glyph-text-layout-system.d.ts +1 -1
  140. package/dist/glyph-text-layout-system.d.ts.map +1 -1
  141. package/dist/gpu-dirty-ranges.d.ts +11 -0
  142. package/dist/gpu-dirty-ranges.d.ts.map +1 -0
  143. package/dist/gpu-driven/batch-topology.d.ts +17 -0
  144. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  145. package/dist/gpu-driven/material-artifacts.d.ts +6 -0
  146. package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
  147. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
  148. package/dist/gpu-driven/production-raster-material.d.ts +178 -0
  149. package/dist/gpu-driven/production-raster-material.d.ts.map +1 -0
  150. package/dist/gpu-driven/production-raster.d.ts +47 -3
  151. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  152. package/dist/gpu-driven/resource-allocation.d.ts +31 -0
  153. package/dist/gpu-driven/resource-allocation.d.ts.map +1 -0
  154. package/dist/gpu-driven/shadow-ownership.d.ts +14 -0
  155. package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -0
  156. package/dist/gpu-driven/view-gpu.d.ts +26 -2
  157. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  158. package/dist/gpu-scene.d.ts +5 -0
  159. package/dist/gpu-scene.d.ts.map +1 -1
  160. package/dist/hdrp-buffers.d.ts +2 -2
  161. package/dist/hdrp-buffers.d.ts.map +1 -1
  162. package/dist/ibl/frame-resources.d.ts.map +1 -1
  163. package/dist/ibl/skylight-bind-group.d.ts +14 -5
  164. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  165. package/dist/index.d.ts +30 -7
  166. package/dist/index.d.ts.map +1 -1
  167. package/dist/index.mjs +780 -9
  168. package/dist/index.mjs.map +1 -1
  169. package/dist/inspection-types.d.ts +135 -1
  170. package/dist/inspection-types.d.ts.map +1 -1
  171. package/dist/instance-buffer-cache.d.ts +4 -4
  172. package/dist/instance-buffer-cache.d.ts.map +1 -1
  173. package/dist/instances.d.ts +47 -100
  174. package/dist/instances.d.ts.map +1 -1
  175. package/dist/internal.mjs +7 -8
  176. package/dist/internal.mjs.map +1 -1
  177. package/dist/pbr-pipeline.d.ts +22 -4
  178. package/dist/pbr-pipeline.d.ts.map +1 -1
  179. package/dist/pipeline/single-layer-medium-passes.d.ts +73 -0
  180. package/dist/pipeline/single-layer-medium-passes.d.ts.map +1 -0
  181. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  182. package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
  183. package/dist/pipeline/standard-output/lut-gpu.d.ts +2 -2
  184. package/dist/pipeline/standard-output/lut-gpu.d.ts.map +1 -1
  185. package/dist/pipeline/standard-output/resources.d.ts +2 -2
  186. package/dist/pipeline/standard-output/resources.d.ts.map +1 -1
  187. package/dist/pipeline/standard-output/types.d.ts +4 -2
  188. package/dist/pipeline/standard-output/types.d.ts.map +1 -1
  189. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  190. package/dist/pipeline/standard-post.d.ts.map +1 -1
  191. package/dist/pipeline-builder.d.ts +1 -1
  192. package/dist/pipeline-builder.d.ts.map +1 -1
  193. package/dist/plugin.d.ts.map +1 -1
  194. package/dist/prepare/prepared-graphics-resolver.d.ts +2 -0
  195. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  196. package/dist/publication/contract.d.ts +77 -0
  197. package/dist/publication/contract.d.ts.map +1 -0
  198. package/dist/publication/dependencies.d.ts +7 -0
  199. package/dist/publication/dependencies.d.ts.map +1 -0
  200. package/dist/publication/prepare-geometry.d.ts +9 -0
  201. package/dist/publication/prepare-geometry.d.ts.map +1 -0
  202. package/dist/publication/programs.d.ts +5 -0
  203. package/dist/publication/programs.d.ts.map +1 -0
  204. package/dist/publication/publisher.d.ts +33 -0
  205. package/dist/publication/publisher.d.ts.map +1 -0
  206. package/dist/publication/receiver.d.ts +29 -0
  207. package/dist/publication/receiver.d.ts.map +1 -0
  208. package/dist/publication/resource-scope.d.ts +18 -0
  209. package/dist/publication/resource-scope.d.ts.map +1 -0
  210. package/dist/publication/targets.d.ts +33 -0
  211. package/dist/publication/targets.d.ts.map +1 -0
  212. package/dist/publication/video.d.ts +5 -0
  213. package/dist/publication/video.d.ts.map +1 -0
  214. package/dist/record/barrel-distortion-frame.d.ts +15 -0
  215. package/dist/record/barrel-distortion-frame.d.ts.map +1 -0
  216. package/dist/record/dynamic-geometry-consumption.d.ts +10 -2
  217. package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -1
  218. package/dist/record/fold-buckets.d.ts +95 -0
  219. package/dist/record/fold-buckets.d.ts.map +1 -0
  220. package/dist/record/fold-instance-buffer.d.ts +6 -0
  221. package/dist/record/fold-instance-buffer.d.ts.map +1 -0
  222. package/dist/record/frame-lighting.d.ts +1 -0
  223. package/dist/record/frame-lighting.d.ts.map +1 -1
  224. package/dist/record/frame-snapshot.d.ts +43 -9
  225. package/dist/record/frame-snapshot.d.ts.map +1 -1
  226. package/dist/record/frame.d.ts +15 -65
  227. package/dist/record/frame.d.ts.map +1 -1
  228. package/dist/record/gpu-draw-receipts.d.ts +11 -0
  229. package/dist/record/gpu-draw-receipts.d.ts.map +1 -0
  230. package/dist/record/gpu-timing.d.ts +8 -0
  231. package/dist/record/gpu-timing.d.ts.map +1 -1
  232. package/dist/record/helpers.d.ts +2 -2
  233. package/dist/record/helpers.d.ts.map +1 -1
  234. package/dist/record/main-pass-geometry.d.ts +22 -6
  235. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  236. package/dist/record/main-pass-material.d.ts +14 -10
  237. package/dist/record/main-pass-material.d.ts.map +1 -1
  238. package/dist/record/main-pass-sprite-draws.d.ts +3 -16
  239. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  240. package/dist/record/main-pass.d.ts +13 -2
  241. package/dist/record/main-pass.d.ts.map +1 -1
  242. package/dist/record/motion-blur-receipt.d.ts +11 -0
  243. package/dist/record/motion-blur-receipt.d.ts.map +1 -0
  244. package/dist/record/prepared-material-bindings.d.ts +3 -3
  245. package/dist/record/prepared-material-bindings.d.ts.map +1 -1
  246. package/dist/record/probe-blend-buffer.d.ts +16 -0
  247. package/dist/record/probe-blend-buffer.d.ts.map +1 -0
  248. package/dist/record/recovery-pipeline.d.ts.map +1 -1
  249. package/dist/record/render-context.d.ts +24 -5
  250. package/dist/record/render-context.d.ts.map +1 -1
  251. package/dist/record/shadow-pass.d.ts +2 -0
  252. package/dist/record/shadow-pass.d.ts.map +1 -1
  253. package/dist/record/skybox-post-pass.d.ts +1 -1
  254. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  255. package/dist/record/sprite-instance-buffer.d.ts +31 -0
  256. package/dist/record/sprite-instance-buffer.d.ts.map +1 -0
  257. package/dist/record/target-capture-graph.d.ts +19 -0
  258. package/dist/record/target-capture-graph.d.ts.map +1 -0
  259. package/dist/record/typed-frame-graph.d.ts +24 -15
  260. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  261. package/dist/record/view-ubo.d.ts +11 -3
  262. package/dist/record/view-ubo.d.ts.map +1 -1
  263. package/dist/record/volume-params.d.ts +9 -0
  264. package/dist/record/volume-params.d.ts.map +1 -0
  265. package/dist/recovery/render-system-candidate.d.ts +14 -4
  266. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  267. package/dist/reflection/record-owner.d.ts.map +1 -1
  268. package/dist/render-contract.d.ts +46 -5
  269. package/dist/render-contract.d.ts.map +1 -1
  270. package/dist/render-graph-primitives.d.ts.map +1 -1
  271. package/dist/render-pipeline.d.ts +103 -2
  272. package/dist/render-pipeline.d.ts.map +1 -1
  273. package/dist/render-system-extract-tail.d.ts +3 -2
  274. package/dist/render-system-extract-tail.d.ts.map +1 -1
  275. package/dist/render-system-extract.d.ts +18 -9
  276. package/dist/render-system-extract.d.ts.map +1 -1
  277. package/dist/render-system-presentation.d.ts +23 -0
  278. package/dist/render-system-presentation.d.ts.map +1 -0
  279. package/dist/render-system-producer-roots.d.ts +10 -0
  280. package/dist/render-system-producer-roots.d.ts.map +1 -0
  281. package/dist/render-system-projections.d.ts +3 -2
  282. package/dist/render-system-projections.d.ts.map +1 -1
  283. package/dist/render-system-residency.d.ts +12 -0
  284. package/dist/render-system-residency.d.ts.map +1 -0
  285. package/dist/render-system.d.ts +22 -21
  286. package/dist/render-system.d.ts.map +1 -1
  287. package/dist/scene/probe-blend.d.ts +27 -0
  288. package/dist/scene/probe-blend.d.ts.map +1 -1
  289. package/dist/scene/render-scene.d.ts +18 -7
  290. package/dist/scene/render-scene.d.ts.map +1 -1
  291. package/dist/scene/render-source.d.ts +42 -0
  292. package/dist/scene/render-source.d.ts.map +1 -0
  293. package/dist/scene/source-systems.d.ts +6 -0
  294. package/dist/scene/source-systems.d.ts.map +1 -0
  295. package/dist/ssao-buffers.d.ts +9 -0
  296. package/dist/ssao-buffers.d.ts.map +1 -1
  297. package/dist/surface/dynamic-input.d.ts +133 -0
  298. package/dist/surface/dynamic-input.d.ts.map +1 -0
  299. package/dist/surface/gpu-driven.d.ts +41 -0
  300. package/dist/surface/gpu-driven.d.ts.map +1 -0
  301. package/dist/surface/submission-observation.d.ts +136 -0
  302. package/dist/surface/submission-observation.d.ts.map +1 -0
  303. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  304. package/dist/systems/skin-palette-types.d.ts +10 -0
  305. package/dist/systems/skin-palette-types.d.ts.map +1 -1
  306. package/dist/systems/transparent-dispatch.d.ts +2 -2
  307. package/dist/systems/transparent-dispatch.d.ts.map +1 -1
  308. package/dist/systems/transparent-sort-config.d.ts +2 -1
  309. package/dist/systems/transparent-sort-config.d.ts.map +1 -1
  310. package/dist/temporal/gpu.d.ts +13 -1
  311. package/dist/temporal/gpu.d.ts.map +1 -1
  312. package/dist/temporal/index.mjs +6 -7
  313. package/dist/temporal/inspection.d.ts.map +1 -1
  314. package/dist/temporal/standard-scene-data.d.ts.map +1 -1
  315. package/dist/temporal/target-coverage-attachment.d.ts.map +1 -1
  316. package/dist/transmission/single-layer-medium.d.ts +89 -0
  317. package/dist/transmission/single-layer-medium.d.ts.map +1 -0
  318. package/dist/typed-render-graph-primitives.d.ts +14 -2
  319. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  320. package/dist/volume/component.d.ts +9 -4
  321. package/dist/volume/component.d.ts.map +1 -1
  322. package/dist/volume/extract.d.ts +1 -1
  323. package/dist/volume/extract.d.ts.map +1 -1
  324. package/dist/volume/inspection.d.ts +2 -0
  325. package/dist/volume/inspection.d.ts.map +1 -1
  326. package/dist/volume/passes.d.ts +4 -1
  327. package/dist/volume/passes.d.ts.map +1 -1
  328. package/dist/volume/resources.d.ts.map +1 -1
  329. package/package.json +22 -21
  330. package/src/__tests__/atmosphere-daylight.dawn.test.ts +72 -0
  331. package/src/__tests__/auto-exposure-transaction.integration.test.ts +4 -9
  332. package/src/__tests__/barrel-distortion-lkg.integration.test.ts +353 -0
  333. package/src/__tests__/barrel-distortion.dawn.test.ts +41 -0
  334. package/src/__tests__/barrel-distortion.unit.test.ts +364 -0
  335. package/src/__tests__/construct-renderer-identity.unit.test.ts +49 -0
  336. package/src/__tests__/detached-recovery-graph.unit.test.ts +277 -0
  337. package/src/__tests__/device-feature-admission.unit.test.ts +3 -2
  338. package/src/__tests__/device-loss-fanout.unit.test.ts +36 -1
  339. package/src/__tests__/docs-gate-green.unit.test.ts +112 -1
  340. package/src/__tests__/factory-contract.integration.test.ts +295 -45
  341. package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
  342. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +14 -3
  343. package/src/__tests__/gpu-dirty-ranges.unit.test.ts +22 -0
  344. package/src/__tests__/gpu-driven-baseline.characterization.test.ts +16 -3
  345. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +12 -0
  346. package/src/__tests__/gpu-driven-material-artifacts.unit.test.ts +143 -0
  347. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +5 -6
  348. package/src/__tests__/gpu-driven-production.integration.test.ts +482 -3
  349. package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +6 -5
  350. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +94 -6
  351. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +18 -2
  352. package/src/__tests__/gpu-driven-view.browser.test.ts +5 -8
  353. package/src/__tests__/gpu-driven-view.dawn.test.ts +6 -2
  354. package/src/__tests__/gpu-driven-view.unit.test.ts +1 -1
  355. package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +1 -0
  356. package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -4
  357. package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +1 -0
  358. package/src/__tests__/gpu-scene.unit.test.ts +119 -9
  359. package/src/__tests__/instance-allocation-failure.unit.test.ts +57 -0
  360. package/src/__tests__/instances-culling.integration.test.ts +10 -36
  361. package/src/__tests__/instances-store.unit.test.ts +97 -305
  362. package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
  363. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +4 -1
  364. package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +145 -0
  365. package/src/__tests__/material-shader-prewarm.unit.test.ts +59 -0
  366. package/src/__tests__/material-snapshot-mutation.integration.test.ts +39 -1
  367. package/src/__tests__/materials-standard-contract.unit.test.ts +0 -1
  368. package/src/__tests__/morph-culling-reentry.dawn.test.ts +5 -5
  369. package/src/__tests__/morph-visual-evidence.integration.test.ts +8 -7
  370. package/src/__tests__/motion-blur-compute.dawn.test.ts +13 -7
  371. package/src/__tests__/motion-blur.pixel.integration.test.ts +2 -2
  372. package/src/__tests__/nineslice-handle-surface.unit.test.ts +4 -4
  373. package/src/__tests__/pbr-view-layout.unit.test.ts +9 -0
  374. package/src/__tests__/physical-clearcoat.integration.test.ts +66 -8
  375. package/src/__tests__/physical-material-budget.unit.test.ts +40 -0
  376. package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
  377. package/src/__tests__/probe-bindings.unit.test.ts +582 -1
  378. package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
  379. package/src/__tests__/receipt-observation-retirement.unit.test.ts +65 -0
  380. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +69 -0
  381. package/src/__tests__/render-error-code-owner.test-d.ts +8 -0
  382. package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
  383. package/src/__tests__/render-feature-error-reporting.unit.test.ts +21 -1
  384. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +10 -1
  385. package/src/__tests__/render-feature-retry.unit.test.ts +12 -1
  386. package/src/__tests__/render-scene-mixed-updates.integration.test.ts +145 -19
  387. package/src/__tests__/render-scene-projection.unit.test.ts +36 -11
  388. package/src/__tests__/render-scene-temporal-retry.unit.test.ts +20 -20
  389. package/src/__tests__/render-target-probe-soak.perf.test.ts +2 -2
  390. package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +3 -3
  391. package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +5 -2
  392. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +42 -8
  393. package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +16 -0
  394. package/src/__tests__/renderer-frame-transaction.integration.test.ts +26 -10
  395. package/src/__tests__/resource-allocation.unit.test.ts +123 -0
  396. package/src/__tests__/single-layer-medium-passes.unit.test.ts +275 -0
  397. package/src/__tests__/skin-motion-regression.unit.test.ts +70 -1
  398. package/src/__tests__/skin-palette-recycling.dawn.test.ts +97 -0
  399. package/src/__tests__/skinned-shadow-caster.test.ts +15 -0
  400. package/src/__tests__/ssr-carrier-public-contract.unit.test.ts +21 -0
  401. package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +4 -4
  402. package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +2 -2
  403. package/src/__tests__/ssr-gpu-dispatch.ts +1 -1
  404. package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +6 -2
  405. package/src/__tests__/standard-output-chain-contract.unit.test.ts +28 -0
  406. package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +46 -1
  407. package/src/__tests__/standard-pipeline.integration.test.ts +182 -1
  408. package/src/__tests__/surface-dynamic-buffer-lifecycle.unit.test.ts +506 -0
  409. package/src/__tests__/surface-submission-observation.unit.test.ts +812 -0
  410. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +32 -0
  411. package/src/__tests__/temporal-performance.integration.test.ts +3 -3
  412. package/src/__tests__/visibility-instances.integration.test.ts +7 -19
  413. package/src/__tests__/visibility-producer-matrix.integration.test.ts +9 -20
  414. package/src/__tests__/volume-optics-oracle.unit.test.ts +4 -2
  415. package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +30 -20
  416. package/src/__tests__/volumetric-fog-errors.unit.test.ts +4 -3
  417. package/src/__tests__/volumetric-fog-multiple.unit.test.ts +55 -0
  418. package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +1 -1
  419. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +113 -9
  420. package/src/__tests__/volumetric-fog-topology.unit.test.ts +5 -3
  421. package/src/assembly/backend-contract.ts +30 -0
  422. package/src/assembly/barrel-distortion-inspection.ts +22 -0
  423. package/src/assembly/canvas-draw-guard.ts +11 -0
  424. package/src/assembly/cloud-shadow-entry.ts +22 -0
  425. package/src/assembly/device-feature-admission.ts +2 -2
  426. package/src/assembly/dynamic-geometry-host.ts +65 -37
  427. package/src/assembly/dynamic-geometry-runtime.ts +7 -1
  428. package/src/assembly/factory.ts +2 -30
  429. package/src/assembly/host-contract.ts +8 -5
  430. package/src/assembly/material/assembly.ts +25 -13
  431. package/src/assembly/material/pipeline-helpers.ts +53 -12
  432. package/src/assembly/material-shader-policy.ts +55 -0
  433. package/src/assembly/material-shader-prewarm.ts +21 -10
  434. package/src/assembly/recovery/device-loss-fanout.ts +13 -0
  435. package/src/assembly/recovery/renderer-recover.ts +50 -18
  436. package/src/assembly/render-feature-post-processes.ts +54 -0
  437. package/src/assembly/render-target-host.ts +57 -47
  438. package/src/assembly/renderer-facade.ts +7 -2
  439. package/src/assembly/renderer-feature-inspection.ts +8 -2
  440. package/src/assembly/renderer-frame-transaction.ts +23 -0
  441. package/src/assembly/renderer-inspection.ts +28 -0
  442. package/src/assembly/skin-palette-owner.ts +1 -1
  443. package/src/assembly/temporal-post-process-prewarm.ts +3 -3
  444. package/src/assembly/webgpu-pbr-ready.ts +9 -1
  445. package/src/assembly/webgpu-ready-per-pass.ts +104 -0
  446. package/src/assembly/webgpu-ready.ts +116 -62
  447. package/src/assembly/webgpu-renderer-bootstrap.ts +0 -12
  448. package/src/assembly/webgpu-renderer-observation-owner.ts +222 -0
  449. package/src/assembly/webgpu-renderer.ts +303 -313
  450. package/src/assembly/webgpu-vertex-layouts.ts +1 -1
  451. package/src/barrel-distortion.ts +247 -0
  452. package/src/cloud/__tests__/cloud-density-parity.dawn.test.ts +173 -0
  453. package/src/cloud/__tests__/cloud-layer-framebuffer-y.dawn.test.ts +265 -0
  454. package/src/cloud/__tests__/cloud-layer.browser.test.ts +432 -0
  455. package/src/cloud/__tests__/cloud-layer.unit.test.ts +634 -0
  456. package/src/cloud/density.ts +600 -0
  457. package/src/cloud/extract.ts +110 -0
  458. package/src/cloud/feature.ts +1810 -0
  459. package/src/cloud/frame-context.ts +42 -0
  460. package/src/cloud/inspection.ts +130 -0
  461. package/src/cloud/optics.ts +285 -0
  462. package/src/cloud/parameters.ts +255 -0
  463. package/src/cloud/resources.ts +122 -0
  464. package/src/cloud/shadow.ts +167 -0
  465. package/src/cloud/temporal.ts +226 -0
  466. package/src/components/barrel-distortion.ts +46 -0
  467. package/src/components/cloud-layer.ts +47 -0
  468. package/src/components/index.ts +2 -0
  469. package/src/components/instances.ts +18 -45
  470. package/src/components/sprite-instances.ts +1 -1
  471. package/src/construct-renderer.ts +1 -1
  472. package/src/device/gpu-residency.ts +26 -25
  473. package/src/dynamic-geometry.ts +12 -1
  474. package/src/errors/cloud.ts +103 -0
  475. package/src/errors/render.ts +47 -8
  476. package/src/examples/single-layer-medium-surface.ts +59 -0
  477. package/src/extract/camera.ts +15 -1
  478. package/src/extract/contracts.ts +5 -0
  479. package/src/extract/material-context.ts +21 -0
  480. package/src/features/barrel-distortion.ts +172 -0
  481. package/src/features/error-reporting.ts +26 -6
  482. package/src/features/host.ts +128 -19
  483. package/src/features/plan.ts +10 -0
  484. package/src/features/render-graph-contribution.ts +9 -0
  485. package/src/features/render-graph-raster.ts +45 -3
  486. package/src/features/targets.ts +66 -0
  487. package/src/features/types.ts +51 -0
  488. package/src/fullscreen-post-process-pass.ts +41 -9
  489. package/src/glyph-text-layout-system.ts +2 -2
  490. package/src/gpu-dirty-ranges.ts +48 -0
  491. package/src/gpu-driven/batch-topology.ts +53 -0
  492. package/src/gpu-driven/material-artifacts.ts +33 -25
  493. package/src/gpu-driven/prepared-draw.ts +12 -4
  494. package/src/gpu-driven/production-raster-material.ts +1894 -0
  495. package/src/gpu-driven/production-raster.ts +825 -784
  496. package/src/gpu-driven/resource-allocation.ts +142 -0
  497. package/src/gpu-driven/shadow-ownership.ts +71 -0
  498. package/src/gpu-driven/view-gpu.ts +164 -10
  499. package/src/gpu-scene.ts +75 -84
  500. package/src/hdrp-buffers.ts +4 -3
  501. package/src/ibl/frame-resources.ts +0 -1
  502. package/src/ibl/skylight-bind-group.ts +62 -32
  503. package/src/index.ts +205 -9
  504. package/src/inspection-types.ts +162 -0
  505. package/src/instance-buffer-cache.ts +4 -4
  506. package/src/instances.ts +152 -569
  507. package/src/pbr-pipeline.ts +230 -30
  508. package/src/pipeline/single-layer-medium-passes.ts +267 -0
  509. package/src/pipeline/standard-forward-lane.ts +313 -57
  510. package/src/pipeline/standard-output/graph.ts +8 -2
  511. package/src/pipeline/standard-output/lut-gpu.ts +3 -3
  512. package/src/pipeline/standard-output/resources.ts +2 -2
  513. package/src/pipeline/standard-output/types.ts +12 -1
  514. package/src/pipeline/standard-pipeline.ts +291 -18
  515. package/src/pipeline/standard-post.ts +90 -24
  516. package/src/pipeline-builder.ts +1 -1
  517. package/src/plugin.ts +4 -0
  518. package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
  519. package/src/prepare/prepared-graphics-resolver.ts +2 -0
  520. package/src/publication/__tests__/derived-geometry.integration.test.ts +177 -0
  521. package/src/publication/__tests__/features.integration.test.ts +122 -0
  522. package/src/publication/__tests__/programs.unit.test.ts +25 -0
  523. package/src/publication/__tests__/publication.integration.test.ts +370 -0
  524. package/src/publication/__tests__/targets.integration.test.ts +120 -0
  525. package/src/publication/__tests__/video.browser.test.ts +50 -0
  526. package/src/publication/contract.ts +104 -0
  527. package/src/publication/dependencies.ts +54 -0
  528. package/src/publication/prepare-geometry.ts +94 -0
  529. package/src/publication/programs.ts +45 -0
  530. package/src/publication/publisher.ts +618 -0
  531. package/src/publication/receiver.ts +297 -0
  532. package/src/publication/resource-scope.ts +31 -0
  533. package/src/publication/targets.ts +182 -0
  534. package/src/publication/video.ts +33 -0
  535. package/src/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
  536. package/src/record/__tests__/material-bg-cache.unit.test.ts +15 -1
  537. package/src/record/__tests__/sprite-material-abi.unit.test.ts +9 -11
  538. package/src/record/__tests__/temporal-payload.unit.test.ts +1 -1
  539. package/src/record/__tests__/transparent-group2-selection.unit.test.ts +11 -0
  540. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -0
  541. package/src/record/__tests__/video-texture-view.unit.test.ts +9 -9
  542. package/src/record/__tests__/view-ubo-layout.unit.test.ts +4 -3
  543. package/src/record/barrel-distortion-frame.ts +110 -0
  544. package/src/record/dynamic-geometry-consumption.ts +39 -9
  545. package/src/record/fold-buckets.ts +855 -0
  546. package/src/record/fold-instance-buffer.ts +51 -0
  547. package/src/record/frame-lighting.ts +36 -2
  548. package/src/record/frame-snapshot.ts +45 -9
  549. package/src/record/frame.ts +258 -1105
  550. package/src/record/gpu-draw-receipts.ts +38 -0
  551. package/src/record/gpu-timing.ts +48 -5
  552. package/src/record/helpers.ts +2 -2
  553. package/src/record/main-pass-geometry.ts +272 -84
  554. package/src/record/main-pass-material.ts +102 -36
  555. package/src/record/main-pass-sprite-draws.ts +13 -217
  556. package/src/record/main-pass.ts +164 -27
  557. package/src/record/motion-blur-receipt.ts +91 -0
  558. package/src/record/prepared-material-bindings.ts +11 -6
  559. package/src/record/probe-blend-buffer.ts +180 -0
  560. package/src/record/recovery-pipeline.ts +35 -3
  561. package/src/record/render-context.ts +41 -5
  562. package/src/record/shadow-pass.ts +30 -4
  563. package/src/record/skybox-post-pass.ts +28 -4
  564. package/src/record/sprite-instance-buffer.ts +155 -0
  565. package/src/record/target-capture-graph.ts +258 -0
  566. package/src/record/typed-frame-graph.ts +776 -340
  567. package/src/record/view-ubo.ts +27 -4
  568. package/src/record/volume-params.ts +225 -0
  569. package/src/recovery/render-system-candidate.ts +243 -50
  570. package/src/reflection/record-owner.ts +7 -3
  571. package/src/render-contract.ts +54 -5
  572. package/src/render-graph-primitives.ts +7 -1
  573. package/src/render-pipeline.ts +130 -0
  574. package/src/render-system-extract-tail.ts +90 -78
  575. package/src/render-system-extract.ts +76 -76
  576. package/src/render-system-presentation.ts +56 -0
  577. package/src/render-system-producer-roots.ts +96 -0
  578. package/src/render-system-projections.ts +3 -2
  579. package/src/render-system-residency.ts +159 -0
  580. package/src/render-system.ts +421 -408
  581. package/src/scene/probe-blend.ts +96 -4
  582. package/src/scene/render-scene.ts +416 -337
  583. package/src/scene/render-source.ts +90 -0
  584. package/src/scene/source-systems.ts +33 -0
  585. package/src/ssao-buffers.ts +95 -2
  586. package/src/surface/__tests__/dynamic-input.unit.test.ts +374 -0
  587. package/src/surface/__tests__/gpu-driven.unit.test.ts +87 -0
  588. package/src/surface/dynamic-input.ts +658 -0
  589. package/src/surface/gpu-driven.ts +147 -0
  590. package/src/surface/submission-observation.ts +517 -0
  591. package/src/systems/skin-palette-allocator.ts +5 -1
  592. package/src/systems/skin-palette-types.ts +11 -0
  593. package/src/systems/transparent-dispatch.ts +2 -2
  594. package/src/systems/transparent-sort-config.ts +3 -1
  595. package/src/temporal/gpu.ts +101 -17
  596. package/src/temporal/inspection.ts +7 -1
  597. package/src/temporal/standard-scene-data.ts +5 -0
  598. package/src/temporal/target-coverage-attachment.ts +4 -0
  599. package/src/transmission/__tests__/single-layer-medium.unit.test.ts +149 -0
  600. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +12 -11
  601. package/src/transmission/single-layer-medium.ts +322 -0
  602. package/src/typed-render-graph-primitives.ts +70 -2
  603. package/src/volume/component.ts +10 -9
  604. package/src/volume/extract.ts +11 -5
  605. package/src/volume/inspection.ts +3 -0
  606. package/src/volume/passes.ts +87 -4
  607. package/src/volume/resources.ts +2 -1
  608. package/dist/chunk-3RTCJTH4.mjs +0 -1610
  609. package/dist/chunk-3RTCJTH4.mjs.map +0 -1
  610. package/dist/chunk-BLXGONR2.mjs.map +0 -1
  611. package/dist/chunk-ILQ5MEZF.mjs +0 -32
  612. package/dist/chunk-ILQ5MEZF.mjs.map +0 -1
  613. package/dist/chunk-LEAXOMYJ.mjs.map +0 -1
  614. package/dist/chunk-NB2S7ZRX.mjs +0 -1783
  615. package/dist/chunk-NB2S7ZRX.mjs.map +0 -1
  616. package/dist/chunk-NNQL7CB3.mjs +0 -1713
  617. package/dist/chunk-NNQL7CB3.mjs.map +0 -1
  618. package/dist/chunk-OO3DRYK7.mjs.map +0 -1
  619. package/dist/chunk-PA5DRJNI.mjs.map +0 -1
  620. package/dist/chunk-PLAXOOX5.mjs +0 -1907
  621. package/dist/chunk-PLAXOOX5.mjs.map +0 -1
  622. package/dist/chunk-RXZ3RGOU.mjs +0 -53
  623. package/dist/chunk-RXZ3RGOU.mjs.map +0 -1
  624. package/dist/chunk-VOZWDM3L.mjs.map +0 -1
@@ -1,1907 +0,0 @@
1
- import { RenderIntentInvalidError, DynamicResolutionRequiresTaaError, ShadowInvalidConfigError, EnvironmentSourceConflictError, FogCardinalityError, VolumeOwnerConflictError, VolumeDensityShapeMismatchError, VolumeInvalidBoundsError, VolumeInvalidParametersError, DynamicResolutionInvalidParameterError, AtmosphereInvalidParameterError } from './chunk-NB2S7ZRX.mjs';
2
- import { defineComponent, Entity } from '@forgeax/engine-ecs';
3
- import { TONEMAP_SHADER_MODE } from '@forgeax/engine-shader';
4
- import { R_MIN, err, ok } from '@forgeax/engine-types';
5
- import { SpawnLightInvalidBoundsError } from '@forgeax/engine-ecs/projection';
6
- import { Transform, projectHierarchy } from '@forgeax/engine-scene';
7
- import { mat4 } from '@forgeax/engine-math';
8
-
9
- var Atmosphere = defineComponent("Atmosphere", {
10
- turbidity: { type: "f32", default: 2 },
11
- rayleigh: { type: "f32", default: 1 },
12
- mieCoefficient: { type: "f32", default: 5e-3 },
13
- mieDirectionalG: { type: "f32", default: 0.8 },
14
- sunAngularRadius: { type: "f32", default: 4675e-6 },
15
- /** Independent multiplier for the analytic circumsolar lobe. */
16
- circumsolarStrength: { type: "f32", default: 1 },
17
- /** Relative angular width of the analytic circumsolar lobe. */
18
- circumsolarWidth: { type: "f32", default: 1 }
19
- });
20
- var CAMERA_PROJECTION_PERSPECTIVE = 0;
21
- var CAMERA_PROJECTION_ORTHOGRAPHIC = 1;
22
- var CAMERA_EXPOSURE_MODE_MANUAL = 0;
23
- var CAMERA_EXPOSURE_MODE_AUTO = 1;
24
- var CAMERA_TEMPERATURE_MIN = 1e3;
25
- var CAMERA_TEMPERATURE_MAX = 4e4;
26
- var CAMERA_TINT_MIN = -1;
27
- var CAMERA_TINT_MAX = 1;
28
- var CameraError = class extends Error {
29
- code;
30
- expected;
31
- hint;
32
- detail;
33
- constructor(code, field, actual, expected, hint) {
34
- super(`${code}: ${field}=${String(actual)}; expected ${expected}`);
35
- this.name = "CameraError";
36
- this.code = code;
37
- this.expected = expected;
38
- this.hint = hint;
39
- this.detail = Object.freeze({ field, actual, expected });
40
- }
41
- };
42
- function actualValue(value) {
43
- if (typeof value === "number" || typeof value === "string") return value;
44
- try {
45
- return JSON.stringify(value) ?? String(value);
46
- } catch {
47
- return String(value);
48
- }
49
- }
50
- function cameraError(code, field, actual, expected, hint) {
51
- return new CameraError(code, field, actualValue(actual), expected, hint);
52
- }
53
- function finitePositive(value) {
54
- return Number.isFinite(value) && value > 0;
55
- }
56
- function validateCameraExposure(exposure) {
57
- if (typeof exposure !== "object" || exposure === null) {
58
- throw cameraError(
59
- "camera-exposure-invalid",
60
- "value",
61
- exposure,
62
- "an object with kind manual or auto",
63
- "choose one member of the CameraExposure union"
64
- );
65
- }
66
- if (exposure.kind === "manual") {
67
- if (!finitePositive(exposure.multiplier)) {
68
- throw cameraError(
69
- "camera-exposure-invalid",
70
- "multiplier",
71
- exposure.multiplier,
72
- "a finite number greater than zero",
73
- "set Camera.exposure to a positive finite manual multiplier"
74
- );
75
- }
76
- return exposure;
77
- }
78
- if (exposure.kind === "auto") {
79
- const [min, max] = exposure.rangeEv;
80
- const [up, down] = exposure.rates;
81
- if (!finitePositive(exposure.fallback) || !Number.isFinite(exposure.compensationEv) || !Number.isFinite(min) || !Number.isFinite(max) || min > max || !Number.isFinite(up) || !Number.isFinite(down) || up < 0 || down < 0) {
82
- throw cameraError(
83
- "camera-exposure-invalid",
84
- "auto",
85
- JSON.stringify(exposure),
86
- "finite fallback/compensation, an ordered range, and non-negative rates",
87
- "inspect fallback, compensationEv, rangeEv, and rates before rebuilding the camera"
88
- );
89
- }
90
- return exposure;
91
- }
92
- throw cameraError(
93
- "camera-exposure-invalid",
94
- "kind",
95
- exposure.kind,
96
- "'manual' or 'auto'",
97
- "choose one member of the CameraExposure union"
98
- );
99
- }
100
- function validateCameraColorGrading(temperature, tint, colorLutStrength) {
101
- if (!Number.isFinite(temperature) || temperature < CAMERA_TEMPERATURE_MIN || temperature > CAMERA_TEMPERATURE_MAX) {
102
- throw cameraError(
103
- "camera-color-grading-invalid",
104
- "temperature",
105
- temperature,
106
- `a finite value in [${CAMERA_TEMPERATURE_MIN}, ${CAMERA_TEMPERATURE_MAX}]`,
107
- "set Camera.temperature to a supported Kelvin value"
108
- );
109
- }
110
- if (!Number.isFinite(tint) || tint < CAMERA_TINT_MIN || tint > CAMERA_TINT_MAX) {
111
- throw cameraError(
112
- "camera-color-grading-invalid",
113
- "tint",
114
- tint,
115
- `a finite value in [${CAMERA_TINT_MIN}, ${CAMERA_TINT_MAX}]`,
116
- "set Camera.tint to a normalized value between -1 and 1"
117
- );
118
- }
119
- if (!Number.isFinite(colorLutStrength) || colorLutStrength < 0 || colorLutStrength > 1) {
120
- throw cameraError(
121
- "camera-color-grading-invalid",
122
- "colorLutStrength",
123
- colorLutStrength,
124
- "a finite value in [0, 1]",
125
- "set Camera.colorLutStrength to zero to disable the LUT or a blend in [0, 1]"
126
- );
127
- }
128
- }
129
- function cameraProjectionFromF32(value) {
130
- return value === CAMERA_PROJECTION_ORTHOGRAPHIC ? "orthographic" : "perspective";
131
- }
132
- var TONEMAP_NONE = TONEMAP_SHADER_MODE.none;
133
- var TONEMAP_REINHARD_EXTENDED = TONEMAP_SHADER_MODE.reinhardExtended;
134
- var TONEMAP_REINHARD = TONEMAP_SHADER_MODE.reinhard;
135
- var TONEMAP_LINEAR = TONEMAP_SHADER_MODE.linear;
136
- var TONEMAP_CINEON = TONEMAP_SHADER_MODE.cineon;
137
- var TONEMAP_ACES_FILMIC = TONEMAP_SHADER_MODE.acesFilmic;
138
- var TONEMAP_AGX = TONEMAP_SHADER_MODE.agx;
139
- var TONEMAP_NEUTRAL = TONEMAP_SHADER_MODE.neutral;
140
- function tonemapFromF32(value) {
141
- switch (value) {
142
- case TONEMAP_REINHARD_EXTENDED:
143
- return "reinhard-extended";
144
- case TONEMAP_REINHARD:
145
- return "reinhard";
146
- case TONEMAP_LINEAR:
147
- return "linear";
148
- case TONEMAP_CINEON:
149
- return "cineon";
150
- case TONEMAP_ACES_FILMIC:
151
- return "aces-filmic";
152
- case TONEMAP_AGX:
153
- return "agx";
154
- case TONEMAP_NEUTRAL:
155
- return "neutral";
156
- default:
157
- return "none";
158
- }
159
- }
160
- function tonemapToU32(mode) {
161
- switch (mode) {
162
- case "reinhard-extended":
163
- return TONEMAP_REINHARD_EXTENDED;
164
- case "reinhard":
165
- return TONEMAP_REINHARD;
166
- case "linear":
167
- return TONEMAP_LINEAR;
168
- case "cineon":
169
- return TONEMAP_CINEON;
170
- case "aces-filmic":
171
- return TONEMAP_ACES_FILMIC;
172
- case "agx":
173
- return TONEMAP_AGX;
174
- case "neutral":
175
- return TONEMAP_NEUTRAL;
176
- case "none":
177
- return TONEMAP_NONE;
178
- }
179
- throw cameraError(
180
- "camera-tonemap-invalid",
181
- "tonemap",
182
- mode,
183
- "one of the closed Tonemap values",
184
- "select a supported Camera tonemap mode"
185
- );
186
- }
187
- var ANTIALIAS_NONE = 0;
188
- var ANTIALIAS_FXAA = 1;
189
- var ANTIALIAS_MSAA = 2;
190
- var ANTIALIAS_TAA = 3;
191
- function antialiasFromF32(value) {
192
- if (value === ANTIALIAS_NONE) return "none";
193
- if (value === ANTIALIAS_FXAA) return "fxaa";
194
- if (value === ANTIALIAS_MSAA) return "msaa";
195
- if (value === ANTIALIAS_TAA) return "taa";
196
- throw cameraError(
197
- "camera-antialias-invalid",
198
- "antialias",
199
- value,
200
- `${ANTIALIAS_NONE}, ${ANTIALIAS_FXAA}, ${ANTIALIAS_MSAA}, or ${ANTIALIAS_TAA}`,
201
- "select a supported Camera antialias mode"
202
- );
203
- }
204
- var BLOOM_DISABLED = 0;
205
- var BLOOM_ENABLED = 1;
206
- var CAMERA_BLOOM_INTENSITY_MIN = 0;
207
- var CAMERA_BLOOM_INTENSITY_MAX = 8;
208
- var CAMERA_BLOOM_THRESHOLD_MIN = 0;
209
- var CAMERA_BLOOM_THRESHOLD_MAX = 65504;
210
- var CAMERA_BLOOM_SOFT_KNEE_MIN = 0;
211
- var CAMERA_BLOOM_SOFT_KNEE_MAX = 1;
212
- var CAMERA_BLOOM_SCATTER_MIN = 0;
213
- var CAMERA_BLOOM_SCATTER_MAX = 0.95;
214
- function bloomEnabledFromF32(value) {
215
- if (value === BLOOM_DISABLED) return "off";
216
- if (value === BLOOM_ENABLED) return "on";
217
- throw cameraError(
218
- "camera-bloom-invalid",
219
- "bloom",
220
- value,
221
- `${BLOOM_DISABLED} or ${BLOOM_ENABLED}`,
222
- "select Camera bloom off or on"
223
- );
224
- }
225
- function validateBloomRange(field, value, min, max) {
226
- if (!Number.isFinite(value) || value < min || value > max) {
227
- throw cameraError(
228
- "camera-bloom-invalid",
229
- field,
230
- value,
231
- `a finite value in [${min}, ${max}]`,
232
- `set Camera.${field} to a finite value in [${min}, ${max}]`
233
- );
234
- }
235
- }
236
- function validateCameraBloom(bloom, threshold, intensity, softKnee, scatter) {
237
- const enabled = bloomEnabledFromF32(bloom);
238
- validateBloomRange(
239
- "bloomThreshold",
240
- threshold,
241
- CAMERA_BLOOM_THRESHOLD_MIN,
242
- CAMERA_BLOOM_THRESHOLD_MAX
243
- );
244
- validateBloomRange(
245
- "bloomIntensity",
246
- intensity,
247
- CAMERA_BLOOM_INTENSITY_MIN,
248
- CAMERA_BLOOM_INTENSITY_MAX
249
- );
250
- validateBloomRange(
251
- "bloomSoftKnee",
252
- softKnee,
253
- CAMERA_BLOOM_SOFT_KNEE_MIN,
254
- CAMERA_BLOOM_SOFT_KNEE_MAX
255
- );
256
- validateBloomRange("bloomScatter", scatter, CAMERA_BLOOM_SCATTER_MIN, CAMERA_BLOOM_SCATTER_MAX);
257
- return enabled;
258
- }
259
- var Camera = defineComponent("Camera", {
260
- fov: { type: "f32" },
261
- aspect: { type: "f32" },
262
- near: { type: "f32" },
263
- far: { type: "f32" },
264
- projection: { type: "f32", default: 0 },
265
- left: { type: "f32", default: -1 },
266
- right: { type: "f32", default: 1 },
267
- bottom: { type: "f32", default: -1 },
268
- top: { type: "f32", default: 1 },
269
- tonemap: { type: "f32", default: 0 },
270
- exposure: { type: "f32", default: 1 },
271
- exposureMode: { type: "f32", default: CAMERA_EXPOSURE_MODE_MANUAL },
272
- compensationEv: { type: "f32", default: 0 },
273
- rangeEv: { type: "array<f32, 2>", default: new Float32Array([-8, 8]) },
274
- rates: { type: "array<f32, 2>", default: new Float32Array([3, 1]) },
275
- whitePoint: { type: "f32", default: 4 },
276
- temperature: { type: "f32", default: 6504 },
277
- tint: { type: "f32", default: 0 },
278
- colorLut: { type: "shared<TextureAsset>", default: 0 },
279
- colorLutStrength: { type: "f32", default: 0 },
280
- antialias: { type: "f32", default: 0 },
281
- historyVersion: { type: "u32", default: 0 },
282
- bloom: { type: "f32", default: 0 },
283
- bloomThreshold: { type: "f32", default: 1 },
284
- bloomIntensity: { type: "f32", default: 1 },
285
- bloomSoftKnee: { type: "f32", default: 0.5 },
286
- bloomScatter: { type: "f32", default: 0.7 },
287
- // M1 target camera role: zero means this camera is eligible for display;
288
- // non-zero shared targets are auxiliary producers whose views and receipt
289
- // promotion remain owned by Renderer.
290
- target: { type: "shared<RenderTarget>", simulationTransient: true },
291
- // feat-20260709 M3 / D-3: clear-color is one inline `array<f32,4>` column.
292
- // The earlier 4-scalar form (clearR/G/B/A) was chosen when this was believed
293
- // to be the only SoA-safe shape; the Transform (pos/quat/scale) and light
294
- // (direction/color) precedents disprove that -- an `array<f32,N>` IS an
295
- // inline stride-N SoA column, read on the hot path as `col[i*N+a]` with zero
296
- // allocation, so collapsing four scalars into one column removes three field
297
- // names a reader must track without changing the storage layout or read
298
- // pattern. The default `[0, 0, 0, 0]` is transparent black; explicit alpha
299
- // stays visible through the same public array field.
300
- clearColor: { type: "array<f32, 4>", default: new Float32Array([0, 0, 0, 0]) },
301
- // feat-20260617-host-engine-contract-and-video-cutscene / M3 / D-4: the
302
- // aspect-sync sidecar on the createApp(canvas) path writes
303
- // canvas.width / canvas.height into `aspect` every frame when this flag is
304
- // true. Reuses the existing `bool` column tier (AnimationPlayer.paused /
305
- // AudioSource.playing precedent) -- zero ECS infrastructure change. Default
306
- // true so demos that never touch aspect track the canvas automatically
307
- // (charter P1 default-is-correct); set false for render-to-texture /
308
- // split-screen cameras that drive aspect themselves. Read it via
309
- // world.get (readRow narrows bool -> JS boolean); the query-bundle path
310
- // returns a raw 0/1 number (the `!== 0` always-true trap).
311
- autoAspect: { type: "bool", default: true }
312
- });
313
- function cameraExposureFromColumns(input) {
314
- if (input.exposureMode === CAMERA_EXPOSURE_MODE_MANUAL) {
315
- return validateCameraExposure({ kind: "manual", multiplier: input.exposure });
316
- }
317
- if (input.exposureMode === CAMERA_EXPOSURE_MODE_AUTO) {
318
- return validateCameraExposure({
319
- kind: "auto",
320
- fallback: input.exposure,
321
- compensationEv: input.compensationEv,
322
- rangeEv: [input.rangeEv[0] ?? -8, input.rangeEv[1] ?? 8],
323
- rates: [input.rates[0] ?? 3, input.rates[1] ?? 1]
324
- });
325
- }
326
- throw cameraError(
327
- "camera-exposure-mode-invalid",
328
- "exposureMode",
329
- input.exposureMode,
330
- `${CAMERA_EXPOSURE_MODE_MANUAL} or ${CAMERA_EXPOSURE_MODE_AUTO}`,
331
- "set Camera.exposureMode to the manual or auto encoding"
332
- );
333
- }
334
- function cameraExposureColumns(exposure) {
335
- const checked = validateCameraExposure(exposure);
336
- if (checked.kind === "manual") {
337
- return {
338
- exposureMode: CAMERA_EXPOSURE_MODE_MANUAL,
339
- exposure: checked.multiplier,
340
- compensationEv: 0,
341
- rangeEv: new Float32Array([-8, 8]),
342
- rates: new Float32Array([3, 1])
343
- };
344
- }
345
- return {
346
- exposureMode: CAMERA_EXPOSURE_MODE_AUTO,
347
- exposure: checked.fallback,
348
- compensationEv: checked.compensationEv,
349
- rangeEv: new Float32Array(checked.rangeEv),
350
- rates: new Float32Array(checked.rates)
351
- };
352
- }
353
- function cameraColorGradingColumns(opts) {
354
- const exposure = opts.exposure ?? { kind: "manual", multiplier: 1 };
355
- const temperature = opts.temperature ?? 6504;
356
- const tint = opts.tint ?? 0;
357
- const colorLutStrength = opts.colorLutStrength ?? 0;
358
- validateCameraColorGrading(temperature, tint, colorLutStrength);
359
- return {
360
- ...cameraExposureColumns(exposure),
361
- temperature,
362
- tint,
363
- colorLut: opts.colorLut ?? 0,
364
- colorLutStrength
365
- };
366
- }
367
- function cameraPodFromDefaults() {
368
- const base = {};
369
- for (const [key, field] of Object.entries(Camera.fields)) {
370
- if ("default" in field && field.default !== void 0) {
371
- base[key] = field.default;
372
- }
373
- }
374
- return base;
375
- }
376
- function perspective(opts) {
377
- return {
378
- // cameraPodFromDefaults() reads autoAspect's schema default (true), so an
379
- // omitted opts.autoAspect lands the default-correct value; an explicit
380
- // false overrides it below (D-4: factory one-step opt-out, charter P1).
381
- ...cameraPodFromDefaults(),
382
- fov: opts.fov,
383
- aspect: opts.aspect,
384
- near: opts.near ?? 0.1,
385
- far: opts.far ?? 100,
386
- projection: CAMERA_PROJECTION_PERSPECTIVE,
387
- ...opts.autoAspect !== void 0 ? { autoAspect: opts.autoAspect } : {},
388
- ...cameraColorGradingColumns(opts)
389
- };
390
- }
391
- function orthographic(opts) {
392
- return {
393
- ...cameraPodFromDefaults(),
394
- fov: 0,
395
- aspect: 1,
396
- near: opts.near ?? 0.1,
397
- far: opts.far ?? 100,
398
- projection: CAMERA_PROJECTION_ORTHOGRAPHIC,
399
- left: opts.left,
400
- right: opts.right,
401
- bottom: opts.bottom,
402
- top: opts.top,
403
- ...cameraColorGradingColumns(opts)
404
- };
405
- }
406
- var CUBE_CAMERA_UPDATE_ONCE = 0;
407
- var CUBE_CAMERA_UPDATE_ON_DEMAND = 1;
408
- var CUBE_CAMERA_UPDATE_CONTINUOUS = 2;
409
- var CUBE_CAMERA_FACE_ORDER = ["+X", "-X", "+Y", "-Y", "+Z", "-Z"];
410
- function cubeCameraUpdateIntentFromF32(value) {
411
- switch (value) {
412
- case CUBE_CAMERA_UPDATE_ONCE:
413
- return "once";
414
- case CUBE_CAMERA_UPDATE_ON_DEMAND:
415
- return "on-demand";
416
- case CUBE_CAMERA_UPDATE_CONTINUOUS:
417
- return "continuous";
418
- default:
419
- throw new RenderIntentInvalidError("CubeCamera", value);
420
- }
421
- }
422
- function cubeCameraUpdateIntentToF32(intent) {
423
- switch (intent) {
424
- case "once":
425
- return CUBE_CAMERA_UPDATE_ONCE;
426
- case "on-demand":
427
- return CUBE_CAMERA_UPDATE_ON_DEMAND;
428
- case "continuous":
429
- return CUBE_CAMERA_UPDATE_CONTINUOUS;
430
- }
431
- }
432
- var CubeCamera = defineComponent("CubeCamera", {
433
- target: { type: "shared<RenderTarget>", simulationTransient: true },
434
- near: { type: "f32", default: 0.1 },
435
- far: { type: "f32", default: 100 },
436
- updateIntent: { type: "f32", default: CUBE_CAMERA_UPDATE_ONCE },
437
- requestVersion: { type: "u32", default: 0 },
438
- faceBudget: { type: "u32", default: 1 }
439
- });
440
- var DepthOfFieldQualityValue = Object.freeze({
441
- low: 0,
442
- medium: 1,
443
- high: 2
444
- });
445
- var DepthOfFieldSideValue = Object.freeze({
446
- both: 0,
447
- near: 1,
448
- far: 2
449
- });
450
- var DepthOfField = defineComponent("DepthOfField", {
451
- focusDistance: { type: "f32", default: 8 },
452
- fStop: { type: "f32", default: 2.8 },
453
- sensorHeight: { type: "f32", default: 0.024 },
454
- maxRadiusPixels: { type: "f32", default: 16 },
455
- quality: { type: "f32", default: DepthOfFieldQualityValue.medium },
456
- blurSide: { type: "f32", default: DepthOfFieldSideValue.both }
457
- });
458
- function depthOfFieldQualityFromF32(value) {
459
- if (value === DepthOfFieldQualityValue.low) return "low";
460
- if (value === DepthOfFieldQualityValue.medium) return "medium";
461
- if (value === DepthOfFieldQualityValue.high) return "high";
462
- return void 0;
463
- }
464
- function depthOfFieldSideFromF32(value) {
465
- if (value === DepthOfFieldSideValue.both) return "both";
466
- if (value === DepthOfFieldSideValue.near) return "near";
467
- if (value === DepthOfFieldSideValue.far) return "far";
468
- return void 0;
469
- }
470
-
471
- // src/components/directional-shadow-filter.ts
472
- var DirectionalShadowFilterValue = Object.freeze({
473
- pcf1: 1,
474
- pcf3: 2,
475
- pcf5: 3,
476
- pcssMedium: 4,
477
- pcssHigh: 5
478
- });
479
- function directionalShadowQualityFromF32(value, angularRadiusRadians, maxPenumbraTexels) {
480
- switch (value) {
481
- case DirectionalShadowFilterValue.pcf1:
482
- return { kind: "pcf", kernel: 1 };
483
- case DirectionalShadowFilterValue.pcf3:
484
- return { kind: "pcf", kernel: 3 };
485
- case DirectionalShadowFilterValue.pcf5:
486
- return { kind: "pcf", kernel: 5 };
487
- case DirectionalShadowFilterValue.pcssMedium:
488
- return {
489
- kind: "pcss",
490
- preset: "medium",
491
- angularRadiusRadians,
492
- maxPenumbraTexels
493
- };
494
- case DirectionalShadowFilterValue.pcssHigh:
495
- return {
496
- kind: "pcss",
497
- preset: "high",
498
- angularRadiusRadians,
499
- maxPenumbraTexels
500
- };
501
- default:
502
- return void 0;
503
- }
504
- }
505
- var DirectionalLight = defineComponent("DirectionalLight", {
506
- // direction is the ONLY field with no default (D-5): omitting it lands the
507
- // array layer-3 all-zero [0,0,0], which the renderer owner rejects -- there is no
508
- // universal default direction, so "default is illegal" forces an explicit
509
- // non-zero value. color carries an explicit layer-2 default [1,1,1] (white);
510
- // the array layer-3 fallback is all-zero, so the default MUST be explicit.
511
- direction: { type: "array<f32, 3>" },
512
- color: { type: "array<f32, 3>", default: new Float32Array([1, 1, 1]) },
513
- intensity: { type: "f32", default: 1 },
514
- // Shadow opt-out gate: defaults to true so zero-config spawns get shadows.
515
- castShadow: { type: "bool", default: true },
516
- // 9 shadow fields migrated from DirectionalLightShadow (feat-20260621 M1).
517
- cascadeCount: { type: "f32", default: 4 },
518
- splitLambda: { type: "f32", default: 0.75 },
519
- cascadeBlend: { type: "f32", default: 0.2 },
520
- mapSize: { type: "f32", default: 2048 },
521
- depthBias: { type: "f32", default: 1e-5 },
522
- normalBias: { type: "f32", default: 0.05 },
523
- // Sole shadow coverage knob (feat replaces nearPlane/farPlane). The PSSM
524
- // near end derives from the active camera near; shadowDistance is the far
525
- // reach. Default 200 world units (matches UE-style "dynamic shadow
526
- // distance"; the old farPlane default was 50).
527
- shadowDistance: { type: "f32", default: 200 },
528
- shadowFilter: {
529
- type: "enum",
530
- default: DirectionalShadowFilterValue.pcf3,
531
- labels: DirectionalShadowFilterValue
532
- },
533
- shadowAngularRadius: { type: "f32", default: 465e-5 },
534
- maxPenumbraTexels: { type: "f32", default: 32 }
535
- });
536
- var DynamicResolution = defineComponent("DynamicResolution", {
537
- targetGpuMs: { type: "f32", default: 16.67 },
538
- minScale: { type: "f32", default: 0.67 },
539
- maxScale: { type: "f32", default: 1 }
540
- });
541
- var DEFAULT_DYNAMIC_RESOLUTION = Object.freeze({
542
- targetGpuMs: 16.67,
543
- minScale: 0.67,
544
- maxScale: 1
545
- });
546
- function invalid(field, value, expected) {
547
- return new DynamicResolutionInvalidParameterError({ field, value, expected });
548
- }
549
- function validateDynamicResolutionParameters(input) {
550
- const value = input ?? {};
551
- const targetGpuMs = value.targetGpuMs ?? DEFAULT_DYNAMIC_RESOLUTION.targetGpuMs;
552
- const minScale = value.minScale ?? DEFAULT_DYNAMIC_RESOLUTION.minScale;
553
- const maxScale = value.maxScale ?? DEFAULT_DYNAMIC_RESOLUTION.maxScale;
554
- if (!Number.isFinite(targetGpuMs) || targetGpuMs <= 0) {
555
- return err(invalid("targetGpuMs", targetGpuMs, "finite and greater than 0"));
556
- }
557
- if (!Number.isFinite(minScale) || minScale < 0.5 || minScale > 1) {
558
- return err(invalid("minScale", minScale, "finite and in [0.5, 1.0]"));
559
- }
560
- if (!Number.isFinite(maxScale) || maxScale < 0.5 || maxScale > 1) {
561
- return err(invalid("maxScale", maxScale, "finite and in [0.5, 1.0]"));
562
- }
563
- if (minScale > maxScale) {
564
- return err(invalid("minScale", minScale, "less than or equal to maxScale"));
565
- }
566
- return ok(Object.freeze({ targetGpuMs, minScale, maxScale }));
567
- }
568
- function validateDynamicResolutionCamera(input, antialias) {
569
- if (input === void 0) return ok(void 0);
570
- const parameters = validateDynamicResolutionParameters(input);
571
- if (!parameters.ok) return parameters;
572
- if (antialias !== "taa") {
573
- return err(new DynamicResolutionRequiresTaaError({ antialias }));
574
- }
575
- return parameters;
576
- }
577
- var Fog = defineComponent("Fog", {
578
- color: { type: "array<f32, 3>", default: new Float32Array([0.5, 0.5, 0.5]) },
579
- density: { type: "f32", default: 0.01 },
580
- heightFalloff: { type: "f32", default: 0 },
581
- maxOpacity: { type: "f32", default: 1 }
582
- });
583
- var Instances = defineComponent("Instances", {
584
- collectionId: { type: "u32", default: 0 }
585
- });
586
- var Layer = defineComponent("Layer", {
587
- value: { type: "i32", default: 0 }
588
- });
589
-
590
- // src/components/light-helpers.ts
591
- var RANGE_ZERO_FALLBACK_INV_R2 = 1e8;
592
- var DEG_TO_RAD = Math.PI / 180;
593
- var PCSS_RADIUS_MIN = 1e-4;
594
- var PCSS_RADIUS_MAX = 0.05;
595
- var PCSS_PENUMBRA_MIN = 1;
596
- var PCSS_PENUMBRA_MAX = 64;
597
- function degToCos(deg) {
598
- return Math.cos(deg * DEG_TO_RAD);
599
- }
600
- function computeInvRangeSquared(range) {
601
- if (range === Number.POSITIVE_INFINITY) return 0;
602
- if (range === 0) return RANGE_ZERO_FALLBACK_INV_R2;
603
- return 1 / (range * range);
604
- }
605
- function validateDirection(componentName, direction) {
606
- const dir = direction;
607
- if (dir === void 0 || (dir[0] ?? 0) === 0 && (dir[1] ?? 0) === 0 && (dir[2] ?? 0) === 0) {
608
- return new SpawnLightInvalidBoundsError(
609
- componentName,
610
- "direction",
611
- dir === void 0 ? [0, 0, 0] : [dir[0] ?? 0, dir[1] ?? 0, dir[2] ?? 0]
612
- );
613
- }
614
- return null;
615
- }
616
- function validateDirectionalLightData(data) {
617
- const directionError = validateDirection(
618
- "DirectionalLight",
619
- data.direction
620
- );
621
- if (directionError !== null) return err(directionError);
622
- if (data.castShadow === false) return ok(void 0);
623
- const mapSize = data.mapSize ?? 2048;
624
- if (mapSize < 1) {
625
- return err(new ShadowInvalidConfigError("mapSize", mapSize, 1));
626
- }
627
- const cascadeCount = data.cascadeCount ?? 4;
628
- if (cascadeCount < 1 || cascadeCount > 4 || !Number.isInteger(cascadeCount)) {
629
- return err(new ShadowInvalidConfigError("cascadeCount", cascadeCount, 1, 4));
630
- }
631
- const splitLambda = data.splitLambda ?? 0.75;
632
- if (splitLambda < 0 || splitLambda > 1) {
633
- return err(new ShadowInvalidConfigError("splitLambda", splitLambda, 0, 1));
634
- }
635
- const cascadeBlend = data.cascadeBlend ?? 0.2;
636
- if (cascadeBlend < 0 || cascadeBlend > 0.5) {
637
- return err(new ShadowInvalidConfigError("cascadeBlend", cascadeBlend, 0, 0.5));
638
- }
639
- const shadowDistance = data.shadowDistance ?? 200;
640
- if (shadowDistance <= 0) {
641
- return err(new ShadowInvalidConfigError("shadowDistance", shadowDistance, 0, ">"));
642
- }
643
- const shadowFilter = data.shadowFilter ?? DirectionalShadowFilterValue.pcf3;
644
- const allowedFilters = Object.values(DirectionalShadowFilterValue);
645
- if (!Number.isFinite(shadowFilter) || !allowedFilters.includes(shadowFilter)) {
646
- return err(
647
- new ShadowInvalidConfigError(
648
- "shadowFilter",
649
- shadowFilter,
650
- { kind: "allowed-values", values: allowedFilters },
651
- void 0,
652
- "one of [pcf1, pcf3, pcf5, pcssMedium, pcssHigh]"
653
- )
654
- );
655
- }
656
- if (shadowFilter === DirectionalShadowFilterValue.pcssMedium || shadowFilter === DirectionalShadowFilterValue.pcssHigh) {
657
- const shadowAngularRadius = data.shadowAngularRadius ?? 465e-5;
658
- if (!Number.isFinite(shadowAngularRadius)) {
659
- return err(
660
- new ShadowInvalidConfigError("shadowAngularRadius", shadowAngularRadius, {
661
- kind: "range",
662
- min: PCSS_RADIUS_MIN,
663
- max: PCSS_RADIUS_MAX
664
- })
665
- );
666
- }
667
- if (shadowAngularRadius < Math.fround(PCSS_RADIUS_MIN) || shadowAngularRadius > Math.fround(PCSS_RADIUS_MAX)) {
668
- return err(
669
- new ShadowInvalidConfigError("shadowAngularRadius", shadowAngularRadius, {
670
- kind: "range",
671
- min: PCSS_RADIUS_MIN,
672
- max: PCSS_RADIUS_MAX
673
- })
674
- );
675
- }
676
- const maxPenumbraTexels = data.maxPenumbraTexels ?? 32;
677
- if (!Number.isFinite(maxPenumbraTexels) || !Number.isInteger(maxPenumbraTexels) || maxPenumbraTexels < PCSS_PENUMBRA_MIN || maxPenumbraTexels > PCSS_PENUMBRA_MAX) {
678
- return err(
679
- new ShadowInvalidConfigError(
680
- "maxPenumbraTexels",
681
- maxPenumbraTexels,
682
- { kind: "range", min: PCSS_PENUMBRA_MIN, max: PCSS_PENUMBRA_MAX },
683
- void 0,
684
- "a finite integer in [1, 64]"
685
- )
686
- );
687
- }
688
- }
689
- return ok(void 0);
690
- }
691
- function validateSpotLightData(data) {
692
- const directionError = validateDirection(
693
- "SpotLight",
694
- data.direction
695
- );
696
- if (directionError !== null) return err(directionError);
697
- if (data.castShadow === false) return ok(void 0);
698
- const range = data.range ?? 10;
699
- if (typeof range !== "number" || Number.isNaN(range) || range < 0) {
700
- return err(new SpawnLightInvalidBoundsError("SpotLight", "range", range));
701
- }
702
- const innerConeDeg = data.innerConeDeg ?? 0;
703
- const outerConeDeg = data.outerConeDeg ?? 45;
704
- if (outerConeDeg > 90) {
705
- return err(new SpawnLightInvalidBoundsError("SpotLight", "outerNinety", outerConeDeg));
706
- }
707
- if (outerConeDeg <= innerConeDeg) {
708
- return err(new SpawnLightInvalidBoundsError("SpotLight", "innerOuter", outerConeDeg));
709
- }
710
- const mapSize = data.mapSize ?? 2048;
711
- if (mapSize < 1) return err(new ShadowInvalidConfigError("mapSize", mapSize, 1));
712
- const nearPlane = data.nearPlane;
713
- const farPlane = data.farPlane;
714
- if (nearPlane !== void 0 && farPlane !== void 0 && farPlane <= nearPlane) {
715
- return err(new ShadowInvalidConfigError("farPlane", farPlane, nearPlane));
716
- }
717
- const pcfKernelSize = data.pcfKernelSize ?? 3;
718
- if (pcfKernelSize < 1 || pcfKernelSize % 2 === 0) {
719
- return err(
720
- new ShadowInvalidConfigError(
721
- "pcfKernelSize",
722
- pcfKernelSize,
723
- { kind: "lower-bound", operator: ">=", value: 1 },
724
- void 0,
725
- "an odd integer >= 1"
726
- )
727
- );
728
- }
729
- const shadowIntensity = data.shadowIntensity ?? 1;
730
- if (!Number.isFinite(shadowIntensity) || shadowIntensity < 0 || shadowIntensity > 1) {
731
- return err(new ShadowInvalidConfigError("shadowIntensity", shadowIntensity, 0, 1));
732
- }
733
- return ok(void 0);
734
- }
735
- function validatePointLightData(data) {
736
- const range = data.range ?? 10;
737
- if (typeof range !== "number" || Number.isNaN(range) || range < 0) {
738
- return err(new SpawnLightInvalidBoundsError("PointLight", "range", range));
739
- }
740
- return ok(void 0);
741
- }
742
- function validatePointLightShadowData(data) {
743
- const mapSize = data.mapSize ?? 512;
744
- if (mapSize < 1) return err(new ShadowInvalidConfigError("mapSize", mapSize, 1));
745
- const nearPlane = data.nearPlane ?? 0.1;
746
- const farPlane = data.farPlane ?? 25;
747
- if (farPlane <= nearPlane) {
748
- return err(new ShadowInvalidConfigError("farPlane", farPlane, nearPlane));
749
- }
750
- const pcfKernelSize = data.pcfKernelSize ?? 3;
751
- if (pcfKernelSize < 1 || pcfKernelSize % 2 === 0) {
752
- return err(
753
- new ShadowInvalidConfigError(
754
- "pcfKernelSize",
755
- pcfKernelSize,
756
- { kind: "lower-bound", operator: ">=", value: 1 },
757
- void 0,
758
- "an odd integer >= 1"
759
- )
760
- );
761
- }
762
- return ok(void 0);
763
- }
764
- function validateRectAreaLightData(data) {
765
- const intensity = data.intensity ?? 1;
766
- if (typeof intensity !== "number" || !Number.isFinite(intensity) || intensity < 0) {
767
- return err(new SpawnLightInvalidBoundsError("RectAreaLight", "intensity", intensity));
768
- }
769
- const color = data.color ?? [1, 1, 1];
770
- if (color.length !== 3 || Array.from(color).some(
771
- (value) => typeof value !== "number" || !Number.isFinite(value) || value < 0
772
- )) {
773
- return err(new SpawnLightInvalidBoundsError("RectAreaLight", "color", Array.from(color)));
774
- }
775
- for (const field of ["width", "height", "range"]) {
776
- const value = data[field] ?? (field === "range" ? 10 : 1);
777
- if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
778
- return err(new SpawnLightInvalidBoundsError("RectAreaLight", field, value));
779
- }
780
- }
781
- return ok(void 0);
782
- }
783
- function validateLightProbeData(data) {
784
- const irradiance = data.irradiance;
785
- if (irradiance === void 0 || irradiance.length !== 27 || Array.from(irradiance).some((value) => typeof value !== "number" || !Number.isFinite(value))) {
786
- return err(
787
- new SpawnLightInvalidBoundsError(
788
- "LightProbe",
789
- "irradiance",
790
- irradiance === void 0 ? [] : Array.from(irradiance)
791
- )
792
- );
793
- }
794
- const radius = data.radius ?? R_MIN;
795
- if (typeof radius !== "number" || !Number.isFinite(radius) || radius < R_MIN) {
796
- return err(new SpawnLightInvalidBoundsError("LightProbe", "radius", radius));
797
- }
798
- return ok(void 0);
799
- }
800
- var LightProbe = defineComponent("LightProbe", {
801
- irradiance: { type: "array<f32, 27>" },
802
- radius: { type: "f32", default: R_MIN }
803
- });
804
- var Lines = defineComponent(
805
- "Lines",
806
- {
807
- widthPx: { type: "f32", default: 1 }
808
- },
809
- {
810
- meta: {
811
- quickStart: "Attach Lines to render line-list MeshAsset pairs in screen pixels.",
812
- diagnostics: "Inspect widthPx at the points-lines admission boundary.",
813
- recovery: "Use points-lines-invalid-style for non-finite or non-positive widthPx values.",
814
- boundaries: "Lines owns raster width only; MeshFilter and MeshRenderer own geometry and material."
815
- }
816
- }
817
- );
818
- var MeshFilter = defineComponent("MeshFilter", {
819
- assetHandle: { type: "shared<MeshAsset>" }
820
- });
821
- var MeshRenderer = defineComponent("MeshRenderer", {
822
- materials: { type: "array<shared<MaterialAsset>>", default: [] }
823
- });
824
- var MotionBlur = defineComponent("MotionBlur", {
825
- shutterAngle: { type: "f32", default: 180 },
826
- maxRadiusPixels: { type: "f32", default: 32 },
827
- sampleCount: { type: "f32", default: 8 },
828
- targetFps: { type: "f32", default: 60 }
829
- });
830
- var PointLight = defineComponent("PointLight", {
831
- // color carries an explicit layer-2 default [1,1,1] (white); the array
832
- // layer-3 fallback is all-zero, so the default MUST be explicit (D-5).
833
- color: { type: "array<f32, 3>", default: new Float32Array([1, 1, 1]) },
834
- intensity: { type: "f32", default: 1 },
835
- range: { type: "f32", default: 10 }
836
- });
837
- var PointLightShadow = defineComponent("PointLightShadow", {
838
- mapSize: { type: "f32", default: 512 },
839
- depthBias: { type: "f32", default: 5e-3 },
840
- normalBias: { type: "f32", default: 0.05 },
841
- nearPlane: { type: "f32", default: 0.1 },
842
- farPlane: { type: "f32", default: 25 },
843
- pcfKernelSize: { type: "f32", default: 3 }
844
- });
845
- var PointShapeValue = Object.freeze({
846
- square: 0,
847
- circle: 1
848
- });
849
- function pointShapeFromU32(value) {
850
- switch (value) {
851
- case PointShapeValue.square:
852
- return "square";
853
- case PointShapeValue.circle:
854
- return "circle";
855
- default:
856
- return void 0;
857
- }
858
- }
859
- var Points = defineComponent(
860
- "Points",
861
- {
862
- sizePx: { type: "f32", default: 4 },
863
- shape: { type: "enum", default: PointShapeValue.square, labels: PointShapeValue }
864
- },
865
- {
866
- meta: {
867
- quickStart: "Attach Points to render point-list MeshAsset vertices in screen pixels.",
868
- diagnostics: "Inspect sizePx and decode shape with pointShapeFromU32.",
869
- recovery: "Use points-lines-invalid-style for non-finite or non-positive sizePx values.",
870
- boundaries: "Points owns raster size and shape only; MeshFilter and MeshRenderer own geometry and material."
871
- }
872
- }
873
- );
874
- var schema = {
875
- shader: "string",
876
- data: "buffer"
877
- };
878
- var PostProcessParams = defineComponent("PostProcessParams", schema);
879
- var RectAreaLight = defineComponent("RectAreaLight", {
880
- color: { type: "array<f32, 3>", default: new Float32Array([1, 1, 1]) },
881
- intensity: { type: "f32", default: 1 },
882
- width: { type: "f32", default: 1 },
883
- height: { type: "f32", default: 1 },
884
- range: { type: "f32", default: 10 }
885
- });
886
- var REFLECTION_PROBE_UPDATE_ONCE = 0;
887
- var REFLECTION_PROBE_UPDATE_ON_CHANGE = 1;
888
- var REFLECTION_PROBE_UPDATE_CONTINUOUS = 2;
889
- function reflectionProbeUpdateIntentFromF32(value) {
890
- switch (value) {
891
- case REFLECTION_PROBE_UPDATE_ONCE:
892
- return "once";
893
- case REFLECTION_PROBE_UPDATE_ON_CHANGE:
894
- return "on-change";
895
- case REFLECTION_PROBE_UPDATE_CONTINUOUS:
896
- return "continuous";
897
- default:
898
- throw new RenderIntentInvalidError("ReflectionProbe", value);
899
- }
900
- }
901
- function reflectionProbeUpdateIntentToF32(intent) {
902
- switch (intent) {
903
- case "once":
904
- return REFLECTION_PROBE_UPDATE_ONCE;
905
- case "on-change":
906
- return REFLECTION_PROBE_UPDATE_ON_CHANGE;
907
- case "continuous":
908
- return REFLECTION_PROBE_UPDATE_CONTINUOUS;
909
- }
910
- }
911
- var ReflectionProbe = defineComponent("ReflectionProbe", {
912
- halfExtents: { type: "array<f32, 3>", default: new Float32Array([1, 1, 1]) },
913
- priority: { type: "f32", default: 0 },
914
- boxProjection: { type: "bool", default: false },
915
- intensity: { type: "f32", default: 1 },
916
- resolution: { type: "u32", default: 256 },
917
- updateIntent: { type: "f32", default: REFLECTION_PROBE_UPDATE_ONCE },
918
- invalidationVersion: { type: "u32", default: 0 }
919
- });
920
- var SceneInstance = defineComponent(
921
- "SceneInstance",
922
- {
923
- source: { type: "shared<SceneAsset>" },
924
- mapping: { type: "array<entity>" },
925
- // The unique slot is the ECS storage seam for the instance's structured
926
- // runtime payload; keep the nested semantic visible to schema consumers.
927
- state: { type: "unique<SceneInstanceState>", shape: "nested" }
928
- },
929
- { transient: true }
930
- );
931
- var ScreenSpaceReflection = defineComponent("ScreenSpaceReflection", {
932
- maxDistance: { type: "f32", default: 40 },
933
- thickness: { type: "f32", default: 0.2 },
934
- maxRoughness: { type: "f32", default: 0.6 }
935
- });
936
- var SKYBOX_MODE_CUBEMAP = 0;
937
- var SkyboxBackground = defineComponent("SkyboxBackground", {
938
- // The GPU skybox projection is render-owned presentation state; restore
939
- // keeps the portable mode/rotation controls and lets the owner re-resolve
940
- // the environment asset on the target world.
941
- equirect: { type: "shared<EquirectAsset>", simulationTransient: true },
942
- mode: { type: "f32", default: SKYBOX_MODE_CUBEMAP },
943
- rotation: { type: "array<f32, 4>", default: new Float32Array([0, 0, 0, 1]) }
944
- });
945
- var Skylight = defineComponent("Skylight", {
946
- // The GPU equirect-to-cubemap projection is render-owned presentation
947
- // state. Record/restore preserves the portable lighting controls while the
948
- // render owner resolves this asset again on the target world.
949
- equirect: { type: "shared<EquirectAsset>", simulationTransient: true },
950
- // color carries an explicit layer-2 default [1,1,1] (white); the array
951
- // layer-3 fallback is all-zero, so the default MUST be explicit (D-5).
952
- color: { type: "array<f32, 3>", default: new Float32Array([1, 1, 1]) },
953
- intensity: { type: "f32", default: 1 },
954
- rotation: { type: "array<f32, 4>", default: new Float32Array([0, 0, 0, 1]) }
955
- });
956
- var SortKey = defineComponent("SortKey", {
957
- value: { type: "f32", default: 0 }
958
- });
959
- var SpotLight = defineComponent("SpotLight", {
960
- // direction has no default (D-5): omitting it lands the array layer-3
961
- // all-zero, which validate() rejects. color carries an explicit layer-2
962
- // default [1,1,1] (white); the array layer-3 fallback is all-zero.
963
- direction: { type: "array<f32, 3>" },
964
- color: { type: "array<f32, 3>", default: new Float32Array([1, 1, 1]) },
965
- intensity: { type: "f32", default: 1 },
966
- range: { type: "f32", default: 10 },
967
- innerConeDeg: { type: "f32", default: 0 },
968
- outerConeDeg: { type: "f32", default: 45 },
969
- iesProfile: { type: "shared<IesProfileAsset>" },
970
- cookie: { type: "shared<TextureAsset>" },
971
- rollDeg: { type: "f32", default: 0 },
972
- // Shadow opt-out gate: defaults to true so zero-config spawns cast shadows.
973
- castShadow: { type: "bool", default: true },
974
- // 7 shadow fields aligned with the shared light shadow vocabulary.
975
- mapSize: { type: "f32", default: 2048 },
976
- depthBias: { type: "f32", default: 5e-3 },
977
- normalBias: { type: "f32", default: 0.05 },
978
- nearPlane: { type: "f32", default: 0.1 },
979
- farPlane: { type: "f32", default: 50 },
980
- pcfKernelSize: { type: "f32", default: 3 },
981
- // Three's SpotLight.shadow.intensity is the fraction of visibility applied
982
- // to a shadowed contribution. Keep it in the author-facing [0,1] domain;
983
- // extract/record transport this one fact to surface and volume consumers.
984
- shadowIntensity: { type: "f32", default: 1 },
985
- // Shared TextureAsset identity; publication and residency remain owned by
986
- // the existing asset and GPU resource owners.
987
- projector: { type: "shared<TextureAsset>", simulationTransient: true }
988
- });
989
- var VisibilityStateValue = Object.freeze({
990
- inherited: 0,
991
- hidden: 1,
992
- visible: 2
993
- });
994
- function visibilityStateFromU32(value) {
995
- switch (value) {
996
- case VisibilityStateValue.inherited:
997
- return "inherited";
998
- case VisibilityStateValue.hidden:
999
- return "hidden";
1000
- case VisibilityStateValue.visible:
1001
- return "visible";
1002
- default:
1003
- return void 0;
1004
- }
1005
- }
1006
- var Visibility = defineComponent(
1007
- "Visibility",
1008
- {
1009
- state: {
1010
- type: "enum",
1011
- default: VisibilityStateValue.inherited,
1012
- labels: VisibilityStateValue
1013
- }
1014
- },
1015
- {
1016
- meta: {
1017
- quickStart: "Attach Visibility to author render participation intent.",
1018
- diagnostics: "Compare the ECS state with resolveVisibility and renderer.visibilityStats.",
1019
- recovery: "Use structured ECS write errors and repair the owning scene relation.",
1020
- boundaries: "Visibility does not own camera, picking, lifecycle, assets, or VFX shadow policy."
1021
- }
1022
- }
1023
- );
1024
-
1025
- // src/environment/signature.ts
1026
- function sorted(items) {
1027
- return [...items].sort((left, right) => left.entityKey - right.entityKey);
1028
- }
1029
- function environmentSignature(input) {
1030
- return JSON.stringify({
1031
- environments: sorted(input.environments),
1032
- fogs: sorted(input.fogs),
1033
- suns: sorted(input.suns)
1034
- });
1035
- }
1036
- function environmentOnlySignature(input) {
1037
- return JSON.stringify({
1038
- environments: sorted(input.environments),
1039
- suns: sorted(input.suns)
1040
- });
1041
- }
1042
- function fogOnlySignature(input) {
1043
- return JSON.stringify({ fogs: sorted(input.fogs) });
1044
- }
1045
- function environmentFactSignatures(input) {
1046
- return {
1047
- environmentSignature: environmentOnlySignature(input),
1048
- fogSignature: fogOnlySignature(input),
1049
- signature: environmentSignature(input)
1050
- };
1051
- }
1052
-
1053
- // src/extract/environment.ts
1054
- var ATMOSPHERE_PARAMETER_RANGES = Object.freeze({
1055
- turbidity: Object.freeze({ min: 1, max: 20 }),
1056
- rayleigh: Object.freeze({ min: 0, max: Number.POSITIVE_INFINITY }),
1057
- mieCoefficient: Object.freeze({ min: 0, max: Number.POSITIVE_INFINITY }),
1058
- mieDirectionalG: Object.freeze({ min: 0, max: 0.999 }),
1059
- sunAngularRadius: Object.freeze({ min: 0, max: Number.POSITIVE_INFINITY }),
1060
- circumsolarStrength: Object.freeze({ min: 0, max: 4 }),
1061
- circumsolarWidth: Object.freeze({ min: 0.25, max: 4 })
1062
- });
1063
- function validateFogParameters(candidate) {
1064
- if (candidate.color.length !== 3) {
1065
- return {
1066
- field: "color",
1067
- value: candidate.color.length,
1068
- expected: "exactly three finite channels in [0, 1]"
1069
- };
1070
- }
1071
- for (let index = 0; index < candidate.color.length; index += 1) {
1072
- const value = candidate.color[index];
1073
- if (value === void 0 || !Number.isFinite(value) || value < 0 || value > 1) {
1074
- return {
1075
- field: `color[${index}]`,
1076
- value: value ?? Number.NaN,
1077
- expected: "a finite number in [0, 1]"
1078
- };
1079
- }
1080
- }
1081
- if (!Number.isFinite(candidate.density) || candidate.density < 0) {
1082
- return { field: "density", value: candidate.density, expected: "a finite number >= 0" };
1083
- }
1084
- if (!Number.isFinite(candidate.heightFalloff) || candidate.heightFalloff < 0) {
1085
- return {
1086
- field: "heightFalloff",
1087
- value: candidate.heightFalloff,
1088
- expected: "a finite number >= 0"
1089
- };
1090
- }
1091
- if (!Number.isFinite(candidate.maxOpacity) || candidate.maxOpacity < 0 || candidate.maxOpacity > 1) {
1092
- return {
1093
- field: "maxOpacity",
1094
- value: candidate.maxOpacity,
1095
- expected: "a finite number in [0, 1]"
1096
- };
1097
- }
1098
- return void 0;
1099
- }
1100
- function validateAtmosphereParameters(parameters) {
1101
- for (const field of Object.keys(ATMOSPHERE_PARAMETER_RANGES)) {
1102
- const value = parameters[field];
1103
- const range = ATMOSPHERE_PARAMETER_RANGES[field];
1104
- if (!Number.isFinite(value) || value < range.min || value > range.max) {
1105
- return new AtmosphereInvalidParameterError(field, value, range);
1106
- }
1107
- }
1108
- return void 0;
1109
- }
1110
-
1111
- // src/environment/frame.ts
1112
- var SKYLIGHT_RECOVERY_FALLBACK = Object.freeze({
1113
- kind: "skylight",
1114
- active: false
1115
- });
1116
- var EnvironmentSelectionParameterError = class extends Error {
1117
- code = "environment-selection-invalid";
1118
- expected;
1119
- hint;
1120
- detail;
1121
- constructor(field, value, expected) {
1122
- super(`environment selection field ${field} is invalid`);
1123
- this.name = "EnvironmentSelectionParameterError";
1124
- this.expected = expected;
1125
- this.hint = `set ${field} to a finite value satisfying ${expected}`;
1126
- this.detail = { field, value };
1127
- }
1128
- };
1129
- var SunCardinalityError = class extends Error {
1130
- code = "sun-cardinality";
1131
- expected = "atmosphere has exactly one sun owner";
1132
- hint = "add exactly one DirectionalLight sun for the atmosphere owner";
1133
- detail;
1134
- constructor(value) {
1135
- super(`atmosphere sun cardinality is ${value}`);
1136
- this.name = "SunCardinalityError";
1137
- this.detail = { field: "sun", value };
1138
- }
1139
- };
1140
- function freezeCandidate(candidate) {
1141
- return Object.freeze(candidate);
1142
- }
1143
- function freezeFog(candidate) {
1144
- return Object.freeze({
1145
- ...candidate,
1146
- color: Object.freeze([...candidate.color])
1147
- });
1148
- }
1149
- function selectEnvironment(input) {
1150
- if (input.environments.length > 1) {
1151
- return err(
1152
- new EnvironmentSourceConflictError(
1153
- [...input.environments].sort((left, right) => left.entityKey - right.entityKey).map(({ kind, entityKey, sourceKey }) => ({ kind, entityKey, sourceKey }))
1154
- )
1155
- );
1156
- }
1157
- if (input.fogs.length > 1) return err(new FogCardinalityError(input.fogs.length));
1158
- const selectedFog = input.fogs[0];
1159
- if (selectedFog !== void 0) {
1160
- const issue = validateFogParameters(selectedFog);
1161
- if (issue !== void 0) {
1162
- return err(new EnvironmentSelectionParameterError(issue.field, issue.value, issue.expected));
1163
- }
1164
- }
1165
- const selected = input.environments[0];
1166
- if (selected?.kind === "atmosphere") {
1167
- const invalid3 = validateAtmosphereParameters(selected.atmosphere);
1168
- if (invalid3 !== void 0) return err(invalid3);
1169
- }
1170
- if (selected?.kind === "atmosphere" && input.suns.length !== 1) {
1171
- return err(new SunCardinalityError(input.suns.length));
1172
- }
1173
- const source = selected === void 0 ? { kind: "none" } : selected.kind === "atmosphere" ? {
1174
- kind: "atmosphere",
1175
- entityKey: selected.entityKey,
1176
- sourceKey: selected.sourceKey,
1177
- atmosphere: Object.freeze({ ...selected.atmosphere })
1178
- } : {
1179
- kind: "image",
1180
- entityKey: selected.entityKey,
1181
- sourceKey: selected.sourceKey
1182
- };
1183
- const sun = input.suns[0] === void 0 ? void 0 : freezeCandidate({ ...input.suns[0] });
1184
- const fog = selectedFog === void 0 ? void 0 : freezeFog(selectedFog);
1185
- const signatureInput = {
1186
- environments: selected === void 0 ? [] : [selected],
1187
- fogs: selectedFog === void 0 ? [] : [selectedFog],
1188
- suns: input.suns
1189
- };
1190
- const signatures = environmentFactSignatures(signatureInput);
1191
- const result = {
1192
- source: Object.freeze(source),
1193
- fog,
1194
- ...signatures,
1195
- revision: 0,
1196
- sun
1197
- };
1198
- Object.defineProperty(result, "lane", { value: input.lane, enumerable: false });
1199
- return ok(Object.freeze(result));
1200
- }
1201
- var DEPTH_OF_FIELD_PARAMS_BYTE_SIZE = 64;
1202
- var MIN_F_STOP = Math.fround(0.7);
1203
- var MAX_F_STOP = Math.fround(32);
1204
- var MAX_LINEAR_DEPTH_RAW = Math.fround(1 - 2 ** -24);
1205
- var DEFAULT_DEPTH_OF_FIELD_PARAMS = Object.freeze({
1206
- focusDistance: 8,
1207
- fStop: 2.8,
1208
- sensorHeight: 0.024,
1209
- maxRadiusPixels: 16,
1210
- quality: "medium",
1211
- blurSide: "both",
1212
- focalLength: 0
1213
- });
1214
- function quantizeF32(value) {
1215
- return Math.fround(value);
1216
- }
1217
- var DepthOfFieldValidationError = class extends Error {
1218
- code;
1219
- expected;
1220
- hint;
1221
- detail;
1222
- constructor(code, detail, expected, hint) {
1223
- super(`${code}: ${expected}`);
1224
- this.name = "DepthOfFieldValidationError";
1225
- this.code = code;
1226
- this.expected = expected;
1227
- this.hint = hint;
1228
- this.detail = detail;
1229
- }
1230
- };
1231
- function depthOfFieldRequestFailure(error) {
1232
- return Object.freeze({
1233
- code: error.code,
1234
- detail: error.detail,
1235
- expected: error.expected,
1236
- hint: error.hint
1237
- });
1238
- }
1239
- function resolveDepthOfFieldFrameParams(requested, requestFailure, accepted) {
1240
- if (requested !== void 0) return requested;
1241
- if (requestFailure === void 0 || requestFailure.code === "depth-of-field-orthographic-unsupported") {
1242
- return void 0;
1243
- }
1244
- return accepted;
1245
- }
1246
- function invalid2(field, value, expected, bound) {
1247
- return new DepthOfFieldValidationError(
1248
- "depth-of-field-invalid-params",
1249
- { field, value, expected, ...bound === void 0 ? {} : { bound } },
1250
- expected,
1251
- `set ${field} to ${expected}`
1252
- );
1253
- }
1254
- function focalLength(sensorHeight, fov) {
1255
- return sensorHeight / (2 * Math.tan(fov / 2));
1256
- }
1257
- function opticalCocScale(params) {
1258
- return params.focalLength / params.sensorHeight / (2 * params.fStop) * (params.focalLength / (params.focusDistance - params.focalLength));
1259
- }
1260
- function frameCocCoefficient(params, outputHeight) {
1261
- return quantizeF32(quantizeF32(outputHeight) * opticalCocScale(params));
1262
- }
1263
- function resolveDepthOfFieldFrameValues(params, input) {
1264
- const focusDistance = quantizeF32(params.focusDistance);
1265
- const fStop = quantizeF32(params.fStop);
1266
- const sensorHeight = quantizeF32(params.sensorHeight);
1267
- const focal = quantizeF32(params.focalLength);
1268
- const maxRadiusPixels = quantizeF32(params.maxRadiusPixels);
1269
- const outputHeight = quantizeF32(input.outputHeight);
1270
- const near = quantizeF32(input.near);
1271
- const far = quantizeF32(input.far);
1272
- const finitePositiveFields = [
1273
- ["focusDistance", focusDistance, params.focusDistance],
1274
- ["sensorHeight", sensorHeight, params.sensorHeight],
1275
- ["focalLength", focal, params.focalLength],
1276
- ["near", near, input.near],
1277
- ["far", far, input.far]
1278
- ];
1279
- for (const [field, value, raw] of finitePositiveFields) {
1280
- if (!Number.isFinite(value) || value <= 0) {
1281
- return err(invalid2(field, raw, "a finite positive f32 value"));
1282
- }
1283
- }
1284
- if (!Number.isFinite(fStop) || fStop < MIN_F_STOP || fStop > MAX_F_STOP) {
1285
- return err(
1286
- invalid2("fStop", params.fStop, "a finite f32 value in [0.7, 32]", [MIN_F_STOP, MAX_F_STOP])
1287
- );
1288
- }
1289
- if (!Number.isFinite(maxRadiusPixels) || maxRadiusPixels < 0 || maxRadiusPixels > 32) {
1290
- return err(
1291
- invalid2("maxRadiusPixels", params.maxRadiusPixels, "a finite f32 value in [0, 32]", [0, 32])
1292
- );
1293
- }
1294
- if (!Number.isFinite(outputHeight) || outputHeight <= 0) {
1295
- return err(invalid2("outputHeight", input.outputHeight, "a finite positive f32 value"));
1296
- }
1297
- if (far <= near) {
1298
- return err(invalid2("near/far", [input.near, input.far], "finite f32 near > 0 and far > near"));
1299
- }
1300
- if (focusDistance <= focal) {
1301
- return err(invalid2("focusDistance", params.focusDistance, "greater than focalLength in f32"));
1302
- }
1303
- const depthRatio = quantizeF32(near / far);
1304
- if (!Number.isFinite(depthRatio) || depthRatio <= 0) {
1305
- return err(invalid2("near/far ratio", depthRatio, "a finite positive f32 value"));
1306
- }
1307
- for (const raw of [quantizeF32(2 ** -149), 0.5, MAX_LINEAR_DEPTH_RAW]) {
1308
- const oneMinusRaw = quantizeF32(1 - raw);
1309
- const weightedRatio = quantizeF32(raw * depthRatio);
1310
- const denominator = quantizeF32(oneMinusRaw + weightedRatio);
1311
- const distance = quantizeF32(near / denominator);
1312
- if (!Number.isFinite(oneMinusRaw) || oneMinusRaw <= 0 || !Number.isFinite(weightedRatio) || !Number.isFinite(denominator) || denominator <= 0 || !Number.isFinite(distance) || distance <= 0) {
1313
- return err(invalid2("linearDepth", distance, "finite positive f32 reconstruction"));
1314
- }
1315
- }
1316
- const cocCoefficient = frameCocCoefficient(
1317
- {
1318
- focusDistance,
1319
- fStop,
1320
- sensorHeight,
1321
- focalLength: focal
1322
- },
1323
- outputHeight
1324
- );
1325
- if (!Number.isFinite(cocCoefficient) || cocCoefficient <= 0) {
1326
- return err(
1327
- invalid2("cocCoefficient", cocCoefficient, "a finite positive value representable as f32")
1328
- );
1329
- }
1330
- for (const [field, depth] of [
1331
- ["near", near],
1332
- ["far", far]
1333
- ]) {
1334
- const focusOverDepth = quantizeF32(focusDistance / depth);
1335
- const depthFactor = quantizeF32(1 - focusOverDepth);
1336
- const radius = quantizeF32(cocCoefficient * depthFactor);
1337
- if (!Number.isFinite(focusOverDepth) || !Number.isFinite(depthFactor) || !Number.isFinite(radius)) {
1338
- return err(invalid2(`coc.${field}`, radius, "a finite value representable as f32"));
1339
- }
1340
- }
1341
- return ok({
1342
- focusDistance,
1343
- fStop,
1344
- sensorHeight,
1345
- focalLength: focal,
1346
- maxRadiusPixels,
1347
- outputHeight,
1348
- near,
1349
- far,
1350
- cocCoefficient
1351
- });
1352
- }
1353
- function validateDepthOfFieldFrameParams(params, input) {
1354
- const resolved = resolveDepthOfFieldFrameValues(params, input);
1355
- return resolved.ok ? ok(void 0) : resolved;
1356
- }
1357
- function validateDepthOfFieldParams(input, camera) {
1358
- if (camera?.projection === "orthographic") {
1359
- return err(
1360
- new DepthOfFieldValidationError(
1361
- "depth-of-field-orthographic-unsupported",
1362
- { projection: "orthographic" },
1363
- "DepthOfField requires a perspective Camera",
1364
- "use a perspective Camera or remove the DepthOfField component"
1365
- )
1366
- );
1367
- }
1368
- const value = input ?? {};
1369
- const focusDistance = quantizeF32(
1370
- value.focusDistance ?? DEFAULT_DEPTH_OF_FIELD_PARAMS.focusDistance
1371
- );
1372
- const fStop = quantizeF32(value.fStop ?? DEFAULT_DEPTH_OF_FIELD_PARAMS.fStop);
1373
- const sensorHeight = quantizeF32(
1374
- value.sensorHeight ?? DEFAULT_DEPTH_OF_FIELD_PARAMS.sensorHeight
1375
- );
1376
- const maxRadiusPixels = quantizeF32(
1377
- value.maxRadiusPixels ?? DEFAULT_DEPTH_OF_FIELD_PARAMS.maxRadiusPixels
1378
- );
1379
- const qualityValue = quantizeF32(value.quality ?? DepthOfFieldQualityValue.medium);
1380
- const blurSideValue = quantizeF32(value.blurSide ?? DepthOfFieldSideValue.both);
1381
- const quality = depthOfFieldQualityFromF32(qualityValue);
1382
- const blurSide = depthOfFieldSideFromF32(blurSideValue);
1383
- if (!Number.isFinite(focusDistance) || focusDistance <= 0) {
1384
- return err(
1385
- invalid2("focusDistance", value.focusDistance ?? focusDistance, "a finite positive f32 value")
1386
- );
1387
- }
1388
- if (!Number.isFinite(fStop) || fStop < MIN_F_STOP || fStop > MAX_F_STOP) {
1389
- return err(
1390
- invalid2("fStop", value.fStop ?? fStop, "a finite f32 value in [0.7, 32]", [
1391
- MIN_F_STOP,
1392
- MAX_F_STOP
1393
- ])
1394
- );
1395
- }
1396
- if (!Number.isFinite(sensorHeight) || sensorHeight <= 0) {
1397
- return err(
1398
- invalid2("sensorHeight", value.sensorHeight ?? sensorHeight, "a finite positive f32 value")
1399
- );
1400
- }
1401
- if (!Number.isFinite(maxRadiusPixels) || maxRadiusPixels < 0 || maxRadiusPixels > 32) {
1402
- return err(
1403
- invalid2(
1404
- "maxRadiusPixels",
1405
- value.maxRadiusPixels ?? maxRadiusPixels,
1406
- "a finite f32 value in [0, 32]",
1407
- [0, 32]
1408
- )
1409
- );
1410
- }
1411
- if (quality === void 0) {
1412
- return err(invalid2("quality", qualityValue, "DepthOfFieldQualityValue.low, medium, or high"));
1413
- }
1414
- if (blurSide === void 0) {
1415
- return err(invalid2("blurSide", blurSideValue, "DepthOfFieldSideValue.both, near, or far"));
1416
- }
1417
- let focal = DEFAULT_DEPTH_OF_FIELD_PARAMS.focalLength;
1418
- if (camera !== void 0) {
1419
- const fov = quantizeF32(camera.fov);
1420
- const near = quantizeF32(camera.near);
1421
- const far = quantizeF32(camera.far);
1422
- if (!Number.isFinite(fov) || fov <= 0 || fov >= Math.PI) {
1423
- return err(invalid2("fov", camera.fov, "a finite f32 value in (0, PI)"));
1424
- }
1425
- if (!Number.isFinite(near) || !Number.isFinite(far) || near <= 0 || far <= near) {
1426
- return err(
1427
- invalid2("near/far", [camera.near, camera.far], "finite f32 near > 0 and far > near")
1428
- );
1429
- }
1430
- focal = quantizeF32(focalLength(sensorHeight, fov));
1431
- if (!Number.isFinite(focal) || focal <= 0) {
1432
- return err(invalid2("focalLength", focal, "a finite positive f32 value"));
1433
- }
1434
- if (focusDistance < near || focusDistance > far) {
1435
- return err(
1436
- invalid2("focusDistance", focusDistance, `a value in [${near}, ${far}]`, [near, far])
1437
- );
1438
- }
1439
- if (focusDistance <= focal) {
1440
- return err(
1441
- invalid2("focusDistance", focusDistance, `greater than focalLength in f32 (${focal})`)
1442
- );
1443
- }
1444
- }
1445
- return ok(
1446
- Object.freeze({
1447
- focusDistance,
1448
- fStop,
1449
- sensorHeight,
1450
- maxRadiusPixels,
1451
- quality,
1452
- blurSide,
1453
- focalLength: focal
1454
- })
1455
- );
1456
- }
1457
- function resolveDepthOfFieldParams(input, camera) {
1458
- if (input === void 0) return ok(void 0);
1459
- return validateDepthOfFieldParams(input, camera);
1460
- }
1461
- function depthOfFieldTapCount(quality) {
1462
- switch (quality) {
1463
- case "low":
1464
- return 16;
1465
- case "medium":
1466
- return 32;
1467
- case "high":
1468
- return 64;
1469
- }
1470
- }
1471
- function depthOfFieldSideCode(side) {
1472
- switch (side) {
1473
- case "both":
1474
- return DepthOfFieldSideValue.both;
1475
- case "near":
1476
- return DepthOfFieldSideValue.near;
1477
- case "far":
1478
- return DepthOfFieldSideValue.far;
1479
- }
1480
- }
1481
- function depthOfFieldQualityCode(quality) {
1482
- switch (quality) {
1483
- case "low":
1484
- return DepthOfFieldQualityValue.low;
1485
- case "medium":
1486
- return DepthOfFieldQualityValue.medium;
1487
- case "high":
1488
- return DepthOfFieldQualityValue.high;
1489
- }
1490
- }
1491
- function signedDepthOfFieldCoC(params, viewDepth, outputHeight) {
1492
- if (!Number.isFinite(viewDepth) || viewDepth <= 0 || !Number.isFinite(outputHeight) || outputHeight <= 0 || !Number.isFinite(params.focalLength) || params.focalLength <= 0 || !Number.isFinite(params.sensorHeight) || params.sensorHeight <= 0 || !Number.isFinite(params.fStop) || params.fStop <= 0 || !Number.isFinite(params.focusDistance) || params.focusDistance <= params.focalLength) {
1493
- return 0;
1494
- }
1495
- const focusDistance = quantizeF32(params.focusDistance);
1496
- const depth = quantizeF32(viewDepth);
1497
- const focalLength2 = quantizeF32(params.focalLength);
1498
- const sensorHeight = quantizeF32(params.sensorHeight);
1499
- const fStop = quantizeF32(params.fStop);
1500
- const coefficient = frameCocCoefficient(
1501
- { focusDistance, focalLength: focalLength2, sensorHeight, fStop },
1502
- outputHeight
1503
- );
1504
- const depthFactor = quantizeF32(1 - quantizeF32(focusDistance / depth));
1505
- const radius = quantizeF32(coefficient * depthFactor);
1506
- const limit = Number.isFinite(params.maxRadiusPixels) ? quantizeF32(params.maxRadiusPixels) : Number.POSITIVE_INFINITY;
1507
- return Math.max(-limit, Math.min(limit, Number.isFinite(radius) ? radius : 0));
1508
- }
1509
- function packDepthOfFieldParams(params, input) {
1510
- const frameValues = resolveDepthOfFieldFrameValues(params, input);
1511
- if (!frameValues.ok) throw frameValues.error;
1512
- const {
1513
- focusDistance,
1514
- fStop,
1515
- sensorHeight,
1516
- focalLength: focal,
1517
- outputHeight,
1518
- maxRadiusPixels,
1519
- near,
1520
- far,
1521
- cocCoefficient
1522
- } = frameValues.value;
1523
- const payload = new Float32Array(DEPTH_OF_FIELD_PARAMS_BYTE_SIZE / 4);
1524
- payload.set([
1525
- focusDistance,
1526
- fStop,
1527
- sensorHeight,
1528
- focal,
1529
- outputHeight,
1530
- maxRadiusPixels,
1531
- depthOfFieldSideCode(params.blurSide),
1532
- depthOfFieldQualityCode(params.quality),
1533
- near,
1534
- far,
1535
- input.useTemporalDepth ? 1 : 0,
1536
- 0,
1537
- // row2.w reserved
1538
- cocCoefficient,
1539
- // row3.x / WGSL reserved.x
1540
- 0,
1541
- 0,
1542
- 0
1543
- ]);
1544
- return new Uint8Array(payload.buffer);
1545
- }
1546
- function hasVolumetricFogCapability(caps, shaders) {
1547
- return caps.compute && caps.storageTexture && shaders !== void 0;
1548
- }
1549
- function resolveVolumetricFogLightPair(world, point, spot) {
1550
- const expected = "PointLight + SpotLight in the same World";
1551
- if (!world.get(point, Entity).ok || !world.get(spot, Entity).ok) {
1552
- return {
1553
- status: "unresolved",
1554
- reason: "missing-entity",
1555
- point,
1556
- spot,
1557
- expected,
1558
- actual: "point or spot entity is absent from this World",
1559
- hint: "assign two live entities from the same World and retry"
1560
- };
1561
- }
1562
- if (point === spot) {
1563
- return {
1564
- status: "unresolved",
1565
- reason: "same-entity",
1566
- point,
1567
- spot,
1568
- expected,
1569
- actual: "PointLight and SpotLight share one EntityHandle",
1570
- hint: "spawn PointLight and SpotLight on two different entities"
1571
- };
1572
- }
1573
- const pointValid = world.hasComponent(point, PointLight) && world.hasComponent(point, Transform);
1574
- const spotValid = world.hasComponent(spot, SpotLight) && world.hasComponent(spot, Transform);
1575
- if (!pointValid || !spotValid) {
1576
- return {
1577
- status: "unresolved",
1578
- reason: "wrong-component",
1579
- point,
1580
- spot,
1581
- expected,
1582
- actual: `pointValid=${pointValid}; spotValid=${spotValid}`,
1583
- hint: "attach PointLight and SpotLight with Transform to separate same-World entities"
1584
- };
1585
- }
1586
- return { status: "available", mode: "point-spot", point, spot };
1587
- }
1588
- function resolveSelectedVolumetricLight(world, entity) {
1589
- const expected = "DirectionalLight | PointLight | SpotLight";
1590
- if (!world.get(entity, Entity).ok) {
1591
- return {
1592
- status: "unresolved",
1593
- reason: "missing-entity",
1594
- entity,
1595
- expected,
1596
- actual: "missing or foreign World entity",
1597
- hint: "assign VolumetricFog.light to a live DirectionalLight or SpotLight in this World"
1598
- };
1599
- }
1600
- const hasDirectional = world.hasComponent(entity, DirectionalLight);
1601
- const hasSpot = world.hasComponent(entity, SpotLight);
1602
- if (hasDirectional && hasSpot) {
1603
- return {
1604
- status: "unresolved",
1605
- reason: "ambiguous",
1606
- entity,
1607
- expected,
1608
- actual: "DirectionalLight + SpotLight",
1609
- hint: "remove one mutually exclusive light component from the selected entity"
1610
- };
1611
- }
1612
- if (hasDirectional) return { status: "available", entity, kind: "directional" };
1613
- if (world.hasComponent(entity, PointLight) && world.hasComponent(entity, Transform)) {
1614
- return { status: "available", entity, kind: "point" };
1615
- }
1616
- if (hasSpot && world.hasComponent(entity, Transform)) {
1617
- return { status: "available", entity, kind: "spot" };
1618
- }
1619
- const actual = hasSpot ? "SpotLight without Transform" : world.hasComponent(entity, PointLight) ? "PointLight" : "other component";
1620
- return {
1621
- status: "unresolved",
1622
- reason: "wrong-component",
1623
- entity,
1624
- expected,
1625
- actual,
1626
- hint: "add exactly one supported light component and a Transform for PointLight or SpotLight in the same World"
1627
- };
1628
- }
1629
- function resolveIntegratedVolumeConsumer(resource, consumer) {
1630
- return { consumer, resource };
1631
- }
1632
- var FACE_ORIENTATION = [
1633
- { direction: [1, 0, 0], up: [0, 1, 0] },
1634
- { direction: [-1, 0, 0], up: [0, 1, 0] },
1635
- { direction: [0, 1, 0], up: [0, 0, -1] },
1636
- { direction: [0, -1, 0], up: [0, 0, 1] },
1637
- { direction: [0, 0, 1], up: [0, 1, 0] },
1638
- { direction: [0, 0, -1], up: [0, 1, 0] }
1639
- ];
1640
- function assertRange(near, far) {
1641
- if (!Number.isFinite(near) || near <= 0 || !Number.isFinite(far) || far <= near) {
1642
- throw new RangeError("CubeCamera requires finite near > 0 and far > near.");
1643
- }
1644
- }
1645
- function buildCubeCameraFaceViews(input) {
1646
- assertRange(input.near, input.far);
1647
- const views = [];
1648
- for (const [index, face] of CUBE_CAMERA_FACE_ORDER.entries()) {
1649
- const orientation = FACE_ORIENTATION[index];
1650
- if (orientation === void 0)
1651
- throw new Error(`CubeCamera face orientation missing at ${index}`);
1652
- const target = [
1653
- (input.position[0] ?? 0) + orientation.direction[0],
1654
- (input.position[1] ?? 0) + orientation.direction[1],
1655
- (input.position[2] ?? 0) + orientation.direction[2]
1656
- ];
1657
- const view = mat4.lookAt(mat4.create(), input.position, target, orientation.up);
1658
- const projection = mat4.perspective(mat4.create(), Math.PI / 2, 1, input.near, input.far);
1659
- const viewProjection = mat4.multiply(mat4.create(), projection, view);
1660
- views.push({
1661
- position: input.position,
1662
- face,
1663
- direction: orientation.direction,
1664
- up: orientation.up,
1665
- near: input.near,
1666
- far: input.far,
1667
- view,
1668
- projection,
1669
- viewProjection
1670
- });
1671
- }
1672
- return views;
1673
- }
1674
-
1675
- // src/mesh-material-bindings.ts
1676
- var EMPTY_RESIDENCY = Object.freeze({
1677
- readiness: "pending",
1678
- samplers: Object.freeze([]),
1679
- textures: Object.freeze([])
1680
- });
1681
- function projectMeshMaterialBindingObservation(input) {
1682
- const residency = input.bindings.map((_, index) => {
1683
- const value = input.residency?.[index] ?? EMPTY_RESIDENCY;
1684
- return Object.freeze({
1685
- ...value,
1686
- samplers: Object.freeze(value.samplers.map((sampler) => Object.freeze({ ...sampler }))),
1687
- textures: Object.freeze(value.textures.map((texture) => Object.freeze({ ...texture }))),
1688
- ...value.preparationFailure === void 0 ? {} : {
1689
- preparationFailure: Object.freeze({
1690
- ...value.preparationFailure,
1691
- ...value.preparationFailure.detail === void 0 ? {} : { detail: Object.freeze({ ...value.preparationFailure.detail }) }
1692
- })
1693
- }
1694
- });
1695
- });
1696
- return {
1697
- worldId: input.worldId,
1698
- ...input.worldIdentity === void 0 ? {} : { worldIdentity: input.worldIdentity },
1699
- entityKey: input.entityKey,
1700
- bindings: Object.freeze([...input.bindings]),
1701
- diagnostics: Object.freeze([...input.diagnostics]),
1702
- residency: Object.freeze(residency)
1703
- };
1704
- }
1705
- function summarizeMeshMaterialBindings(observations) {
1706
- let ready = 0;
1707
- let pending = 0;
1708
- let failed = 0;
1709
- let lastKnownGood = 0;
1710
- let textureCount = 0;
1711
- let samplerCount = 0;
1712
- for (const observation of observations) {
1713
- for (const residency of observation.residency) {
1714
- switch (residency.readiness) {
1715
- case "ready":
1716
- ready += 1;
1717
- break;
1718
- case "pending":
1719
- pending += 1;
1720
- break;
1721
- case "failed":
1722
- failed += 1;
1723
- break;
1724
- case "last-known-good":
1725
- lastKnownGood += 1;
1726
- break;
1727
- }
1728
- textureCount += residency.textures.length;
1729
- samplerCount += residency.samplers.length;
1730
- }
1731
- }
1732
- return {
1733
- total: ready + pending + failed + lastKnownGood,
1734
- ready,
1735
- pending,
1736
- failed,
1737
- lastKnownGood,
1738
- textureCount,
1739
- samplerCount
1740
- };
1741
- }
1742
- function resolveMeshMaterialBindings(mesh, rendererOverrides, deps) {
1743
- const bindings = [];
1744
- const diagnostics = [];
1745
- if (!Array.isArray(mesh.materialSlots)) {
1746
- return { ok: false, code: "mesh-material-slots-missing" };
1747
- }
1748
- if (rendererOverrides.length > mesh.materialSlots.length) {
1749
- diagnostics.push({
1750
- code: "mesh-renderer-material-override-overflow",
1751
- slotIndex: mesh.materialSlots.length
1752
- });
1753
- }
1754
- for (let slotIndex = 0; slotIndex < mesh.materialSlots.length; slotIndex++) {
1755
- const override = rendererOverrides[slotIndex] ?? 0;
1756
- if (override !== 0 && deps.isValidOverride(override)) {
1757
- bindings.push({ handle: override, source: "renderer-override" });
1758
- continue;
1759
- }
1760
- if (override !== 0) {
1761
- diagnostics.push({
1762
- code: "mesh-renderer-material-override-invalid",
1763
- slotIndex,
1764
- handle: override
1765
- });
1766
- }
1767
- const declaredDefault = mesh.materialSlots[slotIndex]?.defaultMaterial;
1768
- if (declaredDefault !== void 0) {
1769
- const handle = deps.resolveMeshDefault(declaredDefault);
1770
- if (handle === void 0) {
1771
- return {
1772
- ok: false,
1773
- code: "mesh-default-material-not-ready",
1774
- slotIndex,
1775
- defaultMaterial: declaredDefault
1776
- };
1777
- }
1778
- bindings.push({ handle, source: "mesh-default" });
1779
- continue;
1780
- }
1781
- bindings.push({ handle: 0, source: "engine-default" });
1782
- }
1783
- return { ok: true, bindings, diagnostics };
1784
- }
1785
- function resolveVisibility(world, hierarchy = projectHierarchy(world)) {
1786
- const query = world.query({ read: [Visibility] });
1787
- const visitVisibilityRows = (visit) => {
1788
- if (!query.ok) return;
1789
- const spans = query.value.spans();
1790
- if (spans.ok) {
1791
- for (const span of spans.value) {
1792
- const states = span.get(Visibility).state;
1793
- for (let index = 0; index < span.length; index += 1) {
1794
- visit(span.entities[index], states[index] ?? 0);
1795
- }
1796
- }
1797
- return;
1798
- }
1799
- for (const row of query.value) {
1800
- visit(row.entity, row.get(Visibility).state);
1801
- }
1802
- };
1803
- let intentCount = 0;
1804
- let hasAnyHiddenIntent = false;
1805
- visitVisibilityRows((_entity, rawState) => {
1806
- intentCount += 1;
1807
- if (rawState === VisibilityStateValue.hidden) {
1808
- hasAnyHiddenIntent = true;
1809
- }
1810
- });
1811
- let resolveEntity;
1812
- let hasIntent;
1813
- const ensureResolver = () => {
1814
- if (resolveEntity !== void 0) return;
1815
- const intentByEntity = /* @__PURE__ */ new Map();
1816
- visitVisibilityRows((entity, rawState) => {
1817
- const intent = visibilityStateFromU32(rawState);
1818
- if (intent !== void 0) {
1819
- intentByEntity.set(entity, intent);
1820
- }
1821
- });
1822
- hasIntent = (entity) => intentByEntity.has(entity);
1823
- const resolved = /* @__PURE__ */ new Map();
1824
- const resolving = /* @__PURE__ */ new Set();
1825
- resolveEntity = (entity) => {
1826
- const existing = resolved.get(entity);
1827
- if (existing !== void 0) return existing;
1828
- if (resolving.has(entity)) return void 0;
1829
- const intent = intentByEntity.get(entity) ?? "inherited";
1830
- resolving.add(entity);
1831
- let result;
1832
- if (intent === "hidden") {
1833
- result = { intent, effective: "hidden", source: "self" };
1834
- } else if (intent === "visible") {
1835
- result = { intent, effective: "visible", source: "self" };
1836
- } else {
1837
- const parent = hierarchy.getParent(entity);
1838
- const parentResult = parent === void 0 ? void 0 : resolveEntity?.(parent);
1839
- result = parentResult === void 0 ? { intent, effective: "visible", source: "default" } : { intent, effective: parentResult.effective, source: "parent" };
1840
- }
1841
- resolving.delete(entity);
1842
- resolved.set(entity, result);
1843
- return result;
1844
- };
1845
- };
1846
- const snapshot = {
1847
- diagnostics: hierarchy.diagnostics,
1848
- hasAnyIntent: intentCount > 0,
1849
- hasAnyHiddenIntent,
1850
- get(entity) {
1851
- ensureResolver();
1852
- return hasIntent?.(entity) ? resolveEntity?.(entity) : void 0;
1853
- },
1854
- effective(entity) {
1855
- ensureResolver();
1856
- return resolveEntity?.(entity)?.effective ?? "visible";
1857
- }
1858
- };
1859
- return snapshot;
1860
- }
1861
- var VolumetricFog = defineComponent("VolumetricFog", {
1862
- light: { type: "entity" },
1863
- spotLight: { type: "entity" },
1864
- density: { type: "shared<TextureAsset>", simulationTransient: true },
1865
- boundsMin: { type: "array<f32, 3>" },
1866
- boundsMax: { type: "array<f32, 3>" },
1867
- extinction: { type: "array<f32, 3>" },
1868
- albedo: { type: "array<f32, 3>" },
1869
- emission: { type: "array<f32, 3>" },
1870
- anisotropy: { type: "f32", default: 0 },
1871
- maxDistance: { type: "f32", default: 100 }
1872
- });
1873
- function finiteVector(value) {
1874
- return value.every(Number.isFinite);
1875
- }
1876
- function validBounds(bounds) {
1877
- if (!finiteVector(bounds.min) || !finiteVector(bounds.max)) return false;
1878
- return bounds.max.every((value, index) => value > (bounds.min[index] ?? value));
1879
- }
1880
- function validRange(value, min, max = Infinity) {
1881
- return value.every((entry) => Number.isFinite(entry) && entry >= min && entry <= max);
1882
- }
1883
- function validateVolumetricFog(input) {
1884
- const ownerCount = input.ownerCount ?? 1;
1885
- if (ownerCount !== 1) return err(new VolumeOwnerConflictError(ownerCount));
1886
- if (input.density.shape.viewDimension !== "3d" || input.density.colorSpace === "srgb") {
1887
- return err(
1888
- new VolumeDensityShapeMismatchError(input.density.guid, input.density.shape.viewDimension)
1889
- );
1890
- }
1891
- if (!validBounds(input.bounds)) return err(new VolumeInvalidBoundsError(input.bounds));
1892
- if (!validRange(input.extinction, 0) || !validRange(input.albedo, 0, 1) || !validRange(input.emission, 0) || !Number.isFinite(input.anisotropy) || input.anisotropy <= -1 || input.anisotropy >= 1 || !Number.isFinite(input.maxDistance) || input.maxDistance <= 0) {
1893
- return err(new VolumeInvalidParametersError(input));
1894
- }
1895
- return ok({ ...input, ownerCount: 1 });
1896
- }
1897
- function extractVolumetricFog(inputs) {
1898
- if (inputs.length === 0) return ok({ status: "off" });
1899
- if (inputs.length !== 1) return err(new VolumeOwnerConflictError(inputs.length));
1900
- const validated = validateVolumetricFog(inputs[0]);
1901
- if (!validated.ok) return validated;
1902
- return ok({ status: "available", fog: validated.value });
1903
- }
1904
-
1905
- export { ANTIALIAS_FXAA, ANTIALIAS_MSAA, ANTIALIAS_NONE, ANTIALIAS_TAA, Atmosphere, BLOOM_DISABLED, BLOOM_ENABLED, CAMERA_BLOOM_INTENSITY_MAX, CAMERA_BLOOM_INTENSITY_MIN, CAMERA_BLOOM_SCATTER_MAX, CAMERA_BLOOM_SCATTER_MIN, CAMERA_BLOOM_SOFT_KNEE_MAX, CAMERA_BLOOM_SOFT_KNEE_MIN, CAMERA_BLOOM_THRESHOLD_MAX, CAMERA_BLOOM_THRESHOLD_MIN, CAMERA_EXPOSURE_MODE_AUTO, CAMERA_EXPOSURE_MODE_MANUAL, CAMERA_PROJECTION_ORTHOGRAPHIC, CAMERA_PROJECTION_PERSPECTIVE, CAMERA_TEMPERATURE_MAX, CAMERA_TEMPERATURE_MIN, CAMERA_TINT_MAX, CAMERA_TINT_MIN, CUBE_CAMERA_FACE_ORDER, CUBE_CAMERA_UPDATE_CONTINUOUS, CUBE_CAMERA_UPDATE_ONCE, CUBE_CAMERA_UPDATE_ON_DEMAND, Camera, CameraError, CubeCamera, DEFAULT_DEPTH_OF_FIELD_PARAMS, DEPTH_OF_FIELD_PARAMS_BYTE_SIZE, DepthOfField, DepthOfFieldQualityValue, DepthOfFieldSideValue, DepthOfFieldValidationError, DirectionalLight, DirectionalShadowFilterValue, DynamicResolution, Fog, Instances, Layer, LightProbe, Lines, MeshFilter, MeshRenderer, MotionBlur, PointLight, PointLightShadow, PointShapeValue, Points, PostProcessParams, REFLECTION_PROBE_UPDATE_CONTINUOUS, REFLECTION_PROBE_UPDATE_ONCE, REFLECTION_PROBE_UPDATE_ON_CHANGE, RectAreaLight, ReflectionProbe, SKYBOX_MODE_CUBEMAP, SKYLIGHT_RECOVERY_FALLBACK, SceneInstance, ScreenSpaceReflection, SkyboxBackground, Skylight, SortKey, SpotLight, SunCardinalityError, TONEMAP_ACES_FILMIC, TONEMAP_AGX, TONEMAP_CINEON, TONEMAP_LINEAR, TONEMAP_NEUTRAL, TONEMAP_NONE, TONEMAP_REINHARD, TONEMAP_REINHARD_EXTENDED, Visibility, VisibilityStateValue, VolumetricFog, antialiasFromF32, buildCubeCameraFaceViews, cameraExposureFromColumns, cameraProjectionFromF32, computeInvRangeSquared, cubeCameraUpdateIntentFromF32, cubeCameraUpdateIntentToF32, degToCos, depthOfFieldQualityCode, depthOfFieldQualityFromF32, depthOfFieldRequestFailure, depthOfFieldSideCode, depthOfFieldSideFromF32, depthOfFieldTapCount, directionalShadowQualityFromF32, extractVolumetricFog, hasVolumetricFogCapability, orthographic, packDepthOfFieldParams, perspective, pointShapeFromU32, projectMeshMaterialBindingObservation, reflectionProbeUpdateIntentFromF32, reflectionProbeUpdateIntentToF32, resolveDepthOfFieldFrameParams, resolveDepthOfFieldParams, resolveIntegratedVolumeConsumer, resolveMeshMaterialBindings, resolveSelectedVolumetricLight, resolveVisibility, resolveVolumetricFogLightPair, selectEnvironment, signedDepthOfFieldCoC, summarizeMeshMaterialBindings, tonemapFromF32, tonemapToU32, validateCameraBloom, validateCameraColorGrading, validateCameraExposure, validateDepthOfFieldFrameParams, validateDepthOfFieldParams, validateDirection, validateDirectionalLightData, validateDynamicResolutionCamera, validateDynamicResolutionParameters, validateLightProbeData, validatePointLightData, validatePointLightShadowData, validateRectAreaLightData, validateSpotLightData, validateVolumetricFog, visibilityStateFromU32 };
1906
- //# sourceMappingURL=chunk-PLAXOOX5.mjs.map
1907
- //# sourceMappingURL=chunk-PLAXOOX5.mjs.map