@forgeax/engine-runtime 0.1.4 → 0.1.7

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 (606) hide show
  1. package/README.md +65 -83
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/__tests__/animation-graph-collect-roundtrip.test.d.ts +2 -0
  4. package/dist/__tests__/animation-graph-collect-roundtrip.test.d.ts.map +1 -0
  5. package/dist/__tests__/animation-graph-serialize.unit.test.d.ts +2 -0
  6. package/dist/__tests__/animation-graph-serialize.unit.test.d.ts.map +1 -0
  7. package/dist/__tests__/asset-brand-and-name-retirement.test.d.ts +2 -0
  8. package/dist/__tests__/asset-brand-and-name-retirement.test.d.ts.map +1 -0
  9. package/dist/__tests__/asset-error-exhaustive.test-d.d.ts +11 -0
  10. package/dist/__tests__/asset-error-exhaustive.test-d.d.ts.map +1 -0
  11. package/dist/__tests__/asset-registry-guid-reverse.test.d.ts +2 -0
  12. package/dist/__tests__/asset-registry-guid-reverse.test.d.ts.map +1 -0
  13. package/dist/__tests__/asset-registry-hdr-equirect.test.d.ts +2 -0
  14. package/dist/__tests__/asset-registry-hdr-equirect.test.d.ts.map +1 -0
  15. package/dist/__tests__/asset-registry-mesh-pack-payload.dawn.test.d.ts +2 -0
  16. package/dist/__tests__/asset-registry-mesh-pack-payload.dawn.test.d.ts.map +1 -0
  17. package/dist/__tests__/asset-registry-mounts.test.d.ts +2 -0
  18. package/dist/__tests__/asset-registry-mounts.test.d.ts.map +1 -0
  19. package/dist/__tests__/asset-registry.browser.test.d.ts +2 -0
  20. package/dist/__tests__/asset-registry.browser.test.d.ts.map +1 -0
  21. package/dist/__tests__/asset-registry.dawn.test.d.ts +2 -0
  22. package/dist/__tests__/asset-registry.dawn.test.d.ts.map +1 -0
  23. package/dist/__tests__/asset-registry.listCatalog.test.d.ts +2 -0
  24. package/dist/__tests__/asset-registry.listCatalog.test.d.ts.map +1 -0
  25. package/dist/__tests__/asset-registry.mesh-bin.test.d.ts +2 -0
  26. package/dist/__tests__/asset-registry.mesh-bin.test.d.ts.map +1 -0
  27. package/dist/__tests__/asset-registry.pack-cache.test.d.ts +2 -0
  28. package/dist/__tests__/asset-registry.pack-cache.test.d.ts.map +1 -0
  29. package/dist/__tests__/asset-registry.raw-container-failfast.test.d.ts +2 -0
  30. package/dist/__tests__/asset-registry.raw-container-failfast.test.d.ts.map +1 -0
  31. package/dist/__tests__/asset-registry.recursive.spec.d.ts +2 -0
  32. package/dist/__tests__/asset-registry.recursive.spec.d.ts.map +1 -0
  33. package/dist/__tests__/asset-registry.unit.test.d.ts +2 -0
  34. package/dist/__tests__/asset-registry.unit.test.d.ts.map +1 -0
  35. package/dist/__tests__/asset.unit.test.d.ts +2 -0
  36. package/dist/__tests__/asset.unit.test.d.ts.map +1 -0
  37. package/dist/__tests__/audio-load-by-guid.unit.test.d.ts +2 -0
  38. package/dist/__tests__/audio-load-by-guid.unit.test.d.ts.map +1 -0
  39. package/dist/__tests__/backend-selection.integration.test.d.ts +2 -0
  40. package/dist/__tests__/backend-selection.integration.test.d.ts.map +1 -0
  41. package/dist/__tests__/basis-catalog-dispatch.integration.test.d.ts +2 -0
  42. package/dist/__tests__/basis-catalog-dispatch.integration.test.d.ts.map +1 -0
  43. package/dist/__tests__/builtin-asset-registry.unit.test.d.ts +2 -0
  44. package/dist/__tests__/builtin-asset-registry.unit.test.d.ts.map +1 -0
  45. package/dist/__tests__/collect-scene-asset.test.d.ts +1 -2
  46. package/dist/__tests__/collect-scene-asset.test.d.ts.map +1 -1
  47. package/dist/__tests__/collect-scene-mount-collapse.test.d.ts +2 -0
  48. package/dist/__tests__/collect-scene-mount-collapse.test.d.ts.map +1 -0
  49. package/dist/__tests__/collect-transient-roundtrip.test.d.ts +1 -1
  50. package/dist/__tests__/collect-transient-roundtrip.test.d.ts.map +1 -1
  51. package/dist/__tests__/collect-transient-skip.test.d.ts +1 -2
  52. package/dist/__tests__/collect-transient-skip.test.d.ts.map +1 -1
  53. package/dist/__tests__/compressed-texture-physical-extent.integration.test.d.ts +2 -0
  54. package/dist/__tests__/compressed-texture-physical-extent.integration.test.d.ts.map +1 -0
  55. package/dist/__tests__/dawn/mesh-update-dawn.test.d.ts +2 -0
  56. package/dist/__tests__/dawn/mesh-update-dawn.test.d.ts.map +1 -0
  57. package/dist/__tests__/dawn/upload-texture.dawn.test.d.ts +2 -0
  58. package/dist/__tests__/dawn/upload-texture.dawn.test.d.ts.map +1 -0
  59. package/dist/__tests__/draw-published.d.ts +2 -2
  60. package/dist/__tests__/draw-published.d.ts.map +1 -1
  61. package/dist/__tests__/dynamic-texture-store.unit.test.d.ts +2 -0
  62. package/dist/__tests__/dynamic-texture-store.unit.test.d.ts.map +1 -0
  63. package/dist/__tests__/errors.unit.test.d.ts +2 -0
  64. package/dist/__tests__/errors.unit.test.d.ts.map +1 -0
  65. package/dist/__tests__/extract-skin-mismatch.unit.test.d.ts +2 -0
  66. package/dist/__tests__/extract-skin-mismatch.unit.test.d.ts.map +1 -0
  67. package/dist/__tests__/fetch-binary-decompress.test.d.ts +2 -0
  68. package/dist/__tests__/fetch-binary-decompress.test.d.ts.map +1 -0
  69. package/dist/__tests__/four-path-compression.integration.test.d.ts +2 -0
  70. package/dist/__tests__/four-path-compression.integration.test.d.ts.map +1 -0
  71. package/dist/__tests__/fullscreen-feature-host.dawn.test.d.ts +2 -0
  72. package/dist/__tests__/fullscreen-feature-host.dawn.test.d.ts.map +1 -0
  73. package/dist/__tests__/guid-for-asset.unit.test.d.ts +2 -0
  74. package/dist/__tests__/guid-for-asset.unit.test.d.ts.map +1 -0
  75. package/dist/__tests__/handle-migration.test.d.ts +2 -0
  76. package/dist/__tests__/handle-migration.test.d.ts.map +1 -0
  77. package/dist/__tests__/helpers/register-runtime-components.d.ts.map +1 -1
  78. package/dist/__tests__/host-custom-kind-contract.test-d.d.ts +2 -0
  79. package/dist/__tests__/host-custom-kind-contract.test-d.d.ts.map +1 -0
  80. package/dist/__tests__/host-custom-kind-contract.test.d.ts +2 -0
  81. package/dist/__tests__/host-custom-kind-contract.test.d.ts.map +1 -0
  82. package/dist/__tests__/inspect-name.test.d.ts +2 -0
  83. package/dist/__tests__/inspect-name.test.d.ts.map +1 -0
  84. package/dist/__tests__/instantiate-mount-deferred-wiring.test.d.ts +2 -0
  85. package/dist/__tests__/instantiate-mount-deferred-wiring.test.d.ts.map +1 -0
  86. package/dist/__tests__/loadbyguid-payload.unit.test.d.ts +2 -0
  87. package/dist/__tests__/loadbyguid-payload.unit.test.d.ts.map +1 -0
  88. package/dist/__tests__/loadbyguid-texture-intern.unit.test.d.ts +2 -0
  89. package/dist/__tests__/loadbyguid-texture-intern.unit.test.d.ts.map +1 -0
  90. package/dist/__tests__/loader-extract-graceful.test.d.ts +2 -0
  91. package/dist/__tests__/loader-extract-graceful.test.d.ts.map +1 -0
  92. package/dist/__tests__/loader-name-survival.test.d.ts +2 -0
  93. package/dist/__tests__/loader-name-survival.test.d.ts.map +1 -0
  94. package/dist/__tests__/mesh-bin-contract.test.d.ts +2 -0
  95. package/dist/__tests__/mesh-bin-contract.test.d.ts.map +1 -0
  96. package/dist/__tests__/mesh-bin-skin-roundtrip.unit.test.d.ts +2 -0
  97. package/dist/__tests__/mesh-bin-skin-roundtrip.unit.test.d.ts.map +1 -0
  98. package/dist/__tests__/mesh-bin.test.d.ts +2 -0
  99. package/dist/__tests__/mesh-bin.test.d.ts.map +1 -0
  100. package/dist/__tests__/mesh-loader-skin-contract.unit.test.d.ts +2 -0
  101. package/dist/__tests__/mesh-loader-skin-contract.unit.test.d.ts.map +1 -0
  102. package/dist/__tests__/new-kind-refs-contract.test.d.ts +2 -0
  103. package/dist/__tests__/new-kind-refs-contract.test.d.ts.map +1 -0
  104. package/dist/__tests__/package-promotion.test.d.ts +2 -0
  105. package/dist/__tests__/package-promotion.test.d.ts.map +1 -0
  106. package/dist/__tests__/package-rename.test.d.ts +2 -0
  107. package/dist/__tests__/package-rename.test.d.ts.map +1 -0
  108. package/dist/__tests__/recover-error-exhaustive.test-d.d.ts +1 -1
  109. package/dist/__tests__/recover-error-exhaustive.test-d.d.ts.map +1 -1
  110. package/dist/__tests__/render-error-exhaustive.test-d.d.ts +1 -1
  111. package/dist/__tests__/render-error-exhaustive.test-d.d.ts.map +1 -1
  112. package/dist/__tests__/render-feature-prepared-graphics.fixture.d.ts +10 -0
  113. package/dist/__tests__/render-feature-prepared-graphics.fixture.d.ts.map +1 -0
  114. package/dist/__tests__/render-system-extract.unit.test.d.ts +2 -0
  115. package/dist/__tests__/render-system-extract.unit.test.d.ts.map +1 -0
  116. package/dist/__tests__/renderer-test-utils.d.ts +10 -0
  117. package/dist/__tests__/renderer-test-utils.d.ts.map +1 -0
  118. package/dist/__tests__/renderer.test-d.d.ts +2 -0
  119. package/dist/__tests__/renderer.test-d.d.ts.map +1 -0
  120. package/dist/__tests__/resolve-asset-handle-err.test.d.ts +2 -0
  121. package/dist/__tests__/resolve-asset-handle-err.test.d.ts.map +1 -0
  122. package/dist/__tests__/resolve-asset-handle.unit.test.d.ts +2 -0
  123. package/dist/__tests__/resolve-asset-handle.unit.test.d.ts.map +1 -0
  124. package/dist/__tests__/resolveName-fallback.test.d.ts +2 -0
  125. package/dist/__tests__/resolveName-fallback.test.d.ts.map +1 -0
  126. package/dist/__tests__/resolveName-null-package.test.d.ts +2 -0
  127. package/dist/__tests__/resolveName-null-package.test.d.ts.map +1 -0
  128. package/dist/__tests__/resolveName-unified-entry.test.d.ts +2 -0
  129. package/dist/__tests__/resolveName-unified-entry.test.d.ts.map +1 -0
  130. package/dist/__tests__/resolveName.test.d.ts +2 -0
  131. package/dist/__tests__/resolveName.test.d.ts.map +1 -0
  132. package/dist/__tests__/roots-to-scene-asset.test.d.ts +1 -1
  133. package/dist/__tests__/roots-to-scene-asset.test.d.ts.map +1 -1
  134. package/dist/__tests__/roundtrip-primitive.test.d.ts +2 -0
  135. package/dist/__tests__/roundtrip-primitive.test.d.ts.map +1 -0
  136. package/dist/__tests__/scene-bare-guid-refs-instantiate.test.d.ts +2 -0
  137. package/dist/__tests__/scene-bare-guid-refs-instantiate.test.d.ts.map +1 -0
  138. package/dist/__tests__/scene-instance-authoring.integration.test.d.ts +2 -0
  139. package/dist/__tests__/scene-instance-authoring.integration.test.d.ts.map +1 -0
  140. package/dist/__tests__/scene-mount-fixed-point.test.d.ts +2 -0
  141. package/dist/__tests__/scene-mount-fixed-point.test.d.ts.map +1 -0
  142. package/dist/__tests__/scene-mount-roundtrip.test.d.ts +2 -0
  143. package/dist/__tests__/scene-mount-roundtrip.test.d.ts.map +1 -0
  144. package/dist/__tests__/scene-mount-wrapper-roundtrip.test.d.ts +2 -0
  145. package/dist/__tests__/scene-mount-wrapper-roundtrip.test.d.ts.map +1 -0
  146. package/dist/__tests__/scene-sugar-instantiate.test.d.ts +2 -0
  147. package/dist/__tests__/scene-sugar-instantiate.test.d.ts.map +1 -0
  148. package/dist/__tests__/serialize-mounts-roundtrip.test.d.ts +2 -0
  149. package/dist/__tests__/serialize-mounts-roundtrip.test.d.ts.map +1 -0
  150. package/dist/__tests__/serialize-scene-asset.test.d.ts +1 -1
  151. package/dist/__tests__/serialize-scene-asset.test.d.ts.map +1 -1
  152. package/dist/__tests__/template-game-default-api-contract.test.d.ts +2 -0
  153. package/dist/__tests__/template-game-default-api-contract.test.d.ts.map +1 -0
  154. package/dist/__tests__/tileset-asset-validate.test.d.ts +2 -0
  155. package/dist/__tests__/tileset-asset-validate.test.d.ts.map +1 -0
  156. package/dist/__tests__/transcode-fallback.unit.test.d.ts +2 -0
  157. package/dist/__tests__/transcode-fallback.unit.test.d.ts.map +1 -0
  158. package/dist/__tests__/transient-runtime-behavior.test.d.ts +2 -0
  159. package/dist/__tests__/transient-runtime-behavior.test.d.ts.map +1 -0
  160. package/dist/__tests__/video-loader-consumption.test.d.ts +2 -0
  161. package/dist/__tests__/video-loader-consumption.test.d.ts.map +1 -0
  162. package/dist/__tests__/video-loader-smoke.dawn.test.d.ts +2 -0
  163. package/dist/__tests__/video-loader-smoke.dawn.test.d.ts.map +1 -0
  164. package/dist/backend-selection.d.ts +13 -0
  165. package/dist/backend-selection.d.ts.map +1 -0
  166. package/dist/collect-scene-asset.d.ts +7 -4
  167. package/dist/collect-scene-asset.d.ts.map +1 -1
  168. package/dist/createRenderer.d.ts +14 -2
  169. package/dist/createRenderer.d.ts.map +1 -1
  170. package/dist/errors/environment.d.ts +1 -1
  171. package/dist/errors/environment.d.ts.map +1 -1
  172. package/dist/index.d.ts +20 -82
  173. package/dist/index.d.ts.map +1 -1
  174. package/dist/index.mjs +107 -108
  175. package/dist/index.mjs.map +1 -1
  176. package/dist/renderer-host.d.ts +9 -0
  177. package/dist/renderer-host.d.ts.map +1 -0
  178. package/dist/renderer-host.mjs +62 -0
  179. package/dist/renderer-host.mjs.map +1 -0
  180. package/dist/scene-instances/index.d.ts +2 -0
  181. package/dist/scene-instances/index.d.ts.map +1 -0
  182. package/dist/scene-utils/mount-override-fold.d.ts +1 -2
  183. package/dist/scene-utils/mount-override-fold.d.ts.map +1 -1
  184. package/dist/systems/sprite-animation-tick.d.ts +1 -1
  185. package/dist/systems/sprite-animation-tick.d.ts.map +1 -1
  186. package/dist/systems/transparent-sort.d.ts +1 -2
  187. package/dist/systems/transparent-sort.d.ts.map +1 -1
  188. package/dist/tilemap-register-validate.d.ts.map +1 -1
  189. package/package.json +34 -33
  190. package/src/__tests__/active-camera.unit.test.ts +19 -9
  191. package/src/__tests__/animation-graph-collect-roundtrip.test.ts +213 -0
  192. package/src/__tests__/animation-graph-serialize.unit.test.ts +171 -0
  193. package/src/__tests__/append-injection.test.ts +1 -1
  194. package/src/__tests__/asset-brand-and-name-retirement.test.ts +102 -0
  195. package/src/__tests__/asset-error-exhaustive.test-d.ts +62 -0
  196. package/src/__tests__/asset-registry-guid-reverse.test.ts +608 -0
  197. package/src/__tests__/asset-registry-hdr-equirect.test.ts +78 -0
  198. package/src/__tests__/asset-registry-mesh-pack-payload.dawn.test.ts +232 -0
  199. package/src/__tests__/asset-registry-mounts.test.ts +806 -0
  200. package/src/__tests__/asset-registry.browser.test.ts +81 -0
  201. package/src/__tests__/asset-registry.dawn.test.ts +94 -0
  202. package/src/__tests__/asset-registry.listCatalog.test.ts +170 -0
  203. package/src/__tests__/asset-registry.mesh-bin.test.ts +316 -0
  204. package/src/__tests__/asset-registry.pack-cache.test.ts +969 -0
  205. package/src/__tests__/asset-registry.raw-container-failfast.test.ts +225 -0
  206. package/src/__tests__/asset-registry.recursive.spec.ts +1397 -0
  207. package/src/__tests__/asset-registry.unit.test.ts +1030 -0
  208. package/src/__tests__/asset.unit.test.ts +7107 -0
  209. package/src/__tests__/audio-load-by-guid.unit.test.ts +126 -0
  210. package/src/__tests__/backend-selection.integration.test.ts +11 -0
  211. package/src/__tests__/basis-catalog-dispatch.integration.test.ts +320 -0
  212. package/src/__tests__/bind-group-cache-keying.test.ts +4 -4
  213. package/src/__tests__/block-upload-math.unit.test.ts +2 -2
  214. package/src/__tests__/builtin-asset-registry.unit.test.ts +112 -0
  215. package/src/__tests__/builtin-shader-register-e2e.test.ts +1 -1
  216. package/src/__tests__/cache-false-eviction.test.ts +2 -1
  217. package/src/__tests__/cache-isolation-matrix.test.ts +2 -1
  218. package/src/__tests__/camera-clear-snapshot-equivalence.unit.test.ts +5 -6
  219. package/src/__tests__/clamp-to-last.e2e.browser.test.ts +29 -19
  220. package/src/__tests__/collect-scene-asset.test.ts +49 -52
  221. package/src/__tests__/collect-scene-mount-collapse.test.ts +391 -0
  222. package/src/__tests__/collect-subtree.unit.test.ts +1 -2
  223. package/src/__tests__/collect-transient-children-absent.test.ts +24 -10
  224. package/src/__tests__/collect-transient-roundtrip.test.ts +44 -20
  225. package/src/__tests__/collect-transient-skip.test.ts +24 -13
  226. package/src/__tests__/components.test-d.ts +1 -6
  227. package/src/__tests__/components.unit.test.ts +20 -19
  228. package/src/__tests__/composite-skybox-cross-world.browser.test.ts +59 -27
  229. package/src/__tests__/compressed-texture-physical-extent.integration.test.ts +139 -0
  230. package/src/__tests__/create-renderer-assembly.integration.test.ts +42 -29
  231. package/src/__tests__/createRenderer-dispose.test.ts +35 -402
  232. package/src/__tests__/createRenderer.browser-no-webgpu.test.ts +25 -30
  233. package/src/__tests__/createRenderer.unit.test.ts +1 -1
  234. package/src/__tests__/dawn/hello-sprite-nineslice-section.dawn.test.ts +27 -63
  235. package/src/__tests__/dawn/ibl-precompute-readback.dawn.test.ts +56 -47
  236. package/src/__tests__/dawn/instances-per-instance-pbr.dawn.test.ts +49 -29
  237. package/src/__tests__/dawn/instances-shadow.dawn.test.ts +26 -15
  238. package/src/__tests__/dawn/instances-uniform-fallback.dawn.test.ts +13 -14
  239. package/src/__tests__/dawn/material-alpha.dawn.test.ts +23 -31
  240. package/src/__tests__/dawn/material-cooked-fixture.dawn.test.ts +24 -9
  241. package/src/__tests__/dawn/{mesh-update.dawn.test.ts → mesh-update-dawn.test.ts} +42 -134
  242. package/src/__tests__/dawn/mipmap-srgb-linear.dawn.test.ts +14 -7
  243. package/src/__tests__/dawn/per-entity-material-texture-isolation.dawn.test.ts +16 -28
  244. package/src/__tests__/dawn/sprite-nineslice-mesh-bind.dawn.test.ts +23 -39
  245. package/src/__tests__/dawn/upload-texture.dawn.test.ts +198 -0
  246. package/src/__tests__/dawn/user-handle-mesh-render.dawn.test.ts +12 -14
  247. package/src/__tests__/dawn/user-mesh-upload.dawn.test.ts +27 -22
  248. package/src/__tests__/dawn/zero-manifest-mesh-fail.dawn.test.ts +25 -28
  249. package/src/__tests__/dawn/zero-manifest-ready.dawn.test.ts +10 -11
  250. package/src/__tests__/demo-sortscope-migration.unit.test.ts +5 -5
  251. package/src/__tests__/derive-bgl-integration.test.ts +34 -44
  252. package/src/__tests__/derive-render-data-skin.unit.test.ts +1 -1
  253. package/src/__tests__/draw-published.ts +11 -4
  254. package/src/__tests__/dynamic-texture-store.unit.test.ts +190 -0
  255. package/src/__tests__/equirect-bc6h.integration.test.ts +144 -21
  256. package/src/__tests__/errors.unit.test.ts +1227 -0
  257. package/src/__tests__/extract-frames-graceful-degradation.test.ts +3 -7
  258. package/src/__tests__/extract-frames-merge.test.ts +35 -22
  259. package/src/__tests__/extract-record-no-hardcoded-texture-fields.test.ts +5 -16
  260. package/src/__tests__/extract-skin-mismatch.unit.test.ts +322 -0
  261. package/src/__tests__/fetch-binary-decompress.test.ts +356 -0
  262. package/src/__tests__/four-path-compression.integration.test.ts +395 -0
  263. package/src/__tests__/frame-targets-shadow-regression.unit.test.ts +1 -1
  264. package/src/__tests__/fullscreen-feature-host.dawn.test.ts +80 -0
  265. package/src/__tests__/fullscreen-post-bgl-depth.test.ts +4 -2
  266. package/src/__tests__/fullscreen-post-depth-params-arity.test.ts +3 -3
  267. package/src/__tests__/fullscreen-post-process-pass.dawn.test.ts +39 -23
  268. package/src/__tests__/fullscreen-post-process-pass.unit.test.ts +4 -2
  269. package/src/__tests__/fxaa-pixel-diff.dawn.test.ts +28 -17
  270. package/src/__tests__/fxaa-validation-and-resize.dawn.test.ts +29 -18
  271. package/src/__tests__/fxaa-zero-overhead.dawn.test.ts +16 -12
  272. package/src/__tests__/geometry.unit.test.ts +525 -159
  273. package/src/__tests__/glyph-tilemap-worldid.test.ts +1 -1
  274. package/src/__tests__/gpu-resource-cow-survivor.test.ts +6 -4
  275. package/src/__tests__/guid-for-asset.unit.test.ts +102 -0
  276. package/src/__tests__/handle-migration.test.ts +136 -0
  277. package/src/__tests__/helpers/register-runtime-components.ts +4 -2
  278. package/src/__tests__/helpers/register-scene-components.ts +1 -1
  279. package/src/__tests__/host-custom-kind-contract.test-d.ts +47 -0
  280. package/src/__tests__/host-custom-kind-contract.test.ts +578 -0
  281. package/src/__tests__/inspect-name.test.ts +139 -0
  282. package/src/__tests__/instances.test-d.ts +1 -1
  283. package/src/__tests__/instantiate-mount-deferred-wiring.test.ts +112 -0
  284. package/src/__tests__/light-casters-9-light.browser.test.ts +73 -76
  285. package/src/__tests__/light-gpu-byte-neutral.unit.test.ts +7 -10
  286. package/src/__tests__/light-snapshot.test-d.ts +2 -2
  287. package/src/__tests__/lights-vec-negative.unit.test.ts +1 -1
  288. package/src/__tests__/lights.unit.test.ts +31 -511
  289. package/src/__tests__/loadbyguid-payload.unit.test.ts +117 -0
  290. package/src/__tests__/loadbyguid-texture-intern.unit.test.ts +213 -0
  291. package/src/__tests__/loader-extract-graceful.test.ts +146 -0
  292. package/src/__tests__/loader-name-survival.test.ts +213 -0
  293. package/src/__tests__/m3-vec-negative.unit.test.ts +3 -2
  294. package/src/__tests__/material-texture-uv-scale.unit.test.ts +101 -31
  295. package/src/__tests__/materials.unit.test.ts +10 -27
  296. package/src/__tests__/mesh-bin-contract.test.ts +28 -0
  297. package/src/__tests__/mesh-bin-skin-roundtrip.unit.test.ts +149 -0
  298. package/src/__tests__/mesh-bin.test.ts +38 -0
  299. package/src/__tests__/mesh-loader-skin-contract.unit.test.ts +120 -0
  300. package/src/__tests__/mesh-ssbo-grow.unit.test.ts +3 -3
  301. package/src/__tests__/mip-gate.unit.test.ts +1 -1
  302. package/src/__tests__/msaa-sprite-pixel-diff.dawn.test.ts +29 -68
  303. package/src/__tests__/new-kind-refs-contract.test.ts +132 -0
  304. package/src/__tests__/node-shims.d.ts +4 -6
  305. package/src/__tests__/package-promotion.test.ts +88 -0
  306. package/src/__tests__/package-rename.test.ts +103 -0
  307. package/src/__tests__/pass-selector.unit.test.ts +2 -2
  308. package/src/__tests__/pbr-pipeline.unit.test.ts +21 -25
  309. package/src/__tests__/pipeline-builder-msaa.unit.test.ts +6 -9
  310. package/src/__tests__/pipeline-cache-keying.unit.test.ts +6 -9
  311. package/src/__tests__/pipeline-spec.test.ts +16 -177
  312. package/src/__tests__/pipeline.unit.test.ts +154 -1693
  313. package/src/__tests__/point-light-shadow.dawn.test.ts +33 -42
  314. package/src/__tests__/point-light-shadow.unit.test.ts +19 -60
  315. package/src/__tests__/post-process-error-codes.unit.test.ts +4 -1
  316. package/src/__tests__/post-process-params-component.unit.test.ts +1 -1
  317. package/src/__tests__/post-process-params-extract.unit.test.ts +2 -5
  318. package/src/__tests__/postprocess-camera-consistency.test.ts +4 -7
  319. package/src/__tests__/profiler-assembly.integration.test.ts +1 -1
  320. package/src/__tests__/propagate-transforms.dawn.test.ts +12 -11
  321. package/src/__tests__/record-worldid-isolation.test.ts +7 -29
  322. package/src/__tests__/recover-error-exhaustive.test-d.ts +1 -1
  323. package/src/__tests__/render-error-exhaustive.test-d.ts +117 -71
  324. package/src/__tests__/render-feature-assembly.test-d.ts +20 -9
  325. package/src/__tests__/render-feature-prepared-graphics-docs.unit.test.ts +8 -6
  326. package/src/__tests__/render-feature-prepared-graphics.browser.test.ts +65 -559
  327. package/src/__tests__/render-feature-prepared-graphics.dawn.test.ts +57 -544
  328. package/src/__tests__/render-feature-prepared-graphics.fixture.ts +104 -0
  329. package/src/__tests__/render-feature-prepared-graphics.integration.test.ts +40 -248
  330. package/src/__tests__/render-feature-prepared-graphics.regression.integration.test.ts +83 -340
  331. package/src/__tests__/render-feature-recover.integration.test.ts +9 -49
  332. package/src/__tests__/render-feature-runtime-surface.test-d.ts +17 -20
  333. package/src/__tests__/render-schema-consumer.integration.test.ts +20 -13
  334. package/src/__tests__/render-schema-owner-boundary.unit.test.ts +2 -6
  335. package/src/__tests__/render-system-cross-world-overlay-queue.test.ts +5 -5
  336. package/src/__tests__/render-system-extract-dispatch-ordering.test.ts +16 -31
  337. package/src/__tests__/render-system-extract.test.ts +36 -51
  338. package/src/__tests__/render-system-extract.unit.test.ts +360 -0
  339. package/src/__tests__/render-system-fold-bucket.unit.test.ts +3 -5
  340. package/src/__tests__/render-system-fold-fallback.unit.test.ts +6 -3
  341. package/src/__tests__/render-system-fold-material.unit.test.ts +3 -5
  342. package/src/__tests__/render-system-fold-metrics.unit.test.ts +5 -5
  343. package/src/__tests__/render-system-fold-modegate.unit.test.ts +6 -6
  344. package/src/__tests__/render-system-fold.dawn.test.ts +7 -5
  345. package/src/__tests__/render-system-mega.test.ts +292 -190
  346. package/src/__tests__/render-system-owner-split-contract.test.ts +10 -32
  347. package/src/__tests__/render-system-record-multi-material-textureview.test.ts +59 -45
  348. package/src/__tests__/render-system-record-per-submesh-transparency.test.ts +23 -29
  349. package/src/__tests__/render-system-record.test.ts +398 -235
  350. package/src/__tests__/render-system-record.unit.test.ts +25 -26
  351. package/src/__tests__/render-system-skin-bg.unit.test.ts +8 -12
  352. package/src/__tests__/renderer-consumer.test-d.ts +16 -3
  353. package/src/__tests__/renderer-health.unit.test.ts +26 -916
  354. package/src/__tests__/renderer-lifecycle.integration.test.ts +19 -6
  355. package/src/__tests__/renderer-recover.unit.test.ts +49 -1069
  356. package/src/__tests__/renderer-result.test-d.ts +19 -9
  357. package/src/__tests__/renderer-surface.unit.test.ts +3 -5
  358. package/src/__tests__/renderer-test-utils.ts +56 -0
  359. package/src/__tests__/renderer.test-d.ts +61 -0
  360. package/src/__tests__/resolve-asset-handle-err.test.ts +111 -0
  361. package/src/__tests__/resolve-asset-handle.unit.test.ts +64 -0
  362. package/src/__tests__/resolve-depth-only-view.test.ts +1 -1
  363. package/src/__tests__/resolveName-fallback.test.ts +64 -0
  364. package/src/__tests__/resolveName-null-package.test.ts +38 -0
  365. package/src/__tests__/resolveName-unified-entry.test.ts +65 -0
  366. package/src/__tests__/resolveName.test.ts +64 -0
  367. package/src/__tests__/rhi-null-command-flow.unit.test.ts +56 -260
  368. package/src/__tests__/rhi-null-renderer-lifecycle.unit.test.ts +41 -169
  369. package/src/__tests__/roots-to-scene-asset.test.ts +199 -93
  370. package/src/__tests__/roundtrip-primitive.test.ts +351 -0
  371. package/src/__tests__/scene-bare-guid-refs-instantiate.test.ts +123 -0
  372. package/src/__tests__/scene-equirect-roundtrip.test.ts +103 -16
  373. package/src/__tests__/scene-instance-authoring.integration.test.ts +8 -0
  374. package/src/__tests__/scene-instance-bridge.integration.test.ts +1 -1
  375. package/src/__tests__/scene-instance-component.test.ts +1 -1
  376. package/src/__tests__/scene-mount-fixed-point.test.ts +257 -0
  377. package/src/__tests__/scene-mount-roundtrip.test.ts +987 -0
  378. package/src/__tests__/scene-mount-wrapper-roundtrip.test.ts +202 -0
  379. package/src/__tests__/scene-sugar-instantiate.test.ts +324 -0
  380. package/src/__tests__/serialize-mounts-roundtrip.test.ts +533 -0
  381. package/src/__tests__/serialize-scene-asset.test.ts +219 -22
  382. package/src/__tests__/shadow-caster-empty-schema.test.ts +3 -3
  383. package/src/__tests__/shadow-csm-cascade-loadop.test.ts +37 -17
  384. package/src/__tests__/shadow-csm-component.test.ts +3 -5
  385. package/src/__tests__/shadow-csm-extract.test.ts +2 -100
  386. package/src/__tests__/shadow-csm-orthoz.test.ts +2 -16
  387. package/src/__tests__/shadow-csm-runtime-vary.dawn.test.ts +19 -14
  388. package/src/__tests__/shadow-csm-tile-consistency.test.ts +32 -26
  389. package/src/__tests__/shadow-csm-ubo.dawn.test.ts +8 -49
  390. package/src/__tests__/shadow-csm-ubo.test.ts +3 -25
  391. package/src/__tests__/shadow-csm-viewport.browser.test.ts +1 -1
  392. package/src/__tests__/shadow-fields-observable.dawn.test.ts +67 -56
  393. package/src/__tests__/shadow-m1.dawn.test.ts +8 -9
  394. package/src/__tests__/shadow-mesh-ssbo-order.test.ts +11 -27
  395. package/src/__tests__/skin-errors.unit.test.ts +1 -1
  396. package/src/__tests__/skin-extract-getarrayview-count.unit.test.ts +7 -5
  397. package/src/__tests__/skylight-lazy-projection.test.ts +36 -15
  398. package/src/__tests__/sparse-tag-scene-roundtrip.test.ts +5 -5
  399. package/src/__tests__/sprite-cullmode-flip.dawn.test.ts +47 -64
  400. package/src/__tests__/sprite-lit-bgl-byte-identical.test.ts +15 -14
  401. package/src/__tests__/sprite-lit-extract-branch.test.ts +1 -1
  402. package/src/__tests__/sprite-lit-pipeline-cache-key.test.ts +1 -1
  403. package/src/__tests__/ssao-bgl.test.ts +16 -9
  404. package/src/__tests__/ssao-buffers.test.ts +2 -2
  405. package/src/__tests__/ssao-data.test.ts +2 -2
  406. package/src/__tests__/ssao-errors.test.ts +1 -1
  407. package/src/__tests__/ssao-passes.test.ts +68 -392
  408. package/src/__tests__/ssao-pipelines.test.ts +1 -1
  409. package/src/__tests__/ssao-uniform-layout.test.ts +8 -6
  410. package/src/__tests__/stencil-outline-pixel.dawn.test.ts +25 -17
  411. package/src/__tests__/swap-chain-format.unit.test.ts +5 -7
  412. package/src/__tests__/systems.unit.test.ts +536 -1326
  413. package/src/__tests__/template-game-default-api-contract.test.ts +362 -0
  414. package/src/__tests__/text.unit.test.ts +56 -33
  415. package/src/__tests__/tilemap-childed-despawn.test.ts +8 -14
  416. package/src/__tests__/tilemap-chunk-extract.overhang-bounds.test.ts +8 -12
  417. package/src/__tests__/tilemap-chunk-extract.propagate-order.test.ts +2 -1
  418. package/src/__tests__/tilemap-chunk-extract.test.ts +13 -17
  419. package/src/__tests__/tilemap-dirty-rebuild.test.ts +7 -11
  420. package/src/__tests__/tilemap-material-cache.test.ts +8 -13
  421. package/src/__tests__/tilemap-multi-atlas.test.ts +12 -32
  422. package/src/__tests__/tilemap-owner-boundary.unit.test.ts +5 -2
  423. package/src/__tests__/tilemap-region-pack.test.ts +8 -12
  424. package/src/__tests__/tilemap-spawn-flip-pivot.test.ts +8 -12
  425. package/src/__tests__/tilemap-uv-inset.test.ts +11 -14
  426. package/src/__tests__/tilemap-validate.test.ts +1 -1
  427. package/src/__tests__/tileset-asset-validate.test.ts +638 -0
  428. package/src/__tests__/transcode-fallback.unit.test.ts +207 -0
  429. package/src/__tests__/transform-hierarchy-pixel-diff.dawn.test.ts +36 -28
  430. package/src/__tests__/transient-fields-collect.test.ts +28 -21
  431. package/src/__tests__/transient-runtime-behavior.test.ts +227 -0
  432. package/src/__tests__/transparent-sort-tilemap-sprite-interleave.test.ts +4 -4
  433. package/src/__tests__/variant-selection.unit.test.ts +1 -1
  434. package/src/__tests__/video-extract-bindgroup.dawn.test.ts +89 -136
  435. package/src/__tests__/video-loader-consumption.test.ts +86 -0
  436. package/src/__tests__/video-loader-smoke.dawn.test.ts +60 -0
  437. package/src/__tests__/view-ubo-layout.browser.test.ts +0 -22
  438. package/src/__tests__/world-entity-key.test.ts +1 -1
  439. package/src/__tests__/world-scene-despawn.test.ts +1 -1
  440. package/src/__tests__/world-scene-instantiate.test.ts +2 -36
  441. package/src/__tests__/world-scene-nested.test.ts +1 -1
  442. package/src/__tests__/world-scene-override.test.ts +1 -1
  443. package/src/backend-selection.ts +69 -0
  444. package/src/collect-scene-asset.ts +35 -23
  445. package/src/components/__tests__/camera.test-d.ts +1 -1
  446. package/src/components/__tests__/camera.test.ts +1 -1
  447. package/src/components/__tests__/sprite-animation.test-d.ts +2 -2
  448. package/src/components/__tests__/tile-layer.test-d.ts +1 -1
  449. package/src/components/__tests__/tile-layer.unit.test.ts +2 -2
  450. package/src/createRenderer.ts +24 -36
  451. package/src/errors/environment.ts +1 -1
  452. package/src/index.ts +51 -113
  453. package/src/renderer-host.ts +33 -0
  454. package/src/scene-instances/__tests__/post-spawn-resolve-joints.unit.test.ts +1 -1
  455. package/src/scene-instances/index.ts +4 -0
  456. package/src/scene-utils/mount-override-fold.ts +3 -7
  457. package/src/systems/__tests__/transparent-sort.bench.ts +3 -3
  458. package/src/systems/sprite-animation-tick.ts +1 -1
  459. package/src/systems/transparent-sort.ts +38 -38
  460. package/src/tilemap-register-validate.ts +4 -4
  461. package/dist/__tests__/bind-group-cache-binding.test.d.ts +0 -2
  462. package/dist/__tests__/bind-group-cache-binding.test.d.ts.map +0 -1
  463. package/dist/__tests__/bind-group-cache-frame.test.d.ts +0 -2
  464. package/dist/__tests__/bind-group-cache-frame.test.d.ts.map +0 -1
  465. package/dist/__tests__/dawn/mesh-update.dawn.test.d.ts +0 -2
  466. package/dist/__tests__/dawn/mesh-update.dawn.test.d.ts.map +0 -1
  467. package/dist/__tests__/dispatch-fullscreen-pass-composite-swapchain.dawn.test.d.ts +0 -2
  468. package/dist/__tests__/dispatch-fullscreen-pass-composite-swapchain.dawn.test.d.ts.map +0 -1
  469. package/dist/__tests__/dispatch-fullscreen-pass-custom-reads.dawn.test.d.ts +0 -2
  470. package/dist/__tests__/dispatch-fullscreen-pass-custom-reads.dawn.test.d.ts.map +0 -1
  471. package/dist/__tests__/dispatch-fullscreen-pass-depth-composite.dawn.test.d.ts +0 -2
  472. package/dist/__tests__/dispatch-fullscreen-pass-depth-composite.dawn.test.d.ts.map +0 -1
  473. package/dist/__tests__/dispatch-fullscreen-pass-params.unit.test.d.ts +0 -2
  474. package/dist/__tests__/dispatch-fullscreen-pass-params.unit.test.d.ts.map +0 -1
  475. package/dist/__tests__/fog-producer-manifest.d.ts +0 -131
  476. package/dist/__tests__/fog-producer-manifest.d.ts.map +0 -1
  477. package/dist/__tests__/fog-producer-pixel-probe.d.ts +0 -42
  478. package/dist/__tests__/fog-producer-pixel-probe.d.ts.map +0 -1
  479. package/dist/__tests__/fog-producer-pixel.browser.test.d.ts +0 -2
  480. package/dist/__tests__/fog-producer-pixel.browser.test.d.ts.map +0 -1
  481. package/dist/__tests__/fog-producer-pixel.dawn.test.d.ts +0 -2
  482. package/dist/__tests__/fog-producer-pixel.dawn.test.d.ts.map +0 -1
  483. package/dist/__tests__/fog-producer-real-fixture.d.ts +0 -5
  484. package/dist/__tests__/fog-producer-real-fixture.d.ts.map +0 -1
  485. package/dist/__tests__/fog-producer-vfx-effect.d.ts +0 -3
  486. package/dist/__tests__/fog-producer-vfx-effect.d.ts.map +0 -1
  487. package/dist/__tests__/fog-scene-asset.integration.test.d.ts +0 -2
  488. package/dist/__tests__/fog-scene-asset.integration.test.d.ts.map +0 -1
  489. package/dist/__tests__/gpu-resource-store-cubemap-status.test.d.ts +0 -2
  490. package/dist/__tests__/gpu-resource-store-cubemap-status.test.d.ts.map +0 -1
  491. package/dist/__tests__/gpu-resource.test.d.ts +0 -2
  492. package/dist/__tests__/gpu-resource.test.d.ts.map +0 -1
  493. package/dist/__tests__/hdrp-bgl-slots.browser.test.d.ts +0 -2
  494. package/dist/__tests__/hdrp-bgl-slots.browser.test.d.ts.map +0 -1
  495. package/dist/__tests__/hdrp-buffers.unit.test.d.ts +0 -2
  496. package/dist/__tests__/hdrp-buffers.unit.test.d.ts.map +0 -1
  497. package/dist/__tests__/hdrp-execute-filter.unit.test.d.ts +0 -2
  498. package/dist/__tests__/hdrp-execute-filter.unit.test.d.ts.map +0 -1
  499. package/dist/__tests__/hdrp-gbuffer-attachments.browser.test.d.ts +0 -2
  500. package/dist/__tests__/hdrp-gbuffer-attachments.browser.test.d.ts.map +0 -1
  501. package/dist/__tests__/hdrp-pipeline-asset-type.test-d.d.ts +0 -2
  502. package/dist/__tests__/hdrp-pipeline-asset-type.test-d.d.ts.map +0 -1
  503. package/dist/__tests__/hdrp-ssao-boundary.test.d.ts +0 -2
  504. package/dist/__tests__/hdrp-ssao-boundary.test.d.ts.map +0 -1
  505. package/dist/__tests__/hdrp-ssao-falsification.test.d.ts +0 -2
  506. package/dist/__tests__/hdrp-ssao-falsification.test.d.ts.map +0 -1
  507. package/dist/__tests__/helpers/primitive-world.d.ts +0 -8
  508. package/dist/__tests__/helpers/primitive-world.d.ts.map +0 -1
  509. package/dist/__tests__/helpers/render-asset-port.d.ts +0 -15
  510. package/dist/__tests__/helpers/render-asset-port.d.ts.map +0 -1
  511. package/dist/__tests__/helpers/scene-asset-port.d.ts +0 -9
  512. package/dist/__tests__/helpers/scene-asset-port.d.ts.map +0 -1
  513. package/dist/__tests__/material-derived-coordinates.integration.test.d.ts +0 -2
  514. package/dist/__tests__/material-derived-coordinates.integration.test.d.ts.map +0 -1
  515. package/dist/__tests__/pipeline-layout-selection.test.d.ts +0 -2
  516. package/dist/__tests__/pipeline-layout-selection.test.d.ts.map +0 -1
  517. package/dist/__tests__/post-process-reads-narrowing.test-d.d.ts +0 -2
  518. package/dist/__tests__/post-process-reads-narrowing.test-d.d.ts.map +0 -1
  519. package/dist/__tests__/post-process-register-roundtrip.dawn.test.d.ts +0 -2
  520. package/dist/__tests__/post-process-register-roundtrip.dawn.test.d.ts.map +0 -1
  521. package/dist/__tests__/render-feature-zero-feature.browser.test.d.ts +0 -2
  522. package/dist/__tests__/render-feature-zero-feature.browser.test.d.ts.map +0 -1
  523. package/dist/__tests__/render-pipeline-trivial.dawn.test.d.ts +0 -2
  524. package/dist/__tests__/render-pipeline-trivial.dawn.test.d.ts.map +0 -1
  525. package/dist/__tests__/shadow-csm-caster-membership.test.d.ts +0 -2
  526. package/dist/__tests__/shadow-csm-caster-membership.test.d.ts.map +0 -1
  527. package/dist/__tests__/shadow-csm-pssm.test.d.ts +0 -2
  528. package/dist/__tests__/shadow-csm-pssm.test.d.ts.map +0 -1
  529. package/dist/__tests__/shadow-csm-temporal.browser.test.d.ts +0 -2
  530. package/dist/__tests__/shadow-csm-temporal.browser.test.d.ts.map +0 -1
  531. package/dist/__tests__/shadow-csm-viewport.test.d.ts +0 -2
  532. package/dist/__tests__/shadow-csm-viewport.test.d.ts.map +0 -1
  533. package/dist/__tests__/shadow-m2.dawn.test.d.ts +0 -2
  534. package/dist/__tests__/shadow-m2.dawn.test.d.ts.map +0 -1
  535. package/dist/__tests__/shadow-m3-calibrate-run.dawn.test.d.ts +0 -2
  536. package/dist/__tests__/shadow-m3-calibrate-run.dawn.test.d.ts.map +0 -1
  537. package/dist/__tests__/shadow-m3-calibrate.d.ts +0 -83
  538. package/dist/__tests__/shadow-m3-calibrate.d.ts.map +0 -1
  539. package/dist/__tests__/shadow-m3.dawn.test.d.ts +0 -2
  540. package/dist/__tests__/shadow-m3.dawn.test.d.ts.map +0 -1
  541. package/dist/__tests__/shadow-probe-control-flow.dawn.test.d.ts +0 -2
  542. package/dist/__tests__/shadow-probe-control-flow.dawn.test.d.ts.map +0 -1
  543. package/dist/__tests__/shadow-quality-metrics.dawn.test.d.ts +0 -2
  544. package/dist/__tests__/shadow-quality-metrics.dawn.test.d.ts.map +0 -1
  545. package/dist/__tests__/temporal-off-path.unit.test.d.ts +0 -2
  546. package/dist/__tests__/temporal-off-path.unit.test.d.ts.map +0 -1
  547. package/dist/__tests__/video-cache-regression.unit.test.d.ts +0 -2
  548. package/dist/__tests__/video-cache-regression.unit.test.d.ts.map +0 -1
  549. package/dist/asset-kind.d.ts +0 -4
  550. package/dist/asset-kind.d.ts.map +0 -1
  551. package/dist/errors/sprite-animation.d.ts +0 -3
  552. package/dist/errors/sprite-animation.d.ts.map +0 -1
  553. package/dist/scene-asset-port.d.ts +0 -17
  554. package/dist/scene-asset-port.d.ts.map +0 -1
  555. package/dist/scene-collect-errors.d.ts +0 -22
  556. package/dist/scene-collect-errors.d.ts.map +0 -1
  557. package/dist/shadow-m3-calibrate.d.ts +0 -40
  558. package/dist/shadow-m3-calibrate.d.ts.map +0 -1
  559. package/src/__tests__/bind-group-cache-binding.test.ts +0 -2513
  560. package/src/__tests__/bind-group-cache-frame.test.ts +0 -1511
  561. package/src/__tests__/dispatch-fullscreen-pass-composite-swapchain.dawn.test.ts +0 -204
  562. package/src/__tests__/dispatch-fullscreen-pass-custom-reads.dawn.test.ts +0 -297
  563. package/src/__tests__/dispatch-fullscreen-pass-depth-composite.dawn.test.ts +0 -271
  564. package/src/__tests__/dispatch-fullscreen-pass-params.unit.test.ts +0 -321
  565. package/src/__tests__/fog-producer-manifest.ts +0 -162
  566. package/src/__tests__/fog-producer-pixel-probe.ts +0 -263
  567. package/src/__tests__/fog-producer-pixel.browser.test.ts +0 -26
  568. package/src/__tests__/fog-producer-pixel.dawn.test.ts +0 -55
  569. package/src/__tests__/fog-producer-real-fixture.ts +0 -805
  570. package/src/__tests__/fog-producer-vfx-effect.ts +0 -272
  571. package/src/__tests__/fog-scene-asset.integration.test.ts +0 -123
  572. package/src/__tests__/gpu-resource-store-cubemap-status.test.ts +0 -207
  573. package/src/__tests__/gpu-resource.test.ts +0 -1206
  574. package/src/__tests__/hdrp-bgl-slots.browser.test.ts +0 -50
  575. package/src/__tests__/hdrp-buffers.unit.test.ts +0 -70
  576. package/src/__tests__/hdrp-execute-filter.unit.test.ts +0 -200
  577. package/src/__tests__/hdrp-gbuffer-attachments.browser.test.ts +0 -64
  578. package/src/__tests__/hdrp-pipeline-asset-type.test-d.ts +0 -139
  579. package/src/__tests__/hdrp-ssao-boundary.test.ts +0 -237
  580. package/src/__tests__/hdrp-ssao-falsification.test.ts +0 -289
  581. package/src/__tests__/helpers/primitive-world.ts +0 -91
  582. package/src/__tests__/helpers/render-asset-port.ts +0 -65
  583. package/src/__tests__/helpers/scene-asset-port.ts +0 -23
  584. package/src/__tests__/material-derived-coordinates.integration.test.ts +0 -100
  585. package/src/__tests__/pipeline-layout-selection.test.ts +0 -298
  586. package/src/__tests__/post-process-reads-narrowing.test-d.ts +0 -52
  587. package/src/__tests__/post-process-register-roundtrip.dawn.test.ts +0 -230
  588. package/src/__tests__/render-feature-zero-feature.browser.test.ts +0 -152
  589. package/src/__tests__/render-pipeline-trivial.dawn.test.ts +0 -525
  590. package/src/__tests__/shadow-csm-caster-membership.test.ts +0 -232
  591. package/src/__tests__/shadow-csm-pssm.test.ts +0 -142
  592. package/src/__tests__/shadow-csm-temporal.browser.test.ts +0 -145
  593. package/src/__tests__/shadow-csm-viewport.test.ts +0 -74
  594. package/src/__tests__/shadow-m2.dawn.test.ts +0 -394
  595. package/src/__tests__/shadow-m3-calibrate-run.dawn.test.ts +0 -248
  596. package/src/__tests__/shadow-m3-calibrate.ts +0 -203
  597. package/src/__tests__/shadow-m3.dawn.test.ts +0 -288
  598. package/src/__tests__/shadow-probe-control-flow.dawn.test.ts +0 -264
  599. package/src/__tests__/shadow-quality-metrics.dawn.test.ts +0 -324
  600. package/src/__tests__/temporal-off-path.unit.test.ts +0 -69
  601. package/src/__tests__/video-cache-regression.unit.test.ts +0 -186
  602. package/src/asset-kind.ts +0 -7
  603. package/src/errors/sprite-animation.ts +0 -5
  604. package/src/scene-asset-port.ts +0 -32
  605. package/src/scene-collect-errors.ts +0 -30
  606. package/src/shadow-m3-calibrate.ts +0 -171
@@ -1,264 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { SHADOW_PROBE_WGSL } from '../../../render/src/renderer/renderer-factory';
3
-
4
- const dawnReady = typeof navigator !== 'undefined' && navigator.gpu !== undefined;
5
-
6
- const PROBE_MAX_COUNT = 64;
7
- const PROBE_LSM_UBO_BYTES = 352;
8
- const PROBE_OUTPUT_WIDTH = PROBE_MAX_COUNT;
9
- const PROBE_OUTPUT_ROW_BYTES = PROBE_OUTPUT_WIDTH * 16;
10
- const DEPTH_ATLAS_WIDTH = 64;
11
- const DEPTH_ATLAS_HEIGHT = 32;
12
- const DEPTH_TILE_SIZE = DEPTH_ATLAS_WIDTH / 2;
13
-
14
- const GPU_BUFFER_MAP_READ = 0x0001;
15
- const GPU_BUFFER_COPY_DST = 0x0008;
16
- const GPU_BUFFER_UNIFORM = 0x0040;
17
- const GPU_BUFFER_STORAGE = 0x0080;
18
- const GPU_TEXTURE_COPY_SRC = 0x0001;
19
- const GPU_TEXTURE_TEXTURE_BINDING = 0x0004;
20
- const GPU_TEXTURE_RENDER_ATTACHMENT = 0x0010;
21
-
22
- const DEPTH_WRITE_WGSL = `
23
- struct VsOut {
24
- @builtin(position) position : vec4<f32>,
25
- };
26
-
27
- @vertex fn vs_main(@builtin(vertex_index) index : u32) -> VsOut {
28
- var positions = array<vec2<f32>, 3>(
29
- vec2<f32>(-1.0, -1.0),
30
- vec2<f32>( 3.0, -1.0),
31
- vec2<f32>(-1.0, 3.0),
32
- );
33
- var out : VsOut;
34
- out.position = vec4<f32>(positions[index], 0.1, 1.0);
35
- return out;
36
- }
37
- `;
38
-
39
- interface ProbeResult {
40
- readonly shadowFactor: number;
41
- readonly sampledDepth: number;
42
- readonly cascadeIndex: number;
43
- readonly receiverDepth: number;
44
- }
45
-
46
- function makeLightMatrix(): Float32Array {
47
- const matrix = new Float32Array(16);
48
- matrix[0] = 1;
49
- matrix[5] = 1;
50
- // Keep XY in clip space while pinning all receivers to a known depth.
51
- matrix[10] = 0;
52
- matrix[14] = 0.5;
53
- matrix[15] = 1;
54
- return matrix;
55
- }
56
-
57
- function makeIdentityMatrix(): Float32Array {
58
- const matrix = new Float32Array(16);
59
- matrix[0] = 1;
60
- matrix[5] = 1;
61
- matrix[10] = 1;
62
- matrix[15] = 1;
63
- return matrix;
64
- }
65
-
66
- async function runControlledProbe(): Promise<ProbeResult[]> {
67
- const gpu = navigator.gpu;
68
- const adapter = await gpu.requestAdapter();
69
- if (adapter === null) throw new Error('no Dawn adapter');
70
- const device = await adapter.requestDevice();
71
-
72
- const shaderModule = device.createShaderModule({ code: SHADOW_PROBE_WGSL });
73
- const pipeline = device.createRenderPipeline({
74
- layout: 'auto',
75
- vertex: { module: shaderModule, entryPoint: 'vs_main' },
76
- fragment: {
77
- module: shaderModule,
78
- entryPoint: 'fs_main',
79
- targets: [{ format: 'rgba32float' }],
80
- },
81
- primitive: { topology: 'triangle-list' },
82
- });
83
-
84
- const depthModule = device.createShaderModule({ code: DEPTH_WRITE_WGSL });
85
- const depthPipeline = device.createRenderPipeline({
86
- layout: 'auto',
87
- vertex: { module: depthModule, entryPoint: 'vs_main' },
88
- primitive: { topology: 'triangle-list' },
89
- depthStencil: {
90
- format: 'depth32float',
91
- depthWriteEnabled: true,
92
- depthCompare: 'less',
93
- },
94
- });
95
-
96
- const depthTexture = device.createTexture({
97
- size: { width: DEPTH_ATLAS_WIDTH, height: DEPTH_ATLAS_HEIGHT, depthOrArrayLayers: 1 },
98
- format: 'depth32float',
99
- usage: GPU_TEXTURE_TEXTURE_BINDING | GPU_TEXTURE_RENDER_ATTACHMENT,
100
- });
101
- const depthView = depthTexture.createView();
102
- const depthEncoder = device.createCommandEncoder();
103
- const depthPass = depthEncoder.beginRenderPass({
104
- colorAttachments: [],
105
- depthStencilAttachment: {
106
- view: depthView,
107
- depthLoadOp: 'clear',
108
- depthStoreOp: 'store',
109
- depthClearValue: 0.9,
110
- },
111
- });
112
- depthPass.setPipeline(depthPipeline);
113
- // Only sibling tile 1 contains a caster. Tile 0 stays at the clear depth.
114
- depthPass.setViewport(0, 0, DEPTH_ATLAS_WIDTH, DEPTH_ATLAS_HEIGHT, 0, 1);
115
- depthPass.setScissorRect(DEPTH_TILE_SIZE, 0, DEPTH_TILE_SIZE, DEPTH_TILE_SIZE);
116
- depthPass.draw(3);
117
- depthPass.end();
118
- device.queue.submit([depthEncoder.finish()]);
119
-
120
- const lsm = new Float32Array(PROBE_LSM_UBO_BYTES / 4);
121
- const lightMatrix = makeLightMatrix();
122
- const viewMatrix = makeIdentityMatrix();
123
- lsm.set(lightMatrix, 0);
124
- lsm.set(lightMatrix, 16);
125
- lsm.set(lightMatrix, 32);
126
- lsm.set(lightMatrix, 48);
127
- lsm.set(viewMatrix, 64);
128
- // Cascade 0 spans viewDepth < 10; cascade 1 ends at shadowDistance 15.
129
- lsm[80] = 10;
130
- lsm[81] = 15;
131
- const lsmU32 = new Uint32Array(lsm.buffer);
132
- lsmU32[84] = 2;
133
- lsmU32[85] = 3;
134
- lsm[86] = 0.2;
135
-
136
- // Three probes are deliberately chosen to falsify three independent
137
- // control-flow regressions:
138
- // 1. local XY outside cascade 0 but inside atlas-space UV;
139
- // 2. beyond the final split / shadowDistance;
140
- // 3. inside the cascade-0 blend band with different sibling depth.
141
- const positions = [
142
- [1.25, 0, 0.5, 0],
143
- [0, 0, -20, 0],
144
- [0, 0, -9, 0],
145
- ] as const;
146
- const input = new Float32Array(PROBE_MAX_COUNT * 4);
147
- for (let index = 0; index < positions.length; index += 1) {
148
- const [x, y, z, bias] = positions[index] ?? [0, 0, 0, 0];
149
- const base = index * 4;
150
- input[base] = x;
151
- input[base + 1] = y;
152
- input[base + 2] = z;
153
- input[base + 3] = bias;
154
- }
155
-
156
- const lsmBuffer = device.createBuffer({
157
- size: PROBE_LSM_UBO_BYTES,
158
- usage: GPU_BUFFER_UNIFORM | GPU_BUFFER_COPY_DST,
159
- });
160
- const inputBuffer = device.createBuffer({
161
- size: input.byteLength,
162
- usage: GPU_BUFFER_STORAGE | GPU_BUFFER_COPY_DST,
163
- });
164
- device.queue.writeBuffer(lsmBuffer, 0, lsm);
165
- device.queue.writeBuffer(inputBuffer, 0, input);
166
-
167
- const sampler = device.createSampler({
168
- addressModeU: 'clamp-to-edge',
169
- addressModeV: 'clamp-to-edge',
170
- magFilter: 'linear',
171
- minFilter: 'linear',
172
- compare: 'less',
173
- });
174
- const bindGroup = device.createBindGroup({
175
- layout: pipeline.getBindGroupLayout(0),
176
- entries: [
177
- { binding: 0, resource: { buffer: lsmBuffer } },
178
- { binding: 1, resource: { buffer: inputBuffer } },
179
- { binding: 2, resource: depthView },
180
- { binding: 3, resource: sampler },
181
- ],
182
- });
183
-
184
- const outputTexture = device.createTexture({
185
- size: { width: PROBE_OUTPUT_WIDTH, height: 1, depthOrArrayLayers: 1 },
186
- format: 'rgba32float',
187
- usage: GPU_TEXTURE_COPY_SRC | GPU_TEXTURE_RENDER_ATTACHMENT,
188
- });
189
- const outputView = outputTexture.createView();
190
- const staging = device.createBuffer({
191
- size: PROBE_OUTPUT_ROW_BYTES,
192
- usage: GPU_BUFFER_COPY_DST | GPU_BUFFER_MAP_READ,
193
- });
194
-
195
- const encoder = device.createCommandEncoder();
196
- const pass = encoder.beginRenderPass({
197
- colorAttachments: [
198
- {
199
- view: outputView,
200
- loadOp: 'clear',
201
- storeOp: 'store',
202
- clearValue: { r: 1, g: 1, b: -1, a: 1 },
203
- },
204
- ],
205
- });
206
- pass.setPipeline(pipeline);
207
- pass.setBindGroup(0, bindGroup);
208
- pass.draw(6, positions.length);
209
- pass.end();
210
- encoder.copyTextureToBuffer(
211
- { texture: outputTexture },
212
- { buffer: staging, bytesPerRow: PROBE_OUTPUT_ROW_BYTES, rowsPerImage: 1 },
213
- { width: PROBE_OUTPUT_WIDTH, height: 1, depthOrArrayLayers: 1 },
214
- );
215
- device.queue.submit([encoder.finish()]);
216
- await staging.mapAsync(GPU_BUFFER_MAP_READ);
217
- const readback = new Float32Array(staging.getMappedRange().slice(0));
218
- staging.unmap();
219
-
220
- const result: ProbeResult[] = [];
221
- for (let index = 0; index < positions.length; index += 1) {
222
- const base = index * 4;
223
- result.push({
224
- shadowFactor: readback[base] ?? 1,
225
- sampledDepth: readback[base + 1] ?? 1,
226
- cascadeIndex: Math.round(readback[base + 2] ?? -1),
227
- receiverDepth: readback[base + 3] ?? 1,
228
- });
229
- }
230
-
231
- staging.destroy();
232
- outputTexture.destroy();
233
- inputBuffer.destroy();
234
- lsmBuffer.destroy();
235
- depthTexture.destroy();
236
- device.destroy();
237
- return result;
238
- }
239
-
240
- describe('production shadow probe control-flow falsifiers', () => {
241
- it.skipIf(!dawnReady)(
242
- 'rejects local-tile OOB, final-split OOB, and blends sibling tiles',
243
- async () => {
244
- const [localOob, finalSplitOob, blendBand] = await runControlledProbe();
245
-
246
- // The local-tile point maps to atlas UV x=0.5625, where the sibling tile
247
- // contains depth 0.1. A global-atlas guard would read that non-clear depth;
248
- // the producer-local guard must fail closed before any texture read.
249
- expect(localOob?.shadowFactor).toBe(1);
250
- expect(localOob?.sampledDepth).toBe(1);
251
- expect(localOob?.cascadeIndex).toBe(0);
252
-
253
- expect(finalSplitOob?.cascadeIndex).toBe(-1);
254
- expect(finalSplitOob?.shadowFactor).toBe(1);
255
-
256
- // At viewDepth=9, split=10 and blend=0.2, t=0.5. Tile 0 is lit (0.9)
257
- // and sibling tile 1 is blocked (0.1), so the exact production blend is
258
- // 0.5. Removing the adjacent-layer sample or the mix makes this RED.
259
- expect(blendBand?.cascadeIndex).toBe(0);
260
- expect(blendBand?.shadowFactor).toBeCloseTo(0.5, 3);
261
- expect(blendBand?.sampledDepth).toBeCloseTo(0.9, 3);
262
- },
263
- );
264
- });
@@ -1,324 +0,0 @@
1
- // shadow-quality-metrics.dawn.test.ts — L1 shadow-quality metric probes.
2
- //
3
- // WHY THIS EXISTS
4
- // ---------------
5
- // Structural smoke ("4 shadowCascade passes, no crash") proves the pipeline is
6
- // wired, not that the shadows look right. Acne, missed occlusion, cascade seams
7
- // and peter-panning all pass a structural gate while looking broken. This suite
8
- // turns "does the shadow look good" into a handful of scalar metrics sampled off
9
- // the real shadow atlas via `renderer.debugSampleShadowFactor`, each with a
10
- // falsifiable assertion band. Regressions move a number; the number has a gate.
11
- //
12
- // WHAT THE PROBE MEASURES (and its honest limits)
13
- // -----------------------------------------------
14
- // `debugSampleShadowFactor(worldPositions)` reads the SAME shadow atlas the
15
- // forward pass samples, selects the cascade by frustum containment (mirrors the
16
- // shader's viewZ+splitPlanes selection), and returns a fixed-bias 3x3-PCF factor
17
- // per point (1 = fully lit, 0 = fully shadowed). That makes these metrics honest:
18
- // - acne — lit ground reads ~1 (no spurious self-shadow)
19
- // - coverage — ground under the occluder reads low (shadow is present)
20
- // - contact — the lit->shadowed transition sits at the occluder edge
21
- // (peter-panning = shadow starts too far from the caster)
22
- // - cascadeSeam — no factor discontinuity as depth crosses a split plane
23
- // NOT measurable here (needs L3 lit-framebuffer readback): penumbra WIDTH driven
24
- // by the material `pcfKernelSize`, because the probe uses its own fixed 3x3 tap,
25
- // not the forward shader's variable kernel. We do not fake that metric.
26
- //
27
- // FALSIFY DISCIPLINE
28
- // ------------------
29
- // Each metric has a paired "must move the right way when the scene breaks" check
30
- // (castShadow:false collapses coverage; a huge shadowDistance degrades near acne)
31
- // so a vacuous all-green (empty atlas, probe returning a constant) cannot pass.
32
-
33
- import { World } from '@forgeax/engine-ecs';
34
- import { createPrimitiveMesh } from '@forgeax/engine-geometry';
35
- import {
36
- Camera,
37
- DirectionalLight,
38
- MeshFilter,
39
- MeshRenderer,
40
- } from '@forgeax/engine-render/internal';
41
- import { Transform } from '@forgeax/engine-scene';
42
- import { describe, expect, it } from 'vitest';
43
- import { createRenderer } from '../index';
44
- import { drawPublished } from './draw-published';
45
-
46
- const ENGINE_MANIFEST = await (async () => {
47
- const { buildEngineShaderManifest } = await import('@forgeax/engine-vite-plugin-shader');
48
- return buildEngineShaderManifest();
49
- })();
50
- const ENGINE_MANIFEST_URL = `data:application/json,${encodeURIComponent(
51
- JSON.stringify(ENGINE_MANIFEST),
52
- )}`;
53
-
54
- // biome-ignore lint/suspicious/noExplicitAny: dawn-node detection guard
55
- const dawnReady = typeof navigator !== 'undefined' && (navigator as any).gpu !== undefined;
56
-
57
- const GROUND_SIZE = 40;
58
- const RT_W = 256;
59
- const RT_H = 256;
60
- const TEXTURE_USAGE_COPY_SRC = 0x01;
61
- const TEXTURE_USAGE_RENDER_ATTACHMENT = 0x10;
62
-
63
- // Mock canvas that exposes a real configurable WebGPU context + captures the
64
- // device, mirroring shadow-m3.dawn.test.ts exactly (per-canvas adapter patch).
65
- function createMockCanvas(): HTMLCanvasElement {
66
- let sharedDevice: GPUDevice | undefined;
67
- const originalRequestAdapter = globalThis.navigator.gpu.requestAdapter.bind(
68
- globalThis.navigator.gpu,
69
- );
70
- globalThis.navigator.gpu.requestAdapter = async (opts) => {
71
- const rawAdapter = await originalRequestAdapter(opts);
72
- if (rawAdapter === null) return rawAdapter;
73
- const originalRequestDevice = rawAdapter.requestDevice.bind(rawAdapter);
74
- rawAdapter.requestDevice = async (desc) => {
75
- const dev = await originalRequestDevice(desc);
76
- if (sharedDevice === undefined) sharedDevice = dev;
77
- return dev;
78
- };
79
- return rawAdapter;
80
- };
81
- let renderTarget: GPUTexture | undefined;
82
- const ensureRenderTarget = (device: GPUDevice, format: GPUTextureFormat): GPUTexture => {
83
- if (renderTarget !== undefined) return renderTarget;
84
- renderTarget = device.createTexture({
85
- size: { width: RT_W, height: RT_H, depthOrArrayLayers: 1 },
86
- format,
87
- usage: TEXTURE_USAGE_RENDER_ATTACHMENT | TEXTURE_USAGE_COPY_SRC,
88
- viewFormats: ['rgba8unorm-srgb'],
89
- });
90
- return renderTarget;
91
- };
92
- return {
93
- width: RT_W,
94
- height: RT_H,
95
- getContext(kind: string): unknown {
96
- if (kind !== 'webgpu') return null;
97
- return {
98
- configure(desc: { device: GPUDevice; format?: GPUTextureFormat }) {
99
- ensureRenderTarget(desc.device, desc.format ?? 'rgba8unorm');
100
- },
101
- unconfigure() {},
102
- getCurrentTexture(): GPUTexture {
103
- if (renderTarget === undefined) {
104
- if (sharedDevice === undefined)
105
- throw new Error('render target requested before device captured');
106
- return ensureRenderTarget(sharedDevice, 'rgba8unorm');
107
- }
108
- return renderTarget;
109
- },
110
- };
111
- },
112
- addEventListener() {},
113
- removeEventListener() {},
114
- } as unknown as HTMLCanvasElement;
115
- }
116
-
117
- interface SceneConfig {
118
- readonly castShadow?: boolean;
119
- readonly cascadeCount?: number;
120
- readonly shadowDistance?: number;
121
- readonly mapSize?: number;
122
- }
123
-
124
- // Ground plane at y=0 with a 2x2x2 occluder centred at y=1.5 (bottom face at
125
- // y=0.5), lit by a straight-down directional light. Orthographic camera framing
126
- // the scene so every probe point lands in the atlas fit. Occluder edges are at
127
- // x = +-1, so the ground shadow footprint is ~[-1,1] in x (light is near-vertical).
128
- function buildScene(world: World, cfg: SceneConfig): void {
129
- const cubeHandle = world.internSharedRef('MeshAsset', createPrimitiveMesh('cube').unwrap());
130
- world
131
- .spawn(
132
- {
133
- component: Transform,
134
- data: {
135
- pos: [0, -0.005, 0],
136
- quat: [0, 0, 0, 1],
137
- scale: [GROUND_SIZE, 0.01, GROUND_SIZE],
138
- },
139
- },
140
- { component: MeshFilter, data: { assetHandle: cubeHandle } },
141
- { component: MeshRenderer, data: {} },
142
- )
143
- .unwrap();
144
-
145
- world
146
- .spawn(
147
- {
148
- component: Transform,
149
- data: { pos: [0, 1.5, 0], quat: [0, 0, 0, 1], scale: [2, 2, 2] },
150
- },
151
- { component: MeshFilter, data: { assetHandle: cubeHandle } },
152
- { component: MeshRenderer, data: {} },
153
- )
154
- .unwrap();
155
-
156
- world
157
- .spawn({
158
- component: DirectionalLight,
159
- data: {
160
- direction: [0, -1, 0],
161
- color: [1, 1, 1],
162
- intensity: 1.5,
163
- castShadow: cfg.castShadow ?? true,
164
- cascadeCount: cfg.cascadeCount ?? 1,
165
- mapSize: cfg.mapSize ?? 1024,
166
- shadowDistance: cfg.shadowDistance ?? 50,
167
- },
168
- })
169
- .unwrap();
170
-
171
- world
172
- .spawn(
173
- { component: Transform, data: { pos: [0, 0, 10], quat: [0, 0, 0, 1] } },
174
- {
175
- component: Camera,
176
- data: {
177
- projection: 1,
178
- left: -GROUND_SIZE / 2,
179
- right: GROUND_SIZE / 2,
180
- bottom: -GROUND_SIZE / 2,
181
- top: GROUND_SIZE / 2,
182
- near: 0.1,
183
- far: 100,
184
- fov: 0,
185
- aspect: 1,
186
- } as Record<string, unknown> as never,
187
- },
188
- )
189
- .unwrap();
190
- }
191
-
192
- // ONE renderer for the whole suite. Creating a second createRenderer in the
193
- // same dawn-node process trips `manifest-malformed` (shared shader-module cache
194
- // state), so every sample() re-draws a fresh world through this single renderer
195
- // and re-reads the atlas — the extract stage rebuilds shadow matrices per frame.
196
- type Renderer = Awaited<ReturnType<typeof createRenderer>>;
197
- let sharedRenderer: Renderer | undefined;
198
- async function getRenderer(): Promise<Renderer> {
199
- if (sharedRenderer !== undefined) return sharedRenderer;
200
- const canvas = createMockCanvas();
201
- const renderer = await createRenderer(canvas, {}, { shaderManifestUrl: ENGINE_MANIFEST_URL });
202
- const ready = await renderer.ready;
203
- if (!ready.ok) throw new Error('renderer not ready');
204
- sharedRenderer = renderer;
205
- return renderer;
206
- }
207
-
208
- async function sample(
209
- cfg: SceneConfig,
210
- points: ReadonlyArray<readonly [number, number, number]>,
211
- ): Promise<number[]> {
212
- const renderer = await getRenderer();
213
- const world = new World();
214
- buildScene(world, cfg);
215
- world.update(1 / 60).unwrap();
216
- const draw = drawPublished(renderer, world);
217
- if (!draw.ok) throw new Error('draw failed');
218
- const res = await renderer.debugSampleShadowFactor?.(points);
219
- if (!res) throw new Error('debugSampleShadowFactor returned null');
220
- return res.map((r) => r.shadowFactor);
221
- }
222
-
223
- const mean = (xs: number[]): number => xs.reduce((a, b) => a + b, 0) / xs.length;
224
-
225
- describe('shadow quality metrics (L1 — off-atlas probe)', () => {
226
- it.skipIf(!dawnReady)('dawn-binding present', () => {
227
- expect(dawnReady).toBe(true);
228
- });
229
-
230
- // ── Metric: ACNE — lit ground far from the occluder must read ~fully lit ──
231
- it.skipIf(!dawnReady)('acne: unoccluded ground reads ~1 (no self-shadow noise)', async () => {
232
- const litPoints: [number, number, number][] = [
233
- [8, 0, 8],
234
- [-8, 0, 8],
235
- [8, 0, -8],
236
- [-8, 0, -8],
237
- [12, 0, 0],
238
- [-12, 0, 0],
239
- ];
240
- const factors = await sample({}, litPoints);
241
- const acneFraction = factors.filter((f) => f < 0.99).length / factors.length;
242
- // METRIC: fraction of clearly-unoccluded samples showing spurious shadow.
243
- // Gate: none should. A future acne regression pushes this above 0.
244
- expect(acneFraction).toBe(0);
245
- expect(mean(factors)).toBeGreaterThan(0.99);
246
- });
247
-
248
- // ── Metric: COVERAGE — ground under the occluder must be shadowed ──
249
- it.skipIf(!dawnReady)('coverage: ground under occluder reads shadowed', async () => {
250
- const under: [number, number, number][] = [
251
- [0, 0, 0],
252
- [0.5, 0, 0],
253
- [0, 0, 0.5],
254
- [-0.5, 0, -0.5],
255
- ];
256
- const factors = await sample({}, under);
257
- // METRIC: mean shadow factor directly under the caster. Gate: strongly
258
- // shadowed. Missed occlusion (bad ortho Z reach / too-small map) raises this.
259
- expect(mean(factors)).toBeLessThan(0.1);
260
- });
261
-
262
- // ── FALSIFY coverage: castShadow=false must collapse the shadow ──
263
- it.skipIf(!dawnReady)(
264
- 'coverage falsify: castShadow=false leaves under-occluder lit',
265
- async () => {
266
- const under: [number, number, number][] = [
267
- [0, 0, 0],
268
- [0.5, 0, 0],
269
- ];
270
- const on = mean(await sample({ castShadow: true }, under));
271
- const off = mean(await sample({ castShadow: false }, under));
272
- // The same points flip from shadowed to lit — proves the probe reads a real
273
- // atlas, not a constant. Guards against a vacuous coverage pass.
274
- expect(on).toBeLessThan(0.1);
275
- expect(off).toBeGreaterThan(0.9);
276
- },
277
- );
278
-
279
- // ── Metric: CONTACT / peter-panning — transition sits at the occluder edge ──
280
- it.skipIf(!dawnReady)('contact: shadow edge tracks the occluder footprint (x≈1)', async () => {
281
- // Scan x from deep-shadow (0) outward past the occluder edge (1.0) into
282
- // full light. The last shadowed sample and first lit sample must straddle
283
- // x≈1. Peter-panning would push the transition well past the edge.
284
- const xs = [0, 0.4, 0.8, 1.0, 1.2, 1.6, 2.0, 3.0];
285
- const factors = await sample(
286
- {},
287
- xs.map((x) => [x, 0, 0] as [number, number, number]),
288
- );
289
- const scan = xs.map((x, i) => ({ x, f: factors[i] ?? 1 }));
290
- const lastShadowedX = scan.filter((s) => s.f < 0.5).at(-1)?.x ?? -1;
291
- const firstLitX = scan.find((s) => s.f > 0.5)?.x ?? 999;
292
- // METRIC: transition band position. Measured contact profile is
293
- // [0,0,0.33,1,1,1,1] over xs => lastShadowedX=1.0, firstLitX=1.2, i.e. a
294
- // one-sample transition straddling the occluder edge (x=1). Gate: shadow
295
- // persists to the edge and clears within ~1 texel of it. Peter-panning
296
- // (shadow detached from the caster) pushes firstLitX out; this catches it.
297
- expect(lastShadowedX).toBeGreaterThanOrEqual(0.8);
298
- expect(firstLitX).toBeLessThanOrEqual(1.2);
299
- });
300
-
301
- // ── Metric: CASCADE SEAM — no factor jump across a split boundary ──
302
- it.skipIf(!dawnReady)(
303
- 'cascadeSeam: 4-cascade lit ground has no discontinuity vs 1-cascade',
304
- async () => {
305
- // Sample lit ground along increasing depth (spanning cascade splits under a
306
- // 4-cascade config). All should stay ~1; a seam would show a sudden dip at a
307
- // split plane. Compare the 4-cascade profile to the single-cascade baseline.
308
- const line: [number, number, number][] = [];
309
- for (let z = -18; z <= 18; z += 3) line.push([6, 0, z]);
310
- const one = await sample({ cascadeCount: 1 }, line);
311
- const four = await sample({ cascadeCount: 4 }, line);
312
- const maxAdjacentJump = (xs: number[]): number =>
313
- xs.reduce(
314
- (m, cur, i) => (i === 0 ? m : Math.max(m, Math.abs(cur - (xs[i - 1] ?? cur)))),
315
- 0,
316
- );
317
- // METRIC: largest factor step between adjacent lit samples. Gate: small for
318
- // both; the 4-cascade path must not introduce a seam the 1-cascade lacks.
319
- expect(maxAdjacentJump(one)).toBeLessThan(0.1);
320
- expect(maxAdjacentJump(four)).toBeLessThan(0.1);
321
- expect(mean(four)).toBeGreaterThan(0.95);
322
- },
323
- );
324
- });
@@ -1,69 +0,0 @@
1
- import { World } from '@forgeax/engine-ecs';
2
- import {
3
- ANTIALIAS_FXAA,
4
- ANTIALIAS_MSAA,
5
- ANTIALIAS_NONE,
6
- Camera,
7
- perspective,
8
- } from '@forgeax/engine-render';
9
- import { rhi } from '@forgeax/engine-rhi-null';
10
- import { Transform } from '@forgeax/engine-scene';
11
- import { describe, expect, it } from 'vitest';
12
- import { createRenderer } from '../createRenderer';
13
-
14
- const manifest = `data:application/json,${encodeURIComponent(
15
- JSON.stringify({
16
- schemaVersion: '1.0.0',
17
- entries: [
18
- { hash: 'pbr00000', wgsl: '/* pbr stub */', glsl: '', bindings: '' },
19
- { hash: 'unlit000', wgsl: '/* unlit stub */', glsl: '', bindings: '' },
20
- { hash: 'tonemap0', wgsl: '/* tonemap stub */', glsl: '', bindings: '' },
21
- ],
22
- }),
23
- )}`;
24
-
25
- function canvas(): HTMLCanvasElement {
26
- return {
27
- width: 64,
28
- height: 64,
29
- getContext: () => null,
30
- addEventListener: () => undefined,
31
- removeEventListener: () => undefined,
32
- } as unknown as HTMLCanvasElement;
33
- }
34
-
35
- describe.each([
36
- ['none', ANTIALIAS_NONE],
37
- ['fxaa', ANTIALIAS_FXAA],
38
- ['msaa', ANTIALIAS_MSAA],
39
- ] as const)('temporal off-path: %s', (_name, antialias) => {
40
- it('allocates no history and records no temporal pass', async () => {
41
- const renderer = await createRenderer(canvas(), { rhi }, { shaderManifestUrl: manifest });
42
- const ready = await renderer.ready;
43
- expect(ready.ok).toBe(true);
44
- const world = new World();
45
- const attached = renderer.attachWorld(world);
46
- expect(attached.ok).toBe(true);
47
- world
48
- .spawn(
49
- { component: Transform, data: { pos: [0, 0, 5] } },
50
- {
51
- component: Camera,
52
- data: { ...perspective({ fov: Math.PI / 4, aspect: 1 }), antialias },
53
- },
54
- )
55
- .unwrap();
56
- world.update(1 / 60).unwrap();
57
- expect(renderer.draw([world], { cameraOwner: 0, resourceOwner: 0 }).ok).toBe(true);
58
-
59
- expect(renderer.renderScene.temporal).toMatchObject({
60
- enabled: false,
61
- status: 'off',
62
- historyBytes: 0,
63
- historyOwnerGeneration: 0,
64
- });
65
- expect(renderer.perFramePassNames).not.toContain('scene-temporal-clear');
66
- expect(renderer.perFramePassNames).not.toContain('taa-resolve');
67
- renderer.dispose();
68
- });
69
- });