@forgeax/engine-render 0.1.20 → 0.1.23

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 (645) hide show
  1. package/README.md +365 -29
  2. package/dist/assembly/backend-contract.d.ts +13 -0
  3. package/dist/assembly/backend-contract.d.ts.map +1 -1
  4. package/dist/assembly/device-feature-admission.d.ts +18 -0
  5. package/dist/assembly/device-feature-admission.d.ts.map +1 -0
  6. package/dist/assembly/directional-shadow-inspection.d.ts +38 -0
  7. package/dist/assembly/directional-shadow-inspection.d.ts.map +1 -0
  8. package/dist/assembly/factory.d.ts +30 -19
  9. package/dist/assembly/factory.d.ts.map +1 -1
  10. package/dist/assembly/host-contract.d.ts +19 -0
  11. package/dist/assembly/host-contract.d.ts.map +1 -1
  12. package/dist/assembly/render-target-host.d.ts +46 -0
  13. package/dist/assembly/render-target-host.d.ts.map +1 -0
  14. package/dist/assets/render-asset-port.d.ts.map +1 -1
  15. package/dist/authoring.mjs +4 -1
  16. package/dist/authoring.mjs.map +1 -1
  17. package/dist/capture/cube-views.d.ts +21 -0
  18. package/dist/capture/cube-views.d.ts.map +1 -0
  19. package/dist/capture/scheduler.d.ts +54 -0
  20. package/dist/capture/scheduler.d.ts.map +1 -0
  21. package/dist/{chunk-PCHBPYML.mjs → chunk-4L3P6DT5.mjs} +2 -2
  22. package/dist/chunk-4L3P6DT5.mjs.map +1 -0
  23. package/dist/{chunk-VFPLTKCU.mjs → chunk-4NPUASZR.mjs} +15 -4
  24. package/dist/chunk-4NPUASZR.mjs.map +1 -0
  25. package/dist/chunk-DIYW3M5D.mjs +5085 -0
  26. package/dist/chunk-DIYW3M5D.mjs.map +1 -0
  27. package/dist/chunk-FBC4R44J.mjs +1003 -0
  28. package/dist/chunk-FBC4R44J.mjs.map +1 -0
  29. package/dist/{chunk-CDTWTHZR.mjs → chunk-FF7K3FSO.mjs} +474 -168
  30. package/dist/chunk-FF7K3FSO.mjs.map +1 -0
  31. package/dist/chunk-HZUPSYW7.mjs +1104 -0
  32. package/dist/chunk-HZUPSYW7.mjs.map +1 -0
  33. package/dist/{chunk-TBQJOK2L.mjs → chunk-QODA5UKU.mjs} +321 -269
  34. package/dist/chunk-QODA5UKU.mjs.map +1 -0
  35. package/dist/chunk-YALPS44A.mjs +296 -0
  36. package/dist/chunk-YALPS44A.mjs.map +1 -0
  37. package/dist/{chunk-4XINDLAY.mjs → chunk-ZUWKAZ2I.mjs} +1963 -2178
  38. package/dist/chunk-ZUWKAZ2I.mjs.map +1 -0
  39. package/dist/cluster-binner.d.ts +5 -0
  40. package/dist/cluster-binner.d.ts.map +1 -1
  41. package/dist/components/camera.d.ts +1 -0
  42. package/dist/components/camera.d.ts.map +1 -1
  43. package/dist/components/cube-camera.d.ts +20 -0
  44. package/dist/components/cube-camera.d.ts.map +1 -0
  45. package/dist/components/directional-light.d.ts +11 -2
  46. package/dist/components/directional-light.d.ts.map +1 -1
  47. package/dist/components/directional-shadow-filter.d.ts +25 -0
  48. package/dist/components/directional-shadow-filter.d.ts.map +1 -0
  49. package/dist/components/index.d.ts +5 -0
  50. package/dist/components/index.d.ts.map +1 -1
  51. package/dist/components/light-helpers.d.ts +4 -0
  52. package/dist/components/light-helpers.d.ts.map +1 -1
  53. package/dist/components/light-probe.d.ts +9 -0
  54. package/dist/components/light-probe.d.ts.map +1 -0
  55. package/dist/components/rect-area-light.d.ts +12 -0
  56. package/dist/components/rect-area-light.d.ts.map +1 -0
  57. package/dist/components/reflection-probe.d.ts +17 -0
  58. package/dist/components/reflection-probe.d.ts.map +1 -0
  59. package/dist/components/scene-instance.d.ts +4 -0
  60. package/dist/components/scene-instance.d.ts.map +1 -1
  61. package/dist/components/spot-light.d.ts +3 -0
  62. package/dist/components/spot-light.d.ts.map +1 -1
  63. package/dist/construct-renderer.mjs +14836 -9620
  64. package/dist/construct-renderer.mjs.map +1 -1
  65. package/dist/device/gpu-residency.d.ts +8 -1
  66. package/dist/device/gpu-residency.d.ts.map +1 -1
  67. package/dist/device/lifecycle-transaction.d.ts +2 -0
  68. package/dist/device/lifecycle-transaction.d.ts.map +1 -0
  69. package/dist/environment/frame.d.ts.map +1 -1
  70. package/dist/environment/lifecycle.d.ts +5 -0
  71. package/dist/environment/lifecycle.d.ts.map +1 -1
  72. package/dist/errors/gpu-driven.d.ts +26 -0
  73. package/dist/errors/gpu-driven.d.ts.map +1 -0
  74. package/dist/errors/index.d.ts +1 -0
  75. package/dist/errors/index.d.ts.map +1 -1
  76. package/dist/errors/recover.d.ts +9 -1
  77. package/dist/errors/recover.d.ts.map +1 -1
  78. package/dist/errors/render.d.ts +166 -93
  79. package/dist/errors/render.d.ts.map +1 -1
  80. package/dist/extract/directional-shadow-projection.d.ts +23 -0
  81. package/dist/extract/directional-shadow-projection.d.ts.map +1 -0
  82. package/dist/extract/environment.d.ts +14 -0
  83. package/dist/extract/environment.d.ts.map +1 -1
  84. package/dist/extract/gpu-driven.d.ts +50 -0
  85. package/dist/extract/gpu-driven.d.ts.map +1 -0
  86. package/dist/extract/visibility.d.ts.map +1 -1
  87. package/dist/features/fullscreen.d.ts.map +1 -1
  88. package/dist/features/targets.d.ts.map +1 -1
  89. package/dist/features/types.d.ts +10 -0
  90. package/dist/features/types.d.ts.map +1 -1
  91. package/dist/fullscreen-post-process-pass.d.ts +13 -2
  92. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  93. package/dist/gpu-driven/batch-topology.d.ts +34 -0
  94. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  95. package/dist/gpu-driven/prepared-draw.d.ts +63 -0
  96. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -0
  97. package/dist/gpu-driven/production-raster.d.ts +97 -2
  98. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  99. package/dist/gpu-driven/view-gpu.d.ts +64 -1
  100. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  101. package/dist/gpu-scene-schema.d.ts +14 -0
  102. package/dist/gpu-scene-schema.d.ts.map +1 -1
  103. package/dist/gpu-scene.d.ts +8 -1
  104. package/dist/gpu-scene.d.ts.map +1 -1
  105. package/dist/gpu-usage.d.ts +0 -1
  106. package/dist/gpu-usage.d.ts.map +1 -1
  107. package/dist/hdrp-buffers.d.ts +21 -19
  108. package/dist/hdrp-buffers.d.ts.map +1 -1
  109. package/dist/ibl/IblPipelineCache.d.ts +4 -0
  110. package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
  111. package/dist/ibl/kernel-cache.d.ts +36 -0
  112. package/dist/ibl/kernel-cache.d.ts.map +1 -0
  113. package/dist/index.d.ts +39 -3
  114. package/dist/index.d.ts.map +1 -1
  115. package/dist/index.mjs +91 -6
  116. package/dist/index.mjs.map +1 -1
  117. package/dist/inspection-types.d.ts +214 -1
  118. package/dist/inspection-types.d.ts.map +1 -1
  119. package/dist/instances-derived-bounds.d.ts +50 -0
  120. package/dist/instances-derived-bounds.d.ts.map +1 -0
  121. package/dist/internal.d.ts +9 -0
  122. package/dist/internal.d.ts.map +1 -1
  123. package/dist/internal.mjs +23 -2
  124. package/dist/internal.mjs.map +1 -1
  125. package/dist/light-buffer-layout.d.ts +58 -140
  126. package/dist/light-buffer-layout.d.ts.map +1 -1
  127. package/dist/materials.d.ts.map +1 -1
  128. package/dist/mesh-material-bindings.d.ts +54 -0
  129. package/dist/mesh-material-bindings.d.ts.map +1 -1
  130. package/dist/pbr-pipeline.d.ts +38 -14
  131. package/dist/pbr-pipeline.d.ts.map +1 -1
  132. package/dist/pipeline/standard-forward-lane.d.ts +2 -1
  133. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  134. package/dist/pipeline/standard-lighting/errors.d.ts +4 -0
  135. package/dist/pipeline/standard-lighting/errors.d.ts.map +1 -0
  136. package/dist/pipeline/standard-lighting/graph.d.ts +24 -0
  137. package/dist/pipeline/standard-lighting/graph.d.ts.map +1 -0
  138. package/dist/pipeline/standard-lighting/inspection.d.ts +38 -0
  139. package/dist/pipeline/standard-lighting/inspection.d.ts.map +1 -0
  140. package/dist/pipeline/standard-lighting/layout.d.ts +28 -0
  141. package/dist/pipeline/standard-lighting/layout.d.ts.map +1 -0
  142. package/dist/pipeline/standard-lighting/light-frame.d.ts +33 -0
  143. package/dist/pipeline/standard-lighting/light-frame.d.ts.map +1 -0
  144. package/dist/pipeline/standard-lighting/membership.d.ts +14 -0
  145. package/dist/pipeline/standard-lighting/membership.d.ts.map +1 -0
  146. package/dist/pipeline/standard-lighting/prepare.d.ts +16 -0
  147. package/dist/pipeline/standard-lighting/prepare.d.ts.map +1 -0
  148. package/dist/pipeline/standard-lighting/topology.d.ts +45 -0
  149. package/dist/pipeline/standard-lighting/topology.d.ts.map +1 -0
  150. package/dist/pipeline/standard-lighting/transport.d.ts +36 -0
  151. package/dist/pipeline/standard-lighting/transport.d.ts.map +1 -0
  152. package/dist/pipeline/standard-pipeline.d.ts +4 -13
  153. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  154. package/dist/pipeline/standard-post.d.ts.map +1 -1
  155. package/dist/pipeline/standard-profile.d.ts +5 -26
  156. package/dist/pipeline/standard-profile.d.ts.map +1 -1
  157. package/dist/pipeline-builder.d.ts +2 -0
  158. package/dist/pipeline-builder.d.ts.map +1 -1
  159. package/dist/pipeline-spec.d.ts +40 -7
  160. package/dist/pipeline-spec.d.ts.map +1 -1
  161. package/dist/plugin.d.ts.map +1 -1
  162. package/dist/point-shadow-inspection.d.ts +21 -0
  163. package/dist/point-shadow-inspection.d.ts.map +1 -0
  164. package/dist/prepare/extended-lighting/ltc-resources.d.ts +31 -0
  165. package/dist/prepare/extended-lighting/ltc-resources.d.ts.map +1 -0
  166. package/dist/prepare/extended-lighting/resources.d.ts +72 -0
  167. package/dist/prepare/extended-lighting/resources.d.ts.map +1 -0
  168. package/dist/prepare/extended-lighting/spot-modifiers.d.ts +42 -0
  169. package/dist/prepare/extended-lighting/spot-modifiers.d.ts.map +1 -0
  170. package/dist/prepare/extended-lighting/state.d.ts +24 -0
  171. package/dist/prepare/extended-lighting/state.d.ts.map +1 -0
  172. package/dist/record/frame-lighting.d.ts +33 -36
  173. package/dist/record/frame-lighting.d.ts.map +1 -1
  174. package/dist/record/frame-snapshot.d.ts +78 -24
  175. package/dist/record/frame-snapshot.d.ts.map +1 -1
  176. package/dist/record/frame-targets.d.ts +5 -0
  177. package/dist/record/frame-targets.d.ts.map +1 -1
  178. package/dist/record/frame.d.ts +16 -6
  179. package/dist/record/frame.d.ts.map +1 -1
  180. package/dist/record/gpu-pass-timing/contract.d.ts +96 -0
  181. package/dist/record/gpu-pass-timing/contract.d.ts.map +1 -0
  182. package/dist/record/gpu-pass-timing/errors.d.ts +18 -0
  183. package/dist/record/gpu-pass-timing/errors.d.ts.map +1 -0
  184. package/dist/record/gpu-pass-timing/index.d.ts +8 -0
  185. package/dist/record/gpu-pass-timing/index.d.ts.map +1 -0
  186. package/dist/record/gpu-pass-timing/parser.d.ts +11 -0
  187. package/dist/record/gpu-pass-timing/parser.d.ts.map +1 -0
  188. package/dist/record/gpu-pass-timing/session.d.ts +43 -0
  189. package/dist/record/gpu-pass-timing/session.d.ts.map +1 -0
  190. package/dist/record/gpu-timing.d.ts +20 -3
  191. package/dist/record/gpu-timing.d.ts.map +1 -1
  192. package/dist/record/helpers.d.ts +0 -20
  193. package/dist/record/helpers.d.ts.map +1 -1
  194. package/dist/record/main-pass-geometry.d.ts +6 -1
  195. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  196. package/dist/record/main-pass-material.d.ts +25 -2
  197. package/dist/record/main-pass-material.d.ts.map +1 -1
  198. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  199. package/dist/record/main-pass.d.ts +2 -0
  200. package/dist/record/main-pass.d.ts.map +1 -1
  201. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  202. package/dist/record/render-context.d.ts +98 -6
  203. package/dist/record/render-context.d.ts.map +1 -1
  204. package/dist/record/shadow-pass.d.ts.map +1 -1
  205. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  206. package/dist/record/typed-frame-graph.d.ts +119 -4
  207. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  208. package/dist/record/view-ubo.d.ts +7 -5
  209. package/dist/record/view-ubo.d.ts.map +1 -1
  210. package/dist/reflection/filter.d.ts +22 -0
  211. package/dist/reflection/filter.d.ts.map +1 -0
  212. package/dist/reflection/gpu-table.d.ts +25 -0
  213. package/dist/reflection/gpu-table.d.ts.map +1 -0
  214. package/dist/reflection/inspection.d.ts +10 -0
  215. package/dist/reflection/inspection.d.ts.map +1 -0
  216. package/dist/reflection/projection.d.ts +140 -0
  217. package/dist/reflection/projection.d.ts.map +1 -0
  218. package/dist/reflection/record-owner.d.ts +60 -0
  219. package/dist/reflection/record-owner.d.ts.map +1 -0
  220. package/dist/render-contract.d.ts +62 -14
  221. package/dist/render-contract.d.ts.map +1 -1
  222. package/dist/render-graph-primitives.d.ts +1 -0
  223. package/dist/render-graph-primitives.d.ts.map +1 -1
  224. package/dist/render-pipeline.d.ts +49 -2
  225. package/dist/render-pipeline.d.ts.map +1 -1
  226. package/dist/render-system-extract.d.ts +160 -31
  227. package/dist/render-system-extract.d.ts.map +1 -1
  228. package/dist/render-system.d.ts +28 -2
  229. package/dist/render-system.d.ts.map +1 -1
  230. package/dist/renderer.d.ts +43 -0
  231. package/dist/renderer.d.ts.map +1 -0
  232. package/dist/scene/probe-blend-record.d.ts +22 -0
  233. package/dist/scene/probe-blend-record.d.ts.map +1 -0
  234. package/dist/scene/probe-blend.d.ts +142 -0
  235. package/dist/scene/probe-blend.d.ts.map +1 -0
  236. package/dist/scene/render-scene-types.d.ts +0 -6
  237. package/dist/scene/render-scene-types.d.ts.map +1 -1
  238. package/dist/scene/render-scene.d.ts +117 -9
  239. package/dist/scene/render-scene.d.ts.map +1 -1
  240. package/dist/scene/visibility/bounds.d.ts +20 -0
  241. package/dist/scene/visibility/bounds.d.ts.map +1 -0
  242. package/dist/scene/visibility/budget.d.ts +16 -0
  243. package/dist/scene/visibility/budget.d.ts.map +1 -0
  244. package/dist/scene/visibility/facet.d.ts +73 -0
  245. package/dist/scene/visibility/facet.d.ts.map +1 -0
  246. package/dist/scene/visibility/gpu-frame-timing.d.ts +41 -0
  247. package/dist/scene/visibility/gpu-frame-timing.d.ts.map +1 -0
  248. package/dist/scene/visibility/gpu-lod.d.ts +46 -0
  249. package/dist/scene/visibility/gpu-lod.d.ts.map +1 -0
  250. package/dist/scene/visibility/inspection.d.ts +132 -0
  251. package/dist/scene/visibility/inspection.d.ts.map +1 -0
  252. package/dist/scene/visibility/lod-selector.d.ts +25 -0
  253. package/dist/scene/visibility/lod-selector.d.ts.map +1 -0
  254. package/dist/scene/visibility/occlusion-confidence.d.ts +81 -0
  255. package/dist/scene/visibility/occlusion-confidence.d.ts.map +1 -0
  256. package/dist/scene/visibility/occlusion-pass.d.ts +57 -0
  257. package/dist/scene/visibility/occlusion-pass.d.ts.map +1 -0
  258. package/dist/scene/visibility/occlusion-query-pool.d.ts +57 -0
  259. package/dist/scene/visibility/occlusion-query-pool.d.ts.map +1 -0
  260. package/dist/scene/visibility/occlusion-runtime.d.ts +96 -0
  261. package/dist/scene/visibility/occlusion-runtime.d.ts.map +1 -0
  262. package/dist/scene/visibility/types.d.ts +34 -0
  263. package/dist/scene/visibility/types.d.ts.map +1 -0
  264. package/dist/shadow-atlas.d.ts +3 -3
  265. package/dist/shadow-atlas.d.ts.map +1 -1
  266. package/dist/ssao-buffers.d.ts +3 -0
  267. package/dist/ssao-buffers.d.ts.map +1 -1
  268. package/dist/ssr/admission.d.ts +122 -0
  269. package/dist/ssr/admission.d.ts.map +1 -0
  270. package/dist/ssr/composition.d.ts +32 -0
  271. package/dist/ssr/composition.d.ts.map +1 -0
  272. package/dist/ssr/errors.d.ts +39 -0
  273. package/dist/ssr/errors.d.ts.map +1 -0
  274. package/dist/ssr/identity.d.ts +13 -0
  275. package/dist/ssr/identity.d.ts.map +1 -0
  276. package/dist/systems/skin-palette-allocator.d.ts +1 -1
  277. package/dist/targets/contracts.d.ts +66 -0
  278. package/dist/targets/contracts.d.ts.map +1 -0
  279. package/dist/targets/graph-projection.d.ts +29 -0
  280. package/dist/targets/graph-projection.d.ts.map +1 -0
  281. package/dist/targets/material-source.d.ts +34 -0
  282. package/dist/targets/material-source.d.ts.map +1 -0
  283. package/dist/targets/owner.d.ts +32 -0
  284. package/dist/targets/owner.d.ts.map +1 -0
  285. package/dist/targets/physical.d.ts +18 -0
  286. package/dist/targets/physical.d.ts.map +1 -0
  287. package/dist/targets/readback.d.ts +39 -0
  288. package/dist/targets/readback.d.ts.map +1 -0
  289. package/dist/temporal/frame-coordinator.d.ts +13 -0
  290. package/dist/temporal/frame-coordinator.d.ts.map +1 -1
  291. package/dist/temporal/frame.d.ts +2 -0
  292. package/dist/temporal/frame.d.ts.map +1 -1
  293. package/dist/temporal/index.mjs +6 -5
  294. package/dist/temporal/view.d.ts +7 -0
  295. package/dist/temporal/view.d.ts.map +1 -1
  296. package/dist/tilemap-chunk-extract-system.d.ts +1 -1
  297. package/dist/typed-render-graph-primitives.d.ts +5 -1
  298. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  299. package/dist/typed-shadow-passes.d.ts +1 -1
  300. package/dist/typed-shadow-passes.d.ts.map +1 -1
  301. package/dist/volume/passes.d.ts +9 -5
  302. package/dist/volume/passes.d.ts.map +1 -1
  303. package/package.json +20 -20
  304. package/src/__tests__/bloom-exact-zero.unit.test.ts +48 -19
  305. package/src/__tests__/bloom-lifecycle.integration.test.ts +41 -13
  306. package/src/__tests__/camera-target-consumption.unit.test.ts +53 -0
  307. package/src/__tests__/cluster-binner.unit.test.ts +35 -0
  308. package/src/__tests__/cluster-grid-default-surface.unit.test.ts +12 -2
  309. package/src/__tests__/cube-camera-scheduler.unit.test.ts +70 -0
  310. package/src/__tests__/cube-camera-single-submit.perf.test.ts +75 -0
  311. package/src/__tests__/cube-camera-view-matrices.unit.test.ts +41 -0
  312. package/src/__tests__/cube-camera-vocabulary.unit.test.ts +47 -0
  313. package/src/__tests__/cube-camera.integration.test.ts +42 -0
  314. package/src/__tests__/detached-inspection.integration.test.ts +6 -0
  315. package/src/__tests__/device-feature-admission.unit.test.ts +85 -0
  316. package/src/__tests__/direct-light-snapshot.unit.test.ts +62 -6
  317. package/src/__tests__/docs-gate-green.unit.test.ts +38 -0
  318. package/src/__tests__/environment-generation.integration.test.ts +16 -0
  319. package/src/__tests__/evidence-identity.ts +13 -0
  320. package/src/__tests__/evidence-identity.unit.test.ts +24 -0
  321. package/src/__tests__/extended-lighting-recovery.browser.test.ts +14 -0
  322. package/src/__tests__/extended-lighting-recovery.dawn.test.ts +14 -0
  323. package/src/__tests__/extended-lighting-recovery.integration.test.ts +81 -0
  324. package/src/__tests__/extended-lighting-resources.unit.test.ts +51 -0
  325. package/src/__tests__/extended-lighting-zero-feature.integration.test.ts +52 -0
  326. package/src/__tests__/factory-contract.integration.test.ts +288 -29
  327. package/src/__tests__/fog-component.unit.test.ts +67 -0
  328. package/src/__tests__/fog.integration.test.ts +86 -0
  329. package/src/__tests__/frame-observation.contract.test.ts +15 -0
  330. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +37 -0
  331. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +146 -0
  332. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +10 -8
  333. package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +18 -1
  334. package/src/__tests__/gpu-driven-production.integration.test.ts +579 -17
  335. package/src/__tests__/gpu-driven-scaling.unit.test.ts +66 -2
  336. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +26 -1
  337. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +101 -6
  338. package/src/__tests__/gpu-driven-view.browser.test.ts +3 -3
  339. package/src/__tests__/gpu-driven-view.dawn.test.ts +3 -3
  340. package/src/__tests__/gpu-driven-view.unit.test.ts +50 -0
  341. package/src/__tests__/gpu-lod-evidence.ts +188 -0
  342. package/src/__tests__/gpu-lod-fallback.integration.test.ts +10 -0
  343. package/src/__tests__/gpu-lod-indirect.integration.test.ts +40 -0
  344. package/src/__tests__/gpu-lod-parity.dawn.test.ts +29 -0
  345. package/src/__tests__/gpu-lod-readiness.integration.test.ts +52 -0
  346. package/src/__tests__/gpu-lod-schema.unit.test.ts +66 -0
  347. package/src/__tests__/gpu-lod-selector.unit.test.ts +28 -0
  348. package/src/__tests__/gpu-lod-silhouette.browser.test.ts +13 -0
  349. package/src/__tests__/gpu-pass-timing-browser-runner.ts +281 -0
  350. package/src/__tests__/gpu-pass-timing-coexistence.integration.test.ts +80 -0
  351. package/src/__tests__/gpu-pass-timing-contract.unit.test.ts +243 -0
  352. package/src/__tests__/gpu-pass-timing-exact-zero.unit.test.ts +131 -0
  353. package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +230 -0
  354. package/src/__tests__/gpu-pass-timing-observation.unit.test.ts +233 -0
  355. package/src/__tests__/gpu-pass-timing-session.unit.test.ts +438 -0
  356. package/src/__tests__/gpu-pass-timing.browser.test.ts +26 -0
  357. package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +125 -0
  358. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +66 -1
  359. package/src/__tests__/gpu-scene.dawn.test.ts +8 -1
  360. package/src/__tests__/gpu-scene.unit.test.ts +49 -3
  361. package/src/__tests__/hdrp-group2-visibility.unit.test.ts +24 -0
  362. package/src/__tests__/instances-culling.integration.test.ts +94 -0
  363. package/src/__tests__/instances-derived-bounds.unit.test.ts +118 -0
  364. package/src/__tests__/light-buffer-layout.unit.test.ts +113 -3
  365. package/src/__tests__/light-inspection.unit.test.ts +55 -0
  366. package/src/__tests__/light-resource-error.unit.test.ts +43 -0
  367. package/src/__tests__/lighting-scene-roundtrip.integration.test.ts +109 -0
  368. package/src/__tests__/lod-bounds.unit.test.ts +42 -0
  369. package/src/__tests__/lod-cpu-lane.integration.test.ts +55 -0
  370. package/src/__tests__/lod-cpu-no-change.perf.test.ts +19 -0
  371. package/src/__tests__/lod-gpu-frame-timing.unit.test.ts +49 -0
  372. package/src/__tests__/lod-multi-view.integration.test.ts +63 -0
  373. package/src/__tests__/lod-occlusion-device-loss.integration.test.ts +27 -0
  374. package/src/__tests__/lod-occlusion-final-decision.integration.test.ts +47 -0
  375. package/src/__tests__/lod-occlusion-inspection.integration.test.ts +217 -0
  376. package/src/__tests__/lod-occlusion-inspection.schema.test-d.ts +14 -0
  377. package/src/__tests__/lod-occlusion-inspection.unit.test.ts +72 -0
  378. package/src/__tests__/lod-occlusion-visual-evidence.ts +91 -0
  379. package/src/__tests__/lod-occlusion.browser.test.ts +15 -0
  380. package/src/__tests__/lod-occlusion.dawn.test.ts +20 -0
  381. package/src/__tests__/lod-selector.profile.test.ts +35 -0
  382. package/src/__tests__/lod-selector.unit.test.ts +68 -0
  383. package/src/__tests__/lod-visibility-identity.unit.test.ts +198 -0
  384. package/src/__tests__/lod-visibility-lifecycle.integration.test.ts +132 -0
  385. package/src/__tests__/ltc-resources.unit.test.ts +32 -0
  386. package/src/__tests__/material-contract-inventory.unit.test.ts +17 -0
  387. package/src/__tests__/material-observation.integration.test.ts +101 -0
  388. package/src/__tests__/occlusion-confidence.unit.test.ts +168 -0
  389. package/src/__tests__/occlusion-invalidation.integration.test.ts +37 -0
  390. package/src/__tests__/occlusion-pass-routing.unit.test.ts +16 -0
  391. package/src/__tests__/occlusion-pass.dawn.test.ts +20 -0
  392. package/src/__tests__/occlusion-pass.integration.test.ts +43 -0
  393. package/src/__tests__/occlusion-pass.rhi-null.test.ts +22 -0
  394. package/src/__tests__/occlusion-query-pool.rhi-null.test.ts +21 -0
  395. package/src/__tests__/occlusion-query-pool.unit.test.ts +95 -0
  396. package/src/__tests__/occlusion-query-ticket.integration.test.ts +47 -0
  397. package/src/__tests__/occlusion-query.dawn.test.ts +16 -0
  398. package/src/__tests__/occlusion-query.evidence.ts +178 -0
  399. package/src/__tests__/occlusion-query.rhi-null.test.ts +31 -0
  400. package/src/__tests__/occlusion-runtime.unit.test.ts +120 -0
  401. package/src/__tests__/pbr-view-layout.unit.test.ts +16 -0
  402. package/src/__tests__/point-shadow-inspection.unit.test.ts +60 -0
  403. package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +196 -0
  404. package/src/__tests__/probe-bindings.unit.test.ts +200 -0
  405. package/src/__tests__/probe-blend-numeric.unit.test.ts +67 -0
  406. package/src/__tests__/probe-blend-oracle.unit.test.ts +136 -0
  407. package/src/__tests__/probe-capacity.integration.test.ts +97 -0
  408. package/src/__tests__/probe-recovery.integration.test.ts +104 -0
  409. package/src/__tests__/probe-scene-dirty.integration.test.ts +211 -0
  410. package/src/__tests__/profiler-phase-catalog.test.ts +4 -1
  411. package/src/__tests__/profiler-phase-token.test.ts +1 -0
  412. package/src/__tests__/public-surface.test-d.ts +10 -0
  413. package/src/__tests__/rect-area-boundary.unit.test.ts +24 -0
  414. package/src/__tests__/reflection-fallback-graph.unit.test.ts +67 -0
  415. package/src/__tests__/reflection-fallback-inspection.unit.test.ts +77 -0
  416. package/src/__tests__/reflection-fallback-lifecycle.integration.test.ts +21 -0
  417. package/src/__tests__/reflection-fallback-projection.unit.test.ts +90 -0
  418. package/src/__tests__/reflection-fallback-source.unit.test.ts +32 -0
  419. package/src/__tests__/reflection-probe-authoring.unit.test.ts +71 -0
  420. package/src/__tests__/reflection-probe-filter.unit.test.ts +54 -0
  421. package/src/__tests__/reflection-probe-ibl-topology.unit.test.ts +45 -0
  422. package/src/__tests__/reflection-probe-owner-placement.unit.test.ts +39 -0
  423. package/src/__tests__/reflection-probe-pass-encode.integration.test.ts +101 -0
  424. package/src/__tests__/reflection-probe-performance.perf.test.ts +60 -0
  425. package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +120 -0
  426. package/src/__tests__/reflection-probe-recovery.integration.test.ts +55 -0
  427. package/src/__tests__/reflection-probe-selection.unit.test.ts +46 -0
  428. package/src/__tests__/render-error-code-owner.test-d.ts +19 -3
  429. package/src/__tests__/render-feature-docs.unit.test.ts +12 -7
  430. package/src/__tests__/render-graph-fallback.integration.test.ts +24 -0
  431. package/src/__tests__/render-perf/extended-lighting.bench.test.ts +66 -0
  432. package/src/__tests__/render-scene-projection.unit.test.ts +447 -18
  433. package/src/__tests__/render-target-admission.unit.test.ts +80 -0
  434. package/src/__tests__/render-target-graph-projection.unit.test.ts +102 -0
  435. package/src/__tests__/render-target-inspection.unit.test.ts +52 -0
  436. package/src/__tests__/render-target-material-source.test-d.ts +30 -0
  437. package/src/__tests__/render-target-material-source.unit.test.ts +97 -0
  438. package/src/__tests__/render-target-owner-placement.unit.test.ts +203 -0
  439. package/src/__tests__/render-target-owner.unit.test.ts +122 -0
  440. package/src/__tests__/render-target-probe-soak.perf.test.ts +94 -0
  441. package/src/__tests__/render-target-public-schema.json +107 -0
  442. package/src/__tests__/render-target-public-schema.unit.test.ts +91 -0
  443. package/src/__tests__/render-target-public-surface.test-d.ts +83 -0
  444. package/src/__tests__/render-target-readback.integration.test.ts +90 -0
  445. package/src/__tests__/render-target-recovery.integration.test.ts +85 -0
  446. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +124 -0
  447. package/src/__tests__/renderer-lifecycle.integration.test.ts +14 -0
  448. package/src/__tests__/shader-stage-surface.unit.test.ts +19 -4
  449. package/src/__tests__/skin-motion-regression.unit.test.ts +154 -0
  450. package/src/__tests__/skinned-shadow-caster.test.ts +13 -4
  451. package/src/__tests__/spot-modifier-projection.unit.test.ts +70 -0
  452. package/src/__tests__/ssr-admission-matrix.integration.test.ts +206 -0
  453. package/src/__tests__/ssr-composition.unit.test.ts +46 -0
  454. package/src/__tests__/ssr-fallback-zero-work.bench.test.ts +94 -0
  455. package/src/__tests__/ssr-recovery-errors.unit.test.ts +58 -0
  456. package/src/__tests__/standard-cluster-capability.integration.test.ts +63 -0
  457. package/src/__tests__/standard-cluster-transport.unit.test.ts +121 -0
  458. package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +299 -0
  459. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +15 -5
  460. package/src/__tests__/standard-lighting-inspection.integration.test.ts +138 -0
  461. package/src/__tests__/standard-lighting-ssot.unit.test.ts +18 -0
  462. package/src/__tests__/standard-lighting-write.unit.test.ts +441 -0
  463. package/src/__tests__/standard-lighting.integration.test.ts +67 -0
  464. package/src/__tests__/standard-pipeline.dawn.test.ts +206 -5
  465. package/src/__tests__/standard-pipeline.integration.test.ts +181 -150
  466. package/src/__tests__/standard-probe-binding.unit.test.ts +25 -0
  467. package/src/__tests__/standard-profile-oracle.unit.test.ts +23 -38
  468. package/src/__tests__/temporal-fallback-generation.integration.test.ts +16 -0
  469. package/src/__tests__/temporal-view.unit.test.ts +3 -3
  470. package/src/__tests__/transmission-prewarm.unit.test.ts +69 -0
  471. package/src/__tests__/typed-pipeline-topology.unit.test.ts +395 -14
  472. package/src/__tests__/urp-pipeline-targets.unit.test.ts +2 -2
  473. package/src/__tests__/visibility-budget.integration.test.ts +140 -0
  474. package/src/__tests__/visibility-budget.unit.test.ts +70 -0
  475. package/src/__tests__/visibility-extract.integration.test.ts +11 -6
  476. package/src/__tests__/visibility-resolver.unit.test.ts +15 -0
  477. package/src/__tests__/volumetric-fog-point-spot-accumulation.integration.test.ts +6 -3
  478. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +31 -28
  479. package/src/assembly/backend-contract.ts +13 -0
  480. package/src/assembly/device-feature-admission.ts +80 -0
  481. package/src/assembly/directional-shadow-inspection.ts +122 -0
  482. package/src/assembly/factory.ts +1411 -366
  483. package/src/assembly/host-contract.ts +35 -0
  484. package/src/assembly/render-target-host.ts +847 -0
  485. package/src/assets/asset-decoders.ts +1 -1
  486. package/src/assets/render-asset-port.ts +7 -1
  487. package/src/capture/cube-views.ts +69 -0
  488. package/src/capture/scheduler.ts +265 -0
  489. package/src/cluster-binner.ts +31 -0
  490. package/src/components/__tests__/lighting-authoring.unit.test.ts +39 -0
  491. package/src/components/__tests__/rect-area-light.unit.test.ts +33 -0
  492. package/src/components/__tests__/schema-contract.unit.test.ts +12 -0
  493. package/src/components/__tests__/schema-parity.unit.test.ts +9 -0
  494. package/src/components/camera.ts +4 -0
  495. package/src/components/cube-camera.ts +52 -0
  496. package/src/components/directional-light.ts +22 -2
  497. package/src/components/directional-shadow-filter.ts +57 -0
  498. package/src/components/index.ts +5 -0
  499. package/src/components/light-helpers.ts +133 -8
  500. package/src/components/light-probe.ts +13 -0
  501. package/src/components/rect-area-light.ts +15 -0
  502. package/src/components/reflection-probe.ts +49 -0
  503. package/src/components/scene-instance.ts +6 -0
  504. package/src/components/spot-light.ts +3 -0
  505. package/src/device/__tests__/extended-lighting-recovery.unit.test.ts +24 -0
  506. package/src/device/gpu-residency.ts +140 -9
  507. package/src/device/lifecycle-transaction.ts +12 -0
  508. package/src/environment/frame.ts +6 -24
  509. package/src/environment/lifecycle.ts +20 -1
  510. package/src/errors/gpu-driven.ts +92 -0
  511. package/src/errors/index.ts +1 -0
  512. package/src/errors/recover.ts +32 -0
  513. package/src/errors/render.ts +341 -143
  514. package/src/extract/camera.ts +3 -3
  515. package/src/extract/directional-shadow-projection.ts +61 -0
  516. package/src/extract/environment.ts +57 -0
  517. package/src/extract/gpu-driven.ts +108 -0
  518. package/src/extract/visibility.ts +2 -1
  519. package/src/features/fullscreen.ts +3 -0
  520. package/src/features/targets.ts +4 -1
  521. package/src/features/types.ts +10 -0
  522. package/src/fullscreen-post-process-pass.ts +43 -2
  523. package/src/gpu-driven/batch-topology.ts +207 -28
  524. package/src/gpu-driven/prepared-draw.ts +208 -0
  525. package/src/gpu-driven/production-raster.ts +953 -43
  526. package/src/gpu-driven/view-gpu.ts +411 -29
  527. package/src/gpu-scene-schema.ts +13 -0
  528. package/src/gpu-scene.ts +140 -64
  529. package/src/gpu-usage.ts +0 -1
  530. package/src/hdrp-buffers.ts +169 -63
  531. package/src/ibl/IblPipelineCache.ts +11 -0
  532. package/src/ibl/kernel-cache.ts +88 -0
  533. package/src/index.ts +222 -0
  534. package/src/inspection-types.ts +276 -1
  535. package/src/instances-derived-bounds.ts +171 -0
  536. package/src/internal.ts +38 -0
  537. package/src/light-buffer-layout.ts +155 -310
  538. package/src/materials.ts +16 -2
  539. package/src/mesh-material-bindings.ts +132 -0
  540. package/src/pbr-pipeline.ts +255 -60
  541. package/src/pipeline/standard-forward-lane.ts +93 -16
  542. package/src/pipeline/standard-lighting/errors.ts +6 -0
  543. package/src/pipeline/standard-lighting/graph.ts +158 -0
  544. package/src/pipeline/standard-lighting/inspection.ts +88 -0
  545. package/src/pipeline/standard-lighting/layout.ts +31 -0
  546. package/src/pipeline/standard-lighting/light-frame.ts +35 -0
  547. package/src/pipeline/standard-lighting/membership.ts +43 -0
  548. package/src/pipeline/standard-lighting/prepare.ts +37 -0
  549. package/src/pipeline/standard-lighting/topology.ts +120 -0
  550. package/src/pipeline/standard-lighting/transport.ts +78 -0
  551. package/src/pipeline/standard-pipeline.ts +124 -193
  552. package/src/pipeline/standard-post.ts +26 -7
  553. package/src/pipeline/standard-profile.ts +17 -47
  554. package/src/pipeline-builder.ts +5 -2
  555. package/src/pipeline-spec.ts +95 -21
  556. package/src/plugin.ts +4 -0
  557. package/src/point-shadow-inspection.ts +55 -0
  558. package/src/prepare/__tests__/extended-lighting-capability.unit.test.ts +56 -0
  559. package/src/prepare/extended-lighting/ltc-resources.ts +136 -0
  560. package/src/prepare/extended-lighting/resources.ts +389 -0
  561. package/src/prepare/extended-lighting/spot-modifiers.ts +194 -0
  562. package/src/prepare/extended-lighting/state.ts +92 -0
  563. package/src/record/__tests__/gpu-timing.unit.test.ts +177 -0
  564. package/src/record/__tests__/temporal-payload.unit.test.ts +64 -1
  565. package/src/record/__tests__/transparent-group2-selection.unit.test.ts +73 -0
  566. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +20 -1
  567. package/src/record/__tests__/view-ubo-layout.unit.test.ts +40 -0
  568. package/src/record/frame-lighting.ts +591 -452
  569. package/src/record/frame-snapshot.ts +92 -39
  570. package/src/record/frame-targets.ts +17 -0
  571. package/src/record/frame.ts +662 -158
  572. package/src/record/gpu-pass-timing/contract.ts +180 -0
  573. package/src/record/gpu-pass-timing/errors.ts +34 -0
  574. package/src/record/gpu-pass-timing/index.ts +37 -0
  575. package/src/record/gpu-pass-timing/parser.ts +97 -0
  576. package/src/record/gpu-pass-timing/session.ts +938 -0
  577. package/src/record/gpu-timing.ts +112 -39
  578. package/src/record/helpers.ts +0 -58
  579. package/src/record/main-pass-geometry.ts +324 -119
  580. package/src/record/main-pass-material.ts +103 -10
  581. package/src/record/main-pass-sprite-draws.ts +99 -103
  582. package/src/record/main-pass.ts +71 -15
  583. package/src/record/mesh-ssbo.ts +47 -36
  584. package/src/record/render-context.ts +136 -3
  585. package/src/record/shadow-pass.ts +83 -68
  586. package/src/record/skybox-post-pass.ts +20 -4
  587. package/src/record/typed-frame-graph.ts +1034 -43
  588. package/src/record/view-ubo.ts +72 -47
  589. package/src/reflection/filter.ts +81 -0
  590. package/src/reflection/gpu-table.ts +44 -0
  591. package/src/reflection/inspection.ts +67 -0
  592. package/src/reflection/projection.ts +476 -0
  593. package/src/reflection/record-owner.ts +1283 -0
  594. package/src/render-contract.ts +93 -10
  595. package/src/render-graph-primitives.ts +9 -4
  596. package/src/render-pipeline.ts +122 -2
  597. package/src/render-system-extract.ts +1041 -225
  598. package/src/render-system.ts +1310 -85
  599. package/src/renderer.ts +222 -0
  600. package/src/scene/__tests__/changed-block-summary.candidate.test.ts +36 -0
  601. package/src/scene/probe-blend-record.ts +54 -0
  602. package/src/scene/probe-blend.ts +813 -0
  603. package/src/scene/render-scene-types.ts +0 -7
  604. package/src/scene/render-scene.ts +942 -171
  605. package/src/scene/visibility/bounds.ts +57 -0
  606. package/src/scene/visibility/budget.ts +40 -0
  607. package/src/scene/visibility/facet.ts +400 -0
  608. package/src/scene/visibility/gpu-frame-timing.ts +101 -0
  609. package/src/scene/visibility/gpu-lod.ts +119 -0
  610. package/src/scene/visibility/inspection.ts +313 -0
  611. package/src/scene/visibility/lod-selector.ts +84 -0
  612. package/src/scene/visibility/occlusion-confidence.ts +478 -0
  613. package/src/scene/visibility/occlusion-pass.ts +165 -0
  614. package/src/scene/visibility/occlusion-query-pool.ts +178 -0
  615. package/src/scene/visibility/occlusion-runtime.ts +672 -0
  616. package/src/scene/visibility/types.ts +50 -0
  617. package/src/shadow-atlas.ts +5 -5
  618. package/src/ssao-buffers.ts +9 -2
  619. package/src/ssr/admission.ts +451 -0
  620. package/src/ssr/composition.ts +73 -0
  621. package/src/ssr/errors.ts +76 -0
  622. package/src/ssr/identity.ts +12 -0
  623. package/src/systems/skin-palette-allocator.ts +1 -1
  624. package/src/targets/contracts.ts +182 -0
  625. package/src/targets/graph-projection.ts +169 -0
  626. package/src/targets/material-source.ts +143 -0
  627. package/src/targets/owner.ts +214 -0
  628. package/src/targets/physical.ts +18 -0
  629. package/src/targets/readback.ts +153 -0
  630. package/src/temporal/frame-coordinator.ts +26 -0
  631. package/src/temporal/frame.ts +14 -1
  632. package/src/temporal/view.ts +11 -0
  633. package/src/tilemap-chunk-extract-system.ts +4 -4
  634. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +59 -20
  635. package/src/typed-render-graph-primitives.ts +53 -3
  636. package/src/typed-shadow-passes.ts +46 -40
  637. package/src/volume/passes.ts +61 -58
  638. package/dist/.tsbuildinfo +0 -1
  639. package/dist/chunk-4XINDLAY.mjs.map +0 -1
  640. package/dist/chunk-CDTWTHZR.mjs.map +0 -1
  641. package/dist/chunk-M2MP4ZOU.mjs +0 -73
  642. package/dist/chunk-M2MP4ZOU.mjs.map +0 -1
  643. package/dist/chunk-PCHBPYML.mjs.map +0 -1
  644. package/dist/chunk-TBQJOK2L.mjs.map +0 -1
  645. package/dist/chunk-VFPLTKCU.mjs.map +0 -1
@@ -76,7 +76,7 @@ function resolveMaterialWireRefs(
76
76
  value.parameters === undefined
77
77
  ? MATERIAL_TEXTURE_SLOTS
78
78
  : value.parameters
79
- .filter((parameter) => parameter.type === 'texture')
79
+ .filter((parameter) => parameter.type === 'texture' || parameter.type === 'texture_cube')
80
80
  .map((parameter) => parameter.name),
81
81
  );
82
82
  const values = { ...value.values };
@@ -31,7 +31,13 @@ export function createRenderAssetPort(
31
31
  const artifact = shaderRegistry.findMaterialArtifact(shaderId);
32
32
  if (!artifact.ok) return [];
33
33
  return artifact.value.paramSchema
34
- .filter((parameter) => parameter.type === 'texture2d')
34
+ .filter(
35
+ (parameter) =>
36
+ parameter.type === 'texture2d' ||
37
+ parameter.type === 'texture_cube' ||
38
+ parameter.type === 'texture_depth_2d' ||
39
+ parameter.type === 'texture_cube_array',
40
+ )
35
41
  .map((parameter) => parameter.name);
36
42
  },
37
43
  };
@@ -0,0 +1,69 @@
1
+ import { type Mat4, mat4, type Vec3Like } from '@forgeax/engine-math';
2
+ import { CUBE_CAMERA_FACE_ORDER, type CubeCameraFace } from '../components/cube-camera';
3
+
4
+ export interface CubeCameraFaceView {
5
+ readonly position: Vec3Like;
6
+ readonly face: CubeCameraFace;
7
+ readonly direction: readonly [number, number, number];
8
+ readonly up: readonly [number, number, number];
9
+ readonly near: number;
10
+ readonly far: number;
11
+ readonly view: Mat4;
12
+ readonly projection: Mat4;
13
+ readonly viewProjection: Mat4;
14
+ }
15
+
16
+ export interface CubeCameraFaceViewInput {
17
+ readonly position: Vec3Like;
18
+ readonly near: number;
19
+ readonly far: number;
20
+ }
21
+
22
+ const FACE_ORIENTATION: ReadonlyArray<{
23
+ readonly direction: readonly [number, number, number];
24
+ readonly up: readonly [number, number, number];
25
+ }> = [
26
+ { direction: [1, 0, 0], up: [0, 1, 0] },
27
+ { direction: [-1, 0, 0], up: [0, 1, 0] },
28
+ { direction: [0, 1, 0], up: [0, 0, -1] },
29
+ { direction: [0, -1, 0], up: [0, 0, 1] },
30
+ { direction: [0, 0, 1], up: [0, 1, 0] },
31
+ { direction: [0, 0, -1], up: [0, 1, 0] },
32
+ ];
33
+
34
+ function assertRange(near: number, far: number): void {
35
+ if (!Number.isFinite(near) || near <= 0 || !Number.isFinite(far) || far <= near) {
36
+ throw new RangeError('CubeCamera requires finite near > 0 and far > near.');
37
+ }
38
+ }
39
+
40
+ /** Build the only supported +X,-X,+Y,-Y,+Z,-Z cube orientation. */
41
+ export function buildCubeCameraFaceViews(input: CubeCameraFaceViewInput): CubeCameraFaceView[] {
42
+ assertRange(input.near, input.far);
43
+ const views: CubeCameraFaceView[] = [];
44
+ for (const [index, face] of CUBE_CAMERA_FACE_ORDER.entries()) {
45
+ const orientation = FACE_ORIENTATION[index];
46
+ if (orientation === undefined)
47
+ throw new Error(`CubeCamera face orientation missing at ${index}`);
48
+ const target: Vec3Like = [
49
+ (input.position[0] ?? 0) + orientation.direction[0],
50
+ (input.position[1] ?? 0) + orientation.direction[1],
51
+ (input.position[2] ?? 0) + orientation.direction[2],
52
+ ];
53
+ const view = mat4.lookAt(mat4.create(), input.position, target, orientation.up);
54
+ const projection = mat4.perspective(mat4.create(), Math.PI / 2, 1, input.near, input.far);
55
+ const viewProjection = mat4.multiply(mat4.create(), projection, view);
56
+ views.push({
57
+ position: input.position,
58
+ face,
59
+ direction: orientation.direction,
60
+ up: orientation.up,
61
+ near: input.near,
62
+ far: input.far,
63
+ view,
64
+ projection,
65
+ viewProjection,
66
+ });
67
+ }
68
+ return views;
69
+ }
@@ -0,0 +1,265 @@
1
+ import {
2
+ CUBE_CAMERA_FACE_ORDER,
3
+ type CubeCameraFace,
4
+ type CubeCameraUpdateIntent,
5
+ } from '../components/cube-camera';
6
+ import type { RenderError } from '../errors/render';
7
+ import { RenderTargetOperationFailedError, RenderTargetStateInvalidError } from '../errors/render';
8
+ import type { RenderResult } from '../render-contract';
9
+ import type { RenderTarget } from '../targets/contracts';
10
+ import { buildCubeCameraFaceViews, type CubeCameraFaceView } from './cube-views';
11
+
12
+ export interface CubeCaptureRequest {
13
+ readonly target: RenderTarget;
14
+ readonly position: readonly [number, number, number];
15
+ readonly near: number;
16
+ readonly far: number;
17
+ readonly updateIntent: CubeCameraUpdateIntent;
18
+ readonly requestVersion: number;
19
+ readonly faceBudget: number;
20
+ }
21
+
22
+ export interface CubeCaptureWork extends CubeCameraFaceView {
23
+ readonly target: RenderTarget;
24
+ readonly requestVersion: number;
25
+ readonly candidateGeneration: number;
26
+ }
27
+
28
+ export interface CubeCaptureInspection {
29
+ readonly target: RenderTarget;
30
+ readonly activeGeneration: number;
31
+ readonly candidateGeneration?: number;
32
+ readonly completedVersion: number;
33
+ readonly pendingFaces: readonly CubeCameraFace[];
34
+ readonly fallback: 'neutral' | 'previous-active';
35
+ readonly nestedRejections: number;
36
+ }
37
+
38
+ export interface CubeCaptureSchedulerOptions {
39
+ readonly maxFacesPerFrame?: number;
40
+ }
41
+
42
+ export type CubeCaptureRenderableKind = 'opaque' | 'transparent' | 'environment' | 'debug' | 'ui';
43
+
44
+ export interface CubeCaptureRenderable {
45
+ readonly kind: CubeCaptureRenderableKind;
46
+ readonly target?: RenderTarget;
47
+ }
48
+
49
+ /** Apply the Standard capture visibility boundary to one extracted scene. */
50
+ export function selectCubeCaptureRenderables(
51
+ renderables: readonly CubeCaptureRenderable[],
52
+ candidateTarget: RenderTarget,
53
+ ): readonly CubeCaptureRenderable[] {
54
+ return renderables.filter(
55
+ (renderable) =>
56
+ renderable.kind !== 'debug' &&
57
+ renderable.kind !== 'ui' &&
58
+ renderable.target !== candidateTarget,
59
+ );
60
+ }
61
+
62
+ export interface CubeCaptureScheduler {
63
+ beginFrame(): void;
64
+ request(request: CubeCaptureRequest): RenderResult<{ readonly scheduled: boolean }, RenderError>;
65
+ nextWork(): readonly CubeCaptureWork[];
66
+ completeSubmission(
67
+ submitted: boolean,
68
+ completed?: Promise<unknown>,
69
+ ): RenderResult<void, RenderError>;
70
+ inspect(target: RenderTarget): CubeCaptureInspection;
71
+ }
72
+
73
+ interface PendingCapture {
74
+ readonly request: CubeCaptureRequest;
75
+ readonly views: readonly CubeCameraFaceView[];
76
+ readonly candidateGeneration: number;
77
+ readonly written: Set<CubeCameraFace>;
78
+ inFlight: readonly CubeCaptureWork[];
79
+ }
80
+
81
+ interface CaptureState {
82
+ readonly target: RenderTarget;
83
+ activeGeneration: number;
84
+ completedVersion: number;
85
+ pending: PendingCapture | undefined;
86
+ nestedRejections: number;
87
+ }
88
+
89
+ function invalid(
90
+ reason: 'generation-mismatch' | 'uninitialized',
91
+ ): RenderResult<never, RenderError> {
92
+ return {
93
+ ok: false,
94
+ error: new RenderTargetStateInvalidError({
95
+ operation: 'source',
96
+ reason,
97
+ state: reason === 'uninitialized' ? 'uninitialized' : 'candidate',
98
+ generation: 0,
99
+ }),
100
+ };
101
+ }
102
+
103
+ function failed(generation: number, cause: unknown): RenderResult<never, RenderError> {
104
+ return {
105
+ ok: false,
106
+ error: new RenderTargetOperationFailedError({
107
+ operation: 'source',
108
+ stage: 'submit',
109
+ generation,
110
+ cause,
111
+ recovery: 'retain-last-known-good',
112
+ }),
113
+ };
114
+ }
115
+
116
+ function validateRequest(request: CubeCaptureRequest): RenderResult<void, RenderError> {
117
+ if (!Number.isInteger(request.requestVersion) || request.requestVersion < 0) {
118
+ return invalid('generation-mismatch');
119
+ }
120
+ if (!Number.isInteger(request.faceBudget) || request.faceBudget < 1 || request.faceBudget > 6) {
121
+ return invalid('uninitialized');
122
+ }
123
+ if (request.updateIntent === 'once' && request.requestVersion > 1) {
124
+ return invalid('generation-mismatch');
125
+ }
126
+ return { ok: true, value: undefined };
127
+ }
128
+
129
+ /**
130
+ * Schedules CubeCamera views inside the existing display frame. The scheduler
131
+ * never owns a World, encoder, or queue; callers contribute the returned work
132
+ * to the frame graph and report the one matching submission result.
133
+ */
134
+ export function createCubeCaptureScheduler(
135
+ options: CubeCaptureSchedulerOptions = {},
136
+ ): CubeCaptureScheduler {
137
+ const maxFacesPerFrame = Math.max(1, Math.min(6, Math.floor(options.maxFacesPerFrame ?? 1)));
138
+ const states = new WeakMap<object, CaptureState>();
139
+ let activeCapture: CaptureState | undefined;
140
+ let frameOpen = false;
141
+
142
+ const stateFor = (target: RenderTarget): CaptureState => {
143
+ const existing = states.get(target as object);
144
+ if (existing !== undefined) return existing;
145
+ const created: CaptureState = {
146
+ target,
147
+ activeGeneration: 0,
148
+ completedVersion: 0,
149
+ pending: undefined,
150
+ nestedRejections: 0,
151
+ };
152
+ states.set(target as object, created);
153
+ return created;
154
+ };
155
+
156
+ return {
157
+ beginFrame() {
158
+ frameOpen = true;
159
+ if (activeCapture?.pending !== undefined) activeCapture.pending.inFlight = [];
160
+ },
161
+
162
+ request(request) {
163
+ const valid = validateRequest(request);
164
+ if (!valid.ok) return valid;
165
+ const state = stateFor(request.target);
166
+ if (activeCapture?.pending !== undefined) {
167
+ state.nestedRejections += 1;
168
+ return invalid('generation-mismatch');
169
+ }
170
+ const shouldSchedule =
171
+ request.updateIntent === 'continuous' ||
172
+ state.activeGeneration === 0 ||
173
+ request.requestVersion > state.completedVersion;
174
+ if (!shouldSchedule) return { ok: true, value: { scheduled: false } };
175
+ const views = buildCubeCameraFaceViews({
176
+ position: request.position,
177
+ near: request.near,
178
+ far: request.far,
179
+ });
180
+ const pending: PendingCapture = {
181
+ request,
182
+ views,
183
+ candidateGeneration: state.activeGeneration + 1,
184
+ written: new Set(),
185
+ inFlight: [],
186
+ };
187
+ state.pending = pending;
188
+ activeCapture = state;
189
+ return { ok: true, value: { scheduled: true } };
190
+ },
191
+
192
+ nextWork() {
193
+ if (!frameOpen || activeCapture?.pending === undefined) return [];
194
+ const pending = activeCapture.pending;
195
+ if (pending.inFlight.length > 0) return pending.inFlight;
196
+ const remaining = pending.views.filter((view) => !pending.written.has(view.face));
197
+ const count = Math.min(maxFacesPerFrame, pending.request.faceBudget, remaining.length);
198
+ const work = remaining.slice(0, count).map((view) => ({
199
+ ...view,
200
+ target: pending.request.target,
201
+ requestVersion: pending.request.requestVersion,
202
+ candidateGeneration: pending.candidateGeneration,
203
+ }));
204
+ pending.inFlight = work;
205
+ return work;
206
+ },
207
+
208
+ completeSubmission(submitted, completed) {
209
+ const state = activeCapture;
210
+ const pending = state?.pending;
211
+ if (state === undefined || pending === undefined) return invalid('uninitialized');
212
+ if (!submitted) {
213
+ state.pending = undefined;
214
+ activeCapture = undefined;
215
+ return failed(pending.candidateGeneration, new Error('cube capture submission failed'));
216
+ }
217
+ const commit = (): void => {
218
+ if (activeCapture !== state || state.pending !== pending) return;
219
+ for (const work of pending.inFlight) pending.written.add(work.face);
220
+ pending.inFlight = [];
221
+ if (pending.written.size === CUBE_CAMERA_FACE_ORDER.length) {
222
+ state.activeGeneration = pending.candidateGeneration;
223
+ state.completedVersion = pending.request.requestVersion;
224
+ state.pending = undefined;
225
+ activeCapture = undefined;
226
+ }
227
+ };
228
+ if (completed === undefined) commit();
229
+ else
230
+ void completed.then(commit, () => {
231
+ if (activeCapture === state && state.pending === pending) {
232
+ state.pending = undefined;
233
+ activeCapture = undefined;
234
+ }
235
+ });
236
+ return { ok: true, value: undefined };
237
+ },
238
+
239
+ inspect(target) {
240
+ const state = stateFor(target);
241
+ const pending = state.pending;
242
+ const pendingFaces =
243
+ pending === undefined
244
+ ? []
245
+ : pending.views
246
+ .filter(
247
+ (view) =>
248
+ !pending.written.has(view.face) &&
249
+ !pending.inFlight.some((work) => work.face === view.face),
250
+ )
251
+ .map((view) => view.face);
252
+ return Object.freeze({
253
+ target: state.target,
254
+ activeGeneration: state.activeGeneration,
255
+ ...(state.pending === undefined
256
+ ? {}
257
+ : { candidateGeneration: state.pending.candidateGeneration }),
258
+ completedVersion: state.completedVersion,
259
+ pendingFaces,
260
+ fallback: state.activeGeneration === 0 ? 'neutral' : 'previous-active',
261
+ nestedRejections: state.nestedRejections,
262
+ });
263
+ },
264
+ };
265
+ }
@@ -27,6 +27,7 @@
27
27
 
28
28
  import { type Mat4, type Vec3, vec3 } from '@forgeax/engine-math';
29
29
  import { err, ok, type Result } from '@forgeax/engine-rhi';
30
+ import type { RectAreaWorldFrame } from './render-system-extract';
30
31
 
31
32
  // ── types ──────────────────────────────────────────────────────────────────
32
33
 
@@ -174,6 +175,36 @@ export function deriveCullingRadius(range: number, intensity: number, threshold
174
175
  return Math.min(derived, 1000);
175
176
  }
176
177
 
178
+ /** Conservative bounding-sphere radius for a finite Rect and its light range. */
179
+ export function rectAreaClusterRadius(frame: RectAreaWorldFrame, range: number): number {
180
+ return Math.max(0, range) + Math.hypot(frame.halfWidth, frame.halfHeight);
181
+ }
182
+
183
+ /** Test the finite Rect's closest-point distance against a strict range window. */
184
+ export function rectAreaIsInRange(
185
+ frame: RectAreaWorldFrame,
186
+ point: ArrayLike<number>,
187
+ range: number,
188
+ ): boolean {
189
+ const toPoint = vec3.create(
190
+ (point[0] ?? 0) - (frame.center[0] ?? 0),
191
+ (point[1] ?? 0) - (frame.center[1] ?? 0),
192
+ (point[2] ?? 0) - (frame.center[2] ?? 0),
193
+ );
194
+ const localX = Math.min(
195
+ frame.halfWidth,
196
+ Math.max(-frame.halfWidth, vec3.dot(toPoint, frame.axisX)),
197
+ );
198
+ const localY = Math.min(
199
+ frame.halfHeight,
200
+ Math.max(-frame.halfHeight, vec3.dot(toPoint, frame.axisY)),
201
+ );
202
+ const dx = (toPoint[0] ?? 0) - (frame.axisX[0] ?? 0) * localX - (frame.axisY[0] ?? 0) * localY;
203
+ const dy = (toPoint[1] ?? 0) - (frame.axisX[1] ?? 0) * localX - (frame.axisY[1] ?? 0) * localY;
204
+ const dz = (toPoint[2] ?? 0) - (frame.axisX[2] ?? 0) * localX - (frame.axisY[2] ?? 0) * localY;
205
+ return dx * dx + dy * dy + dz * dz < range * range;
206
+ }
207
+
177
208
  // ── view_z_to_z_slice ──────────────────────────────────────────────────────
178
209
 
179
210
  /**
@@ -0,0 +1,39 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import {
3
+ LightProbe,
4
+ RectAreaLight,
5
+ SpotLight,
6
+ validateLightProbeData,
7
+ validateRectAreaLightData,
8
+ } from '../index';
9
+
10
+ describe('lighting authoring contracts', () => {
11
+ it('exposes only the declared Rect, Spot modifier, and Probe fields', () => {
12
+ expect(Object.keys(RectAreaLight.fields)).toEqual([
13
+ 'color',
14
+ 'intensity',
15
+ 'width',
16
+ 'height',
17
+ 'range',
18
+ ]);
19
+ expect(Object.keys(LightProbe.fields)).toEqual(['irradiance', 'radius']);
20
+ expect(SpotLight.fields.iesProfile.type).toBe('shared<IesProfileAsset>');
21
+ expect(SpotLight.fields.cookie.type).toBe('shared<TextureAsset>');
22
+ expect(SpotLight.fields.rollDeg.default).toBe(0);
23
+ });
24
+
25
+ it('keeps defaults and rejects invalid Rect/Probe facts before rendering', () => {
26
+ expect(RectAreaLight.fields.width.default).toBe(1);
27
+ expect(RectAreaLight.fields.height.default).toBe(1);
28
+ expect(LightProbe.fields.irradiance.type).toBe('array<f32, 27>');
29
+ expect(LightProbe.fields.radius.default).toBe(1e-4);
30
+
31
+ expect(validateRectAreaLightData({}).ok).toBe(true);
32
+ expect(validateRectAreaLightData({ width: 0 }).ok).toBe(false);
33
+ expect(validateRectAreaLightData({ intensity: Number.NaN }).ok).toBe(false);
34
+ expect(validateLightProbeData({ irradiance: new Float32Array(26), radius: 1 }).ok).toBe(false);
35
+ expect(validateLightProbeData({ irradiance: new Float32Array(27), radius: 1e-5 }).ok).toBe(
36
+ false,
37
+ );
38
+ });
39
+ });
@@ -0,0 +1,33 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { buildRectAreaWorldFrame, rectAreaFacesPoint } from '../../render-system-extract';
3
+
4
+ describe('RectAreaLight world frame', () => {
5
+ it('normalizes world axes while preserving authored half extents', () => {
6
+ const frame = buildRectAreaWorldFrame({
7
+ center: [1, 2, 3],
8
+ axisX: [0, 2, 0],
9
+ axisY: [-3, 0, 0],
10
+ width: 4,
11
+ height: 2,
12
+ });
13
+
14
+ expect(Array.from(frame.axisX)).toEqual([0, 1, 0]);
15
+ expect(Array.from(frame.axisY)).toEqual([-1, 0, 0]);
16
+ expect(Array.from(frame.normal)).toEqual([0, 0, 1]);
17
+ expect(frame.halfWidth).toBe(2);
18
+ expect(frame.halfHeight).toBe(1);
19
+ });
20
+
21
+ it('defines the front from the world-axis cross product', () => {
22
+ const frame = buildRectAreaWorldFrame({
23
+ center: [0, 0, 0],
24
+ axisX: [1, 0, 0],
25
+ axisY: [0, 1, 0],
26
+ width: 2,
27
+ height: 2,
28
+ });
29
+
30
+ expect(rectAreaFacesPoint(frame, [0, 0, 1])).toBe(true);
31
+ expect(rectAreaFacesPoint(frame, [0, 0, -1])).toBe(false);
32
+ });
33
+ });
@@ -5,6 +5,18 @@ describe('canonical render schema owners', () => {
5
5
  it('keeps mesh, light, and camera facts on their component owners', () => {
6
6
  expect(MeshFilter.fields.assetHandle.type).toBe('shared<MeshAsset>');
7
7
  expect(DirectionalLight.fields.direction.type).toBe('array<f32, 3>');
8
+ expect(DirectionalLight.fields.shadowFilter.type).toBe('enum');
9
+ expect(DirectionalLight.fields.shadowFilter.default).toBe(2);
10
+ expect(DirectionalLight.fields.shadowFilter.labels).toEqual({
11
+ pcf1: 1,
12
+ pcf3: 2,
13
+ pcf5: 3,
14
+ pcssMedium: 4,
15
+ pcssHigh: 5,
16
+ });
17
+ expect(DirectionalLight.fields.shadowAngularRadius.default).toBeCloseTo(0.00465, 8);
18
+ expect(DirectionalLight.fields.maxPenumbraTexels.default).toBe(32);
19
+ expect('pcfKernelSize' in DirectionalLight.fields).toBe(false);
8
20
  expect(Camera.fields.projection.default).toBe(0);
9
21
  expect(Camera.fields.antialias.default).toBe(0);
10
22
  expect(Camera.fields.historyVersion.default).toBe(0);
@@ -13,6 +13,15 @@ describe('render schema parity', () => {
13
13
  expect(MeshFilter.fields.assetHandle.type).toBe('shared<MeshAsset>');
14
14
  expect(DirectionalLight.fields.direction.type).toBe('array<f32, 3>');
15
15
  expect(DirectionalLight.fields.castShadow.default).toBe(true);
16
+ expect(DirectionalLight.fields.shadowFilter.labels).toEqual({
17
+ pcf1: 1,
18
+ pcf3: 2,
19
+ pcf5: 3,
20
+ pcssMedium: 4,
21
+ pcssHigh: 5,
22
+ });
23
+ expect(DirectionalLight.fields.shadowFilter.default).toBe(2);
24
+ expect('pcfKernelSize' in DirectionalLight.fields).toBe(false);
16
25
  expect(MeshRenderer.fields.materials.type).toBe('array<shared<MaterialAsset>>');
17
26
  });
18
27
 
@@ -320,6 +320,10 @@ export const Camera = defineComponent('Camera', {
320
320
  bloomThreshold: { type: 'f32', default: 1.0 },
321
321
  bloomIntensity: { type: 'f32', default: 1.0 },
322
322
  bloomBlurRadius: { type: 'f32', default: 4.0 },
323
+ // M1 target camera role: zero means this camera is eligible for display;
324
+ // non-zero shared targets are auxiliary producers whose views and receipt
325
+ // promotion remain owned by Renderer.
326
+ target: { type: 'shared<RenderTarget>', simulationTransient: true },
323
327
  // feat-20260709 M3 / D-3: clear-color is one inline `array<f32,4>` column.
324
328
  // The earlier 4-scalar form (clearR/G/B/A) was chosen when this was believed
325
329
  // to be the only SoA-safe shape; the Transform (pos/quat/scale) and light
@@ -0,0 +1,52 @@
1
+ // @forgeax/engine-render - CubeCamera capture vocabulary.
2
+ //
3
+ // CubeCamera is an ECS capture intent paired with Transform. GPU resources,
4
+ // face views, completed-receipt promotion, and publication remain renderer-owned.
5
+
6
+ import { defineComponent, type SchemaOf, type ShapeOf } from '@forgeax/engine-ecs';
7
+ import { RenderIntentInvalidError } from '../errors/render';
8
+
9
+ export const CUBE_CAMERA_UPDATE_ONCE = 0;
10
+ export const CUBE_CAMERA_UPDATE_ON_DEMAND = 1;
11
+ export const CUBE_CAMERA_UPDATE_CONTINUOUS = 2;
12
+
13
+ export type CubeCameraUpdateIntent = 'once' | 'on-demand' | 'continuous';
14
+
15
+ export const CUBE_CAMERA_FACE_ORDER = ['+X', '-X', '+Y', '-Y', '+Z', '-Z'] as const;
16
+ export type CubeCameraFace = (typeof CUBE_CAMERA_FACE_ORDER)[number];
17
+
18
+ export function cubeCameraUpdateIntentFromF32(value: number): CubeCameraUpdateIntent {
19
+ switch (value) {
20
+ case CUBE_CAMERA_UPDATE_ONCE:
21
+ return 'once';
22
+ case CUBE_CAMERA_UPDATE_ON_DEMAND:
23
+ return 'on-demand';
24
+ case CUBE_CAMERA_UPDATE_CONTINUOUS:
25
+ return 'continuous';
26
+ default:
27
+ throw new RenderIntentInvalidError('CubeCamera', value);
28
+ }
29
+ }
30
+
31
+ export function cubeCameraUpdateIntentToF32(intent: CubeCameraUpdateIntent): number {
32
+ switch (intent) {
33
+ case 'once':
34
+ return CUBE_CAMERA_UPDATE_ONCE;
35
+ case 'on-demand':
36
+ return CUBE_CAMERA_UPDATE_ON_DEMAND;
37
+ case 'continuous':
38
+ return CUBE_CAMERA_UPDATE_CONTINUOUS;
39
+ }
40
+ }
41
+
42
+ /** ECS declaration for a bounded, transient six-face capture request. */
43
+ export const CubeCamera = defineComponent('CubeCamera', {
44
+ target: { type: 'shared<RenderTarget>', simulationTransient: true },
45
+ near: { type: 'f32', default: 0.1 },
46
+ far: { type: 'f32', default: 100 },
47
+ updateIntent: { type: 'f32', default: CUBE_CAMERA_UPDATE_ONCE },
48
+ requestVersion: { type: 'u32', default: 0 },
49
+ faceBudget: { type: 'u32', default: 1 },
50
+ });
51
+
52
+ export type CubeCameraData = ShapeOf<SchemaOf<typeof CubeCamera>>;
@@ -31,6 +31,14 @@
31
31
  // with the shadow atlas owner.
32
32
 
33
33
  import { defineComponent } from '@forgeax/engine-ecs';
34
+ import { DirectionalShadowFilterValue } from './directional-shadow-filter';
35
+
36
+ export {
37
+ type DirectionalShadowFilterLabel,
38
+ DirectionalShadowFilterValue,
39
+ type DirectionalShadowQuality,
40
+ directionalShadowQualityFromF32,
41
+ } from './directional-shadow-filter';
34
42
 
35
43
  /**
36
44
  * Directional light (sun-like infinite light source) with merged shadow
@@ -64,7 +72,9 @@ import { defineComponent } from '@forgeax/engine-ecs';
64
72
  * plane (no separate near knob — any value other
65
73
  * than the camera near either drops near shadows
66
74
  * or wastes cascade-0 resolution).
67
- * pcfKernelSize odd >= 1 PCF kernel width (default 3)
75
+ * shadowFilter ∈ {pcf1, pcf3, pcf5, pcssMedium, pcssHigh} closed filter profile (default pcf3)
76
+ * shadowAngularRadius ∈ [0.0001, 0.05] radians — PCSS angular light radius (default 0.00465)
77
+ * maxPenumbraTexels ∈ [1, 64], finite integer — PCSS search/filter cap (default 32)
68
78
  *
69
79
  * @example Spawn a single directional light with default shadows:
70
80
  * world.spawn({ component: DirectionalLight, data: {
@@ -85,7 +95,11 @@ import { defineComponent } from '@forgeax/engine-ecs';
85
95
  * color: [1, 1, 1], intensity: 1, // color is [r, g, b]
86
96
  * cascadeCount: 4, splitLambda: 0.75, cascadeBlend: 0.2,
87
97
  * mapSize: 2048, shadowDistance: 200,
98
+ * shadowFilter: DirectionalShadowFilterValue.pcssHigh,
99
+ * shadowAngularRadius: 0.00465, maxPenumbraTexels: 32,
88
100
  * } });
101
+ * // shadowFilter uses the numeric DirectionalShadowFilterValue constant,
102
+ * // not the serialized label string 'pcssHigh'.
89
103
  *
90
104
  * @example 0-light scene must use an unlit shader (standard 0 light = physically correct black):
91
105
  * const world = new World();
@@ -116,5 +130,11 @@ export const DirectionalLight = defineComponent('DirectionalLight', {
116
130
  // reach. Default 200 world units (matches UE-style "dynamic shadow
117
131
  // distance"; the old farPlane default was 50).
118
132
  shadowDistance: { type: 'f32', default: 200 },
119
- pcfKernelSize: { type: 'f32', default: 3 },
133
+ shadowFilter: {
134
+ type: 'enum',
135
+ default: DirectionalShadowFilterValue.pcf3,
136
+ labels: DirectionalShadowFilterValue,
137
+ },
138
+ shadowAngularRadius: { type: 'f32', default: 0.00465 },
139
+ maxPenumbraTexels: { type: 'f32', default: 32 },
120
140
  });