@forgeax/engine-runtime 0.1.2

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 (937) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +183 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/__tests__/active-camera.unit.test.d.ts +2 -0
  5. package/dist/__tests__/active-camera.unit.test.d.ts.map +1 -0
  6. package/dist/__tests__/animation-graph-add.unit.test.d.ts +2 -0
  7. package/dist/__tests__/animation-graph-add.unit.test.d.ts.map +1 -0
  8. package/dist/__tests__/animation-graph-asset-union.test-d.d.ts +2 -0
  9. package/dist/__tests__/animation-graph-asset-union.test-d.d.ts.map +1 -0
  10. package/dist/__tests__/animation-graph-blend.unit.test.d.ts +2 -0
  11. package/dist/__tests__/animation-graph-blend.unit.test.d.ts.map +1 -0
  12. package/dist/__tests__/animation-graph-build.unit.test.d.ts +2 -0
  13. package/dist/__tests__/animation-graph-build.unit.test.d.ts.map +1 -0
  14. package/dist/__tests__/animation-graph-clip-missing.unit.test.d.ts +2 -0
  15. package/dist/__tests__/animation-graph-clip-missing.unit.test.d.ts.map +1 -0
  16. package/dist/__tests__/animation-graph-clip.unit.test.d.ts +2 -0
  17. package/dist/__tests__/animation-graph-clip.unit.test.d.ts.map +1 -0
  18. package/dist/__tests__/animation-graph-default-path.integration.test.d.ts +2 -0
  19. package/dist/__tests__/animation-graph-default-path.integration.test.d.ts.map +1 -0
  20. package/dist/__tests__/animation-graph-describe.unit.test.d.ts +2 -0
  21. package/dist/__tests__/animation-graph-describe.unit.test.d.ts.map +1 -0
  22. package/dist/__tests__/animation-graph-errors.unit.test.d.ts +2 -0
  23. package/dist/__tests__/animation-graph-errors.unit.test.d.ts.map +1 -0
  24. package/dist/__tests__/animation-graph-nesting.unit.test.d.ts +2 -0
  25. package/dist/__tests__/animation-graph-nesting.unit.test.d.ts.map +1 -0
  26. package/dist/__tests__/animation-graph-orthogonal-weight.unit.test.d.ts +2 -0
  27. package/dist/__tests__/animation-graph-orthogonal-weight.unit.test.d.ts.map +1 -0
  28. package/dist/__tests__/animation-graph-slot-fill.unit.test.d.ts +2 -0
  29. package/dist/__tests__/animation-graph-slot-fill.unit.test.d.ts.map +1 -0
  30. package/dist/__tests__/animation-nslot.unit.test.d.ts +2 -0
  31. package/dist/__tests__/animation-nslot.unit.test.d.ts.map +1 -0
  32. package/dist/__tests__/animation-slot-length-guard.unit.test.d.ts +2 -0
  33. package/dist/__tests__/animation-slot-length-guard.unit.test.d.ts.map +1 -0
  34. package/dist/__tests__/append-injection.test.d.ts +2 -0
  35. package/dist/__tests__/append-injection.test.d.ts.map +1 -0
  36. package/dist/__tests__/asi-world-baseline-export.unit.test.d.ts +2 -0
  37. package/dist/__tests__/asi-world-baseline-export.unit.test.d.ts.map +1 -0
  38. package/dist/__tests__/asi-world-ci-config.unit.test.d.ts +2 -0
  39. package/dist/__tests__/asi-world-ci-config.unit.test.d.ts.map +1 -0
  40. package/dist/__tests__/asi-world-smoke.unit.test.d.ts +2 -0
  41. package/dist/__tests__/asi-world-smoke.unit.test.d.ts.map +1 -0
  42. package/dist/__tests__/asset-registry-scene.test-d.d.ts +2 -0
  43. package/dist/__tests__/asset-registry-scene.test-d.d.ts.map +1 -0
  44. package/dist/__tests__/bind-group-cache-binding.test.d.ts +2 -0
  45. package/dist/__tests__/bind-group-cache-binding.test.d.ts.map +1 -0
  46. package/dist/__tests__/bind-group-cache-frame.test.d.ts +2 -0
  47. package/dist/__tests__/bind-group-cache-frame.test.d.ts.map +1 -0
  48. package/dist/__tests__/bind-group-cache-keying.test.d.ts +2 -0
  49. package/dist/__tests__/bind-group-cache-keying.test.d.ts.map +1 -0
  50. package/dist/__tests__/block-upload-math.unit.test.d.ts +2 -0
  51. package/dist/__tests__/block-upload-math.unit.test.d.ts.map +1 -0
  52. package/dist/__tests__/builtin-shader-register-e2e.test.d.ts +2 -0
  53. package/dist/__tests__/builtin-shader-register-e2e.test.d.ts.map +1 -0
  54. package/dist/__tests__/cache-false-eviction.test.d.ts +2 -0
  55. package/dist/__tests__/cache-false-eviction.test.d.ts.map +1 -0
  56. package/dist/__tests__/cache-isolation-matrix.test.d.ts +2 -0
  57. package/dist/__tests__/cache-isolation-matrix.test.d.ts.map +1 -0
  58. package/dist/__tests__/camera-clear-snapshot-equivalence.unit.test.d.ts +2 -0
  59. package/dist/__tests__/camera-clear-snapshot-equivalence.unit.test.d.ts.map +1 -0
  60. package/dist/__tests__/clamp-to-last.e2e.browser.test.d.ts +2 -0
  61. package/dist/__tests__/clamp-to-last.e2e.browser.test.d.ts.map +1 -0
  62. package/dist/__tests__/clamp-to-last.e2e.dawn.test.d.ts +2 -0
  63. package/dist/__tests__/clamp-to-last.e2e.dawn.test.d.ts.map +1 -0
  64. package/dist/__tests__/collect-scene-asset.test.d.ts +3 -0
  65. package/dist/__tests__/collect-scene-asset.test.d.ts.map +1 -0
  66. package/dist/__tests__/collect-subtree.unit.test.d.ts +2 -0
  67. package/dist/__tests__/collect-subtree.unit.test.d.ts.map +1 -0
  68. package/dist/__tests__/collect-transient-children-absent.test.d.ts +2 -0
  69. package/dist/__tests__/collect-transient-children-absent.test.d.ts.map +1 -0
  70. package/dist/__tests__/collect-transient-roundtrip.test.d.ts +2 -0
  71. package/dist/__tests__/collect-transient-roundtrip.test.d.ts.map +1 -0
  72. package/dist/__tests__/collect-transient-skip.test.d.ts +3 -0
  73. package/dist/__tests__/collect-transient-skip.test.d.ts.map +1 -0
  74. package/dist/__tests__/components.test-d.d.ts +2 -0
  75. package/dist/__tests__/components.test-d.d.ts.map +1 -0
  76. package/dist/__tests__/components.unit.test.d.ts +2 -0
  77. package/dist/__tests__/components.unit.test.d.ts.map +1 -0
  78. package/dist/__tests__/composite-skybox-cross-world.browser.test.d.ts +2 -0
  79. package/dist/__tests__/composite-skybox-cross-world.browser.test.d.ts.map +1 -0
  80. package/dist/__tests__/create-renderer-assembly.integration.test.d.ts +2 -0
  81. package/dist/__tests__/create-renderer-assembly.integration.test.d.ts.map +1 -0
  82. package/dist/__tests__/createRenderer-dispose.test.d.ts +2 -0
  83. package/dist/__tests__/createRenderer-dispose.test.d.ts.map +1 -0
  84. package/dist/__tests__/createRenderer-requiredFeatures.unit.test.d.ts +2 -0
  85. package/dist/__tests__/createRenderer-requiredFeatures.unit.test.d.ts.map +1 -0
  86. package/dist/__tests__/createRenderer.browser-no-webgpu.test.d.ts +2 -0
  87. package/dist/__tests__/createRenderer.browser-no-webgpu.test.d.ts.map +1 -0
  88. package/dist/__tests__/createRenderer.unit.test.d.ts +2 -0
  89. package/dist/__tests__/createRenderer.unit.test.d.ts.map +1 -0
  90. package/dist/__tests__/dawn/hello-sprite-nineslice-section.dawn.test.d.ts +2 -0
  91. package/dist/__tests__/dawn/hello-sprite-nineslice-section.dawn.test.d.ts.map +1 -0
  92. package/dist/__tests__/dawn/ibl-compose.dawn.test.d.ts +2 -0
  93. package/dist/__tests__/dawn/ibl-compose.dawn.test.d.ts.map +1 -0
  94. package/dist/__tests__/dawn/ibl-modules-compose.dawn.test.d.ts +2 -0
  95. package/dist/__tests__/dawn/ibl-modules-compose.dawn.test.d.ts.map +1 -0
  96. package/dist/__tests__/dawn/ibl-precompute-readback.dawn.test.d.ts +2 -0
  97. package/dist/__tests__/dawn/ibl-precompute-readback.dawn.test.d.ts.map +1 -0
  98. package/dist/__tests__/dawn/instances-per-instance-pbr.dawn.test.d.ts +2 -0
  99. package/dist/__tests__/dawn/instances-per-instance-pbr.dawn.test.d.ts.map +1 -0
  100. package/dist/__tests__/dawn/instances-shadow.dawn.test.d.ts +2 -0
  101. package/dist/__tests__/dawn/instances-shadow.dawn.test.d.ts.map +1 -0
  102. package/dist/__tests__/dawn/instances-uniform-fallback.dawn.test.d.ts +2 -0
  103. package/dist/__tests__/dawn/instances-uniform-fallback.dawn.test.d.ts.map +1 -0
  104. package/dist/__tests__/dawn/material-alpha.dawn.test.d.ts +2 -0
  105. package/dist/__tests__/dawn/material-alpha.dawn.test.d.ts.map +1 -0
  106. package/dist/__tests__/dawn/material-cooked-fixture.dawn.test.d.ts +2 -0
  107. package/dist/__tests__/dawn/material-cooked-fixture.dawn.test.d.ts.map +1 -0
  108. package/dist/__tests__/dawn/mesh-ssbo-normal-matrix.dawn.test.d.ts +2 -0
  109. package/dist/__tests__/dawn/mesh-ssbo-normal-matrix.dawn.test.d.ts.map +1 -0
  110. package/dist/__tests__/dawn/mesh-update.dawn.test.d.ts +2 -0
  111. package/dist/__tests__/dawn/mesh-update.dawn.test.d.ts.map +1 -0
  112. package/dist/__tests__/dawn/mipmap-srgb-linear.dawn.test.d.ts +2 -0
  113. package/dist/__tests__/dawn/mipmap-srgb-linear.dawn.test.d.ts.map +1 -0
  114. package/dist/__tests__/dawn/per-entity-material-texture-isolation.dawn.test.d.ts +2 -0
  115. package/dist/__tests__/dawn/per-entity-material-texture-isolation.dawn.test.d.ts.map +1 -0
  116. package/dist/__tests__/dawn/sprite-nineslice-mesh-bind.dawn.test.d.ts +2 -0
  117. package/dist/__tests__/dawn/sprite-nineslice-mesh-bind.dawn.test.d.ts.map +1 -0
  118. package/dist/__tests__/dawn/tonemap.dawn.test.d.ts +2 -0
  119. package/dist/__tests__/dawn/tonemap.dawn.test.d.ts.map +1 -0
  120. package/dist/__tests__/dawn/user-handle-mesh-render.dawn.test.d.ts +2 -0
  121. package/dist/__tests__/dawn/user-handle-mesh-render.dawn.test.d.ts.map +1 -0
  122. package/dist/__tests__/dawn/user-mesh-upload.dawn.test.d.ts +2 -0
  123. package/dist/__tests__/dawn/user-mesh-upload.dawn.test.d.ts.map +1 -0
  124. package/dist/__tests__/dawn/zero-manifest-mesh-fail.dawn.test.d.ts +2 -0
  125. package/dist/__tests__/dawn/zero-manifest-mesh-fail.dawn.test.d.ts.map +1 -0
  126. package/dist/__tests__/dawn/zero-manifest-ready.dawn.test.d.ts +2 -0
  127. package/dist/__tests__/dawn/zero-manifest-ready.dawn.test.d.ts.map +1 -0
  128. package/dist/__tests__/demo-sortscope-migration.unit.test.d.ts +2 -0
  129. package/dist/__tests__/demo-sortscope-migration.unit.test.d.ts.map +1 -0
  130. package/dist/__tests__/derive-bgl-integration.test.d.ts +2 -0
  131. package/dist/__tests__/derive-bgl-integration.test.d.ts.map +1 -0
  132. package/dist/__tests__/derive-render-data-skin.unit.test.d.ts +2 -0
  133. package/dist/__tests__/derive-render-data-skin.unit.test.d.ts.map +1 -0
  134. package/dist/__tests__/dispatch-fullscreen-pass-composite-swapchain.dawn.test.d.ts +2 -0
  135. package/dist/__tests__/dispatch-fullscreen-pass-composite-swapchain.dawn.test.d.ts.map +1 -0
  136. package/dist/__tests__/dispatch-fullscreen-pass-custom-reads.dawn.test.d.ts +2 -0
  137. package/dist/__tests__/dispatch-fullscreen-pass-custom-reads.dawn.test.d.ts.map +1 -0
  138. package/dist/__tests__/dispatch-fullscreen-pass-depth-composite.dawn.test.d.ts +2 -0
  139. package/dist/__tests__/dispatch-fullscreen-pass-depth-composite.dawn.test.d.ts.map +1 -0
  140. package/dist/__tests__/dispatch-fullscreen-pass-params.unit.test.d.ts +2 -0
  141. package/dist/__tests__/dispatch-fullscreen-pass-params.unit.test.d.ts.map +1 -0
  142. package/dist/__tests__/draw-published.d.ts +5 -0
  143. package/dist/__tests__/draw-published.d.ts.map +1 -0
  144. package/dist/__tests__/environment-error-exhaustive.test-d.d.ts +8 -0
  145. package/dist/__tests__/environment-error-exhaustive.test-d.d.ts.map +1 -0
  146. package/dist/__tests__/equirect-bc6h.integration.test.d.ts +2 -0
  147. package/dist/__tests__/equirect-bc6h.integration.test.d.ts.map +1 -0
  148. package/dist/__tests__/error-exhaustive.test.d.ts +2 -0
  149. package/dist/__tests__/error-exhaustive.test.d.ts.map +1 -0
  150. package/dist/__tests__/extract-frames-graceful-degradation.test.d.ts +2 -0
  151. package/dist/__tests__/extract-frames-graceful-degradation.test.d.ts.map +1 -0
  152. package/dist/__tests__/extract-frames-merge.test.d.ts +2 -0
  153. package/dist/__tests__/extract-frames-merge.test.d.ts.map +1 -0
  154. package/dist/__tests__/extract-frames-reset.test.d.ts +2 -0
  155. package/dist/__tests__/extract-frames-reset.test.d.ts.map +1 -0
  156. package/dist/__tests__/extract-record-no-hardcoded-texture-fields.test.d.ts +2 -0
  157. package/dist/__tests__/extract-record-no-hardcoded-texture-fields.test.d.ts.map +1 -0
  158. package/dist/__tests__/fog-producer-manifest.d.ts +131 -0
  159. package/dist/__tests__/fog-producer-manifest.d.ts.map +1 -0
  160. package/dist/__tests__/fog-producer-pixel-probe.d.ts +42 -0
  161. package/dist/__tests__/fog-producer-pixel-probe.d.ts.map +1 -0
  162. package/dist/__tests__/fog-producer-pixel.browser.test.d.ts +2 -0
  163. package/dist/__tests__/fog-producer-pixel.browser.test.d.ts.map +1 -0
  164. package/dist/__tests__/fog-producer-pixel.dawn.test.d.ts +2 -0
  165. package/dist/__tests__/fog-producer-pixel.dawn.test.d.ts.map +1 -0
  166. package/dist/__tests__/fog-producer-real-fixture.d.ts +5 -0
  167. package/dist/__tests__/fog-producer-real-fixture.d.ts.map +1 -0
  168. package/dist/__tests__/fog-producer-vfx-effect.d.ts +3 -0
  169. package/dist/__tests__/fog-producer-vfx-effect.d.ts.map +1 -0
  170. package/dist/__tests__/fog-scene-asset.integration.test.d.ts +2 -0
  171. package/dist/__tests__/fog-scene-asset.integration.test.d.ts.map +1 -0
  172. package/dist/__tests__/frame-targets-shadow-regression.unit.test.d.ts +2 -0
  173. package/dist/__tests__/frame-targets-shadow-regression.unit.test.d.ts.map +1 -0
  174. package/dist/__tests__/fullscreen-post-bgl-depth.test.d.ts +2 -0
  175. package/dist/__tests__/fullscreen-post-bgl-depth.test.d.ts.map +1 -0
  176. package/dist/__tests__/fullscreen-post-depth-params-arity.test.d.ts +2 -0
  177. package/dist/__tests__/fullscreen-post-depth-params-arity.test.d.ts.map +1 -0
  178. package/dist/__tests__/fullscreen-post-process-pass.dawn.test.d.ts +2 -0
  179. package/dist/__tests__/fullscreen-post-process-pass.dawn.test.d.ts.map +1 -0
  180. package/dist/__tests__/fullscreen-post-process-pass.unit.test.d.ts +2 -0
  181. package/dist/__tests__/fullscreen-post-process-pass.unit.test.d.ts.map +1 -0
  182. package/dist/__tests__/fxaa-pixel-diff.dawn.test.d.ts +2 -0
  183. package/dist/__tests__/fxaa-pixel-diff.dawn.test.d.ts.map +1 -0
  184. package/dist/__tests__/fxaa-validation-and-resize.dawn.test.d.ts +2 -0
  185. package/dist/__tests__/fxaa-validation-and-resize.dawn.test.d.ts.map +1 -0
  186. package/dist/__tests__/fxaa-zero-overhead.dawn.test.d.ts +2 -0
  187. package/dist/__tests__/fxaa-zero-overhead.dawn.test.d.ts.map +1 -0
  188. package/dist/__tests__/geometry.unit.test.d.ts +2 -0
  189. package/dist/__tests__/geometry.unit.test.d.ts.map +1 -0
  190. package/dist/__tests__/glyph-tilemap-worldid.test.d.ts +2 -0
  191. package/dist/__tests__/glyph-tilemap-worldid.test.d.ts.map +1 -0
  192. package/dist/__tests__/gpu-resource-cow-survivor.test.d.ts +2 -0
  193. package/dist/__tests__/gpu-resource-cow-survivor.test.d.ts.map +1 -0
  194. package/dist/__tests__/gpu-resource-store-cubemap-status.test.d.ts +2 -0
  195. package/dist/__tests__/gpu-resource-store-cubemap-status.test.d.ts.map +1 -0
  196. package/dist/__tests__/gpu-resource.test.d.ts +2 -0
  197. package/dist/__tests__/gpu-resource.test.d.ts.map +1 -0
  198. package/dist/__tests__/hdrp-bgl-slots.browser.test.d.ts +2 -0
  199. package/dist/__tests__/hdrp-bgl-slots.browser.test.d.ts.map +1 -0
  200. package/dist/__tests__/hdrp-buffers.unit.test.d.ts +2 -0
  201. package/dist/__tests__/hdrp-buffers.unit.test.d.ts.map +1 -0
  202. package/dist/__tests__/hdrp-execute-filter.unit.test.d.ts +2 -0
  203. package/dist/__tests__/hdrp-execute-filter.unit.test.d.ts.map +1 -0
  204. package/dist/__tests__/hdrp-gbuffer-attachments.browser.test.d.ts +2 -0
  205. package/dist/__tests__/hdrp-gbuffer-attachments.browser.test.d.ts.map +1 -0
  206. package/dist/__tests__/hdrp-pipeline-asset-type.test-d.d.ts +2 -0
  207. package/dist/__tests__/hdrp-pipeline-asset-type.test-d.d.ts.map +1 -0
  208. package/dist/__tests__/hdrp-ssao-boundary.test.d.ts +2 -0
  209. package/dist/__tests__/hdrp-ssao-boundary.test.d.ts.map +1 -0
  210. package/dist/__tests__/hdrp-ssao-falsification.test.d.ts +2 -0
  211. package/dist/__tests__/hdrp-ssao-falsification.test.d.ts.map +1 -0
  212. package/dist/__tests__/hello-tilemap-smoke-upgrade.unit.test.d.ts +2 -0
  213. package/dist/__tests__/hello-tilemap-smoke-upgrade.unit.test.d.ts.map +1 -0
  214. package/dist/__tests__/helpers/mock-shader-registry.d.ts +11 -0
  215. package/dist/__tests__/helpers/mock-shader-registry.d.ts.map +1 -0
  216. package/dist/__tests__/helpers/primitive-world.d.ts +8 -0
  217. package/dist/__tests__/helpers/primitive-world.d.ts.map +1 -0
  218. package/dist/__tests__/helpers/register-runtime-components.d.ts +4 -0
  219. package/dist/__tests__/helpers/register-runtime-components.d.ts.map +1 -0
  220. package/dist/__tests__/helpers/register-scene-components.d.ts +4 -0
  221. package/dist/__tests__/helpers/register-scene-components.d.ts.map +1 -0
  222. package/dist/__tests__/helpers/render-asset-port.d.ts +15 -0
  223. package/dist/__tests__/helpers/render-asset-port.d.ts.map +1 -0
  224. package/dist/__tests__/helpers/scene-asset-port.d.ts +9 -0
  225. package/dist/__tests__/helpers/scene-asset-port.d.ts.map +1 -0
  226. package/dist/__tests__/helpers/tilemap-assets.d.ts +6 -0
  227. package/dist/__tests__/helpers/tilemap-assets.d.ts.map +1 -0
  228. package/dist/__tests__/instances.test-d.d.ts +2 -0
  229. package/dist/__tests__/instances.test-d.d.ts.map +1 -0
  230. package/dist/__tests__/light-attenuation-formula.test.d.ts +2 -0
  231. package/dist/__tests__/light-attenuation-formula.test.d.ts.map +1 -0
  232. package/dist/__tests__/light-casters-9-light.browser.test.d.ts +2 -0
  233. package/dist/__tests__/light-casters-9-light.browser.test.d.ts.map +1 -0
  234. package/dist/__tests__/light-gpu-byte-neutral.unit.test.d.ts +2 -0
  235. package/dist/__tests__/light-gpu-byte-neutral.unit.test.d.ts.map +1 -0
  236. package/dist/__tests__/light-snapshot.test-d.d.ts +2 -0
  237. package/dist/__tests__/light-snapshot.test-d.d.ts.map +1 -0
  238. package/dist/__tests__/lights-vec-negative.unit.test.d.ts +2 -0
  239. package/dist/__tests__/lights-vec-negative.unit.test.d.ts.map +1 -0
  240. package/dist/__tests__/lights.unit.test.d.ts +2 -0
  241. package/dist/__tests__/lights.unit.test.d.ts.map +1 -0
  242. package/dist/__tests__/m3-vec-negative.unit.test.d.ts +2 -0
  243. package/dist/__tests__/m3-vec-negative.unit.test.d.ts.map +1 -0
  244. package/dist/__tests__/m5-browser-dawn-sweep.integration.test.d.ts +2 -0
  245. package/dist/__tests__/m5-browser-dawn-sweep.integration.test.d.ts.map +1 -0
  246. package/dist/__tests__/material-derived-coordinates.integration.test.d.ts +2 -0
  247. package/dist/__tests__/material-derived-coordinates.integration.test.d.ts.map +1 -0
  248. package/dist/__tests__/material-texture-uv-scale.unit.test.d.ts +2 -0
  249. package/dist/__tests__/material-texture-uv-scale.unit.test.d.ts.map +1 -0
  250. package/dist/__tests__/materials.unit.test.d.ts +2 -0
  251. package/dist/__tests__/materials.unit.test.d.ts.map +1 -0
  252. package/dist/__tests__/mesh-ssbo-grow.unit.test.d.ts +2 -0
  253. package/dist/__tests__/mesh-ssbo-grow.unit.test.d.ts.map +1 -0
  254. package/dist/__tests__/mip-gate.unit.test.d.ts +2 -0
  255. package/dist/__tests__/mip-gate.unit.test.d.ts.map +1 -0
  256. package/dist/__tests__/msaa-sprite-pixel-diff.dawn.test.d.ts +2 -0
  257. package/dist/__tests__/msaa-sprite-pixel-diff.dawn.test.d.ts.map +1 -0
  258. package/dist/__tests__/multi-uv-8set.e2e.dawn.test.d.ts +2 -0
  259. package/dist/__tests__/multi-uv-8set.e2e.dawn.test.d.ts.map +1 -0
  260. package/dist/__tests__/name.unit.test.d.ts +2 -0
  261. package/dist/__tests__/name.unit.test.d.ts.map +1 -0
  262. package/dist/__tests__/pass-selector.unit.test.d.ts +2 -0
  263. package/dist/__tests__/pass-selector.unit.test.d.ts.map +1 -0
  264. package/dist/__tests__/pbr-pipeline.unit.test.d.ts +2 -0
  265. package/dist/__tests__/pbr-pipeline.unit.test.d.ts.map +1 -0
  266. package/dist/__tests__/pipeline-builder-msaa.unit.test.d.ts +2 -0
  267. package/dist/__tests__/pipeline-builder-msaa.unit.test.d.ts.map +1 -0
  268. package/dist/__tests__/pipeline-cache-keying.unit.test.d.ts +2 -0
  269. package/dist/__tests__/pipeline-cache-keying.unit.test.d.ts.map +1 -0
  270. package/dist/__tests__/pipeline-layout-selection.test.d.ts +2 -0
  271. package/dist/__tests__/pipeline-layout-selection.test.d.ts.map +1 -0
  272. package/dist/__tests__/pipeline-spec.test.d.ts +2 -0
  273. package/dist/__tests__/pipeline-spec.test.d.ts.map +1 -0
  274. package/dist/__tests__/pipeline.unit.test.d.ts +2 -0
  275. package/dist/__tests__/pipeline.unit.test.d.ts.map +1 -0
  276. package/dist/__tests__/point-light-shadow.browser.test.d.ts +2 -0
  277. package/dist/__tests__/point-light-shadow.browser.test.d.ts.map +1 -0
  278. package/dist/__tests__/point-light-shadow.dawn.test.d.ts +2 -0
  279. package/dist/__tests__/point-light-shadow.dawn.test.d.ts.map +1 -0
  280. package/dist/__tests__/point-light-shadow.unit.test.d.ts +2 -0
  281. package/dist/__tests__/point-light-shadow.unit.test.d.ts.map +1 -0
  282. package/dist/__tests__/post-process-error-codes.unit.test.d.ts +2 -0
  283. package/dist/__tests__/post-process-error-codes.unit.test.d.ts.map +1 -0
  284. package/dist/__tests__/post-process-params-component.unit.test.d.ts +2 -0
  285. package/dist/__tests__/post-process-params-component.unit.test.d.ts.map +1 -0
  286. package/dist/__tests__/post-process-params-extract.unit.test.d.ts +2 -0
  287. package/dist/__tests__/post-process-params-extract.unit.test.d.ts.map +1 -0
  288. package/dist/__tests__/post-process-reads-narrowing.test-d.d.ts +2 -0
  289. package/dist/__tests__/post-process-reads-narrowing.test-d.d.ts.map +1 -0
  290. package/dist/__tests__/post-process-register-roundtrip.dawn.test.d.ts +2 -0
  291. package/dist/__tests__/post-process-register-roundtrip.dawn.test.d.ts.map +1 -0
  292. package/dist/__tests__/postprocess-camera-consistency.test.d.ts +2 -0
  293. package/dist/__tests__/postprocess-camera-consistency.test.d.ts.map +1 -0
  294. package/dist/__tests__/profiler-assembly.integration.test.d.ts +2 -0
  295. package/dist/__tests__/profiler-assembly.integration.test.d.ts.map +1 -0
  296. package/dist/__tests__/propagate-transforms.dawn.test.d.ts +2 -0
  297. package/dist/__tests__/propagate-transforms.dawn.test.d.ts.map +1 -0
  298. package/dist/__tests__/record-worldid-isolation.test.d.ts +2 -0
  299. package/dist/__tests__/record-worldid-isolation.test.d.ts.map +1 -0
  300. package/dist/__tests__/recover-error-exhaustive.test-d.d.ts +11 -0
  301. package/dist/__tests__/recover-error-exhaustive.test-d.d.ts.map +1 -0
  302. package/dist/__tests__/render-error-exhaustive.test-d.d.ts +11 -0
  303. package/dist/__tests__/render-error-exhaustive.test-d.d.ts.map +1 -0
  304. package/dist/__tests__/render-feature-assembly.test-d.d.ts +2 -0
  305. package/dist/__tests__/render-feature-assembly.test-d.d.ts.map +1 -0
  306. package/dist/__tests__/render-feature-prepared-graphics-docs.unit.test.d.ts +2 -0
  307. package/dist/__tests__/render-feature-prepared-graphics-docs.unit.test.d.ts.map +1 -0
  308. package/dist/__tests__/render-feature-prepared-graphics.browser.test.d.ts +2 -0
  309. package/dist/__tests__/render-feature-prepared-graphics.browser.test.d.ts.map +1 -0
  310. package/dist/__tests__/render-feature-prepared-graphics.dawn.test.d.ts +2 -0
  311. package/dist/__tests__/render-feature-prepared-graphics.dawn.test.d.ts.map +1 -0
  312. package/dist/__tests__/render-feature-prepared-graphics.integration.test.d.ts +2 -0
  313. package/dist/__tests__/render-feature-prepared-graphics.integration.test.d.ts.map +1 -0
  314. package/dist/__tests__/render-feature-prepared-graphics.regression.integration.test.d.ts +2 -0
  315. package/dist/__tests__/render-feature-prepared-graphics.regression.integration.test.d.ts.map +1 -0
  316. package/dist/__tests__/render-feature-recover.integration.test.d.ts +2 -0
  317. package/dist/__tests__/render-feature-recover.integration.test.d.ts.map +1 -0
  318. package/dist/__tests__/render-feature-runtime-surface.test-d.d.ts +2 -0
  319. package/dist/__tests__/render-feature-runtime-surface.test-d.d.ts.map +1 -0
  320. package/dist/__tests__/render-feature-zero-feature.browser.test.d.ts +2 -0
  321. package/dist/__tests__/render-feature-zero-feature.browser.test.d.ts.map +1 -0
  322. package/dist/__tests__/render-pipeline-trivial.dawn.test.d.ts +2 -0
  323. package/dist/__tests__/render-pipeline-trivial.dawn.test.d.ts.map +1 -0
  324. package/dist/__tests__/render-schema-consumer.integration.test.d.ts +2 -0
  325. package/dist/__tests__/render-schema-consumer.integration.test.d.ts.map +1 -0
  326. package/dist/__tests__/render-schema-owner-boundary.unit.test.d.ts +2 -0
  327. package/dist/__tests__/render-schema-owner-boundary.unit.test.d.ts.map +1 -0
  328. package/dist/__tests__/render-system-cross-world-overlay-queue.test.d.ts +2 -0
  329. package/dist/__tests__/render-system-cross-world-overlay-queue.test.d.ts.map +1 -0
  330. package/dist/__tests__/render-system-extract-dispatch-ordering.test.d.ts +2 -0
  331. package/dist/__tests__/render-system-extract-dispatch-ordering.test.d.ts.map +1 -0
  332. package/dist/__tests__/render-system-extract.test.d.ts +2 -0
  333. package/dist/__tests__/render-system-extract.test.d.ts.map +1 -0
  334. package/dist/__tests__/render-system-fold-bucket.unit.test.d.ts +2 -0
  335. package/dist/__tests__/render-system-fold-bucket.unit.test.d.ts.map +1 -0
  336. package/dist/__tests__/render-system-fold-fallback.unit.test.d.ts +2 -0
  337. package/dist/__tests__/render-system-fold-fallback.unit.test.d.ts.map +1 -0
  338. package/dist/__tests__/render-system-fold-material.unit.test.d.ts +2 -0
  339. package/dist/__tests__/render-system-fold-material.unit.test.d.ts.map +1 -0
  340. package/dist/__tests__/render-system-fold-metrics.unit.test.d.ts +2 -0
  341. package/dist/__tests__/render-system-fold-metrics.unit.test.d.ts.map +1 -0
  342. package/dist/__tests__/render-system-fold-modegate.unit.test.d.ts +2 -0
  343. package/dist/__tests__/render-system-fold-modegate.unit.test.d.ts.map +1 -0
  344. package/dist/__tests__/render-system-fold-scene-instances.unit.test.d.ts +2 -0
  345. package/dist/__tests__/render-system-fold-scene-instances.unit.test.d.ts.map +1 -0
  346. package/dist/__tests__/render-system-fold.dawn.test.d.ts +2 -0
  347. package/dist/__tests__/render-system-fold.dawn.test.d.ts.map +1 -0
  348. package/dist/__tests__/render-system-mega.test.d.ts +2 -0
  349. package/dist/__tests__/render-system-mega.test.d.ts.map +1 -0
  350. package/dist/__tests__/render-system-owner-split-contract.test.d.ts +2 -0
  351. package/dist/__tests__/render-system-owner-split-contract.test.d.ts.map +1 -0
  352. package/dist/__tests__/render-system-record-multi-material-textureview.test.d.ts +2 -0
  353. package/dist/__tests__/render-system-record-multi-material-textureview.test.d.ts.map +1 -0
  354. package/dist/__tests__/render-system-record-per-submesh-transparency.test.d.ts +2 -0
  355. package/dist/__tests__/render-system-record-per-submesh-transparency.test.d.ts.map +1 -0
  356. package/dist/__tests__/render-system-record.test.d.ts +2 -0
  357. package/dist/__tests__/render-system-record.test.d.ts.map +1 -0
  358. package/dist/__tests__/render-system-record.unit.test.d.ts +2 -0
  359. package/dist/__tests__/render-system-record.unit.test.d.ts.map +1 -0
  360. package/dist/__tests__/render-system-skin-bg.unit.test.d.ts +2 -0
  361. package/dist/__tests__/render-system-skin-bg.unit.test.d.ts.map +1 -0
  362. package/dist/__tests__/renderer-consumer.test-d.d.ts +2 -0
  363. package/dist/__tests__/renderer-consumer.test-d.d.ts.map +1 -0
  364. package/dist/__tests__/renderer-health.unit.test.d.ts +2 -0
  365. package/dist/__tests__/renderer-health.unit.test.d.ts.map +1 -0
  366. package/dist/__tests__/renderer-lifecycle.integration.test.d.ts +2 -0
  367. package/dist/__tests__/renderer-lifecycle.integration.test.d.ts.map +1 -0
  368. package/dist/__tests__/renderer-recover.unit.test.d.ts +2 -0
  369. package/dist/__tests__/renderer-recover.unit.test.d.ts.map +1 -0
  370. package/dist/__tests__/renderer-result.test-d.d.ts +2 -0
  371. package/dist/__tests__/renderer-result.test-d.d.ts.map +1 -0
  372. package/dist/__tests__/renderer-surface.unit.test.d.ts +2 -0
  373. package/dist/__tests__/renderer-surface.unit.test.d.ts.map +1 -0
  374. package/dist/__tests__/resolve-depth-only-view.test.d.ts +2 -0
  375. package/dist/__tests__/resolve-depth-only-view.test.d.ts.map +1 -0
  376. package/dist/__tests__/rhi-null-command-flow.unit.test.d.ts +2 -0
  377. package/dist/__tests__/rhi-null-command-flow.unit.test.d.ts.map +1 -0
  378. package/dist/__tests__/rhi-null-noop-behavior.unit.test.d.ts +2 -0
  379. package/dist/__tests__/rhi-null-noop-behavior.unit.test.d.ts.map +1 -0
  380. package/dist/__tests__/rhi-null-renderer-lifecycle.unit.test.d.ts +2 -0
  381. package/dist/__tests__/rhi-null-renderer-lifecycle.unit.test.d.ts.map +1 -0
  382. package/dist/__tests__/roots-to-scene-asset.test.d.ts +2 -0
  383. package/dist/__tests__/roots-to-scene-asset.test.d.ts.map +1 -0
  384. package/dist/__tests__/runtime-authority-scan.unit.test.d.ts +2 -0
  385. package/dist/__tests__/runtime-authority-scan.unit.test.d.ts.map +1 -0
  386. package/dist/__tests__/runtime-domain-residue.unit.test.d.ts +2 -0
  387. package/dist/__tests__/runtime-domain-residue.unit.test.d.ts.map +1 -0
  388. package/dist/__tests__/scene-equirect-roundtrip.test.d.ts +2 -0
  389. package/dist/__tests__/scene-equirect-roundtrip.test.d.ts.map +1 -0
  390. package/dist/__tests__/scene-instance-bridge.integration.test.d.ts +2 -0
  391. package/dist/__tests__/scene-instance-bridge.integration.test.d.ts.map +1 -0
  392. package/dist/__tests__/scene-instance-component.test.d.ts +2 -0
  393. package/dist/__tests__/scene-instance-component.test.d.ts.map +1 -0
  394. package/dist/__tests__/scene-instantiate-cycle-runtime.test.d.ts +2 -0
  395. package/dist/__tests__/scene-instantiate-cycle-runtime.test.d.ts.map +1 -0
  396. package/dist/__tests__/serialize-scene-asset.test.d.ts +2 -0
  397. package/dist/__tests__/serialize-scene-asset.test.d.ts.map +1 -0
  398. package/dist/__tests__/shadow-caster-empty-schema.test.d.ts +2 -0
  399. package/dist/__tests__/shadow-caster-empty-schema.test.d.ts.map +1 -0
  400. package/dist/__tests__/shadow-csm-atlas.test.d.ts +2 -0
  401. package/dist/__tests__/shadow-csm-atlas.test.d.ts.map +1 -0
  402. package/dist/__tests__/shadow-csm-blend.dawn.test.d.ts +2 -0
  403. package/dist/__tests__/shadow-csm-blend.dawn.test.d.ts.map +1 -0
  404. package/dist/__tests__/shadow-csm-cascade-loadop.test.d.ts +2 -0
  405. package/dist/__tests__/shadow-csm-cascade-loadop.test.d.ts.map +1 -0
  406. package/dist/__tests__/shadow-csm-caster-membership.test.d.ts +2 -0
  407. package/dist/__tests__/shadow-csm-caster-membership.test.d.ts.map +1 -0
  408. package/dist/__tests__/shadow-csm-component.test.d.ts +2 -0
  409. package/dist/__tests__/shadow-csm-component.test.d.ts.map +1 -0
  410. package/dist/__tests__/shadow-csm-extract.test.d.ts +2 -0
  411. package/dist/__tests__/shadow-csm-extract.test.d.ts.map +1 -0
  412. package/dist/__tests__/shadow-csm-orthoz.test.d.ts +2 -0
  413. package/dist/__tests__/shadow-csm-orthoz.test.d.ts.map +1 -0
  414. package/dist/__tests__/shadow-csm-pssm.test.d.ts +2 -0
  415. package/dist/__tests__/shadow-csm-pssm.test.d.ts.map +1 -0
  416. package/dist/__tests__/shadow-csm-runtime-vary.dawn.test.d.ts +2 -0
  417. package/dist/__tests__/shadow-csm-runtime-vary.dawn.test.d.ts.map +1 -0
  418. package/dist/__tests__/shadow-csm-shader.dawn.test.d.ts +2 -0
  419. package/dist/__tests__/shadow-csm-shader.dawn.test.d.ts.map +1 -0
  420. package/dist/__tests__/shadow-csm-temporal.browser.test.d.ts +2 -0
  421. package/dist/__tests__/shadow-csm-temporal.browser.test.d.ts.map +1 -0
  422. package/dist/__tests__/shadow-csm-tile-consistency.test.d.ts +2 -0
  423. package/dist/__tests__/shadow-csm-tile-consistency.test.d.ts.map +1 -0
  424. package/dist/__tests__/shadow-csm-ubo.dawn.test.d.ts +2 -0
  425. package/dist/__tests__/shadow-csm-ubo.dawn.test.d.ts.map +1 -0
  426. package/dist/__tests__/shadow-csm-ubo.test.d.ts +2 -0
  427. package/dist/__tests__/shadow-csm-ubo.test.d.ts.map +1 -0
  428. package/dist/__tests__/shadow-csm-viewport.browser.test.d.ts +2 -0
  429. package/dist/__tests__/shadow-csm-viewport.browser.test.d.ts.map +1 -0
  430. package/dist/__tests__/shadow-csm-viewport.test.d.ts +2 -0
  431. package/dist/__tests__/shadow-csm-viewport.test.d.ts.map +1 -0
  432. package/dist/__tests__/shadow-fields-observable.dawn.test.d.ts +2 -0
  433. package/dist/__tests__/shadow-fields-observable.dawn.test.d.ts.map +1 -0
  434. package/dist/__tests__/shadow-m1.dawn.test.d.ts +2 -0
  435. package/dist/__tests__/shadow-m1.dawn.test.d.ts.map +1 -0
  436. package/dist/__tests__/shadow-m2.dawn.test.d.ts +2 -0
  437. package/dist/__tests__/shadow-m2.dawn.test.d.ts.map +1 -0
  438. package/dist/__tests__/shadow-m3-calibrate-run.dawn.test.d.ts +2 -0
  439. package/dist/__tests__/shadow-m3-calibrate-run.dawn.test.d.ts.map +1 -0
  440. package/dist/__tests__/shadow-m3-calibrate.d.ts +83 -0
  441. package/dist/__tests__/shadow-m3-calibrate.d.ts.map +1 -0
  442. package/dist/__tests__/shadow-m3.dawn.test.d.ts +2 -0
  443. package/dist/__tests__/shadow-m3.dawn.test.d.ts.map +1 -0
  444. package/dist/__tests__/shadow-mesh-ssbo-order.test.d.ts +2 -0
  445. package/dist/__tests__/shadow-mesh-ssbo-order.test.d.ts.map +1 -0
  446. package/dist/__tests__/shadow-probe-control-flow.dawn.test.d.ts +2 -0
  447. package/dist/__tests__/shadow-probe-control-flow.dawn.test.d.ts.map +1 -0
  448. package/dist/__tests__/shadow-quality-metrics.dawn.test.d.ts +2 -0
  449. package/dist/__tests__/shadow-quality-metrics.dawn.test.d.ts.map +1 -0
  450. package/dist/__tests__/skin-error-exhaustive.test-d.d.ts +11 -0
  451. package/dist/__tests__/skin-error-exhaustive.test-d.d.ts.map +1 -0
  452. package/dist/__tests__/skin-errors.unit.test.d.ts +2 -0
  453. package/dist/__tests__/skin-errors.unit.test.d.ts.map +1 -0
  454. package/dist/__tests__/skin-extract-getarrayview-count.unit.test.d.ts +2 -0
  455. package/dist/__tests__/skin-extract-getarrayview-count.unit.test.d.ts.map +1 -0
  456. package/dist/__tests__/skin-parented-double-transform.test.d.ts +14 -0
  457. package/dist/__tests__/skin-parented-double-transform.test.d.ts.map +1 -0
  458. package/dist/__tests__/skylight-lazy-projection.test.d.ts +2 -0
  459. package/dist/__tests__/skylight-lazy-projection.test.d.ts.map +1 -0
  460. package/dist/__tests__/sparse-tag-scene-roundtrip.test.d.ts +2 -0
  461. package/dist/__tests__/sparse-tag-scene-roundtrip.test.d.ts.map +1 -0
  462. package/dist/__tests__/sprite-cullmode-flip.dawn.test.d.ts +2 -0
  463. package/dist/__tests__/sprite-cullmode-flip.dawn.test.d.ts.map +1 -0
  464. package/dist/__tests__/sprite-lit-bgl-byte-identical.test.d.ts +2 -0
  465. package/dist/__tests__/sprite-lit-bgl-byte-identical.test.d.ts.map +1 -0
  466. package/dist/__tests__/sprite-lit-extract-branch.test.d.ts +2 -0
  467. package/dist/__tests__/sprite-lit-extract-branch.test.d.ts.map +1 -0
  468. package/dist/__tests__/sprite-lit-pipeline-cache-key.test.d.ts +2 -0
  469. package/dist/__tests__/sprite-lit-pipeline-cache-key.test.d.ts.map +1 -0
  470. package/dist/__tests__/sprite-param-values.test-d.d.ts +2 -0
  471. package/dist/__tests__/sprite-param-values.test-d.d.ts.map +1 -0
  472. package/dist/__tests__/ssao-bgl.test.d.ts +2 -0
  473. package/dist/__tests__/ssao-bgl.test.d.ts.map +1 -0
  474. package/dist/__tests__/ssao-buffers.test.d.ts +2 -0
  475. package/dist/__tests__/ssao-buffers.test.d.ts.map +1 -0
  476. package/dist/__tests__/ssao-data.test.d.ts +2 -0
  477. package/dist/__tests__/ssao-data.test.d.ts.map +1 -0
  478. package/dist/__tests__/ssao-errors.test.d.ts +2 -0
  479. package/dist/__tests__/ssao-errors.test.d.ts.map +1 -0
  480. package/dist/__tests__/ssao-manifest.test.d.ts +2 -0
  481. package/dist/__tests__/ssao-manifest.test.d.ts.map +1 -0
  482. package/dist/__tests__/ssao-passes.test.d.ts +2 -0
  483. package/dist/__tests__/ssao-passes.test.d.ts.map +1 -0
  484. package/dist/__tests__/ssao-pipelines.test.d.ts +2 -0
  485. package/dist/__tests__/ssao-pipelines.test.d.ts.map +1 -0
  486. package/dist/__tests__/ssao-uniform-layout.test.d.ts +2 -0
  487. package/dist/__tests__/ssao-uniform-layout.test.d.ts.map +1 -0
  488. package/dist/__tests__/static-rig.integration.test.d.ts +2 -0
  489. package/dist/__tests__/static-rig.integration.test.d.ts.map +1 -0
  490. package/dist/__tests__/stencil-outline-pixel.dawn.test.d.ts +2 -0
  491. package/dist/__tests__/stencil-outline-pixel.dawn.test.d.ts.map +1 -0
  492. package/dist/__tests__/swap-chain-format.unit.test.d.ts +2 -0
  493. package/dist/__tests__/swap-chain-format.unit.test.d.ts.map +1 -0
  494. package/dist/__tests__/systems.unit.test.d.ts +2 -0
  495. package/dist/__tests__/systems.unit.test.d.ts.map +1 -0
  496. package/dist/__tests__/temporal-off-path.unit.test.d.ts +2 -0
  497. package/dist/__tests__/temporal-off-path.unit.test.d.ts.map +1 -0
  498. package/dist/__tests__/text.unit.test.d.ts +2 -0
  499. package/dist/__tests__/text.unit.test.d.ts.map +1 -0
  500. package/dist/__tests__/tilemap-childed-despawn.test.d.ts +2 -0
  501. package/dist/__tests__/tilemap-childed-despawn.test.d.ts.map +1 -0
  502. package/dist/__tests__/tilemap-chunk-extract.overhang-bounds.test.d.ts +2 -0
  503. package/dist/__tests__/tilemap-chunk-extract.overhang-bounds.test.d.ts.map +1 -0
  504. package/dist/__tests__/tilemap-chunk-extract.propagate-order.test.d.ts +2 -0
  505. package/dist/__tests__/tilemap-chunk-extract.propagate-order.test.d.ts.map +1 -0
  506. package/dist/__tests__/tilemap-chunk-extract.terrain-rewrite.unit.test.d.ts +2 -0
  507. package/dist/__tests__/tilemap-chunk-extract.terrain-rewrite.unit.test.d.ts.map +1 -0
  508. package/dist/__tests__/tilemap-chunk-extract.test.d.ts +2 -0
  509. package/dist/__tests__/tilemap-chunk-extract.test.d.ts.map +1 -0
  510. package/dist/__tests__/tilemap-chunk-extract.unit.test.d.ts +2 -0
  511. package/dist/__tests__/tilemap-chunk-extract.unit.test.d.ts.map +1 -0
  512. package/dist/__tests__/tilemap-chunk-y-sort-bench.unit.test.d.ts +2 -0
  513. package/dist/__tests__/tilemap-chunk-y-sort-bench.unit.test.d.ts.map +1 -0
  514. package/dist/__tests__/tilemap-dirty-rebuild.test.d.ts +2 -0
  515. package/dist/__tests__/tilemap-dirty-rebuild.test.d.ts.map +1 -0
  516. package/dist/__tests__/tilemap-material-cache.test.d.ts +2 -0
  517. package/dist/__tests__/tilemap-material-cache.test.d.ts.map +1 -0
  518. package/dist/__tests__/tilemap-multi-atlas.test.d.ts +2 -0
  519. package/dist/__tests__/tilemap-multi-atlas.test.d.ts.map +1 -0
  520. package/dist/__tests__/tilemap-owner-boundary.unit.test.d.ts +2 -0
  521. package/dist/__tests__/tilemap-owner-boundary.unit.test.d.ts.map +1 -0
  522. package/dist/__tests__/tilemap-region-pack.test.d.ts +2 -0
  523. package/dist/__tests__/tilemap-region-pack.test.d.ts.map +1 -0
  524. package/dist/__tests__/tilemap-spawn-flip-pivot.test.d.ts +2 -0
  525. package/dist/__tests__/tilemap-spawn-flip-pivot.test.d.ts.map +1 -0
  526. package/dist/__tests__/tilemap-uv-inset.test.d.ts +2 -0
  527. package/dist/__tests__/tilemap-uv-inset.test.d.ts.map +1 -0
  528. package/dist/__tests__/tilemap-validate.test.d.ts +2 -0
  529. package/dist/__tests__/tilemap-validate.test.d.ts.map +1 -0
  530. package/dist/__tests__/transform-hierarchy-pixel-diff.dawn.test.d.ts +2 -0
  531. package/dist/__tests__/transform-hierarchy-pixel-diff.dawn.test.d.ts.map +1 -0
  532. package/dist/__tests__/transient-fields-collect.test.d.ts +2 -0
  533. package/dist/__tests__/transient-fields-collect.test.d.ts.map +1 -0
  534. package/dist/__tests__/transitional-authoring.integration.test.d.ts +2 -0
  535. package/dist/__tests__/transitional-authoring.integration.test.d.ts.map +1 -0
  536. package/dist/__tests__/transparent-sort-tilemap-sprite-interleave.test.d.ts +2 -0
  537. package/dist/__tests__/transparent-sort-tilemap-sprite-interleave.test.d.ts.map +1 -0
  538. package/dist/__tests__/variant-selection.unit.test.d.ts +2 -0
  539. package/dist/__tests__/variant-selection.unit.test.d.ts.map +1 -0
  540. package/dist/__tests__/vertex-attribute-layout.test.d.ts +2 -0
  541. package/dist/__tests__/vertex-attribute-layout.test.d.ts.map +1 -0
  542. package/dist/__tests__/video-cache-regression.unit.test.d.ts +2 -0
  543. package/dist/__tests__/video-cache-regression.unit.test.d.ts.map +1 -0
  544. package/dist/__tests__/video-extract-bindgroup.dawn.test.d.ts +2 -0
  545. package/dist/__tests__/video-extract-bindgroup.dawn.test.d.ts.map +1 -0
  546. package/dist/__tests__/view-ubo-layout.browser.test.d.ts +2 -0
  547. package/dist/__tests__/view-ubo-layout.browser.test.d.ts.map +1 -0
  548. package/dist/__tests__/world-entity-key.test.d.ts +2 -0
  549. package/dist/__tests__/world-entity-key.test.d.ts.map +1 -0
  550. package/dist/__tests__/world-scene-despawn.test.d.ts +2 -0
  551. package/dist/__tests__/world-scene-despawn.test.d.ts.map +1 -0
  552. package/dist/__tests__/world-scene-instantiate.test.d.ts +2 -0
  553. package/dist/__tests__/world-scene-instantiate.test.d.ts.map +1 -0
  554. package/dist/__tests__/world-scene-nested.test.d.ts +2 -0
  555. package/dist/__tests__/world-scene-nested.test.d.ts.map +1 -0
  556. package/dist/__tests__/world-scene-override.test.d.ts +2 -0
  557. package/dist/__tests__/world-scene-override.test.d.ts.map +1 -0
  558. package/dist/__tests__/zero-compression-zero-load.integration.test.d.ts +2 -0
  559. package/dist/__tests__/zero-compression-zero-load.integration.test.d.ts.map +1 -0
  560. package/dist/asset-contributions.d.ts +3 -0
  561. package/dist/asset-contributions.d.ts.map +1 -0
  562. package/dist/asset-kind.d.ts +4 -0
  563. package/dist/asset-kind.d.ts.map +1 -0
  564. package/dist/collect-scene-asset.d.ts +16 -0
  565. package/dist/collect-scene-asset.d.ts.map +1 -0
  566. package/dist/components/__tests__/camera.test-d.d.ts +2 -0
  567. package/dist/components/__tests__/camera.test-d.d.ts.map +1 -0
  568. package/dist/components/__tests__/camera.test.d.ts +2 -0
  569. package/dist/components/__tests__/camera.test.d.ts.map +1 -0
  570. package/dist/components/__tests__/child-of.test.d.ts +2 -0
  571. package/dist/components/__tests__/child-of.test.d.ts.map +1 -0
  572. package/dist/components/__tests__/sprite-animation.test-d.d.ts +2 -0
  573. package/dist/components/__tests__/sprite-animation.test-d.d.ts.map +1 -0
  574. package/dist/components/__tests__/sprite-instances.unit.test.d.ts +2 -0
  575. package/dist/components/__tests__/sprite-instances.unit.test.d.ts.map +1 -0
  576. package/dist/components/__tests__/sprite-region-override.test-d.d.ts +2 -0
  577. package/dist/components/__tests__/sprite-region-override.test-d.d.ts.map +1 -0
  578. package/dist/components/__tests__/tile-layer.test-d.d.ts +2 -0
  579. package/dist/components/__tests__/tile-layer.test-d.d.ts.map +1 -0
  580. package/dist/components/__tests__/tile-layer.unit.test.d.ts +2 -0
  581. package/dist/components/__tests__/tile-layer.unit.test.d.ts.map +1 -0
  582. package/dist/components/__tests__/tilemap.test-d.d.ts +2 -0
  583. package/dist/components/__tests__/tilemap.test-d.d.ts.map +1 -0
  584. package/dist/components/__tests__/transform-vec-schema.test.d.ts +2 -0
  585. package/dist/components/__tests__/transform-vec-schema.test.d.ts.map +1 -0
  586. package/dist/create-renderer-env-classify.d.ts +21 -0
  587. package/dist/create-renderer-env-classify.d.ts.map +1 -0
  588. package/dist/createRenderer.d.ts +3 -0
  589. package/dist/createRenderer.d.ts.map +1 -0
  590. package/dist/dev-import-transport.d.ts +24 -0
  591. package/dist/dev-import-transport.d.ts.map +1 -0
  592. package/dist/errors/environment.d.ts +2 -0
  593. package/dist/errors/environment.d.ts.map +1 -0
  594. package/dist/errors/sprite-animation.d.ts +3 -0
  595. package/dist/errors/sprite-animation.d.ts.map +1 -0
  596. package/dist/index.d.ts +280 -0
  597. package/dist/index.d.ts.map +1 -0
  598. package/dist/index.mjs +814 -0
  599. package/dist/index.mjs.map +1 -0
  600. package/dist/scene-asset-port.d.ts +17 -0
  601. package/dist/scene-asset-port.d.ts.map +1 -0
  602. package/dist/scene-collect-errors.d.ts +22 -0
  603. package/dist/scene-collect-errors.d.ts.map +1 -0
  604. package/dist/scene-instances/__tests__/post-spawn-resolve-joints.unit.test.d.ts +2 -0
  605. package/dist/scene-instances/__tests__/post-spawn-resolve-joints.unit.test.d.ts.map +1 -0
  606. package/dist/scene-utils/mount-override-fold.d.ts +16 -0
  607. package/dist/scene-utils/mount-override-fold.d.ts.map +1 -0
  608. package/dist/shadow-m3-calibrate.d.ts +40 -0
  609. package/dist/shadow-m3-calibrate.d.ts.map +1 -0
  610. package/dist/sprite-param-values.d.ts +62 -0
  611. package/dist/sprite-param-values.d.ts.map +1 -0
  612. package/dist/systems/__tests__/_xorshift.d.ts +28 -0
  613. package/dist/systems/__tests__/_xorshift.d.ts.map +1 -0
  614. package/dist/systems/__tests__/argsort-in-place.test.d.ts +2 -0
  615. package/dist/systems/__tests__/argsort-in-place.test.d.ts.map +1 -0
  616. package/dist/systems/__tests__/transparent-sort.bench.d.ts +2 -0
  617. package/dist/systems/__tests__/transparent-sort.bench.d.ts.map +1 -0
  618. package/dist/systems/sprite-animation-tick.d.ts +50 -0
  619. package/dist/systems/sprite-animation-tick.d.ts.map +1 -0
  620. package/dist/systems/tonemap.d.ts +27 -0
  621. package/dist/systems/tonemap.d.ts.map +1 -0
  622. package/dist/systems/transparent-sort.d.ts +51 -0
  623. package/dist/systems/transparent-sort.d.ts.map +1 -0
  624. package/dist/tilemap-register-validate.d.ts +21 -0
  625. package/dist/tilemap-register-validate.d.ts.map +1 -0
  626. package/package.json +100 -0
  627. package/src/__tests__/active-camera.unit.test.ts +193 -0
  628. package/src/__tests__/animation-graph-add.unit.test.ts +67 -0
  629. package/src/__tests__/animation-graph-asset-union.test-d.ts +83 -0
  630. package/src/__tests__/animation-graph-blend.unit.test.ts +66 -0
  631. package/src/__tests__/animation-graph-build.unit.test.ts +100 -0
  632. package/src/__tests__/animation-graph-clip-missing.unit.test.ts +62 -0
  633. package/src/__tests__/animation-graph-clip.unit.test.ts +77 -0
  634. package/src/__tests__/animation-graph-default-path.integration.test.ts +65 -0
  635. package/src/__tests__/animation-graph-describe.unit.test.ts +68 -0
  636. package/src/__tests__/animation-graph-errors.unit.test.ts +75 -0
  637. package/src/__tests__/animation-graph-nesting.unit.test.ts +84 -0
  638. package/src/__tests__/animation-graph-orthogonal-weight.unit.test.ts +98 -0
  639. package/src/__tests__/animation-graph-slot-fill.unit.test.ts +95 -0
  640. package/src/__tests__/animation-nslot.unit.test.ts +63 -0
  641. package/src/__tests__/animation-slot-length-guard.unit.test.ts +81 -0
  642. package/src/__tests__/append-injection.test.ts +105 -0
  643. package/src/__tests__/asi-world-baseline-export.unit.test.ts +173 -0
  644. package/src/__tests__/asi-world-ci-config.unit.test.ts +186 -0
  645. package/src/__tests__/asi-world-smoke.unit.test.ts +192 -0
  646. package/src/__tests__/asset-registry-scene.test-d.ts +49 -0
  647. package/src/__tests__/bind-group-cache-binding.test.ts +2513 -0
  648. package/src/__tests__/bind-group-cache-frame.test.ts +1511 -0
  649. package/src/__tests__/bind-group-cache-keying.test.ts +295 -0
  650. package/src/__tests__/block-upload-math.unit.test.ts +192 -0
  651. package/src/__tests__/builtin-shader-register-e2e.test.ts +151 -0
  652. package/src/__tests__/cache-false-eviction.test.ts +126 -0
  653. package/src/__tests__/cache-isolation-matrix.test.ts +182 -0
  654. package/src/__tests__/camera-clear-snapshot-equivalence.unit.test.ts +76 -0
  655. package/src/__tests__/clamp-to-last.e2e.browser.test.ts +183 -0
  656. package/src/__tests__/clamp-to-last.e2e.dawn.test.ts +325 -0
  657. package/src/__tests__/collect-scene-asset.test.ts +876 -0
  658. package/src/__tests__/collect-subtree.unit.test.ts +76 -0
  659. package/src/__tests__/collect-transient-children-absent.test.ts +154 -0
  660. package/src/__tests__/collect-transient-roundtrip.test.ts +245 -0
  661. package/src/__tests__/collect-transient-skip.test.ts +165 -0
  662. package/src/__tests__/components.test-d.ts +236 -0
  663. package/src/__tests__/components.unit.test.ts +2665 -0
  664. package/src/__tests__/composite-skybox-cross-world.browser.test.ts +378 -0
  665. package/src/__tests__/create-renderer-assembly.integration.test.ts +42 -0
  666. package/src/__tests__/createRenderer-dispose.test.ts +416 -0
  667. package/src/__tests__/createRenderer-requiredFeatures.unit.test.ts +134 -0
  668. package/src/__tests__/createRenderer.browser-no-webgpu.test.ts +59 -0
  669. package/src/__tests__/createRenderer.unit.test.ts +231 -0
  670. package/src/__tests__/dawn/hello-sprite-nineslice-section.dawn.test.ts +393 -0
  671. package/src/__tests__/dawn/ibl-compose.dawn.test.ts +151 -0
  672. package/src/__tests__/dawn/ibl-modules-compose.dawn.test.ts +223 -0
  673. package/src/__tests__/dawn/ibl-precompute-readback.dawn.test.ts +241 -0
  674. package/src/__tests__/dawn/instances-per-instance-pbr.dawn.test.ts +611 -0
  675. package/src/__tests__/dawn/instances-shadow.dawn.test.ts +443 -0
  676. package/src/__tests__/dawn/instances-uniform-fallback.dawn.test.ts +313 -0
  677. package/src/__tests__/dawn/material-alpha.dawn.test.ts +304 -0
  678. package/src/__tests__/dawn/material-cooked-fixture.dawn.test.ts +64 -0
  679. package/src/__tests__/dawn/mesh-ssbo-normal-matrix.dawn.test.ts +106 -0
  680. package/src/__tests__/dawn/mesh-update.dawn.test.ts +342 -0
  681. package/src/__tests__/dawn/mipmap-srgb-linear.dawn.test.ts +117 -0
  682. package/src/__tests__/dawn/per-entity-material-texture-isolation.dawn.test.ts +567 -0
  683. package/src/__tests__/dawn/sprite-nineslice-mesh-bind.dawn.test.ts +251 -0
  684. package/src/__tests__/dawn/tonemap.dawn.test.ts +107 -0
  685. package/src/__tests__/dawn/user-handle-mesh-render.dawn.test.ts +291 -0
  686. package/src/__tests__/dawn/user-mesh-upload.dawn.test.ts +204 -0
  687. package/src/__tests__/dawn/zero-manifest-mesh-fail.dawn.test.ts +122 -0
  688. package/src/__tests__/dawn/zero-manifest-ready.dawn.test.ts +99 -0
  689. package/src/__tests__/demo-sortscope-migration.unit.test.ts +115 -0
  690. package/src/__tests__/derive-bgl-integration.test.ts +398 -0
  691. package/src/__tests__/derive-render-data-skin.unit.test.ts +90 -0
  692. package/src/__tests__/dispatch-fullscreen-pass-composite-swapchain.dawn.test.ts +204 -0
  693. package/src/__tests__/dispatch-fullscreen-pass-custom-reads.dawn.test.ts +297 -0
  694. package/src/__tests__/dispatch-fullscreen-pass-depth-composite.dawn.test.ts +271 -0
  695. package/src/__tests__/dispatch-fullscreen-pass-params.unit.test.ts +321 -0
  696. package/src/__tests__/draw-published.ts +10 -0
  697. package/src/__tests__/environment-error-exhaustive.test-d.ts +28 -0
  698. package/src/__tests__/equirect-bc6h.integration.test.ts +35 -0
  699. package/src/__tests__/error-exhaustive.test.ts +220 -0
  700. package/src/__tests__/extract-frames-graceful-degradation.test.ts +298 -0
  701. package/src/__tests__/extract-frames-merge.test.ts +643 -0
  702. package/src/__tests__/extract-frames-reset.test.ts +158 -0
  703. package/src/__tests__/extract-record-no-hardcoded-texture-fields.test.ts +92 -0
  704. package/src/__tests__/fog-producer-manifest.ts +162 -0
  705. package/src/__tests__/fog-producer-pixel-probe.ts +263 -0
  706. package/src/__tests__/fog-producer-pixel.browser.test.ts +26 -0
  707. package/src/__tests__/fog-producer-pixel.dawn.test.ts +55 -0
  708. package/src/__tests__/fog-producer-real-fixture.ts +805 -0
  709. package/src/__tests__/fog-producer-vfx-effect.ts +272 -0
  710. package/src/__tests__/fog-scene-asset.integration.test.ts +123 -0
  711. package/src/__tests__/frame-targets-shadow-regression.unit.test.ts +28 -0
  712. package/src/__tests__/fullscreen-post-bgl-depth.test.ts +131 -0
  713. package/src/__tests__/fullscreen-post-depth-params-arity.test.ts +84 -0
  714. package/src/__tests__/fullscreen-post-process-pass.dawn.test.ts +320 -0
  715. package/src/__tests__/fullscreen-post-process-pass.unit.test.ts +107 -0
  716. package/src/__tests__/fxaa-pixel-diff.dawn.test.ts +292 -0
  717. package/src/__tests__/fxaa-validation-and-resize.dawn.test.ts +358 -0
  718. package/src/__tests__/fxaa-zero-overhead.dawn.test.ts +254 -0
  719. package/src/__tests__/geometry.unit.test.ts +2265 -0
  720. package/src/__tests__/glyph-tilemap-worldid.test.ts +146 -0
  721. package/src/__tests__/gpu-resource-cow-survivor.test.ts +388 -0
  722. package/src/__tests__/gpu-resource-store-cubemap-status.test.ts +207 -0
  723. package/src/__tests__/gpu-resource.test.ts +1206 -0
  724. package/src/__tests__/hdrp-bgl-slots.browser.test.ts +50 -0
  725. package/src/__tests__/hdrp-buffers.unit.test.ts +70 -0
  726. package/src/__tests__/hdrp-execute-filter.unit.test.ts +200 -0
  727. package/src/__tests__/hdrp-gbuffer-attachments.browser.test.ts +64 -0
  728. package/src/__tests__/hdrp-pipeline-asset-type.test-d.ts +139 -0
  729. package/src/__tests__/hdrp-ssao-boundary.test.ts +237 -0
  730. package/src/__tests__/hdrp-ssao-falsification.test.ts +289 -0
  731. package/src/__tests__/hello-tilemap-smoke-upgrade.unit.test.ts +147 -0
  732. package/src/__tests__/helpers/mock-shader-registry.ts +139 -0
  733. package/src/__tests__/helpers/primitive-world.ts +91 -0
  734. package/src/__tests__/helpers/register-runtime-components.ts +69 -0
  735. package/src/__tests__/helpers/register-scene-components.ts +10 -0
  736. package/src/__tests__/helpers/render-asset-port.ts +65 -0
  737. package/src/__tests__/helpers/scene-asset-port.ts +23 -0
  738. package/src/__tests__/helpers/tilemap-assets.ts +29 -0
  739. package/src/__tests__/instances.test-d.ts +61 -0
  740. package/src/__tests__/light-attenuation-formula.test.ts +171 -0
  741. package/src/__tests__/light-casters-9-light.browser.test.ts +880 -0
  742. package/src/__tests__/light-gpu-byte-neutral.unit.test.ts +163 -0
  743. package/src/__tests__/light-snapshot.test-d.ts +84 -0
  744. package/src/__tests__/lights-vec-negative.unit.test.ts +52 -0
  745. package/src/__tests__/lights.unit.test.ts +2936 -0
  746. package/src/__tests__/m3-vec-negative.unit.test.ts +45 -0
  747. package/src/__tests__/m5-browser-dawn-sweep.integration.test.ts +8 -0
  748. package/src/__tests__/material-derived-coordinates.integration.test.ts +100 -0
  749. package/src/__tests__/material-texture-uv-scale.unit.test.ts +49 -0
  750. package/src/__tests__/materials.unit.test.ts +271 -0
  751. package/src/__tests__/mesh-ssbo-grow.unit.test.ts +244 -0
  752. package/src/__tests__/mip-gate.unit.test.ts +79 -0
  753. package/src/__tests__/msaa-sprite-pixel-diff.dawn.test.ts +406 -0
  754. package/src/__tests__/multi-uv-8set.e2e.dawn.test.ts +296 -0
  755. package/src/__tests__/name.unit.test.ts +123 -0
  756. package/src/__tests__/node-shims.d.ts +33 -0
  757. package/src/__tests__/pass-selector.unit.test.ts +102 -0
  758. package/src/__tests__/pbr-pipeline.unit.test.ts +204 -0
  759. package/src/__tests__/pipeline-builder-msaa.unit.test.ts +224 -0
  760. package/src/__tests__/pipeline-cache-keying.unit.test.ts +316 -0
  761. package/src/__tests__/pipeline-layout-selection.test.ts +298 -0
  762. package/src/__tests__/pipeline-spec.test.ts +1061 -0
  763. package/src/__tests__/pipeline.unit.test.ts +6974 -0
  764. package/src/__tests__/point-light-shadow.browser.test.ts +278 -0
  765. package/src/__tests__/point-light-shadow.dawn.test.ts +822 -0
  766. package/src/__tests__/point-light-shadow.unit.test.ts +716 -0
  767. package/src/__tests__/post-process-error-codes.unit.test.ts +158 -0
  768. package/src/__tests__/post-process-params-component.unit.test.ts +153 -0
  769. package/src/__tests__/post-process-params-extract.unit.test.ts +100 -0
  770. package/src/__tests__/post-process-reads-narrowing.test-d.ts +52 -0
  771. package/src/__tests__/post-process-register-roundtrip.dawn.test.ts +230 -0
  772. package/src/__tests__/postprocess-camera-consistency.test.ts +378 -0
  773. package/src/__tests__/profiler-assembly.integration.test.ts +74 -0
  774. package/src/__tests__/propagate-transforms.dawn.test.ts +253 -0
  775. package/src/__tests__/record-worldid-isolation.test.ts +247 -0
  776. package/src/__tests__/recover-error-exhaustive.test-d.ts +35 -0
  777. package/src/__tests__/render-error-exhaustive.test-d.ts +245 -0
  778. package/src/__tests__/render-feature-assembly.test-d.ts +28 -0
  779. package/src/__tests__/render-feature-prepared-graphics-docs.unit.test.ts +124 -0
  780. package/src/__tests__/render-feature-prepared-graphics.browser.test.ts +582 -0
  781. package/src/__tests__/render-feature-prepared-graphics.dawn.test.ts +602 -0
  782. package/src/__tests__/render-feature-prepared-graphics.integration.test.ts +264 -0
  783. package/src/__tests__/render-feature-prepared-graphics.regression.integration.test.ts +361 -0
  784. package/src/__tests__/render-feature-recover.integration.test.ts +142 -0
  785. package/src/__tests__/render-feature-runtime-surface.test-d.ts +45 -0
  786. package/src/__tests__/render-feature-zero-feature.browser.test.ts +152 -0
  787. package/src/__tests__/render-pipeline-trivial.dawn.test.ts +525 -0
  788. package/src/__tests__/render-schema-consumer.integration.test.ts +25 -0
  789. package/src/__tests__/render-schema-owner-boundary.unit.test.ts +26 -0
  790. package/src/__tests__/render-system-cross-world-overlay-queue.test.ts +172 -0
  791. package/src/__tests__/render-system-extract-dispatch-ordering.test.ts +322 -0
  792. package/src/__tests__/render-system-extract.test.ts +1399 -0
  793. package/src/__tests__/render-system-fold-bucket.unit.test.ts +288 -0
  794. package/src/__tests__/render-system-fold-fallback.unit.test.ts +148 -0
  795. package/src/__tests__/render-system-fold-material.unit.test.ts +145 -0
  796. package/src/__tests__/render-system-fold-metrics.unit.test.ts +170 -0
  797. package/src/__tests__/render-system-fold-modegate.unit.test.ts +166 -0
  798. package/src/__tests__/render-system-fold-scene-instances.unit.test.ts +51 -0
  799. package/src/__tests__/render-system-fold.dawn.test.ts +306 -0
  800. package/src/__tests__/render-system-mega.test.ts +1578 -0
  801. package/src/__tests__/render-system-owner-split-contract.test.ts +200 -0
  802. package/src/__tests__/render-system-record-multi-material-textureview.test.ts +684 -0
  803. package/src/__tests__/render-system-record-per-submesh-transparency.test.ts +464 -0
  804. package/src/__tests__/render-system-record.test.ts +1505 -0
  805. package/src/__tests__/render-system-record.unit.test.ts +270 -0
  806. package/src/__tests__/render-system-skin-bg.unit.test.ts +147 -0
  807. package/src/__tests__/renderer-consumer.test-d.ts +5 -0
  808. package/src/__tests__/renderer-health.unit.test.ts +935 -0
  809. package/src/__tests__/renderer-lifecycle.integration.test.ts +29 -0
  810. package/src/__tests__/renderer-recover.unit.test.ts +1075 -0
  811. package/src/__tests__/renderer-result.test-d.ts +26 -0
  812. package/src/__tests__/renderer-surface.unit.test.ts +416 -0
  813. package/src/__tests__/resolve-depth-only-view.test.ts +173 -0
  814. package/src/__tests__/rhi-null-command-flow.unit.test.ts +273 -0
  815. package/src/__tests__/rhi-null-noop-behavior.unit.test.ts +196 -0
  816. package/src/__tests__/rhi-null-renderer-lifecycle.unit.test.ts +182 -0
  817. package/src/__tests__/roots-to-scene-asset.test.ts +605 -0
  818. package/src/__tests__/runtime-authority-scan.unit.test.ts +19 -0
  819. package/src/__tests__/runtime-domain-residue.unit.test.ts +13 -0
  820. package/src/__tests__/scene-equirect-roundtrip.test.ts +33 -0
  821. package/src/__tests__/scene-instance-bridge.integration.test.ts +8 -0
  822. package/src/__tests__/scene-instance-component.test.ts +45 -0
  823. package/src/__tests__/scene-instantiate-cycle-runtime.test.ts +66 -0
  824. package/src/__tests__/serialize-scene-asset.test.ts +336 -0
  825. package/src/__tests__/shadow-caster-empty-schema.test.ts +83 -0
  826. package/src/__tests__/shadow-csm-atlas.test.ts +178 -0
  827. package/src/__tests__/shadow-csm-blend.dawn.test.ts +230 -0
  828. package/src/__tests__/shadow-csm-cascade-loadop.test.ts +334 -0
  829. package/src/__tests__/shadow-csm-caster-membership.test.ts +232 -0
  830. package/src/__tests__/shadow-csm-component.test.ts +286 -0
  831. package/src/__tests__/shadow-csm-extract.test.ts +334 -0
  832. package/src/__tests__/shadow-csm-orthoz.test.ts +151 -0
  833. package/src/__tests__/shadow-csm-pssm.test.ts +142 -0
  834. package/src/__tests__/shadow-csm-runtime-vary.dawn.test.ts +198 -0
  835. package/src/__tests__/shadow-csm-shader.dawn.test.ts +358 -0
  836. package/src/__tests__/shadow-csm-temporal.browser.test.ts +145 -0
  837. package/src/__tests__/shadow-csm-tile-consistency.test.ts +419 -0
  838. package/src/__tests__/shadow-csm-ubo.dawn.test.ts +293 -0
  839. package/src/__tests__/shadow-csm-ubo.test.ts +300 -0
  840. package/src/__tests__/shadow-csm-viewport.browser.test.ts +85 -0
  841. package/src/__tests__/shadow-csm-viewport.test.ts +74 -0
  842. package/src/__tests__/shadow-fields-observable.dawn.test.ts +615 -0
  843. package/src/__tests__/shadow-m1.dawn.test.ts +105 -0
  844. package/src/__tests__/shadow-m2.dawn.test.ts +394 -0
  845. package/src/__tests__/shadow-m3-calibrate-run.dawn.test.ts +248 -0
  846. package/src/__tests__/shadow-m3-calibrate.ts +203 -0
  847. package/src/__tests__/shadow-m3.dawn.test.ts +288 -0
  848. package/src/__tests__/shadow-mesh-ssbo-order.test.ts +64 -0
  849. package/src/__tests__/shadow-probe-control-flow.dawn.test.ts +264 -0
  850. package/src/__tests__/shadow-quality-metrics.dawn.test.ts +324 -0
  851. package/src/__tests__/skin-error-exhaustive.test-d.ts +74 -0
  852. package/src/__tests__/skin-errors.unit.test.ts +10 -0
  853. package/src/__tests__/skin-extract-getarrayview-count.unit.test.ts +23 -0
  854. package/src/__tests__/skin-parented-double-transform.test.ts +268 -0
  855. package/src/__tests__/skylight-lazy-projection.test.ts +359 -0
  856. package/src/__tests__/sparse-tag-scene-roundtrip.test.ts +43 -0
  857. package/src/__tests__/sprite-cullmode-flip.dawn.test.ts +470 -0
  858. package/src/__tests__/sprite-lit-bgl-byte-identical.test.ts +141 -0
  859. package/src/__tests__/sprite-lit-extract-branch.test.ts +117 -0
  860. package/src/__tests__/sprite-lit-pipeline-cache-key.test.ts +123 -0
  861. package/src/__tests__/sprite-param-values.test-d.ts +104 -0
  862. package/src/__tests__/ssao-bgl.test.ts +347 -0
  863. package/src/__tests__/ssao-buffers.test.ts +211 -0
  864. package/src/__tests__/ssao-data.test.ts +121 -0
  865. package/src/__tests__/ssao-errors.test.ts +162 -0
  866. package/src/__tests__/ssao-manifest.test.ts +109 -0
  867. package/src/__tests__/ssao-passes.test.ts +1229 -0
  868. package/src/__tests__/ssao-pipelines.test.ts +275 -0
  869. package/src/__tests__/ssao-uniform-layout.test.ts +178 -0
  870. package/src/__tests__/static-rig.integration.test.ts +9 -0
  871. package/src/__tests__/stencil-outline-pixel.dawn.test.ts +295 -0
  872. package/src/__tests__/swap-chain-format.unit.test.ts +117 -0
  873. package/src/__tests__/systems.unit.test.ts +9957 -0
  874. package/src/__tests__/temporal-off-path.unit.test.ts +69 -0
  875. package/src/__tests__/text.unit.test.ts +466 -0
  876. package/src/__tests__/tilemap-childed-despawn.test.ts +468 -0
  877. package/src/__tests__/tilemap-chunk-extract.overhang-bounds.test.ts +314 -0
  878. package/src/__tests__/tilemap-chunk-extract.propagate-order.test.ts +80 -0
  879. package/src/__tests__/tilemap-chunk-extract.terrain-rewrite.unit.test.ts +424 -0
  880. package/src/__tests__/tilemap-chunk-extract.test.ts +236 -0
  881. package/src/__tests__/tilemap-chunk-extract.unit.test.ts +383 -0
  882. package/src/__tests__/tilemap-chunk-y-sort-bench.unit.test.ts +109 -0
  883. package/src/__tests__/tilemap-dirty-rebuild.test.ts +300 -0
  884. package/src/__tests__/tilemap-material-cache.test.ts +137 -0
  885. package/src/__tests__/tilemap-multi-atlas.test.ts +237 -0
  886. package/src/__tests__/tilemap-owner-boundary.unit.test.ts +63 -0
  887. package/src/__tests__/tilemap-region-pack.test.ts +153 -0
  888. package/src/__tests__/tilemap-spawn-flip-pivot.test.ts +274 -0
  889. package/src/__tests__/tilemap-uv-inset.test.ts +204 -0
  890. package/src/__tests__/tilemap-validate.test.ts +201 -0
  891. package/src/__tests__/transform-hierarchy-pixel-diff.dawn.test.ts +274 -0
  892. package/src/__tests__/transient-fields-collect.test.ts +203 -0
  893. package/src/__tests__/transitional-authoring.integration.test.ts +7 -0
  894. package/src/__tests__/transparent-sort-tilemap-sprite-interleave.test.ts +227 -0
  895. package/src/__tests__/variant-selection.unit.test.ts +21 -0
  896. package/src/__tests__/vertex-attribute-layout.test.ts +324 -0
  897. package/src/__tests__/video-cache-regression.unit.test.ts +186 -0
  898. package/src/__tests__/video-extract-bindgroup.dawn.test.ts +450 -0
  899. package/src/__tests__/view-ubo-layout.browser.test.ts +183 -0
  900. package/src/__tests__/world-entity-key.test.ts +92 -0
  901. package/src/__tests__/world-scene-despawn.test.ts +132 -0
  902. package/src/__tests__/world-scene-instantiate.test.ts +228 -0
  903. package/src/__tests__/world-scene-nested.test.ts +230 -0
  904. package/src/__tests__/world-scene-override.test.ts +199 -0
  905. package/src/__tests__/zero-compression-zero-load.integration.test.ts +107 -0
  906. package/src/asset-contributions.ts +48 -0
  907. package/src/asset-kind.ts +7 -0
  908. package/src/collect-scene-asset.ts +689 -0
  909. package/src/components/__tests__/camera.test-d.ts +57 -0
  910. package/src/components/__tests__/camera.test.ts +95 -0
  911. package/src/components/__tests__/child-of.test.ts +35 -0
  912. package/src/components/__tests__/sprite-animation.test-d.ts +160 -0
  913. package/src/components/__tests__/sprite-instances.unit.test.ts +108 -0
  914. package/src/components/__tests__/sprite-region-override.test-d.ts +101 -0
  915. package/src/components/__tests__/tile-layer.test-d.ts +33 -0
  916. package/src/components/__tests__/tile-layer.unit.test.ts +125 -0
  917. package/src/components/__tests__/tilemap.test-d.ts +35 -0
  918. package/src/components/__tests__/transform-vec-schema.test.ts +121 -0
  919. package/src/create-renderer-env-classify.ts +110 -0
  920. package/src/createRenderer.ts +61 -0
  921. package/src/dev-import-transport.ts +97 -0
  922. package/src/errors/environment.ts +6 -0
  923. package/src/errors/sprite-animation.ts +5 -0
  924. package/src/index.ts +442 -0
  925. package/src/scene-asset-port.ts +32 -0
  926. package/src/scene-collect-errors.ts +30 -0
  927. package/src/scene-instances/__tests__/post-spawn-resolve-joints.unit.test.ts +183 -0
  928. package/src/scene-utils/mount-override-fold.ts +217 -0
  929. package/src/shadow-m3-calibrate.ts +171 -0
  930. package/src/sprite-param-values.ts +61 -0
  931. package/src/systems/__tests__/_xorshift.ts +83 -0
  932. package/src/systems/__tests__/argsort-in-place.test.ts +155 -0
  933. package/src/systems/__tests__/transparent-sort.bench.ts +218 -0
  934. package/src/systems/sprite-animation-tick.ts +302 -0
  935. package/src/systems/tonemap.ts +68 -0
  936. package/src/systems/transparent-sort.ts +434 -0
  937. package/src/tilemap-register-validate.ts +100 -0
@@ -0,0 +1,1399 @@
1
+ // Consolidated by feat-20260608-ci-time-cut M5 w13/w14: merges
2
+ // - render-system-extract.test.ts
3
+ // - render-system-extract-material-inheritance.test.ts
4
+ // - render-system-extract-sprite-slices.test.ts
5
+ // - render-system-clear-camera.test.ts
6
+ // Each original file body sits in its own block-scope so helper names
7
+ // cannot collide; describe() inside still registers globally with vitest.
8
+
9
+ import { World } from '@forgeax/engine-ecs';
10
+ import { createPrimitiveMesh } from '@forgeax/engine-geometry';
11
+ import { mat4, vec3 } from '@forgeax/engine-math';
12
+ import { AssetGuid } from '@forgeax/engine-pack/guid';
13
+ import type { RenderAssetPort } from '@forgeax/engine-render/internal';
14
+ import {
15
+ Camera,
16
+ DirectionalLight,
17
+ extractFrame,
18
+ extractFrames,
19
+ MeshFilter,
20
+ MeshRenderer,
21
+ PointLight,
22
+ prepareExtractContext,
23
+ SpotLight,
24
+ } from '@forgeax/engine-render/internal';
25
+ import { ChildOf, propagateTransforms, Transform } from '@forgeax/engine-scene';
26
+ import { ShaderRegistry, type ShaderRegistryDevice } from '@forgeax/engine-shader';
27
+ import type {
28
+ Handle,
29
+ MaterialAsset,
30
+ MaterialPass,
31
+ MeshAsset,
32
+ TextureAsset,
33
+ } from '@forgeax/engine-types';
34
+ import { srgbChannelToLinear } from '@forgeax/engine-types';
35
+ import { describe, expect, it, vi } from 'vitest';
36
+ import { makeMockShaderRegistry } from './helpers/mock-shader-registry';
37
+ import {
38
+ createTestRenderAssetOwner,
39
+ createTestRenderAssetStore,
40
+ type TestRenderAssetResolver,
41
+ } from './helpers/render-asset-port';
42
+
43
+ // ─── from render-system-extract.test.ts ───
44
+ {
45
+ // w9 -- render-system-extract consumer migration unit tests (M3, AC-07 / AC-15).
46
+ //
47
+ // Post-migration extract reads the single resolved `Transform.world` mat4
48
+ // (written by propagateTransforms) for every world-space consumer; the legacy
49
+ // GlobalTransform-column-switch + per-snapshot `mat4.compose` are gone.
50
+ //
51
+ // Five consumer classes covered:
52
+ // 1. mesh-walk -> RenderableSnapshot.transform.world is the 16-float
53
+ // column-major world mat4 (parent x child), copied straight from the
54
+ // Transform.world view; no per-snapshot compose.
55
+ // 2. frustum cull -> the cull AABB follows the world mat4 (a child placed
56
+ // off-screen by its parent is culled; in-screen is kept) -- same-source
57
+ // with the rendered world (AC-05 carried forward).
58
+ // 3. camera view -> CameraSnapshot.position is the world-space translation
59
+ // (mat4.getTranslation of Transform.world); a child camera reflects
60
+ // parent x child.
61
+ // 4. light position -> point / spot light position is the world-space
62
+ // translation extracted from Transform.world (mat4.getTranslation).
63
+ // 5. AC-15 zero-materialization -> the mesh-walk reads world through the
64
+ // column-level array view; it does NOT call `world.get` per renderable
65
+ // to materialize a `{}` whole-component object.
66
+ //
67
+ // extractFrame + propagateTransforms are pure CPU functions; no GPU is touched.
68
+
69
+ function identity() {
70
+ return {
71
+ pos: [0, 0, 0],
72
+ quat: [0, 0, 0, 1],
73
+ scale: [1, 1, 1],
74
+ };
75
+ }
76
+
77
+ const cameraData = {
78
+ fov: 1.0,
79
+ aspect: 1.0,
80
+ near: 0.1,
81
+ far: 100.0,
82
+ projection: 0,
83
+ left: -1,
84
+ right: 1,
85
+ bottom: -1,
86
+ top: 1,
87
+ };
88
+
89
+ function perspectiveCameraData() {
90
+ return {
91
+ fov: Math.PI / 4,
92
+ aspect: 1,
93
+ near: 0.1,
94
+ far: 100,
95
+ projection: 0,
96
+ left: -1,
97
+ right: 1,
98
+ bottom: -1,
99
+ top: 1,
100
+ };
101
+ }
102
+
103
+ function spawnCamera(world: World): void {
104
+ world
105
+ .spawn({ component: Transform, data: identity() }, { component: Camera, data: cameraData })
106
+ .unwrap();
107
+ }
108
+
109
+ function registerMesh(world: World): Handle<'MeshAsset', 'shared'> {
110
+ return registerMeshWithAabb(world, new Float32Array([-1, -1, -1, 1, 1, 1]));
111
+ }
112
+
113
+ function registerMeshWithAabb(
114
+ world: World,
115
+ aabb: Float32Array | undefined,
116
+ ): Handle<'MeshAsset', 'shared'> {
117
+ const positions = new Float32Array([0, 0, 0, 1, 0, 0, 0, 1, 0]);
118
+ const mesh: MeshAsset = {
119
+ kind: 'mesh',
120
+ vertices: new Float32Array([
121
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0,
122
+ 1, 0, 0, 0, 0,
123
+ ]),
124
+ indices: new Uint16Array([0, 1, 2]),
125
+ attributes: { position: positions },
126
+ submeshes: [
127
+ {
128
+ indexOffset: 0,
129
+ indexCount: 3,
130
+ vertexCount: 36,
131
+ topology: 'triangle-list',
132
+ materialSlot: 0,
133
+ },
134
+ ],
135
+ ...(aabb !== undefined ? { aabb } : {}),
136
+
137
+ materialSlots: [{ slotName: 'Default' }],
138
+ };
139
+ return world.allocSharedRef<'MeshAsset', MeshAsset>('MeshAsset', mesh);
140
+ }
141
+
142
+ function registerMaterial(world: World): Handle<'MaterialAsset', 'shared'> {
143
+ return world.allocSharedRef<'MaterialAsset', MaterialAsset>('MaterialAsset', {
144
+ kind: 'material',
145
+ passes: [
146
+ {
147
+ name: 'Forward',
148
+ program: { module: 'forgeax::default-unlit' },
149
+ renderState: { tags: { LightMode: 'Forward' }, queue: 2000 },
150
+ },
151
+ ],
152
+ values: { baseColor: [1, 1, 1] },
153
+ });
154
+ }
155
+
156
+ function registerBuiltinCube(world: World): Handle<'MeshAsset', 'shared'> {
157
+ return world.internSharedRef('MeshAsset', createPrimitiveMesh('cube').unwrap());
158
+ }
159
+
160
+ describe('render-system-extract consumer migration (w9, AC-07 / AC-15)', () => {
161
+ it('reuses one frame-local material snapshot for repeated shared handles', () => {
162
+ const world = new World();
163
+ spawnCamera(world);
164
+ const assets = createTestRenderAssetOwner(makeMockShaderRegistry());
165
+ const mesh = registerMesh(world);
166
+ const material = registerMaterial(world);
167
+
168
+ for (let index = 0; index < 64; index++) {
169
+ world
170
+ .spawn(
171
+ {
172
+ component: Transform,
173
+ data: { ...identity(), pos: [0, 0, -index - 2] },
174
+ },
175
+ { component: MeshFilter, data: { assetHandle: mesh } },
176
+ { component: MeshRenderer, data: { materials: [material] } },
177
+ )
178
+ .unwrap();
179
+ }
180
+
181
+ const frame = extractFrame(world, prepareExtractContext(world, { assets }));
182
+ expect(frame.renderables).toHaveLength(64);
183
+ const first = frame.renderables[0]?.material;
184
+ expect(first).toBeDefined();
185
+ expect(new Set(frame.renderables.map((renderable) => renderable.material)).size).toBe(1);
186
+ for (const renderable of frame.renderables) expect(renderable.material).toBe(first);
187
+ });
188
+
189
+ it('mesh-walk: RenderableSnapshot.transform.world is the resolved world mat4 (parent x child), zero per-snapshot compose', () => {
190
+ const world = new World();
191
+ const cubeHandle = registerBuiltinCube(world);
192
+ world
193
+ .spawn(
194
+ { component: Transform, data: { ...identity(), pos: [12, 3, 5] } },
195
+ { component: Camera, data: cameraData },
196
+ )
197
+ .unwrap();
198
+ const parent = world
199
+ .spawn({ component: Transform, data: { ...identity(), pos: [10, 0, 0] } })
200
+ .unwrap();
201
+ world
202
+ .spawn(
203
+ { component: Transform, data: { ...identity(), pos: [2, 3, 0] } },
204
+ { component: ChildOf, data: { parent } },
205
+ { component: MeshFilter, data: { assetHandle: cubeHandle } },
206
+ { component: MeshRenderer, data: {} },
207
+ )
208
+ .unwrap();
209
+
210
+ expect(propagateTransforms(world).ok).toBe(true);
211
+ const frame = extractFrame(world, prepareExtractContext(world));
212
+ expect(frame.renderables.length).toBe(1);
213
+
214
+ const w = frame.renderables[0]?.transform.world;
215
+ expect(w).toBeInstanceOf(Float32Array);
216
+ expect(w?.length).toBe(16);
217
+ // world translation column (col3 = m[12,13,14]) = parent (10,0,0) + child local (2,3,0).
218
+ expect(w?.[12]).toBeCloseTo(12, 5);
219
+ expect(w?.[13]).toBeCloseTo(3, 5);
220
+ expect(w?.[14]).toBeCloseTo(0, 5);
221
+ // The snapshot world must equal the entity's Transform.world column byte-for-byte.
222
+ });
223
+
224
+ it('mesh-walk: flat root world mat4 equals compose(local)', () => {
225
+ const world = new World();
226
+ const cubeHandle = registerBuiltinCube(world);
227
+ world
228
+ .spawn(
229
+ { component: Transform, data: { ...identity(), pos: [5, 6, 12] } },
230
+ { component: Camera, data: cameraData },
231
+ )
232
+ .unwrap();
233
+ world
234
+ .spawn(
235
+ { component: Transform, data: { ...identity(), pos: [5, 6, 7], scale: [2, 1, 1] } },
236
+ { component: MeshFilter, data: { assetHandle: cubeHandle } },
237
+ { component: MeshRenderer, data: {} },
238
+ )
239
+ .unwrap();
240
+
241
+ expect(propagateTransforms(world).ok).toBe(true);
242
+ const frame = extractFrame(world, prepareExtractContext(world));
243
+ expect(frame.renderables.length).toBe(1);
244
+ const w = frame.renderables[0]?.transform.world as Float32Array;
245
+ const expected = mat4.create();
246
+ mat4.compose(expected, vec3.create(5, 6, 7), [0, 0, 0, 1], vec3.create(2, 1, 1));
247
+ for (let i = 0; i < 16; i++) {
248
+ expect(w[i]).toBeCloseTo((expected as unknown as number[])[i] as number, 5);
249
+ }
250
+ });
251
+
252
+ it('camera view: child camera position reflects world translation (parent x child)', () => {
253
+ const world = new World();
254
+ const rig = world
255
+ .spawn({ component: Transform, data: { ...identity(), pos: [0, 5, 0] } })
256
+ .unwrap();
257
+ world
258
+ .spawn(
259
+ { component: Transform, data: { ...identity(), pos: [1, 0, 2] } },
260
+ { component: ChildOf, data: { parent: rig } },
261
+ { component: Camera, data: cameraData },
262
+ )
263
+ .unwrap();
264
+
265
+ expect(propagateTransforms(world).ok).toBe(true);
266
+ const frame = extractFrame(world, prepareExtractContext(world));
267
+ expect(frame.cameras.length).toBe(1);
268
+ const pos = frame.cameras[0]?.position;
269
+ // rig (0,5,0) x camera local (1,0,2) -> world (1,5,2).
270
+ expect(pos?.[0]).toBeCloseTo(1, 5);
271
+ expect(pos?.[1]).toBeCloseTo(5, 5);
272
+ expect(pos?.[2]).toBeCloseTo(2, 5);
273
+ });
274
+
275
+ it('light position: child point + spot light position reflects world translation', () => {
276
+ const world = new World();
277
+ const rig = world
278
+ .spawn({ component: Transform, data: { ...identity(), pos: [0, 0, 7] } })
279
+ .unwrap();
280
+ world
281
+ .spawn(
282
+ { component: Transform, data: { ...identity(), pos: [3, 0, 0] } },
283
+ { component: ChildOf, data: { parent: rig } },
284
+ { component: PointLight, data: { intensity: 1 } },
285
+ )
286
+ .unwrap();
287
+ const spotRig = world
288
+ .spawn({ component: Transform, data: { ...identity(), pos: [0, 4, 0] } })
289
+ .unwrap();
290
+ world
291
+ .spawn(
292
+ { component: Transform, data: identity() },
293
+ { component: ChildOf, data: { parent: spotRig } },
294
+ {
295
+ component: SpotLight,
296
+ data: { direction: [0, -1, 0], intensity: 1 },
297
+ },
298
+ )
299
+ .unwrap();
300
+
301
+ expect(propagateTransforms(world).ok).toBe(true);
302
+ const frame = extractFrame(world, prepareExtractContext(world));
303
+ expect(frame.lights.point.length).toBe(1);
304
+ expect(frame.lights.point[0]?.position?.[0]).toBeCloseTo(3, 5);
305
+ expect(frame.lights.point[0]?.position?.[2]).toBeCloseTo(7, 5);
306
+ expect(frame.lights.spot.length).toBe(1);
307
+ expect(frame.lights.spot[0]?.position?.[1]).toBeCloseTo(4, 5);
308
+ // D-6 carried forward: spot direction stays from the SpotLight component.
309
+ expect(frame.lights.spot[0]?.direction?.[1]).toBeCloseTo(-1, 5);
310
+ });
311
+
312
+ it('directional light snapshot is unchanged regardless of hierarchy (no Transform dependency)', () => {
313
+ const world = new World();
314
+ world
315
+ .spawn({
316
+ component: DirectionalLight,
317
+ data: {
318
+ direction: [0, -1, 0],
319
+ color: [1, 1, 1],
320
+ intensity: 1,
321
+ },
322
+ })
323
+ .unwrap();
324
+ expect(propagateTransforms(world).ok).toBe(true);
325
+ const frame = extractFrame(world, prepareExtractContext(world));
326
+ expect(frame.lights.directional).toBeDefined();
327
+ expect(frame.lights.directional?.direction?.[1]).toBeCloseTo(-1, 5);
328
+ });
329
+
330
+ it('AC-05: cull AABB follows the world mat4 (parent off-screen -> child culled; in-screen -> kept)', () => {
331
+ {
332
+ const world = new World();
333
+ const mesh = registerMesh(world);
334
+ const mat = registerMaterial(world);
335
+ world
336
+ .spawn(
337
+ { component: Transform, data: { ...identity(), pos: [0, 0, 5] } },
338
+ { component: Camera, data: perspectiveCameraData() },
339
+ )
340
+ .unwrap();
341
+ const parent = world
342
+ .spawn({ component: Transform, data: { ...identity(), pos: [0, 0, 100] } })
343
+ .unwrap();
344
+ world
345
+ .spawn(
346
+ { component: Transform, data: identity() },
347
+ { component: ChildOf, data: { parent } },
348
+ { component: MeshFilter, data: { assetHandle: mesh } },
349
+ { component: MeshRenderer, data: { materials: [mat] } },
350
+ )
351
+ .unwrap();
352
+ expect(propagateTransforms(world).ok).toBe(true);
353
+ const frame = extractFrame(world, prepareExtractContext(world));
354
+ expect(frame.renderables).toHaveLength(0);
355
+ }
356
+ {
357
+ const world = new World();
358
+ const mesh = registerMesh(world);
359
+ const mat = registerMaterial(world);
360
+ world
361
+ .spawn(
362
+ { component: Transform, data: { ...identity(), pos: [0, 0, 5] } },
363
+ { component: Camera, data: perspectiveCameraData() },
364
+ )
365
+ .unwrap();
366
+ const parent = world.spawn({ component: Transform, data: identity() }).unwrap();
367
+ world
368
+ .spawn(
369
+ { component: Transform, data: identity() },
370
+ { component: ChildOf, data: { parent } },
371
+ { component: MeshFilter, data: { assetHandle: mesh } },
372
+ { component: MeshRenderer, data: { materials: [mat] } },
373
+ )
374
+ .unwrap();
375
+ expect(propagateTransforms(world).ok).toBe(true);
376
+ const frame = extractFrame(world, prepareExtractContext(world));
377
+ expect(frame.renderables).toHaveLength(1);
378
+ }
379
+ });
380
+
381
+ it('AC-02: builtin MeshAsset AABB enters the same frustum path as imported meshes', () => {
382
+ const world = new World();
383
+ const cubeHandle = registerBuiltinCube(world);
384
+ spawnCamera(world);
385
+ world
386
+ .spawn(
387
+ { component: Transform, data: { ...identity(), pos: [0, 0, 200] } },
388
+ { component: MeshFilter, data: { assetHandle: cubeHandle } },
389
+ { component: MeshRenderer, data: {} },
390
+ )
391
+ .unwrap();
392
+
393
+ expect(propagateTransforms(world).ok).toBe(true);
394
+ const frame = extractFrame(world, prepareExtractContext(world));
395
+
396
+ expect(frame.renderables).toHaveLength(0);
397
+ expect(frame.frustumStats).toEqual({ culled: 1, total: 1 });
398
+ });
399
+
400
+ it('cross-world extract keeps frustum culling against the surfaced camera-owner camera', () => {
401
+ const cameraWorld = new World();
402
+ cameraWorld
403
+ .spawn(
404
+ { component: Transform, data: identity() },
405
+ { component: Camera, data: perspectiveCameraData() },
406
+ )
407
+ .unwrap();
408
+
409
+ const sceneWorld = new World();
410
+ const cubeHandle = registerBuiltinCube(sceneWorld);
411
+ sceneWorld
412
+ .spawn(
413
+ { component: Transform, data: { ...identity(), pos: [0, 0, 0] } },
414
+ { component: MeshFilter, data: { assetHandle: cubeHandle } },
415
+ { component: MeshRenderer, data: {} },
416
+ )
417
+ .unwrap();
418
+ sceneWorld
419
+ .spawn(
420
+ { component: Transform, data: { ...identity(), pos: [0, 0, 200] } },
421
+ { component: MeshFilter, data: { assetHandle: cubeHandle } },
422
+ { component: MeshRenderer, data: {} },
423
+ )
424
+ .unwrap();
425
+
426
+ propagateTransforms(cameraWorld).unwrap();
427
+ propagateTransforms(sceneWorld).unwrap();
428
+
429
+ const frame = extractFrames([cameraWorld, sceneWorld], { cameraOwner: 0, resourceOwner: 1 });
430
+
431
+ expect(frame.renderables).toHaveLength(1);
432
+ expect(frame.frustumStats).toEqual({ culled: 1, total: 2 });
433
+ });
434
+
435
+ it('AC-02: malformed MeshAsset AABBs stay conservative and out of cull statistics', () => {
436
+ const malformedAabbs: Array<Float32Array | undefined> = [
437
+ undefined,
438
+ new Float32Array([
439
+ Number.POSITIVE_INFINITY,
440
+ Number.POSITIVE_INFINITY,
441
+ Number.POSITIVE_INFINITY,
442
+ Number.NEGATIVE_INFINITY,
443
+ Number.NEGATIVE_INFINITY,
444
+ Number.NEGATIVE_INFINITY,
445
+ ]),
446
+ new Float32Array([1, 0, 0, 0, 1, 1]),
447
+ new Float32Array([0, 1, 0, 1, 0, 1]),
448
+ new Float32Array([0, 0, 1, 1, 1, 0]),
449
+ new Float32Array([Number.NaN, 0, 0, 1, 1, 1]),
450
+ new Float32Array([0, 0, 0, Number.POSITIVE_INFINITY, 1, 1]),
451
+ new Float32Array([0, 0, 0, 1]),
452
+ ];
453
+
454
+ for (const [index, aabb] of malformedAabbs.entries()) {
455
+ const world = new World();
456
+ spawnCamera(world);
457
+ const mesh = registerMeshWithAabb(world, aabb);
458
+ const material = registerMaterial(world);
459
+ world
460
+ .spawn(
461
+ { component: Transform, data: { ...identity(), pos: [0, 0, 200] } },
462
+ { component: MeshFilter, data: { assetHandle: mesh } },
463
+ { component: MeshRenderer, data: { materials: [material] } },
464
+ )
465
+ .unwrap();
466
+
467
+ expect(propagateTransforms(world).ok).toBe(true);
468
+ const frame = extractFrame(world, prepareExtractContext(world));
469
+
470
+ // Invalid/missing bounds must never cause a false negative visibility
471
+ // result. They are a producer-contract failure, not a valid cull
472
+ // candidate, so they stay out of frustumStats.
473
+ expect(frame.renderables, `malformed AABB case ${index}`).toHaveLength(1);
474
+ expect(frame.frustumStats, `malformed AABB case ${index}`).toEqual({ culled: 0, total: 0 });
475
+ }
476
+ });
477
+
478
+ it('AC-15: mesh-walk reads world via the column array view, not a per-renderable world.get materialization', () => {
479
+ const world = new World();
480
+ const cubeHandle = registerBuiltinCube(world);
481
+ spawnCamera(world);
482
+ world
483
+ .spawn(
484
+ { component: Transform, data: { ...identity(), pos: [1, 2, 3] } },
485
+ { component: MeshFilter, data: { assetHandle: cubeHandle } },
486
+ { component: MeshRenderer, data: {} },
487
+ )
488
+ .unwrap();
489
+ expect(propagateTransforms(world).ok).toBe(true);
490
+
491
+ const getSpy = vi.spyOn(world, 'get');
492
+ extractFrame(world, prepareExtractContext(world));
493
+ // The mesh-walk must NOT call world.get(entity, Transform) to read the
494
+ // resolved world mat4 -- it goes through the zero-materialization column
495
+ // array view (_getArrayView). Any Transform materialization here would
496
+ // re-introduce the per-frame `{}` allocation AC-15 forbids.
497
+ const transformGets = getSpy.mock.calls.filter((c) => {
498
+ const comp = c[1] as { name?: string } | undefined;
499
+ return comp?.name === 'Transform';
500
+ });
501
+ expect(transformGets.length).toBe(0);
502
+ getSpy.mockRestore();
503
+ });
504
+ });
505
+ }
506
+
507
+ // ─── from render-system-extract-material-inheritance.test.ts ───
508
+ {
509
+ // render-system-extract-material-inheritance.test.ts — M3 / w10 (TDD red)
510
+ //
511
+ // feat-20260529-material-parent-inheritance-read-through-drop-reso
512
+ //
513
+ // Integration tests for material parent-chain inheritance through the
514
+ // extract stage. These tests intentionally FAIL (red) because w11 has not
515
+ // yet wired extract:976 to consume passesOf/paramValueOf — extract still
516
+ // reads asset.passes directly without walking the parent chain.
517
+ //
518
+ // Coverage:
519
+ // (a) inherit-passes: child with no passes, parent ref — snapshot passes
520
+ // come from parent (AC-05 core signal)
521
+ // (b) shoot-76-equivalent: 1 parent + 76 children — extract produces
522
+ // materials with inherited passes (AC-06: non-empty hull.passes)
523
+ // (c) values-merge: child key overrides parent, parent-only key
524
+ // retained (AC-06 shallow-merge)
525
+ // (d) no-parent-regression: material with no parent — extract still works
526
+ //
527
+ // Anchors: requirements AC-05 (extract inheritance core signal) /
528
+ // AC-06 (76 materials equivalent reproduction); plan-strategy D-6
529
+ // (extract:976-999 transformation scope); research Finding 2 (L976 is the
530
+ // sole direct-read point + dataflow).
531
+
532
+ // ── Fixture constants ────────────────────────────────────────────────────────
533
+
534
+ const FORWARD_PBR_PASS: MaterialPass = {
535
+ name: 'Forward',
536
+ program: { module: 'forgeax::default-standard-pbr' },
537
+ };
538
+
539
+ const FORWARD_UNLIT_PASS: MaterialPass = {
540
+ name: 'Forward',
541
+ program: { module: 'forgeax::default-unlit' },
542
+ };
543
+
544
+ // ── Helpers ──────────────────────────────────────────────────────────────────
545
+
546
+ function makeWorldWithComponents(): World {
547
+ const world = new World();
548
+ return world;
549
+ }
550
+
551
+ function registerTestMesh(world: World): Handle<'MeshAsset', 'shared'> {
552
+ const positions = new Float32Array([0, 0, 0, 1, 0, 0, 0, 1, 0]);
553
+ return world.allocSharedRef<'MeshAsset', MeshAsset>('MeshAsset', {
554
+ kind: 'mesh',
555
+ vertices: new Float32Array([
556
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0,
557
+ 1, 0, 0, 0, 0,
558
+ ]),
559
+ indices: new Uint16Array([0, 1, 2]),
560
+ attributes: { position: positions },
561
+ aabb: new Float32Array([0, 0, 0, 1, 1, 1]),
562
+ submeshes: [
563
+ {
564
+ indexOffset: 0,
565
+ indexCount: 3,
566
+ vertexCount: 36,
567
+ topology: 'triangle-list',
568
+ materialSlot: 0,
569
+ },
570
+ ],
571
+
572
+ materialSlots: [{ slotName: 'Default' }],
573
+ });
574
+ }
575
+
576
+ // D-19: a material's parent is an embedded AssetGuid resolved through the
577
+ // registry catalogue (registry.lookup), while the material itself is
578
+ // resolved from a column handle via world.sharedRefs. So a parent material is
579
+ // catalogued by GUID (lookupable during the walk) and the child references
580
+ // that GUID; the returned handle is what MeshRenderer.materials carries.
581
+ function registerMaterial(
582
+ world: World,
583
+ resolver: TestRenderAssetResolver,
584
+ passes: MaterialPass[] | undefined,
585
+ parentGuid?: AssetGuid,
586
+ values?: Readonly<Record<string, unknown>>,
587
+ ): { handle: Handle<'MaterialAsset', 'shared'>; guid: AssetGuid } {
588
+ const asset: MaterialAsset = {
589
+ kind: 'material',
590
+ passes,
591
+ values: values ?? {},
592
+ } as unknown as MaterialAsset;
593
+ if (parentGuid !== undefined) {
594
+ (asset as { parent: AssetGuid }).parent = parentGuid;
595
+ }
596
+ const guid = AssetGuid.random();
597
+ resolver.publish(AssetGuid.format(guid), asset);
598
+ const handle = world.allocSharedRef<'MaterialAsset', MaterialAsset>('MaterialAsset', asset);
599
+ return { handle, guid };
600
+ }
601
+
602
+ function transformData(
603
+ x: number,
604
+ y: number,
605
+ z: number,
606
+ ): {
607
+ pos: number[];
608
+ quat: number[];
609
+ scale: number[];
610
+ } {
611
+ return {
612
+ pos: [x, y, z],
613
+ quat: [0, 0, 0, 1],
614
+ scale: [1, 1, 1],
615
+ };
616
+ }
617
+
618
+ function spawnRenderable(
619
+ world: World,
620
+ meshHandle: Handle<'MeshAsset', 'shared'>,
621
+ matHandle: Handle<'MaterialAsset', 'shared'>,
622
+ x = 0,
623
+ y = 0,
624
+ z = 0,
625
+ ): void {
626
+ world
627
+ .spawn(
628
+ { component: Transform, data: transformData(x, y, z) },
629
+ { component: MeshFilter, data: { assetHandle: meshHandle } },
630
+ { component: MeshRenderer, data: { materials: [matHandle] } },
631
+ )
632
+ .unwrap();
633
+ }
634
+
635
+ function spawnCamera(world: World): void {
636
+ world
637
+ .spawn(
638
+ {
639
+ component: Transform,
640
+ data: transformData(0, 0, 5),
641
+ },
642
+ {
643
+ component: Camera,
644
+ data: {
645
+ fov: Math.PI / 4,
646
+ aspect: 1,
647
+ near: 0.1,
648
+ far: 100,
649
+ projection: 0,
650
+ left: -1,
651
+ right: 1,
652
+ bottom: -1,
653
+ top: 1,
654
+ },
655
+ },
656
+ )
657
+ .unwrap();
658
+ }
659
+
660
+ // ── Tests ────────────────────────────────────────────────────────────────────
661
+
662
+ describe('render-system-extract material inheritance (M3 w10, TDD red)', () => {
663
+ // ── (a) AC-05: inherit passes from parent ─────────────────────────────
664
+
665
+ it('AC-05 core signal: child no-passes inherits passes from parent via extract', () => {
666
+ const world = makeWorldWithComponents();
667
+ spawnCamera(world);
668
+ const { port: assets, resolver } = createTestRenderAssetStore(makeMockShaderRegistry());
669
+ const mesh = registerTestMesh(world);
670
+
671
+ const parentMat = registerMaterial(world, resolver, [FORWARD_PBR_PASS]);
672
+ const childMat = registerMaterial(world, resolver, undefined, parentMat.guid);
673
+
674
+ spawnRenderable(world, mesh, childMat.handle);
675
+
676
+ propagateTransforms(world);
677
+
678
+ const frame = extractFrame(world, prepareExtractContext(world, { assets }));
679
+ expect(frame.renderables.length).toBe(1);
680
+
681
+ // AC-05: the child's snapshot should inherit passes from the parent,
682
+ // yielding a non-undefined materialShaderId derived from the first pass.
683
+ // RED: with direct asset.passes read, child with undefined passes
684
+ // yields passes=[] -> materialShaderId=undefined.
685
+ const snap = frame.renderables[0]?.material;
686
+ expect(snap).toBeDefined();
687
+ expect(snap?.materialShaderId).toBe('forgeax::default-standard-pbr');
688
+ });
689
+
690
+ // ── (b) AC-06: shoot-76 equivalent (1 parent + 76 children) ─────────
691
+
692
+ it('AC-06 shoot-76 equivalent: N children inherit from 1 parent', () => {
693
+ const world = makeWorldWithComponents();
694
+ spawnCamera(world);
695
+ const { port: assets, resolver } = createTestRenderAssetStore(makeMockShaderRegistry());
696
+ const mesh = registerTestMesh(world);
697
+
698
+ const parentMat = registerMaterial(world, resolver, [FORWARD_PBR_PASS]);
699
+
700
+ const childCount = 76;
701
+ for (let i = 0; i < childCount; i++) {
702
+ const childMat = registerMaterial(world, resolver, undefined, parentMat.guid);
703
+ // Spread across Z axis (0 to -60) so all entities stay within
704
+ // the perspective camera frustum (far=100, fov=PI/4 at (0,0,5)).
705
+ spawnRenderable(world, mesh, childMat.handle, 0, 0, -i * 0.8);
706
+ }
707
+
708
+ propagateTransforms(world);
709
+
710
+ const frame = extractFrame(world, prepareExtractContext(world, { assets }));
711
+
712
+ // AC-06: all 76 entities should produce renderables with non-empty
713
+ // inherited passes.
714
+ expect(frame.renderables.length).toBe(childCount);
715
+
716
+ for (let i = 0; i < childCount; i++) {
717
+ const snap = frame.renderables[i]?.material;
718
+ // RED: each child's snapshot currently has undefined materialShaderId
719
+ // because asset.passes is undefined (direct read, no parent walk).
720
+ expect(snap?.materialShaderId).toBe('forgeax::default-standard-pbr');
721
+ }
722
+ });
723
+
724
+ // ── (c) AC-06: values shallow-merge ───────────────────────────
725
+
726
+ it('AC-06 values shallow-merge: child overrides parent, parent-only key retained', () => {
727
+ const world = makeWorldWithComponents();
728
+ spawnCamera(world);
729
+ const { port: assets, resolver } = createTestRenderAssetStore(makeMockShaderRegistry());
730
+ const mesh = registerTestMesh(world);
731
+
732
+ const parentMat = registerMaterial(world, resolver, [FORWARD_PBR_PASS], undefined, {
733
+ metallic: 0.3,
734
+ roughness: 0.7,
735
+ });
736
+ const childMat = registerMaterial(world, resolver, undefined, parentMat.guid, {
737
+ metallic: 0.9,
738
+ });
739
+
740
+ spawnRenderable(world, mesh, childMat.handle);
741
+
742
+ propagateTransforms(world);
743
+
744
+ const frame = extractFrame(world, prepareExtractContext(world, { assets }));
745
+ expect(frame.renderables.length).toBe(1);
746
+
747
+ // RED: child's metallic should be 0.9 (child overrides), roughness
748
+ // should be 0.7 (inherited from parent). With direct asset read,
749
+ // roughness comes from child's own values which is { metallic: 0.9 }
750
+ // — roughness defaults to 0.5, not inherited from parent.
751
+ const snap = frame.renderables[0]?.material;
752
+ expect(snap).toBeDefined();
753
+ expect(snap?.metallic).toBe(0.9);
754
+ expect(snap?.roughness).toBe(0.7);
755
+ });
756
+
757
+ // ── (d) regression: no-parent path still works ─────────────────────
758
+
759
+ it('no-parent regression: material without parent still extracts correctly', () => {
760
+ const world = makeWorldWithComponents();
761
+ spawnCamera(world);
762
+ const { port: assets, resolver } = createTestRenderAssetStore(makeMockShaderRegistry());
763
+ const mesh = registerTestMesh(world);
764
+
765
+ const mat = registerMaterial(world, resolver, [FORWARD_UNLIT_PASS], undefined, {
766
+ baseColor: [0.2, 0.3, 0.4],
767
+ });
768
+
769
+ spawnRenderable(world, mesh, mat.handle);
770
+
771
+ propagateTransforms(world);
772
+
773
+ const frame = extractFrame(world, prepareExtractContext(world, { assets }));
774
+ expect(frame.renderables.length).toBe(1);
775
+
776
+ const snap = frame.renderables[0]?.material;
777
+ expect(snap).toBeDefined();
778
+ expect(snap?.materialShaderId).toBe('forgeax::default-unlit');
779
+ expect(snap?.baseColor[0]).toBeCloseTo(srgbChannelToLinear(0.2));
780
+ expect(snap?.baseColor[1]).toBeCloseTo(srgbChannelToLinear(0.3));
781
+ expect(snap?.baseColor[2]).toBeCloseTo(srgbChannelToLinear(0.4));
782
+ });
783
+ });
784
+ }
785
+
786
+ // --- from render-system-extract-sprite-slices.test.ts ---
787
+ {
788
+ // feat-20260625-refactor-sprite-as-transparent-mesh M3 / w9 (TDD red).
789
+ //
790
+ // Sprite extract now walks the same generic else-branch every other
791
+ // paramSchema-driven material consumes: extract produces a MaterialSnapshot
792
+ // carrying `materialShaderId === 'forgeax::sprite'` + `paramSnapshot` keyed
793
+ // on the WGSL Material UBO struct field names (colorTint / region /
794
+ // pivotAndSize / slicesAndMode). `shadingModel` is undefined on the sprite
795
+ // path -- the 'sprite' union member is removed (AC-01 w15 closes the type
796
+ // layer; this test asserts the production behaviour change at w12).
797
+ //
798
+ // Three sentinel states match the post-ablation slicesAndMode encoding:
799
+ // - undefined slices: paramSnapshot.slicesAndMode === [0, 0, 0, 0]
800
+ // - stretch [.25,.25,.25,.25] sliceMode=0 -> [.25, .25, .25, .25]
801
+ // - tile [.25,.25,.25,.25] sliceMode=1 -> [.25, .25, .25, -.25]
802
+ // (extract pre-folds sliceMode=1 by negating slicesAndMode.w; the
803
+ // shader recovers magnitude via abs() and dispatches on sign.)
804
+ //
805
+ // RED before w12 -- the legacy isSprite branch still emits
806
+ // shadingModel='sprite' + spriteFields. Goes green after w12.
807
+
808
+ function makeShaderRegistryWithSprite(): ShaderRegistry {
809
+ const mockDevice: ShaderRegistryDevice = {
810
+ createShaderModule() {
811
+ return {
812
+ ok: true,
813
+ value: undefined,
814
+ unwrap: () => undefined,
815
+ unwrapOr: (d: unknown) => d,
816
+ } as unknown as ReturnType<ShaderRegistryDevice['createShaderModule']>;
817
+ },
818
+ };
819
+ const sr = new ShaderRegistry({ device: mockDevice, manifestUrl: undefined });
820
+ // Sprite paramSchema mirrors sprite.material.json post-w11. The four
821
+ // UBO entries (colorTint / region / pivotAndSize / slicesAndMode) are
822
+ // the WGSL Material struct field names; user-facing inputs
823
+ // (region/pivot/slices/sliceMode/flipX/flipY) are folded into these
824
+ // entries by the sprite extract branch (D-8 flip + sliceMode fold).
825
+ // The texture entry uses the post-w11 baseColorTexture name (D-4).
826
+ sr.installMaterialArtifact('forgeax::sprite', {
827
+ source: 'fn main() {}',
828
+ paramSchema: [
829
+ { name: 'colorTint', type: 'vec4', default: [1.0, 1.0, 1.0, 1.0] },
830
+ { name: 'region', type: 'vec4', default: [0.0, 0.0, 1.0, 1.0] },
831
+ { name: 'pivotAndSize', type: 'vec4', default: [0.5, 0.5, 1.0, 1.0] },
832
+ { name: 'slicesAndMode', type: 'vec4', default: [0.0, 0.0, 0.0, 0.0] },
833
+ { name: 'baseColorTexture', type: 'texture2d' },
834
+ ],
835
+ });
836
+ return sr;
837
+ }
838
+
839
+ const SPRITE_PASS: MaterialPass = {
840
+ name: 'Sprite',
841
+ program: { module: 'forgeax::sprite' },
842
+ renderState: { queue: 3000 },
843
+ };
844
+
845
+ function identity() {
846
+ return {
847
+ pos: [0, 0, 0],
848
+ quat: [0, 0, 0, 1],
849
+ scale: [1, 1, 1],
850
+ };
851
+ }
852
+
853
+ function registerSpriteMesh(world: World): Handle<'MeshAsset', 'shared'> {
854
+ const positions = new Float32Array([0, 0, 0, 1, 0, 0, 0, 1, 0]);
855
+ return world.allocSharedRef<'MeshAsset', MeshAsset>('MeshAsset', {
856
+ kind: 'mesh',
857
+ vertices: new Float32Array([
858
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0,
859
+ 1, 0, 0, 0, 0,
860
+ ]),
861
+ indices: new Uint16Array([0, 1, 2]),
862
+ attributes: { position: positions },
863
+ aabb: new Float32Array([0, 0, 0, 1, 1, 1]),
864
+ submeshes: [
865
+ {
866
+ indexOffset: 0,
867
+ indexCount: 3,
868
+ vertexCount: 36,
869
+ topology: 'triangle-list',
870
+ materialSlot: 0,
871
+ },
872
+ ],
873
+
874
+ materialSlots: [{ slotName: 'Default' }],
875
+ });
876
+ }
877
+
878
+ function spawnSpriteScene(values: Record<string, unknown>): {
879
+ world: World;
880
+ assets: RenderAssetPort;
881
+ } {
882
+ const world = new World();
883
+ const assets = createTestRenderAssetOwner(makeShaderRegistryWithSprite());
884
+ const mesh = registerSpriteMesh(world);
885
+ const matHandle = world.allocSharedRef<'MaterialAsset', MaterialAsset>('MaterialAsset', {
886
+ kind: 'material',
887
+ passes: [SPRITE_PASS],
888
+ values,
889
+ } as MaterialAsset);
890
+ // Spawn a camera so extract has a viewport.
891
+ world
892
+ .spawn(
893
+ { component: Transform, data: { ...identity(), pos: [0, 0, 5] } },
894
+ {
895
+ component: Camera,
896
+ data: {
897
+ fov: Math.PI / 4,
898
+ aspect: 1,
899
+ near: 0.1,
900
+ far: 100,
901
+ projection: 0,
902
+ left: -1,
903
+ right: 1,
904
+ bottom: -1,
905
+ top: 1,
906
+ },
907
+ },
908
+ )
909
+ .unwrap();
910
+ // Spawn sprite entity.
911
+ world
912
+ .spawn(
913
+ { component: Transform, data: identity() },
914
+ { component: MeshFilter, data: { assetHandle: mesh } },
915
+ { component: MeshRenderer, data: { materials: [matHandle] } },
916
+ )
917
+ .unwrap();
918
+ propagateTransforms(world);
919
+ return { world, assets };
920
+ }
921
+
922
+ describe('render-system-extract sprite paramSnapshot slicesAndMode (M3 / w9)', () => {
923
+ it('(1) no slicesAndMode in values -> paramSnapshot.slicesAndMode absent', () => {
924
+ const { world, assets } = spawnSpriteScene({});
925
+ const frame = extractFrame(world, prepareExtractContext(world, { assets }));
926
+ // Renderable filter: post-ablation sprite carries forgeax::sprite
927
+ // shaderId, NOT shadingModel='sprite' (the union member is gone in
928
+ // AC-01).
929
+ const renderable = frame.renderables.find(
930
+ (r) => r.material.materialShaderId === 'forgeax::sprite',
931
+ );
932
+ expect(renderable).toBeDefined();
933
+ const snap = renderable?.material.paramSnapshot;
934
+ expect(snap).toBeDefined();
935
+ // w0a SSOT-collapse fix: extract stage now explicitly seeds the
936
+ // slicesAndMode slot with [0,0,0,0] when absent from values so
937
+ // the record-stage UBO writer overrides the PBR baseline (which would
938
+ // otherwise leave occlusionStrength=1 at offset 48 -> trips
939
+ // useSlices=true in sprite.wgsl -> degenerate quad).
940
+ expect(snap?.slicesAndMode).toEqual([0, 0, 0, 0]);
941
+ });
942
+
943
+ it('(2) stretch slicesAndMode [0.25,0.25,0.25,0.25] -> paramSnapshot.slicesAndMode verbatim', () => {
944
+ const { world, assets } = spawnSpriteScene({
945
+ slicesAndMode: [0.25, 0.25, 0.25, 0.25],
946
+ });
947
+ const frame = extractFrame(world, prepareExtractContext(world, { assets }));
948
+ const renderable = frame.renderables.find(
949
+ (r) => r.material.materialShaderId === 'forgeax::sprite',
950
+ );
951
+ expect(renderable).toBeDefined();
952
+ const snap = renderable?.material.paramSnapshot;
953
+ expect(snap?.slicesAndMode).toEqual([0.25, 0.25, 0.25, 0.25]);
954
+ });
955
+
956
+ it('(3) tile slicesAndMode [.25,.25,.25,-.25] -> .w negative sentinel verbatim', () => {
957
+ // Post-fix-up F-1: callers encode tile mode at the call site by
958
+ // supplying a negative `.w`; the extract path no longer folds a
959
+ // separate `sliceMode` scalar (the shim layer is gone).
960
+ const { world, assets } = spawnSpriteScene({
961
+ slicesAndMode: [0.25, 0.25, 0.25, -0.25],
962
+ });
963
+ const frame = extractFrame(world, prepareExtractContext(world, { assets }));
964
+ const renderable = frame.renderables.find(
965
+ (r) => r.material.materialShaderId === 'forgeax::sprite',
966
+ );
967
+ expect(renderable).toBeDefined();
968
+ const snap = renderable?.material.paramSnapshot;
969
+ const slicesAndMode = snap?.slicesAndMode as readonly number[] | undefined;
970
+ expect(slicesAndMode?.[0]).toBe(0.25);
971
+ expect(slicesAndMode?.[1]).toBe(0.25);
972
+ expect(slicesAndMode?.[2]).toBe(0.25);
973
+ // Sentinel encoding: D-3 .w negative on tile mode (shader abs() recovers).
974
+ expect(slicesAndMode?.[3]).toBe(-0.25);
975
+ });
976
+
977
+ it('(4) default identity region fold; pivotAndSize absent when not supplied', () => {
978
+ const { world, assets } = spawnSpriteScene({});
979
+ const frame = extractFrame(world, prepareExtractContext(world, { assets }));
980
+ const renderable = frame.renderables.find(
981
+ (r) => r.material.materialShaderId === 'forgeax::sprite',
982
+ );
983
+ const snap = renderable?.material.paramSnapshot;
984
+ // The sprite block still writes paramSnap.region unconditionally because
985
+ // SpriteRegionOverride + flipX/flipY fold (plan D-8) need a base to
986
+ // operate on; the [0,0,1,1] identity is that base.
987
+ expect(snap?.region).toEqual([0, 0, 1, 1]);
988
+ // Post-fix-up F-1: no legacy `pivot` -> `pivotAndSize` fold; absence on
989
+ // input means absence on snapshot (UBO writer fills std140 zero).
990
+ expect(snap?.pivotAndSize).toBeUndefined();
991
+ });
992
+
993
+ it('(5) flipX=1 folds into paramSnapshot.region: region.x += region.z; region.z = -region.z (D-8)', () => {
994
+ const { world, assets } = spawnSpriteScene({ flipX: 1 });
995
+ const frame = extractFrame(world, prepareExtractContext(world, { assets }));
996
+ const renderable = frame.renderables.find(
997
+ (r) => r.material.materialShaderId === 'forgeax::sprite',
998
+ );
999
+ const snap = renderable?.material.paramSnapshot;
1000
+ // Identity region [0,0,1,1] with flipX -> [1, 0, -1, 1].
1001
+ const region = snap?.region as readonly number[] | undefined;
1002
+ expect(region?.[0]).toBe(1);
1003
+ expect(region?.[1]).toBe(0);
1004
+ expect(region?.[2]).toBe(-1);
1005
+ expect(region?.[3]).toBe(1);
1006
+ });
1007
+ });
1008
+ }
1009
+
1010
+ // ─── from render-system-clear-camera.test.ts ───
1011
+ {
1012
+ // @forgeax/engine-runtime/__tests__/render-system-clear-camera.test.ts -
1013
+ // feat-20260608-create-app-param-surface-trim / M1 / TASK-002.
1014
+ //
1015
+ // Asserts the clear-color flow from a Camera entity's SoA column into
1016
+ // the per-frame CameraSnapshot the record stage reads. The extract stage
1017
+ // is the boundary between the ECS column-views and the record stage's
1018
+ // GPU recording calls; once clearColor is on the snapshot, the record
1019
+ // stage can drop `internals.clearColor ?? [0.06, 0.06, 0.08, 1.0]` and
1020
+ // read directly from `cameras[0]` (first-archetype-hit per
1021
+ // requirements §OOS-2).
1022
+ //
1023
+ // feat-20260709 M3 / D-3: clear-color is one inline `array<f32,4>` column
1024
+ // (collapsed from the feat-20260608 clearR/G/B/A quartet) read on the hot
1025
+ // path as a stride-4 subscript, mirroring the light direction/color SoA
1026
+ // idiom.
1027
+ //
1028
+ // AC-03 asserts the boundary: if the snapshot does not surface clearColor,
1029
+ // the record stage cannot read it without re-walking the ECS, defeating the
1030
+ // SoA pipeline.
1031
+
1032
+ function identityTransform() {
1033
+ return {
1034
+ pos: [0, 0, 0],
1035
+ quat: [0, 0, 0, 1],
1036
+ scale: [1, 1, 1],
1037
+ };
1038
+ }
1039
+
1040
+ function spawnCamera(
1041
+ world: World,
1042
+ cam: { clearColor: readonly [number, number, number, number] },
1043
+ ) {
1044
+ world
1045
+ .spawn(
1046
+ { component: Transform, data: identityTransform() },
1047
+ {
1048
+ component: Camera,
1049
+ data: {
1050
+ fov: Math.PI / 4,
1051
+ aspect: 1,
1052
+ near: 0.1,
1053
+ far: 100,
1054
+ clearColor: cam.clearColor,
1055
+ },
1056
+ },
1057
+ )
1058
+ .unwrap();
1059
+ }
1060
+
1061
+ describe('render-system-extract clear-color SoA flow (TASK-002)', () => {
1062
+ it('CameraSnapshot surfaces clearColor read straight from the Camera SoA column', () => {
1063
+ const world = new World();
1064
+ spawnCamera(world, { clearColor: [0.25, 0.5, 0.75, 1.0] });
1065
+ propagateTransforms(world);
1066
+ const frame = extractFrame(world, prepareExtractContext(world));
1067
+ expect(frame.cameras.length).toBe(1);
1068
+ const cam = frame.cameras[0];
1069
+ expect(cam).toBeDefined();
1070
+ if (!cam) return;
1071
+ expect(cam.clearColor[0]).toBeCloseTo(0.25, 6);
1072
+ expect(cam.clearColor[1]).toBeCloseTo(0.5, 6);
1073
+ expect(cam.clearColor[2]).toBeCloseTo(0.75, 6);
1074
+ expect(cam.clearColor[3]).toBeCloseTo(1.0, 6);
1075
+ });
1076
+
1077
+ it('first-archetype-hit semantics: when N>1 cameras carry distinct clear, snapshot[0] is the first one', () => {
1078
+ const world = new World();
1079
+ spawnCamera(world, { clearColor: [0.1, 0.2, 0.3, 1.0] });
1080
+ spawnCamera(world, { clearColor: [0.9, 0.8, 0.7, 1.0] });
1081
+ propagateTransforms(world);
1082
+ const frame = extractFrame(world, prepareExtractContext(world));
1083
+ expect(frame.cameras.length).toBeGreaterThanOrEqual(1);
1084
+ const cam0 = frame.cameras[0];
1085
+ expect(cam0).toBeDefined();
1086
+ if (!cam0) return;
1087
+ // The record stage uses cameras[0] (first-archetype-hit) per OOS-2;
1088
+ // assert the snapshot ordering preserves the spawn order so the
1089
+ // record stage's cameras[0] read is deterministic.
1090
+ expect(cam0.clearColor[0]).toBeCloseTo(0.1, 6);
1091
+ expect(cam0.clearColor[1]).toBeCloseTo(0.2, 6);
1092
+ expect(cam0.clearColor[2]).toBeCloseTo(0.3, 6);
1093
+ });
1094
+
1095
+ it('Camera spawned without explicit clearColor defaults to transparent black [0,0,0,0]', () => {
1096
+ const world = new World();
1097
+ world
1098
+ .spawn(
1099
+ { component: Transform, data: identityTransform() },
1100
+ {
1101
+ component: Camera,
1102
+ data: { fov: Math.PI / 4, aspect: 1, near: 0.1, far: 100 },
1103
+ },
1104
+ )
1105
+ .unwrap();
1106
+ propagateTransforms(world);
1107
+ const frame = extractFrame(world, prepareExtractContext(world));
1108
+ const cam = frame.cameras[0];
1109
+ expect(cam).toBeDefined();
1110
+ if (!cam) return;
1111
+ expect(Array.from(cam.clearColor)).toEqual([0, 0, 0, 0]);
1112
+ });
1113
+ });
1114
+ }
1115
+
1116
+ // ─── M2 / w3: extract MaterialSnapshot carries a 4th texture (heightTexture) ───
1117
+ //
1118
+ // feat-20260621-learn-render-5-5-parallax-mapping-demo-aligned-wit M2 / w3
1119
+ //
1120
+ // A custom parallax shader declares heightTexture (the 4th user-region texture).
1121
+ // The extract stage must iterate derive(paramSchema).textureFieldNames so the
1122
+ // heightTexture handle flows into the MaterialSnapshot. Today extract hardcodes
1123
+ // the 3 standard texture fields, so the 4th texture's handle is silently
1124
+ // dropped — this test is RED until w7 wires the iteration. Post-w7 the snapshot
1125
+ // carries the handle under MaterialSnapshot.textureHandles (a field-name keyed
1126
+ // map that holds every declared user-region texture handle).
1127
+ {
1128
+ function makeShaderRegistryWithParallax(): ShaderRegistry {
1129
+ const mockDevice: ShaderRegistryDevice = {
1130
+ createShaderModule() {
1131
+ return {
1132
+ ok: true,
1133
+ value: undefined,
1134
+ unwrap: () => undefined,
1135
+ unwrapOr: (d: unknown) => d,
1136
+ } as unknown as ReturnType<ShaderRegistryDevice['createShaderModule']>;
1137
+ },
1138
+ };
1139
+ const sr = new ShaderRegistry({ device: mockDevice, manifestUrl: undefined });
1140
+ sr.installMaterialArtifact('learn-render::5-5-parallax', {
1141
+ source: 'fn main() {}',
1142
+ paramSchema: [
1143
+ { name: 'baseColor', type: 'color', default: [1.0, 1.0, 1.0, 1.0] },
1144
+ { name: 'metallic', type: 'f32', default: 0.0 },
1145
+ { name: 'roughness', type: 'f32', default: 0.5 },
1146
+ { name: 'heightScale', type: 'f32', default: 0.1 },
1147
+ { name: 'algoMode', type: 'f32', default: 0.0 },
1148
+ { name: 'baseColorTexture', type: 'texture2d' },
1149
+ { name: 'metallicRoughnessTexture', type: 'texture2d' },
1150
+ { name: 'normalTexture', type: 'texture2d' },
1151
+ { name: 'heightTexture', type: 'texture2d' },
1152
+ ],
1153
+ });
1154
+ return sr;
1155
+ }
1156
+
1157
+ function makeShaderRegistryWithEmptyBuiltinPbrSchema(): ShaderRegistry {
1158
+ const sr = makeShaderRegistryWithParallax();
1159
+ sr.installMaterialArtifact('forgeax::default-standard-pbr', {
1160
+ source: 'fn main() {}',
1161
+ paramSchema: [],
1162
+ });
1163
+ return sr;
1164
+ }
1165
+
1166
+ const PARALLAX_PASS: MaterialPass = {
1167
+ name: 'Forward',
1168
+ program: { module: 'learn-render::5-5-parallax' },
1169
+ };
1170
+
1171
+ function identityTx() {
1172
+ return {
1173
+ pos: [0, 0, 0],
1174
+ quat: [0, 0, 0, 1],
1175
+ scale: [1, 1, 1],
1176
+ };
1177
+ }
1178
+
1179
+ function registerQuadMesh(world: World): Handle<'MeshAsset', 'shared'> {
1180
+ const positions = new Float32Array([0, 0, 0, 1, 0, 0, 0, 1, 0]);
1181
+ return world.allocSharedRef<'MeshAsset', MeshAsset>('MeshAsset', {
1182
+ kind: 'mesh',
1183
+ vertices: new Float32Array([
1184
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0,
1185
+ 1, 0, 0, 0, 0,
1186
+ ]),
1187
+ indices: new Uint16Array([0, 1, 2]),
1188
+ attributes: { position: positions },
1189
+ aabb: new Float32Array([0, 0, 0, 1, 1, 1]),
1190
+ submeshes: [
1191
+ {
1192
+ indexOffset: 0,
1193
+ indexCount: 3,
1194
+ vertexCount: 36,
1195
+ topology: 'triangle-list',
1196
+ materialSlot: 0,
1197
+ },
1198
+ ],
1199
+
1200
+ materialSlots: [{ slotName: 'Default' }],
1201
+ });
1202
+ }
1203
+
1204
+ function makeTextureHandle(world: World): Handle<'TextureAsset', 'shared'> {
1205
+ return world.allocSharedRef<'TextureAsset', import('@forgeax/engine-types').TextureAsset>(
1206
+ 'TextureAsset',
1207
+ {
1208
+ kind: 'texture',
1209
+ width: 1,
1210
+ height: 1,
1211
+ format: 'rgba8unorm',
1212
+ data: new Uint8Array([255, 255, 255, 255]),
1213
+ colorSpace: 'linear',
1214
+ mipmap: false,
1215
+ },
1216
+ );
1217
+ }
1218
+
1219
+ describe('render-system-extract heightTexture (4th texture) snapshot pass-through (M2 w3)', () => {
1220
+ it('resolves a binary AssetGuid texture reference through the material owner path', () => {
1221
+ const world = new World();
1222
+ const { port: assets, resolver } = createTestRenderAssetStore(
1223
+ makeShaderRegistryWithParallax(),
1224
+ );
1225
+ const mesh = registerQuadMesh(world);
1226
+ const textureGuid = AssetGuid.random();
1227
+ resolver.publish(AssetGuid.format(textureGuid), {
1228
+ kind: 'texture',
1229
+ width: 1,
1230
+ height: 1,
1231
+ format: 'rgba8unorm',
1232
+ data: new Uint8Array([255, 255, 255, 255]),
1233
+ colorSpace: 'linear',
1234
+ mipmap: false,
1235
+ } satisfies TextureAsset);
1236
+ const matHandle = world.allocSharedRef<'MaterialAsset', MaterialAsset>('MaterialAsset', {
1237
+ kind: 'material',
1238
+ passes: [PARALLAX_PASS],
1239
+ values: { baseColorTexture: { texture: textureGuid } },
1240
+ });
1241
+
1242
+ world
1243
+ .spawn(
1244
+ { component: Transform, data: identityTx() },
1245
+ { component: MeshFilter, data: { assetHandle: mesh } },
1246
+ { component: MeshRenderer, data: { materials: [matHandle] } },
1247
+ )
1248
+ .unwrap();
1249
+ propagateTransforms(world);
1250
+
1251
+ const frame = extractFrame(world, prepareExtractContext(world, { assets }));
1252
+ const textureHandle = frame.renderables[0]?.material.textureHandles?.get('baseColorTexture');
1253
+ expect(textureHandle).toBeDefined();
1254
+ expect(
1255
+ world.sharedRefs.resolve<string, TextureAsset>(textureHandle as never).unwrap().kind,
1256
+ ).toBe('texture');
1257
+ });
1258
+
1259
+ it('MaterialSnapshot.textureHandles carries heightTexture handle (non-undefined, matches input)', () => {
1260
+ const world = new World();
1261
+ const assets = createTestRenderAssetOwner(makeShaderRegistryWithParallax());
1262
+ const mesh = registerQuadMesh(world);
1263
+
1264
+ const baseColorHandle = makeTextureHandle(world);
1265
+ const normalHandle = makeTextureHandle(world);
1266
+ const heightHandle = makeTextureHandle(world);
1267
+
1268
+ const matHandle = world.allocSharedRef<'MaterialAsset', MaterialAsset>('MaterialAsset', {
1269
+ kind: 'material',
1270
+ passes: [PARALLAX_PASS],
1271
+ values: {
1272
+ baseColor: [1, 1, 1, 1],
1273
+ heightScale: 0.1,
1274
+ algoMode: 0,
1275
+ baseColorTexture: baseColorHandle,
1276
+ normalTexture: normalHandle,
1277
+ heightTexture: heightHandle,
1278
+ },
1279
+ } as MaterialAsset);
1280
+
1281
+ world
1282
+ .spawn(
1283
+ { component: Transform, data: { ...identityTx(), pos: [0, 0, 5] } },
1284
+ {
1285
+ component: Camera,
1286
+ data: {
1287
+ fov: Math.PI / 4,
1288
+ aspect: 1,
1289
+ near: 0.1,
1290
+ far: 100,
1291
+ projection: 0,
1292
+ left: -1,
1293
+ right: 1,
1294
+ bottom: -1,
1295
+ top: 1,
1296
+ },
1297
+ },
1298
+ )
1299
+ .unwrap();
1300
+ world
1301
+ .spawn(
1302
+ { component: Transform, data: identityTx() },
1303
+ { component: MeshFilter, data: { assetHandle: mesh } },
1304
+ { component: MeshRenderer, data: { materials: [matHandle] } },
1305
+ )
1306
+ .unwrap();
1307
+ propagateTransforms(world);
1308
+
1309
+ const frame = extractFrame(world, prepareExtractContext(world, { assets }));
1310
+ const renderable = frame.renderables.find(
1311
+ (r) => r.material.materialShaderId === 'learn-render::5-5-parallax',
1312
+ );
1313
+ expect(renderable).toBeDefined();
1314
+ // The 4th texture handle must survive extract under the field-name keyed
1315
+ // map MaterialSnapshot.textureHandles (added + populated by w7). Read via
1316
+ // a structural cast so this test compiles in the red phase before the
1317
+ // field lands; the runtime assertion stays RED until w7 wires extract.
1318
+ const snap = renderable?.material as
1319
+ | {
1320
+ readonly textureHandles?: ReadonlyMap<string, Handle<'TextureAsset', 'shared'>>;
1321
+ readonly materialShaderId?: string;
1322
+ }
1323
+ | undefined;
1324
+ const heightFromSnap = snap?.textureHandles?.get('heightTexture');
1325
+ expect(heightFromSnap).toBeDefined();
1326
+ expect(heightFromSnap).toBe(heightHandle);
1327
+ // The standard fields also land in the same map (single SSOT path).
1328
+ expect(snap?.textureHandles?.get('baseColorTexture')).toBe(baseColorHandle);
1329
+ expect(snap?.textureHandles?.get('normalTexture')).toBe(normalHandle);
1330
+ });
1331
+
1332
+ it('keeps built-in PBR texture handles when its manifest schema is empty', () => {
1333
+ const world = new World();
1334
+ const assets = createTestRenderAssetOwner(makeShaderRegistryWithEmptyBuiltinPbrSchema());
1335
+ const mesh = registerQuadMesh(world);
1336
+ const baseColorHandle = makeTextureHandle(world);
1337
+ const metallicRoughnessHandle = makeTextureHandle(world);
1338
+ const samplerHandle = world.allocSharedRef('SamplerAsset', {
1339
+ kind: 'sampler',
1340
+ magFilter: 'nearest',
1341
+ minFilter: 'nearest',
1342
+ });
1343
+ const material = world.allocSharedRef<'MaterialAsset', MaterialAsset>('MaterialAsset', {
1344
+ kind: 'material',
1345
+ passes: [
1346
+ {
1347
+ name: 'Forward',
1348
+ program: { module: 'forgeax::default-standard-pbr' },
1349
+ renderState: { tags: { LightMode: 'Forward' } },
1350
+ },
1351
+ ],
1352
+ values: {
1353
+ baseColor: [1, 1, 1, 1],
1354
+ baseColorTexture: {
1355
+ texture: baseColorHandle,
1356
+ sampler: samplerHandle,
1357
+ } as unknown as number,
1358
+ metallicRoughnessTexture: metallicRoughnessHandle,
1359
+ },
1360
+ });
1361
+
1362
+ world
1363
+ .spawn(
1364
+ { component: Transform, data: { ...identityTx(), pos: [0, 0, 5] } },
1365
+ {
1366
+ component: Camera,
1367
+ data: {
1368
+ fov: Math.PI / 4,
1369
+ aspect: 1,
1370
+ near: 0.1,
1371
+ far: 100,
1372
+ projection: 0,
1373
+ left: -1,
1374
+ right: 1,
1375
+ bottom: -1,
1376
+ top: 1,
1377
+ },
1378
+ },
1379
+ )
1380
+ .unwrap();
1381
+ world
1382
+ .spawn(
1383
+ { component: Transform, data: identityTx() },
1384
+ { component: MeshFilter, data: { assetHandle: mesh } },
1385
+ { component: MeshRenderer, data: { materials: [material] } },
1386
+ )
1387
+ .unwrap();
1388
+ propagateTransforms(world);
1389
+
1390
+ const snapshot = extractFrame(world, prepareExtractContext(world, { assets })).renderables[0]
1391
+ ?.material;
1392
+ expect(snapshot?.textureHandles?.get('baseColorTexture')).toBe(baseColorHandle);
1393
+ expect(snapshot?.textureHandles?.get('metallicRoughnessTexture')).toBe(
1394
+ metallicRoughnessHandle,
1395
+ );
1396
+ expect(snapshot?.samplerHandles?.get('baseColorTexture')).toBe(samplerHandle);
1397
+ });
1398
+ });
1399
+ }