@woosh/meep-engine 3.1.0 → 3.3.0

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 (1869) hide show
  1. package/LICENSE +188 -188
  2. package/README.md +152 -152
  3. package/editor/Editor.js +598 -598
  4. package/editor/EditorCameraNavigation.js +205 -205
  5. package/editor/EditorKeyMap.js +182 -182
  6. package/editor/SelectionVisualizer.js +127 -127
  7. package/editor/actions/concrete/ActionInvalidateSampler.js +27 -27
  8. package/editor/actions/concrete/PatchTerrainHeightAction.js +85 -85
  9. package/editor/camera/camera_framing.js +104 -104
  10. package/editor/clipboard.js +184 -184
  11. package/editor/ecs/component/editors/ObservedIntegerEditor.js +22 -22
  12. package/editor/ecs/component/editors/ObservedStringEditor.js +34 -34
  13. package/editor/ecs/component/editors/common/two_way_sync.js +50 -50
  14. package/editor/ecs/component/editors/ecs/GridObstacleEditor.js +19 -19
  15. package/editor/ecs/component/editors/ecs/ParameterLookupTableEditor.js +35 -35
  16. package/editor/ecs/component/editors/ecs/ParameterTrackEditor.js +17 -17
  17. package/editor/ecs/component/editors/ecs/SGMeshEditor.js +24 -24
  18. package/editor/ecs/component/editors/ecs/ShadedGeometryEditor.js +33 -33
  19. package/editor/ecs/component/editors/ecs/Trail3DEditor.js +45 -45
  20. package/editor/ecs/component/editors/ecs/buildGridObstaclePreview.js +19 -19
  21. package/editor/ecs/component/editors/ecs/terrain/TerrainEditor.js +72 -72
  22. package/editor/ecs/component/editors/shade/MeshletGeometryEditor.js +30 -30
  23. package/editor/ecs/component/editors/shade/ShadeImageEditor.js +70 -70
  24. package/editor/ecs/component/editors/shade/ShadeMaterialEditor.js +34 -34
  25. package/editor/ecs/component/editors/shade/ShadeTextureEditor.js +46 -46
  26. package/editor/ecs/component/editors/shade/StandardShadeMaterialEditor.js +24 -24
  27. package/editor/ecs/component/prototypeObjectEditor.js +265 -265
  28. package/editor/ecs/component/registerBasicTypeEditors.js +100 -100
  29. package/editor/ecs/component/registerEngineComponentEditors.js +95 -95
  30. package/editor/entity_world_bounds.js +27 -27
  31. package/editor/particles/lut_ops.js +148 -148
  32. package/editor/particles/particleEditEvents.js +12 -12
  33. package/editor/particles/rebuildParticleEmitter.js +31 -31
  34. package/editor/persistence/EditorLayoutStore.js +71 -71
  35. package/editor/persistence/SceneMetadata.js +52 -52
  36. package/editor/persistence/SceneSlotManager.js +144 -144
  37. package/editor/persistence/buildNewSceneDataset.js +67 -67
  38. package/editor/persistence/files.js +68 -68
  39. package/editor/persistence/scene_import.js +143 -143
  40. package/editor/persistence/scene_serialization.js +79 -79
  41. package/editor/persistence/string_buffer_codec.js +41 -41
  42. package/editor/process/GridDisplayProcess.js +125 -125
  43. package/editor/process/SymbolicDisplayProcess.js +106 -108
  44. package/editor/process/symbolic/CameraSymbolicDisplay.js +146 -146
  45. package/editor/process/symbolic/LightSymbolicDisplay.js +172 -172
  46. package/editor/process/symbolic/PathSymbolicDisplay.js +118 -118
  47. package/editor/process/symbolic/PositionedMarkerSymbolicDisplay.js +79 -79
  48. package/editor/process/symbolic/SoundEmitterSymbolicDisplay.js +57 -57
  49. package/editor/process/symbolic/SymbolicDisplay.js +62 -62
  50. package/editor/process/symbolic/gizmo_draw_wire_box_oriented.js +85 -85
  51. package/editor/process/symbolic/gizmo_draw_wire_circle.js +53 -53
  52. package/editor/prototypeEditorShell.js +156 -156
  53. package/editor/selection/editor_pick.js +130 -130
  54. package/editor/selection/screen_rect_frustum.js +119 -119
  55. package/editor/style/controls.scss +168 -168
  56. package/editor/style/inspector.scss +223 -223
  57. package/editor/templates/entity_templates.js +167 -167
  58. package/editor/tools/GridPaintTool.js +273 -273
  59. package/editor/tools/SelectionTool.js +307 -307
  60. package/editor/tools/TransformToolV2.js +378 -378
  61. package/editor/tools/engine/ToolEngine.js +188 -188
  62. package/editor/tools/paint/TerrainTexturePaintTool.js +250 -250
  63. package/editor/tools/v2/BlenderCameraOrientationGizmo.js +501 -501
  64. package/editor/tools/v2/TransformControls.js +971 -971
  65. package/editor/tools/v2/handle/gizmo_drag_plane.js +141 -141
  66. package/editor/tools/v2/handle/gizmo_draw.js +399 -399
  67. package/editor/tools/v2/handle/gizmo_handles.js +364 -364
  68. package/editor/tools/v2/handle/gizmo_ray_shapes.js +239 -239
  69. package/editor/view/ecs/HierarchicalEntityListView.js +339 -339
  70. package/editor/view/ecs/components/DatGuiController.js +2 -2
  71. package/editor/view/ecs/components/common/AutoCanvasView.js +100 -100
  72. package/editor/view/ecs/components/common/TextController.js +59 -59
  73. package/editor/view/library/MeshLibraryView.js +175 -175
  74. package/editor/view/library/mesh_library_drag.js +63 -63
  75. package/editor/view/library/model_thumbnail_source.js +86 -86
  76. package/editor/view/makeEntityDecorators.js +125 -125
  77. package/editor/view/node-graph/NodeGraphSelection.js +89 -89
  78. package/editor/view/node-graph/NodeView.js +211 -211
  79. package/editor/view/node-graph/actions/ConnectionDeleteAction.js +36 -36
  80. package/editor/view/node-graph/actions/NodesMoveAction.js +41 -41
  81. package/editor/view/node-graph/connection_wire_geometry.js +107 -107
  82. package/editor/view/particles/ColorLutGradientView.js +291 -291
  83. package/editor/view/particles/ScalarLutCurveView.js +279 -279
  84. package/editor/view/prepareMeshLibrary.js +188 -188
  85. package/editor/view/shell/SceneTreePanelView.js +119 -119
  86. package/editor/view/v2/SplitView.js +2 -2
  87. package/package.json +94 -94
  88. package/samples/generation/generators/interactive/mir_generator_place_buff_objects.js +362 -362
  89. package/src/DUPLICATION_AUDIT_2026_08_07/00_core_reuse_surface.md +738 -738
  90. package/src/DUPLICATION_AUDIT_2026_08_07/A_core_math_geom.md +79 -79
  91. package/src/DUPLICATION_AUDIT_2026_08_07/B_core_data.md +93 -93
  92. package/src/DUPLICATION_AUDIT_2026_08_07/C_gfx_render.md +80 -80
  93. package/src/DUPLICATION_AUDIT_2026_08_07/D_gfx_features.md +164 -164
  94. package/src/DUPLICATION_AUDIT_2026_08_07/E_physics.md +69 -69
  95. package/src/DUPLICATION_AUDIT_2026_08_07/F_sound.md +102 -102
  96. package/src/DUPLICATION_AUDIT_2026_08_07/G_net_save.md +129 -129
  97. package/src/DUPLICATION_AUDIT_2026_08_07/H_engine_misc.md +72 -72
  98. package/src/DUPLICATION_AUDIT_2026_08_07/I_generation_view.md +74 -74
  99. package/src/DUPLICATION_AUDIT_2026_08_07/K_crosscutting.md +169 -169
  100. package/src/DUPLICATION_AUDIT_2026_08_07.md +254 -254
  101. package/src/DUPLICATION_AUDIT_REMEDIATION.md +250 -250
  102. package/src/REVIEW_2026_08_06/adv-core.md +511 -511
  103. package/src/REVIEW_2026_08_06/adv-gfx.md +480 -480
  104. package/src/REVIEW_2026_08_06/adv-view.md +446 -446
  105. package/src/REVIEW_2026_08_06/api-core.md +296 -296
  106. package/src/REVIEW_2026_08_06/api-engine.md +195 -195
  107. package/src/REVIEW_2026_08_06/bvh-phys-sound-net.md +507 -507
  108. package/src/REVIEW_2026_08_06/core-binary.md +348 -348
  109. package/src/REVIEW_2026_08_06/core-collection.md +376 -376
  110. package/src/REVIEW_2026_08_06/core-math.md +221 -221
  111. package/src/REVIEW_2026_08_06/core-process.md +266 -266
  112. package/src/REVIEW_2026_08_06/core-science.md +223 -223
  113. package/src/REVIEW_2026_08_06/engine-ai-nav.md +279 -279
  114. package/src/REVIEW_2026_08_06/engine-animation.md +167 -167
  115. package/src/REVIEW_2026_08_06/engine-asset.md +166 -166
  116. package/src/REVIEW_2026_08_06/engine-ecs.md +920 -920
  117. package/src/REVIEW_2026_08_06/engine-input.md +197 -197
  118. package/src/REVIEW_2026_08_06/engine-misc.md +248 -248
  119. package/src/REVIEW_2026_08_06/engine-terrain.md +52 -52
  120. package/src/REVIEW_2026_08_06/generation.md +176 -176
  121. package/src/REVIEW_2026_08_06/geom-2d.md +434 -434
  122. package/src/REVIEW_2026_08_06/geom-3d.md +117 -117
  123. package/src/REVIEW_2026_08_06/gfx-gi.md +143 -143
  124. package/src/REVIEW_2026_08_06/gfx-render.md +740 -740
  125. package/src/REVIEW_2026_08_06/gfx-texture.md +690 -690
  126. package/src/REVIEW_2026_08_06/prior-criticals.md +49 -49
  127. package/src/REVIEW_2026_08_06/prior-highs.md +138 -138
  128. package/src/REVIEW_2026_08_06/test-gaps.md +364 -364
  129. package/src/REVIEW_2026_08_06/view.md +667 -667
  130. package/src/REVIEW_2026_08_06.md +610 -610
  131. package/src/avif/codec/dec/avif_dec.cpp +233 -233
  132. package/src/avif/codec/dec/avif_dec.js +16 -16
  133. package/src/avif/encoder_worker.js +5 -18
  134. package/src/core/binary/BitImage2.js +246 -246
  135. package/src/core/binary/align_32.js +21 -21
  136. package/src/core/binary/data_view/DataType2DataViewReaders.js +23 -23
  137. package/src/core/binary/data_view/DataType2DataViewWriters.js +25 -25
  138. package/src/core/binary/hash/XXH128Hash.js +55 -55
  139. package/src/core/binary/hash/XXH3_SECRET.js +25 -25
  140. package/src/core/binary/hash/xxh3_128.js +341 -341
  141. package/src/core/binary/hash/xxh3_64.js +241 -241
  142. package/src/core/binary/hash/xxh3_common.js +476 -476
  143. package/src/core/binary/lz4/LZ4_MAX_INPUT_SIZE.js +9 -9
  144. package/src/core/binary/lz4/lz4_compress_block.js +385 -385
  145. package/src/core/binary/lz4/lz4_compress_bound.js +25 -25
  146. package/src/core/binary/lz4/lz4_decompress_block.js +139 -139
  147. package/src/core/binary/lz4/lz4_decompress_bound.js +30 -30
  148. package/src/core/binary/meshopt/MESHOPT_GROUP_SIZE.js +18 -18
  149. package/src/core/binary/meshopt/MeshoptCompressionFilter.js +30 -30
  150. package/src/core/binary/meshopt/MeshoptCompressionMode.js +21 -21
  151. package/src/core/binary/meshopt/__meshopt_test_streams.js +237 -237
  152. package/src/core/binary/meshopt/meshopt_decode.js +73 -73
  153. package/src/core/binary/meshopt/meshopt_decode_byte_group.js +67 -67
  154. package/src/core/binary/meshopt/meshopt_decode_data_block.js +59 -59
  155. package/src/core/binary/meshopt/meshopt_decode_filter_color.js +69 -69
  156. package/src/core/binary/meshopt/meshopt_decode_filter_exponential.js +43 -43
  157. package/src/core/binary/meshopt/meshopt_decode_filter_octahedral.js +60 -60
  158. package/src/core/binary/meshopt/meshopt_decode_filter_quaternion.js +71 -71
  159. package/src/core/binary/meshopt/meshopt_decode_index_buffer.js +294 -294
  160. package/src/core/binary/meshopt/meshopt_decode_index_sequence.js +115 -115
  161. package/src/core/binary/meshopt/meshopt_decode_vertex_buffer.js +381 -381
  162. package/src/core/binary/meshopt/meshopt_read_uint_var.js +59 -59
  163. package/src/core/binary/reinterpret_float32_as_uint32.js +13 -13
  164. package/src/core/binary/reinterpret_uint32_as_float32.js +14 -14
  165. package/src/core/binary/type/DataType2TypedArrayConstructorMapping.js +35 -35
  166. package/src/core/bvh2/bvh3/ebvh_geometry_query_any_triangle_ray.js +149 -149
  167. package/src/core/bvh2/bvh3/ebvh_sort_for_traversal_depth_first.js +96 -96
  168. package/src/core/bvh2/bvh3/query/bvh_query_depth_range_in_frustum.js +101 -101
  169. package/src/core/bvh2/bvh3/query/bvh_query_leaves_generic.js +77 -77
  170. package/src/core/bvh2/bvh3/query/bvh_query_leaves_ray.js +90 -90
  171. package/src/core/bvh2/bvh3/query/bvh_query_leaves_ray_segment.js +94 -94
  172. package/src/core/bvh2/bvh3/query/bvh_query_user_data_generic.js +86 -86
  173. package/src/core/bvh2/bvh3/query/bvh_query_user_data_intersects_capsule.js +101 -101
  174. package/src/core/bvh2/bvh3/query/bvh_query_user_data_intersects_sphere.js +92 -92
  175. package/src/core/bvh2/bvh3/query/bvh_query_user_data_ray.js +96 -96
  176. package/src/core/bvh2/bvh3/query/bvh_query_user_data_ray_segment.js +100 -100
  177. package/src/core/bvh2/visual/BVHGeometry.js +131 -131
  178. package/src/core/bvh8/BVH8.js +436 -436
  179. package/src/core/bvh8/aabb3_round_to_float32.js +22 -22
  180. package/src/core/bvh8/build/BVH8Converter.js +588 -588
  181. package/src/core/bvh8/build/TriangleCluster.js +122 -122
  182. package/src/core/bvh8/build/aabb3_compute_merge_cost.js +28 -28
  183. package/src/core/bvh8/build/aabb3_from_triangle_by_index.js +17 -17
  184. package/src/core/bvh8/build/bvh8_build_for_geometry.js +303 -303
  185. package/src/core/bvh8/build/bvh8_from_proxy.js +256 -256
  186. package/src/core/bvh8/build/byte.js +9 -9
  187. package/src/core/bvh8/build/encode_bounds_e.js +11 -11
  188. package/src/core/bvh8/bvh8_convert_to_dot.js +132 -132
  189. package/src/core/bvh8/bvh8_count_primitives.js +98 -98
  190. package/src/core/bvh8/bvh8_geometry_validate.js +138 -138
  191. package/src/core/bvh8/bvh8_geometry_validate_indirect.js +166 -166
  192. package/src/core/bvh8/bvh8_get_node_bounds.js +34 -34
  193. package/src/core/bvh8/bvh8_get_node_child_bounds.js +52 -52
  194. package/src/core/bvh8/bvh8_node_child_surface_area.js +18 -18
  195. package/src/core/bvh8/bvh8_node_count_triangles.js +27 -27
  196. package/src/core/bvh8/bvh8_quality.js +72 -72
  197. package/src/core/bvh8/bvh8_validate_structure.js +87 -87
  198. package/src/core/clipboard/obtainClipBoard.js +29 -29
  199. package/src/core/clipboard/safeClipboardReadText.js +55 -55
  200. package/src/core/clipboard/safeClipboardWriteText.js +23 -23
  201. package/src/core/collection/array/typed/typed_array_value_denormalize.js +52 -52
  202. package/src/core/collection/array/typed/typed_array_value_normalize.js +51 -51
  203. package/src/core/collection/union-find/union_find.js +79 -79
  204. package/src/core/color/PQ/PQ_constants.d.ts +43 -0
  205. package/src/core/color/PQ/PQ_constants.d.ts.map +1 -0
  206. package/src/core/color/PQ/PQ_constants.js +50 -0
  207. package/src/core/color/PQ/PQ_to_linear.d.ts +24 -0
  208. package/src/core/color/PQ/PQ_to_linear.d.ts.map +1 -0
  209. package/src/core/color/PQ/PQ_to_linear.js +35 -0
  210. package/src/core/color/PQ/linear_to_PQ.d.ts +27 -0
  211. package/src/core/color/PQ/linear_to_PQ.d.ts.map +1 -0
  212. package/src/core/color/PQ/linear_to_PQ.js +32 -0
  213. package/src/core/color/YCoCg/rgb_to_ycocg.js +20 -20
  214. package/src/core/color/YCoCg/ycocg_to_rgb.js +17 -17
  215. package/src/core/color/colormap/MAGMA_LUT.js +26 -26
  216. package/src/core/color/illuminant/D65_TRISTIMULUS_XYZ.js +19 -19
  217. package/src/core/color/lab/lab_apply_hunt_adjustment.js +27 -27
  218. package/src/core/color/lab/lab_distance_hyab.js +23 -23
  219. package/src/core/color/lab/xyz_to_lab.js +62 -62
  220. package/src/core/color/operations/color_darken.js +24 -24
  221. package/src/core/color/operations/color_desaturate.js +24 -24
  222. package/src/core/color/operations/color_lighten.js +24 -24
  223. package/src/core/color/operations/color_saturate.js +24 -24
  224. package/src/core/color/operations/color_scale_okhsv_channel.js +45 -45
  225. package/src/core/color/tonemap/tonemap_aces.js +41 -41
  226. package/src/core/color/ycxcz/xyz_to_ycxcz.js +28 -28
  227. package/src/core/color/ycxcz/ycxcz_to_xyz.js +19 -19
  228. package/src/core/dom/isImageBitmap.js +12 -12
  229. package/src/core/function/frameThrottle.js +23 -23
  230. package/src/core/geom/2d/aabb/aabb2_array_combine.js +7 -7
  231. package/src/core/geom/2d/aabb/aabb2_compute_area.js +7 -7
  232. package/src/core/geom/2d/aabb/aabb2_compute_center_from_multiple.js +7 -7
  233. package/src/core/geom/2d/aabb/aabb2_compute_overlap.js +7 -7
  234. package/src/core/geom/2d/aabb/aabb2_from_v2_array.js +7 -7
  235. package/src/core/geom/2d/aabb/aabb2_intersects_point.js +7 -7
  236. package/src/core/geom/2d/aabb/aabb2_overlap_exists.js +7 -7
  237. package/src/core/geom/2d/circle/circle_compute_circle_intersection.js +7 -7
  238. package/src/core/geom/2d/circle/circle_compute_circle_penetration.js +7 -7
  239. package/src/core/geom/2d/circle/circle_intersects_point.js +7 -7
  240. package/src/core/geom/2d/compute_polygon_area_2d.js +7 -7
  241. package/src/core/geom/2d/convex-hull/fixed_convex_hull_humus.js +7 -7
  242. package/src/core/geom/2d/convex-hull/fixed_convex_hull_relaxation.js +7 -7
  243. package/src/core/geom/2d/convex-hull/orientation3_array.js +7 -7
  244. package/src/core/geom/2d/intersect_ray_2d.js +7 -7
  245. package/src/core/geom/2d/line/line2_distance_to_point_sqr.js +7 -7
  246. package/src/core/geom/2d/line/line2_segment_intersection_fraction_2d.js +44 -44
  247. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_2d.js +7 -7
  248. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_array_2d.js +7 -7
  249. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_vectors_2d.js +7 -7
  250. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_vectors_array_2d.js +7 -7
  251. package/src/core/geom/2d/line/line_segment_intersection_fraction_2d.js +7 -7
  252. package/src/core/geom/2d/line/line_segment_line_segment_intersection_exists_2d.js +7 -7
  253. package/src/core/geom/2d/line/segment2_intersects_segment2_2d.js +25 -25
  254. package/src/core/geom/2d/line/segment2_segment_compute_intersection_array_2d.js +46 -46
  255. package/src/core/geom/2d/line/segment2_segment_intersection_fractions.js +52 -52
  256. package/src/core/geom/2d/oriented-box/min_area_rect_2d.js +69 -69
  257. package/src/core/geom/2d/polygon/TRIANGULATION_DESIGN.md +433 -433
  258. package/src/core/geom/2d/polygon/polygon2_clip_axis_halfplane.js +51 -51
  259. package/src/core/geom/2d/polygon/polygon2_clip_halfplane.js +50 -50
  260. package/src/core/geom/2d/polygon/polygon2_is_counter_clockwise.js +84 -84
  261. package/src/core/geom/2d/polygon/polygon2_signed_area.js +52 -52
  262. package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.js +86 -86
  263. package/src/core/geom/2d/polygon/polygon2_triangulate.js +1280 -1280
  264. package/src/core/geom/2d/polygon/polygon2_triangulation_deviation.js +77 -77
  265. package/src/core/geom/2d/quad-tree/qt_collect_by_circle.js +39 -39
  266. package/src/core/geom/2d/quad-tree/qt_match_data_by_circle.js +101 -101
  267. package/src/core/geom/2d/quad-tree/qt_query_data_nearest_to_point.js +7 -7
  268. package/src/core/geom/2d/rectangle_to_aabb.js +7 -7
  269. package/src/core/geom/2d/spline_bezier2_2d.js +7 -7
  270. package/src/core/geom/2d/triangle/tri2_rasterize_conservative.js +99 -99
  271. package/src/core/geom/2d/triangle/tri2_signed_area.js +35 -35
  272. package/src/core/geom/2d/triangle2d_compute_area.js +7 -7
  273. package/src/core/geom/2d/triangle2d_contains_point.js +7 -7
  274. package/src/core/geom/2d/triangle2d_get_barycentric.js +7 -7
  275. package/src/core/geom/2d/v2_morton_encode.js +23 -23
  276. package/src/core/geom/3d/aabb/aabb3_array_intersects_frustum_degree.js +7 -7
  277. package/src/core/geom/3d/aabb/aabb3_box_surface_area_2.js +7 -7
  278. package/src/core/geom/3d/aabb/aabb3_build_frustum.js +5 -5
  279. package/src/core/geom/3d/aabb/aabb3_closest_point_on_surface.js +57 -57
  280. package/src/core/geom/3d/aabb/aabb3_combined_surface_area.js +7 -7
  281. package/src/core/geom/3d/aabb/aabb3_compute_half_surface_area.js +7 -7
  282. package/src/core/geom/3d/aabb/aabb3_compute_projected_area.js +7 -7
  283. package/src/core/geom/3d/aabb/aabb3_compute_surface_area.js +7 -7
  284. package/src/core/geom/3d/aabb/aabb3_detailed_volume_intersection.js +7 -7
  285. package/src/core/geom/3d/aabb/aabb3_estimate_projected_area2.js +7 -7
  286. package/src/core/geom/3d/aabb/aabb3_from_threejs_geometry.js +7 -7
  287. package/src/core/geom/3d/aabb/aabb3_from_triangle_group.js +46 -46
  288. package/src/core/geom/3d/aabb/aabb3_intersects_frustum_degree.js +7 -7
  289. package/src/core/geom/3d/aabb/aabb3_intersects_line_segment.js +7 -7
  290. package/src/core/geom/3d/aabb/aabb3_near_distance_to_intersection_ray_segment.js +7 -7
  291. package/src/core/geom/3d/aabb/aabb3_nearest_point_on_surface.js +7 -7
  292. package/src/core/geom/3d/aabb/aabb3_ray_segment_entry_distance.js +95 -95
  293. package/src/core/geom/3d/aabb/aabb3_raycast.js +7 -7
  294. package/src/core/geom/3d/aabb/aabb3_transform_oriented.js +93 -93
  295. package/src/core/geom/3d/aabb/aabb3_transform_oriented_inverse.js +82 -82
  296. package/src/core/geom/3d/aabb/compute_aabb_from_points.js +7 -7
  297. package/src/core/geom/3d/aabb/compute_triangle_group_aabb3.js +7 -7
  298. package/src/core/geom/3d/atlas/ATLAS_PORT_PLAN.md +486 -486
  299. package/src/core/geom/3d/atlas/BFF_PLAN.md +174 -174
  300. package/src/core/geom/3d/atlas/Chart.js +77 -77
  301. package/src/core/geom/3d/atlas/REVIEW_02.md +392 -392
  302. package/src/core/geom/3d/atlas/atlas_bench_lib.js +315 -315
  303. package/src/core/geom/3d/atlas/atlas_chart_type.js +16 -16
  304. package/src/core/geom/3d/atlas/atlas_compute_charts.js +188 -188
  305. package/src/core/geom/3d/atlas/atlas_extract_chart.js +107 -107
  306. package/src/core/geom/3d/atlas/atlas_generate.js +50 -50
  307. package/src/core/geom/3d/atlas/atlas_test_fixtures.js +266 -266
  308. package/src/core/geom/3d/atlas/atlas_write_chart_uvs.js +36 -36
  309. package/src/core/geom/3d/atlas/data/atlas_build_edge_dihedrals.js +62 -62
  310. package/src/core/geom/3d/atlas/data/atlas_build_edge_lengths.js +33 -33
  311. package/src/core/geom/3d/atlas/data/atlas_build_face_areas.js +50 -50
  312. package/src/core/geom/3d/atlas/io/atlas_mesh_weld_colocals.js +39 -39
  313. package/src/core/geom/3d/atlas/io/bt_loop_uv.js +35 -35
  314. package/src/core/geom/3d/atlas/pack/ChartPlacement.js +46 -46
  315. package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_bff.js +269 -269
  316. package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_lscm.js +209 -209
  317. package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_ortho.js +38 -38
  318. package/src/core/geom/3d/atlas/param/atlas_chart_stretch_metric.js +86 -86
  319. package/src/core/geom/3d/atlas/param/atlas_piecewise_resegment.js +183 -183
  320. package/src/core/geom/3d/atlas/param/fit_plane_basis.js +66 -66
  321. package/src/core/geom/3d/atlas/segment/RegionGraph.js +40 -40
  322. package/src/core/geom/3d/atlas/segment/atlas_build_region_graph.js +136 -136
  323. package/src/core/geom/3d/atlas/segment/atlas_chart_roundness_delta.js +30 -30
  324. package/src/core/geom/3d/atlas/segment/atlas_compute_planar_regions.js +77 -77
  325. package/src/core/geom/3d/atlas/segment/atlas_merge_charts.js +116 -116
  326. package/src/core/geom/3d/atlas/segment/atlas_segment_charts.js +271 -271
  327. package/src/core/geom/3d/atlas/segment/atlas_segment_charts_atomic.js +191 -191
  328. package/src/core/geom/3d/box/box3_projected_half_extent.js +35 -35
  329. package/src/core/geom/3d/capsule/capsule_intersects_aabb3_closed.js +67 -67
  330. package/src/core/geom/3d/capsule/capsule_intersects_aabb3_iterative.js +137 -137
  331. package/src/core/geom/3d/compute_circle_bounding_box.js +7 -7
  332. package/src/core/geom/3d/cone/computeConeBoundingBox.js +7 -7
  333. package/src/core/geom/3d/cone/computeConePlaneSide.js +7 -7
  334. package/src/core/geom/3d/cone/compute_bounding_cone_of_2_cones.js +7 -7
  335. package/src/core/geom/3d/cylinder/cylinder3_raycast.d.ts +38 -0
  336. package/src/core/geom/3d/cylinder/cylinder3_raycast.d.ts.map +1 -0
  337. package/src/core/geom/3d/cylinder/cylinder3_raycast.js +105 -0
  338. package/src/core/geom/3d/equirectangular/equirectangular_direction_to_uv.js +18 -18
  339. package/src/core/geom/3d/equirectangular/equirectangular_uv_to_direction.js +24 -24
  340. package/src/core/geom/3d/frustum/clipping_volume_matrix4_project.js +7 -7
  341. package/src/core/geom/3d/frustum/frustum3_computeNearestPointToPoint.js +7 -7
  342. package/src/core/geom/3d/frustum/frustum3_compute_closest_point.js +117 -117
  343. package/src/core/geom/3d/frustum/frustum_matrix4_project.js +7 -7
  344. package/src/core/geom/3d/frustum/hexahedron_from_aabb.js +7 -7
  345. package/src/core/geom/3d/frustum/read_frustum_corner.js +17 -17
  346. package/src/core/geom/3d/frustum/read_three_planes_to_array.js +7 -7
  347. package/src/core/geom/3d/frustum/slice_frustum_linear_to_points.js +7 -7
  348. package/src/core/geom/3d/gjk/GJK_REVIEW_NOTES.md +146 -146
  349. package/src/core/geom/3d/gjk/gjk.js +430 -430
  350. package/src/core/geom/3d/gjk/gjk_epa_penetration.js +520 -520
  351. package/src/core/geom/3d/gjk/minkowski_support.js +71 -71
  352. package/src/core/geom/3d/gjk/mpr.js +368 -368
  353. package/src/core/geom/3d/line/line3_closest_points_segment_segment.js +7 -7
  354. package/src/core/geom/3d/line/line3_compute_nearest_point_to_point.js +7 -7
  355. package/src/core/geom/3d/line/line3_compute_point_segment_point_distance_unfolded.js +64 -64
  356. package/src/core/geom/3d/line/line3_compute_segment_closest_point_to_aabb3_t.js +153 -153
  357. package/src/core/geom/3d/line/line3_compute_segment_nearest_point_to_aabb3_t.js +7 -7
  358. package/src/core/geom/3d/line/line3_compute_segment_nearest_point_to_point_t.js +7 -7
  359. package/src/core/geom/3d/line/line3_compute_segment_segment_closest_points.js +88 -88
  360. package/src/core/geom/3d/line/line3_segment_segment_closest_point_pair.js +71 -71
  361. package/src/core/geom/3d/line/segment3_point_distance_to_segments.js +25 -25
  362. package/src/core/geom/3d/mat4/allocate_m4.js +7 -7
  363. package/src/core/geom/3d/mat4/apply_mat4_transform_to_direction_v3_array.js +7 -7
  364. package/src/core/geom/3d/mat4/apply_mat4_transform_to_v3_array.js +7 -7
  365. package/src/core/geom/3d/mat4/compose_matrix4_array.js +7 -7
  366. package/src/core/geom/3d/mat4/decompose_matrix_4_array.js +7 -7
  367. package/src/core/geom/3d/mat4/eulerAnglesFromMatrix.js +7 -7
  368. package/src/core/geom/3d/mat4/m4_compose.js +22 -22
  369. package/src/core/geom/3d/mat4/m4_compute_normal_matrix3.js +7 -7
  370. package/src/core/geom/3d/mat4/m4_decompose.js +64 -64
  371. package/src/core/geom/3d/mat4/m4_decompose_array.js +157 -157
  372. package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale.js +32 -32
  373. package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale_scalar.js +67 -67
  374. package/src/core/geom/3d/mat4/m4_linear_matrix3.js +29 -29
  375. package/src/core/geom/3d/mat4/m4_look_at.js +96 -96
  376. package/src/core/geom/3d/mat4/m4_make_rotation_x.js +47 -47
  377. package/src/core/geom/3d/mat4/m4_make_rotation_y.js +47 -47
  378. package/src/core/geom/3d/mat4/m4_make_rotation_z.js +47 -47
  379. package/src/core/geom/3d/mat4/m4_normal_matrix3.js +39 -39
  380. package/src/core/geom/3d/mat4/m4_perspective.js +66 -66
  381. package/src/core/geom/3d/mat4/m4_transpose.js +48 -48
  382. package/src/core/geom/3d/morton/mortonEncode_LUT.js +7 -7
  383. package/src/core/geom/3d/morton/mortonEncode_magicbits.js +7 -7
  384. package/src/core/geom/3d/normal/hemioct/encode_unit3_hemioct.js +5 -5
  385. package/src/core/geom/3d/normal/hemioct/encode_unit_to_hemioct.js +28 -28
  386. package/src/core/geom/3d/normal/lambert_azimuth/decode_azimuth_to_unit.js +30 -30
  387. package/src/core/geom/3d/normal/lambert_azimuth/encode_unit_to_azimuth.js +19 -19
  388. package/src/core/geom/3d/normal/spherical/decode_spheremap_to_unit.js +38 -38
  389. package/src/core/geom/3d/normal/spherical/encode_unit_to_spheremap.js +30 -30
  390. package/src/core/geom/3d/plane/is_point_within_planes.js +7 -7
  391. package/src/core/geom/3d/plane/orient3d_fast_point.js +47 -47
  392. package/src/core/geom/3d/plane/plane3_compute_convex_3_plane_intersection.js +7 -7
  393. package/src/core/geom/3d/plane/plane3_compute_plane_intersection.js +7 -7
  394. package/src/core/geom/3d/plane/plane3_intersect_plane.js +7 -7
  395. package/src/core/geom/3d/plane/plane3_three_compute_convex_3_plane_intersection.js +7 -7
  396. package/src/core/geom/3d/point/point3_raycast.d.ts +33 -0
  397. package/src/core/geom/3d/point/point3_raycast.d.ts.map +1 -0
  398. package/src/core/geom/3d/point/point3_raycast.js +47 -0
  399. package/src/core/geom/3d/polygon/polygon3_compute_normal.js +60 -60
  400. package/src/core/geom/3d/polygon/polygon3_triangulate.js +94 -94
  401. package/src/core/geom/3d/polyhedron/convex_polyhedron3_raycast.d.ts +40 -0
  402. package/src/core/geom/3d/polyhedron/convex_polyhedron3_raycast.d.ts.map +1 -0
  403. package/src/core/geom/3d/polyhedron/convex_polyhedron3_raycast.js +94 -0
  404. package/src/core/geom/3d/quadric/QUADRIC3_SIZE.js +14 -14
  405. package/src/core/geom/3d/quadric/Quadric3.js +282 -282
  406. package/src/core/geom/3d/quadric/quadric3_add.js +33 -33
  407. package/src/core/geom/3d/quadric/quadric3_clear.js +25 -25
  408. package/src/core/geom/3d/quadric/quadric3_copy.js +27 -27
  409. package/src/core/geom/3d/quadric/quadric3_distance.js +36 -36
  410. package/src/core/geom/3d/quadric/quadric3_evaluate.js +25 -25
  411. package/src/core/geom/3d/quadric/quadric3_optimize.js +45 -45
  412. package/src/core/geom/3d/quadric/quadric3_scale.js +32 -32
  413. package/src/core/geom/3d/quadric/quadric3_set_from_plane_through_point.js +30 -30
  414. package/src/core/geom/3d/quadric/quadric3_set_from_vector4.js +35 -35
  415. package/src/core/geom/3d/quadric/quadric3_sub.js +36 -36
  416. package/src/core/geom/3d/quadric/quadric3_to_tensor_m3.js +28 -28
  417. package/src/core/geom/3d/quadric/quadric3_to_tensor_m3_inverse.js +56 -56
  418. package/src/core/geom/3d/quadric/quadric3_to_vector3.js +19 -19
  419. package/src/core/geom/3d/quaternion/quat3_createFromAxisAngle.js +7 -7
  420. package/src/core/geom/3d/quaternion/quat3_integrate.js +62 -62
  421. package/src/core/geom/3d/quaternion/quat3_multiply.js +31 -31
  422. package/src/core/geom/3d/quaternion/quat3_nlerp.js +72 -72
  423. package/src/core/geom/3d/quaternion/quat3_to_matrix3.js +69 -69
  424. package/src/core/geom/3d/quaternion/quat_decode_from_uint32.js +7 -7
  425. package/src/core/geom/3d/quaternion/quat_encode_to_uint32.js +7 -7
  426. package/src/core/geom/3d/ray/ray3_array_compose.js +7 -7
  427. package/src/core/geom/3d/ray/ray3_compute_nearest_point_to_point.js +7 -7
  428. package/src/core/geom/3d/ray/ray3_distance_to_point.js +7 -7
  429. package/src/core/geom/3d/ray/ray3_shift_origin_along_direction.js +7 -7
  430. package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts +17 -0
  431. package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts.map +1 -1
  432. package/src/core/geom/3d/shape/ConvexHullShape3D.js +43 -0
  433. package/src/core/geom/3d/shape/CylinderShape3D.d.ts +1 -0
  434. package/src/core/geom/3d/shape/CylinderShape3D.d.ts.map +1 -1
  435. package/src/core/geom/3d/shape/CylinderShape3D.js +21 -0
  436. package/src/core/geom/3d/shape/PointShape3D.d.ts +7 -0
  437. package/src/core/geom/3d/shape/PointShape3D.d.ts.map +1 -1
  438. package/src/core/geom/3d/shape/PointShape3D.js +88 -63
  439. package/src/core/geom/3d/shape/PosedShape3D.d.ts +6 -0
  440. package/src/core/geom/3d/shape/PosedShape3D.d.ts.map +1 -1
  441. package/src/core/geom/3d/shape/PosedShape3D.js +27 -0
  442. package/src/core/geom/3d/shape/TransformedShape3D.d.ts +10 -0
  443. package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
  444. package/src/core/geom/3d/shape/TransformedShape3D.js +13 -0
  445. package/src/core/geom/3d/shape/Triangle3D.d.ts +1 -0
  446. package/src/core/geom/3d/shape/Triangle3D.d.ts.map +1 -1
  447. package/src/core/geom/3d/shape/Triangle3D.js +26 -0
  448. package/src/core/geom/3d/shape/UnionShape3D.d.ts +6 -0
  449. package/src/core/geom/3d/shape/UnionShape3D.d.ts.map +1 -1
  450. package/src/core/geom/3d/shape/UnionShape3D.js +7 -0
  451. package/src/core/geom/3d/shape/UnitCubeShape3D.js +45 -45
  452. package/src/core/geom/3d/shape/UnitSphereShape3D.js +44 -44
  453. package/src/core/geom/3d/shape/shape3_mesh_from_geometry.js +64 -64
  454. package/src/core/geom/3d/shape/shape_mesh_from_geometry.js +7 -7
  455. package/src/core/geom/3d/shape/util/compute_signed_distance_gradient_by_sampling.js +51 -51
  456. package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.js +7 -7
  457. package/src/core/geom/3d/sphere/compute_bounding_sphere_of_2_spheres.js +7 -7
  458. package/src/core/geom/3d/sphere/harmonics/sh3_convolve_with_zh.js +53 -53
  459. package/src/core/geom/3d/sphere/harmonics/sh3_ggx_zh.js +30 -30
  460. package/src/core/geom/3d/sphere/harmonics/sh3_rotate_bl.js +7 -7
  461. package/src/core/geom/3d/sphere/harmonics/sh_compute_K.js +7 -7
  462. package/src/core/geom/3d/sphere/sphere_array_intersects_point.js +7 -7
  463. package/src/core/geom/3d/sphere/sphere_array_intersects_ray.js +7 -7
  464. package/src/core/geom/3d/sphere/sphere_intersects_point.js +7 -7
  465. package/src/core/geom/3d/sphere/sphere_matrix4_transform.js +5 -5
  466. package/src/core/geom/3d/sphere/sphere_projected_sphere_radius_sqr.js +7 -7
  467. package/src/core/geom/3d/sphere/sphere_radius_sqr_from_v3_array_transformed.js +7 -7
  468. package/src/core/geom/3d/sphere/spherical_from_cartesian.js +7 -7
  469. package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.js +174 -174
  470. package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.js +7 -7
  471. package/src/core/geom/3d/tetrahedra/compute_tetrahedron_volume.js +7 -7
  472. package/src/core/geom/3d/tetrahedra/delaunay/fill_in_a_cavity.js +7 -7
  473. package/src/core/geom/3d/tetrahedra/graphics/build_tetrahedral_mesh_geometry.js +39 -39
  474. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_build_vertex_to_tets_map.js +48 -48
  475. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.js +173 -173
  476. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_compute_tet_quality.js +22 -22
  477. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.js +146 -146
  478. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.js +232 -232
  479. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.js +255 -255
  480. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.js +387 -387
  481. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.js +140 -140
  482. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_tet_get_neighbours.js +7 -7
  483. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.js +97 -97
  484. package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.js +66 -66
  485. package/src/core/geom/3d/tetrahedra/triangle/triangle_decode_depth.js +59 -59
  486. package/src/core/geom/3d/tetrahedra/triangle/triangle_rasterized_depth_sample_index.js +54 -54
  487. package/src/core/geom/3d/tetrahedra/validate_neighbour.js +70 -70
  488. package/src/core/geom/3d/topology/struct/binary/BinaryDataBlock.js +314 -314
  489. package/src/core/geom/3d/topology/struct/binary/BinaryDataLayer.js +364 -364
  490. package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.js +567 -567
  491. package/src/core/geom/3d/topology/struct/binary/BinaryTopology.js +1085 -1085
  492. package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.js +73 -73
  493. package/src/core/geom/3d/topology/struct/binary/io/bt_loop_kill.js +35 -35
  494. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_append.js +119 -119
  495. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.js +84 -84
  496. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.js +172 -172
  497. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_face_normals.js +56 -56
  498. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_vertex_quadratics.js +7 -7
  499. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_vertex_quadrics.js +227 -227
  500. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_decouple.js +161 -161
  501. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_island_erode.js +490 -490
  502. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.js +120 -120
  503. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_from_indexed_geometry.js +120 -120
  504. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_collapse.js +52 -52
  505. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_create.js +115 -115
  506. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_flip.js +142 -142
  507. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_get_or_create.js +21 -21
  508. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.js +92 -92
  509. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_split.js +179 -179
  510. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_swap_vertex_slots.js +28 -28
  511. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_kill_only_edge.js +8 -8
  512. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_fuse_duplicate_edges.js +83 -83
  513. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.js +89 -89
  514. package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_kill.js +25 -25
  515. package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_poke.js +127 -127
  516. package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_triangulate.js +268 -268
  517. package/src/core/geom/3d/topology/struct/binary/io/face/bt_kill_only_face.js +8 -8
  518. package/src/core/geom/3d/topology/struct/binary/io/face/bt_mesh_kill_degenerate_faces.js +72 -72
  519. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_kill_only_vert.js +7 -7
  520. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_merge_verts_by_distance.js +7 -7
  521. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_mesh_relative_merge_distance.js +48 -48
  522. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_mesh_split_pinched_vertices.js +256 -256
  523. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_mesh_vertex_merge_distance.js +77 -77
  524. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vert_fuse_duplicate_edges.js +7 -7
  525. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vert_kill.js +7 -7
  526. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_fuse_duplicate_edges.js +148 -148
  527. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_kill_only.js +7 -7
  528. package/src/core/geom/3d/topology/struct/binary/query/bt_collect_boundary_segments.js +29 -29
  529. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_collapse_breaks_link_condition.js +107 -107
  530. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_flip_is_legal.js +41 -41
  531. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_flip_would_fold.js +120 -120
  532. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.js +42 -42
  533. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_is_boundary.js +20 -20
  534. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_other_face.d.ts +32 -0
  535. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_other_face.d.ts.map +1 -0
  536. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_other_face.js +59 -0
  537. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_read_diamond.js +96 -96
  538. package/src/core/geom/3d/topology/struct/binary/query/bt_face_compute_newell_normal.js +72 -72
  539. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_attached_faces.js +7 -7
  540. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_edge_adjacent_faces.js +39 -39
  541. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_edge_adjacent_faces_weighted.js +93 -93
  542. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_neighbour_faces.js +7 -7
  543. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_shared_loop.js +48 -48
  544. package/src/core/geom/3d/topology/struct/binary/query/bt_face_island_flood_fill.js +45 -45
  545. package/src/core/geom/3d/topology/struct/binary/query/bt_face_read_triangle.js +66 -66
  546. package/src/core/geom/3d/topology/struct/binary/query/bt_face_third_vertex.d.ts +26 -0
  547. package/src/core/geom/3d/topology/struct/binary/query/bt_face_third_vertex.d.ts.map +1 -0
  548. package/src/core/geom/3d/topology/struct/binary/query/bt_face_third_vertex.js +55 -0
  549. package/src/core/geom/3d/topology/struct/binary/query/bt_faces_shared_loop.js +7 -7
  550. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_assert_valid.js +44 -44
  551. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_build_boundary_euclidean_distance_field.js +32 -32
  552. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_compute_face_islands.js +53 -53
  553. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path.js +703 -703
  554. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.js +181 -181
  555. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_segment_penetrates_surface.js +133 -133
  556. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_surface_ray_parity.js +82 -82
  557. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_validate.js +599 -599
  558. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.js +108 -108
  559. package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.js +7 -7
  560. package/src/core/geom/3d/triangle/computeTriangleClosestPointToPointBarycentric.js +7 -7
  561. package/src/core/geom/3d/triangle/computeTriangleRayIntersection.js +7 -7
  562. package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentric.js +7 -7
  563. package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentricEdge.js +7 -7
  564. package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentricGeometry.js +7 -7
  565. package/src/core/geom/3d/triangle/compute_triangle_area_3d.js +7 -7
  566. package/src/core/geom/3d/triangle/compute_triangle_normal.js +7 -7
  567. package/src/core/geom/3d/triangle/rayTriangleIntersection.js +7 -7
  568. package/src/core/geom/3d/triangle/tri3_closest_point.js +65 -65
  569. package/src/core/geom/3d/triangle/tri3_closest_point_barycentric.js +171 -171
  570. package/src/core/geom/3d/triangle/tri3_flatten_isometric.js +79 -79
  571. package/src/core/geom/3d/triangle/tri3_ray_intersection.js +160 -160
  572. package/src/core/geom/3d/triangle/tri3_ray_intersection_barycentric.js +96 -96
  573. package/src/core/geom/3d/triangle/tri3_raycast.d.ts +42 -0
  574. package/src/core/geom/3d/triangle/tri3_raycast.d.ts.map +1 -0
  575. package/src/core/geom/3d/triangle/tri3_raycast.js +94 -0
  576. package/src/core/geom/3d/triangle/triangle3_incenter.js +7 -7
  577. package/src/core/geom/3d/triangle/triangle_compute_plane_side.js +7 -7
  578. package/src/core/geom/3d/triangle/triangle_compute_signed_volume.js +7 -7
  579. package/src/core/geom/3d/triangle/triangle_intersects_clipping_volume.js +7 -7
  580. package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.js +7 -7
  581. package/src/core/geom/3d/triangle/v3_compute_triangle_normal.js +7 -7
  582. package/src/core/geom/3d/util/make_justified_point_grid.js +7 -7
  583. package/src/core/geom/GEOMETRY_REVIEW_002_API_ISSUES.md +381 -381
  584. package/src/core/geom/GEOMETRY_REVIEW_002_NAMING.md +684 -684
  585. package/src/core/geom/MANIFOLD_COMPARISON_2026_08_01.md +554 -554
  586. package/src/core/geom/mat3/m3_cm_from_translation.js +7 -7
  587. package/src/core/geom/mat3/m3_cm_invert.js +7 -7
  588. package/src/core/geom/mat3/m3_make_rotation.js +5 -5
  589. package/src/core/geom/mat3/m3_make_rotation_TBN.js +31 -31
  590. package/src/core/geom/mat3/m3_multiply_vec3.js +7 -7
  591. package/src/core/geom/packing/computeBoundingSphereOfSpheres.js +7 -7
  592. package/src/core/geom/packing/max-rect/cost/costByBestShortSide.js +7 -7
  593. package/src/core/geom/packing/max-rect/cost/costByRemainingArea.js +7 -7
  594. package/src/core/geom/packing/max-rect/cutArea.js +7 -7
  595. package/src/core/geom/packing/max-rect/findBestContainer.js +7 -7
  596. package/src/core/geom/packing/max-rect/packMaxRectangles.js +7 -7
  597. package/src/core/geom/packing/max-rect/packOneBox.js +7 -7
  598. package/src/core/geom/packing/max-rect/removeRedundantBoxes.js +7 -7
  599. package/src/core/geom/packing/max-rect/removeRedundantBoxesArray.js +7 -7
  600. package/src/core/geom/random/randomPointInBox.js +7 -7
  601. package/src/core/geom/random/randomPointInCircle.js +7 -7
  602. package/src/core/geom/random/randomPointInPoint.js +7 -7
  603. package/src/core/geom/random/randomPointInSphere.js +7 -7
  604. package/src/core/geom/random/randomPointOnBox.js +7 -7
  605. package/src/core/geom/random/randomPointOnSphere.js +7 -7
  606. package/src/core/geom/random/random_orthonormal_basis.js +31 -31
  607. package/src/core/geom/vec/vector_axpy.js +15 -15
  608. package/src/core/geom/vec/vector_axpy_offset.js +20 -20
  609. package/src/core/geom/vec/vector_copy.js +7 -7
  610. package/src/core/geom/vec/vector_dot_offset.js +25 -25
  611. package/src/core/geom/vec/vector_scale_array.js +7 -7
  612. package/src/core/geom/vec2/v2_rotate.js +21 -21
  613. package/src/core/geom/vec2/v2_rotate_cos_sin.js +21 -21
  614. package/src/core/geom/vec3/v3_angle_atan2_between.js +7 -7
  615. package/src/core/geom/vec3/v3_angle_between.js +7 -7
  616. package/src/core/geom/vec3/v3_angle_cos_between.js +7 -7
  617. package/src/core/geom/vec3/v3_array_add_in_place.js +7 -7
  618. package/src/core/geom/vec3/v3_array_centroid.js +7 -7
  619. package/src/core/geom/vec3/v3_array_copy.js +7 -7
  620. package/src/core/geom/vec3/v3_array_displace_in_direction.js +7 -7
  621. package/src/core/geom/vec3/v3_array_equals.js +7 -7
  622. package/src/core/geom/vec3/v3_array_immediate_add.js +7 -7
  623. package/src/core/geom/vec3/v3_array_matrix4_rotate.js +7 -7
  624. package/src/core/geom/vec3/v3_array_normalize.js +7 -7
  625. package/src/core/geom/vec3/v3_array_scale.js +7 -7
  626. package/src/core/geom/vec3/v3_compute_interior_angle.js +7 -7
  627. package/src/core/geom/vec3/v3_cotangent.js +33 -33
  628. package/src/core/geom/vec3/v3_dot_array_array.js +7 -7
  629. package/src/core/geom/vec3/v3_matrix3_multiply.js +30 -30
  630. package/src/core/geom/vec3/v3_matrix3_rotate.js +49 -49
  631. package/src/core/geom/vec3/v3_matrix4_rotate.js +7 -7
  632. package/src/core/geom/vec3/v3_multiply.js +23 -23
  633. package/src/core/geom/vec3/v3_multiply_scalar.js +7 -7
  634. package/src/core/geom/vec3/v3_orthonormal_matrix_from_normal.js +49 -49
  635. package/src/core/geom/vec3/v3_quat3_apply.js +7 -7
  636. package/src/core/geom/vec3/v3_quat3_apply_inverse.js +7 -7
  637. package/src/core/geom/vec3/v3_quaternion_apply.js +39 -39
  638. package/src/core/geom/vec3/v3_quaternion_apply_inverse.js +41 -41
  639. package/src/core/geom/vec3/v3_reflect.js +24 -24
  640. package/src/core/geom/vec3/v3_scale_array.js +18 -18
  641. package/src/core/geom/vec3/v3_triple_cross.js +45 -45
  642. package/src/core/geom/vec3/v3_triple_cross_product.js +7 -7
  643. package/src/core/geom/vec3/v3_uniform_sample_cone.js +21 -21
  644. package/src/core/geom/vec4/v4_multiply_mat4.js +7 -7
  645. package/src/core/graph/csr/csr_graph_build_distance_field.js +112 -112
  646. package/src/core/graph/csr/csr_graph_find_edge.js +25 -25
  647. package/src/core/graph/csr/csr_graph_find_shortest_path.js +105 -105
  648. package/src/core/graph/csr/csr_graph_from_undirected_edge_list.js +94 -94
  649. package/src/core/graph/graph_k_means_cluster.js +250 -250
  650. package/src/core/graph/layout/CircleLayout.js +1 -1
  651. package/src/core/graph/layout/box/BoxLayouter.js +1 -1
  652. package/src/core/graph/layout/graph_peel_topological_layer.js +45 -45
  653. package/src/core/graph/metis/BinaryTopologyFaceGraph.js +49 -49
  654. package/src/core/graph/metis/bt_mesh_build_face_graph.js +111 -111
  655. package/src/core/graph/metis/cluster_mesh_metis.js +137 -137
  656. package/src/core/graph/metis/native/bisection/bisect_graph.js +100 -100
  657. package/src/core/graph/metis/native/bisection/compute_2way_params.js +86 -86
  658. package/src/core/graph/metis/native/bisection/fm_2way.js +297 -297
  659. package/src/core/graph/metis/native/bisection/grow_bisection.js +137 -137
  660. package/src/core/graph/metis/native/bisection/split_graph_two_way.js +119 -119
  661. package/src/core/graph/metis/native/coarsen/coarsen_graph.js +94 -94
  662. package/src/core/graph/metis/native/coarsen/create_coarse_graph.js +158 -158
  663. package/src/core/graph/metis/native/coarsen/match_shem.js +175 -175
  664. package/src/core/graph/metis/native/initial/initial_kway_bfs.js +122 -122
  665. package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.js +170 -170
  666. package/src/core/graph/metis/native/metis_partition_kway.js +126 -126
  667. package/src/core/graph/metis/native/refine/RefinementScratch.js +53 -53
  668. package/src/core/graph/metis/native/refine/fm_kway.js +487 -487
  669. package/src/core/graph/metis/native/refine/project_kway.js +43 -43
  670. package/src/core/graph/metis/native/refine/refine_kway.js +43 -43
  671. package/src/core/lang/reactive/pegjs/parser.js +3458 -3458
  672. package/src/core/math/complex/complex_horner_eval.js +31 -31
  673. package/src/core/math/computeWholeDivisorLow.js +33 -33
  674. package/src/core/math/f32_next_down.js +24 -24
  675. package/src/core/math/f32_next_up.js +27 -27
  676. package/src/core/math/hash/hash_mix2.js +22 -22
  677. package/src/core/math/hash/hash_mix3.js +19 -19
  678. package/src/core/math/linalg/cg/cg_solve.js +106 -106
  679. package/src/core/math/linalg/cg/cg_solve_normal_equations.js +59 -59
  680. package/src/core/math/linalg/cubic_residual_times_derivative_accumulate.js +43 -43
  681. package/src/core/math/linalg/eigen/matrix_householder_in_place.js +122 -122
  682. package/src/core/math/linalg/eigen/matrix_qr_in_place.js +190 -190
  683. package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.js +117 -117
  684. package/src/core/math/linalg/givens/givens_apply_rows.js +28 -28
  685. package/src/core/math/linalg/givens/givens_apply_rows_offset.js +30 -30
  686. package/src/core/math/linalg/givens/givens_rotation_coefficients.js +39 -39
  687. package/src/core/math/linalg/lu_factor_linear_system.js +108 -108
  688. package/src/core/math/linalg/lu_solve_linear_system.js +53 -53
  689. package/src/core/math/linalg/polynomial_add_into.js +29 -29
  690. package/src/core/math/linalg/polynomial_complex_roots_aberth_ehrlich.js +159 -159
  691. package/src/core/math/linalg/polynomial_cubic_derivative_eval.js +16 -16
  692. package/src/core/math/linalg/polynomial_cubic_horner_eval.js +19 -19
  693. package/src/core/math/linalg/polynomial_cubic_second_derivative_eval.js +14 -14
  694. package/src/core/math/linalg/polynomial_multiply.js +41 -41
  695. package/src/core/math/linalg/polynomial_real_roots_in_interval.js +211 -211
  696. package/src/core/math/linalg/polynomial_root_bound_cauchy.js +30 -30
  697. package/src/core/math/linalg/polynomial_scale_into.js +17 -17
  698. package/src/core/math/linalg/polynomial_sub_into.js +29 -29
  699. package/src/core/math/linalg/solve_linear_system_GEPP_2x2.js +96 -96
  700. package/src/core/math/linalg/sor_optimal_omega.js +42 -42
  701. package/src/core/math/linalg/sparse/SparseMatrixCSR.js +88 -88
  702. package/src/core/math/linalg/sparse/spm_matvec.js +22 -22
  703. package/src/core/math/linalg/sparse/spm_matvec_transpose.js +29 -29
  704. package/src/core/math/lookup/LUT_HEATMAP.js +30 -30
  705. package/src/core/math/lookup/ParameterLookupTable.js +495 -495
  706. package/src/core/math/lookup/ParameterLookupTableFlags.js +6 -6
  707. package/src/core/math/noise/curl_noise_3d.js +18 -18
  708. package/src/core/math/physics/brdf/cone_cosine_from_roughness.js +28 -28
  709. package/src/core/math/physics/brdf/reflection_sample_weight.js +48 -48
  710. package/src/core/math/physics/kinematics/computeInterceptPoint.js +79 -79
  711. package/src/core/math/random/randomSeed.js +16 -16
  712. package/src/core/math/random/random_pick_weighted_index.js +26 -26
  713. package/src/core/math/round_half_away_from_zero.js +13 -13
  714. package/src/core/math/spline/spline3_hermite_apply_transform.js +107 -107
  715. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_1d.js +125 -125
  716. package/src/core/math/spline/spline3_hermite_intersects_spline3_hermite.js +50 -50
  717. package/src/core/math/spline/spline3_hermite_reverse.js +49 -49
  718. package/src/core/math/spline/spline3_hermite_to_monomial.js +37 -37
  719. package/src/core/math/statistics/hammersley_sequence.js +53 -53
  720. package/src/core/model/reactive/model/util/createRandomReactiveExpression.js +185 -185
  721. package/src/core/path/convertPathToURL.js +107 -107
  722. package/src/core/process/delay.js +16 -16
  723. package/src/core/science/units/MEASUREMENT_UNITS_SCIENTIFIC.js +87 -87
  724. package/src/core/science/units/MEASUREMENT_UNITS_SI.js +17 -17
  725. package/src/core/science/units/NamedUnit.js +48 -48
  726. package/src/core/science/units/UNIT_DIMENSION_MAPPING.js +29 -29
  727. package/src/core/science/units/UnitDimension.js +28 -28
  728. package/src/core/science/units/format_quantity.js +74 -74
  729. package/src/core/science/units/magnitude_prefix.js +127 -127
  730. package/src/core/science/units/si/AMPERE.js +13 -13
  731. package/src/core/science/units/si/CANDELA.js +13 -13
  732. package/src/core/science/units/si/DIMENSIONLESS.js +14 -14
  733. package/src/core/science/units/si/KELVIN.js +13 -13
  734. package/src/core/science/units/si/KILOGRAM.js +13 -13
  735. package/src/core/science/units/si/METER.js +13 -13
  736. package/src/core/science/units/si/MOLE.js +13 -13
  737. package/src/core/science/units/si/SECOND.js +13 -13
  738. package/src/core/science/units/si/derived/BECQUEREL.js +16 -16
  739. package/src/core/science/units/si/derived/COULOMB.js +13 -13
  740. package/src/core/science/units/si/derived/FARAD.js +13 -13
  741. package/src/core/science/units/si/derived/GRAY.js +16 -16
  742. package/src/core/science/units/si/derived/HENRY.js +13 -13
  743. package/src/core/science/units/si/derived/HERTZ.js +16 -16
  744. package/src/core/science/units/si/derived/JOULE.js +13 -13
  745. package/src/core/science/units/si/derived/KATAL.js +13 -13
  746. package/src/core/science/units/si/derived/LUMEN.js +14 -14
  747. package/src/core/science/units/si/derived/LUX.js +13 -13
  748. package/src/core/science/units/si/derived/NEWTON.js +13 -13
  749. package/src/core/science/units/si/derived/OHM.js +13 -13
  750. package/src/core/science/units/si/derived/PASCAL.js +13 -13
  751. package/src/core/science/units/si/derived/SIEMENS.js +13 -13
  752. package/src/core/science/units/si/derived/SIEVERT.js +16 -16
  753. package/src/core/science/units/si/derived/TESLA.js +13 -13
  754. package/src/core/science/units/si/derived/VOLT.js +13 -13
  755. package/src/core/science/units/si/derived/WATT.js +13 -13
  756. package/src/core/science/units/si/derived/WEBER.js +13 -13
  757. package/src/core/science/units/unit_matrix_to_string.js +403 -403
  758. package/src/engine/Engine.js +726 -726
  759. package/src/engine/EngineHarness.js +590 -590
  760. package/src/engine/REVIEW_2026_07_03.md +211 -211
  761. package/src/engine/animation/AnimatedActions.js +81 -81
  762. package/src/engine/animation/AnimationUtils.js +252 -252
  763. package/src/engine/animation/async/TimeSeries.js +300 -300
  764. package/src/engine/animation/curve/animation_curve_binary_codec.js +60 -60
  765. package/src/engine/animation/curve/draw/canvas_point_to_curve.js +22 -22
  766. package/src/engine/animation/curve/draw/curve_point_to_canvas.js +38 -38
  767. package/src/engine/animation/curve/draw/position_canvas_to_curve.js +22 -22
  768. package/src/engine/animation/curve/draw/position_curve_to_canvas.js +22 -22
  769. package/src/engine/asset/GameAssetType.d.ts +0 -1
  770. package/src/engine/asset/GameAssetType.js +0 -1
  771. package/src/engine/asset/load_model_scene_bundle.js +27 -27
  772. package/src/engine/asset/loaders/font/FontAsset.js +21 -21
  773. package/src/engine/asset/loaders/font/FontAssetLoader.js +20 -20
  774. package/src/engine/asset/loaders/gltf_test_fixtures.js +358 -358
  775. package/src/engine/asset/loaders/image/ImageBitmapAssetLoader.js +52 -52
  776. package/src/engine/asset/loaders/image/ImageRGBADataLoader.js +94 -94
  777. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterAverage.js +59 -59
  778. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterNone.js +55 -55
  779. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterPaeth.js +74 -74
  780. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterSub.js +34 -34
  781. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterUp.js +46 -46
  782. package/src/engine/control/first-person/DESIGN.md +640 -640
  783. package/src/engine/control/first-person/DESIGN_EXTENSIONS.md +563 -563
  784. package/src/engine/control/first-person/FirstPersonMotionPhase.js +134 -134
  785. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +2045 -2045
  786. package/src/engine/control/first-person/mastery/DecisionPoint.js +30 -30
  787. package/src/engine/control/first-person/math/Spring.js +71 -71
  788. package/src/engine/control/first-person/math/computeJumpFromApex.js +23 -23
  789. package/src/engine/control/first-person/math/computeLRCBreathRate.js +41 -41
  790. package/src/engine/control/first-person/math/computeMassRatios.js +44 -44
  791. package/src/engine/control/first-person/math/criticallyDampedSpring.js +34 -34
  792. package/src/engine/control/first-person/math/dampedSpringStep.js +72 -72
  793. package/src/engine/control/first-person/math/jumpDynamics.js +108 -108
  794. package/src/engine/control/first-person/math/stepTowards.js +20 -20
  795. package/src/engine/control/first-person/pose/FirstPersonPose.js +137 -137
  796. package/src/engine/control/first-person/pose/FirstPersonPosture.js +27 -27
  797. package/src/engine/control/first-person/test/buildTestPlayer.js +36 -36
  798. package/src/engine/ecs/ASYNC_SYSTEMS_PROPOSAL.md +531 -531
  799. package/src/engine/ecs/EntityManager.d.ts +7 -3
  800. package/src/engine/ecs/EntityManager.d.ts.map +1 -1
  801. package/src/engine/ecs/EntityManager.js +10 -5
  802. package/src/engine/ecs/HIERARCHY_REVIEW.md +717 -717
  803. package/src/engine/ecs/async/SystemWorkerHost.js +329 -329
  804. package/src/engine/ecs/async/SystemWorkerLoopback.js +143 -143
  805. package/src/engine/ecs/async/WORKER_SYSTEM_PLAN.md +246 -246
  806. package/src/engine/ecs/async/WorkerSystem.js +702 -702
  807. package/src/engine/ecs/async/WorkerSystemProtocol.js +150 -150
  808. package/src/engine/ecs/fow/FogOfWar.js +707 -707
  809. package/src/engine/ecs/fow/FogOfWarEdgeMode.js +40 -40
  810. package/src/engine/ecs/fow/fog_of_war_mask_world_bounds.js +24 -24
  811. package/src/engine/ecs/fow/fog_of_war_uv_transform.js +30 -30
  812. package/src/engine/ecs/gui/hud/testHudEdgeStick.js +132 -134
  813. package/src/engine/ecs/hierarchy/EntityChildIndex.js +140 -140
  814. package/src/engine/ecs/ik/IKProblem.js +42 -42
  815. package/src/engine/ecs/ik/InverseKinematicsSystem.js +193 -193
  816. package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.js +134 -134
  817. package/src/engine/ecs/ik/TwoBoneInverseKinematicsSolver.js +97 -97
  818. package/src/engine/ecs/ik/ik_bone_chain.js +85 -85
  819. package/src/engine/ecs/ik/ik_probe_terrain_contact.js +119 -119
  820. package/src/engine/ecs/parent/EntityNode.d.ts +1 -1
  821. package/src/engine/ecs/parent/EntityNode.js +2 -2
  822. package/src/engine/ecs/parent/ParentEntitySystem.js +255 -255
  823. package/src/engine/ecs/speaker/VoiceSystem.d.ts +2 -2
  824. package/src/engine/ecs/speaker/VoiceSystem.d.ts.map +1 -1
  825. package/src/engine/ecs/speaker/VoiceSystem.js +13 -7
  826. package/src/engine/ecs/storage/binary/SERIALIZATION_COVERAGE.md +269 -269
  827. package/src/engine/ecs/storage/binary/object-v2/BinaryObjectDeSerializer.js +315 -315
  828. package/src/engine/ecs/storage/binary/object-v2/BinaryObjectSerializer.js +331 -331
  829. package/src/engine/ecs/storage/binary/object-v2/DESIGN.md +199 -199
  830. package/src/engine/ecs/storage/binary/object-v2/ObjectBinaryFormat.js +57 -57
  831. package/src/engine/ecs/storage/binary/object-v2/ObjectSerializationAdapter.js +56 -56
  832. package/src/engine/ecs/storage/binary/object-v2/README.md +110 -110
  833. package/src/engine/ecs/storage/binary/object-v2/objectStringCodec.js +48 -48
  834. package/src/engine/ecs/storage/binary/object-v2/serializerTestHarness.js +44 -44
  835. package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
  836. package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +5 -1
  837. package/src/engine/ecs/terrain/TerrainClouds.js +97 -97
  838. package/src/engine/ecs/terrain/ecs/StubTerrainBuildWorker.js +65 -65
  839. package/src/engine/ecs/terrain/ecs/Terrain.d.ts +4 -0
  840. package/src/engine/ecs/terrain/ecs/Terrain.d.ts.map +1 -1
  841. package/src/engine/ecs/terrain/ecs/Terrain.js +790 -790
  842. package/src/engine/ecs/terrain/ecs/TerrainSystem.js +209 -209
  843. package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.js +316 -316
  844. package/src/engine/ecs/terrain/ecs/layers/TerrainLayers.js +416 -416
  845. package/src/engine/ecs/terrain/ecs/splat/SplatMapping.js +525 -525
  846. package/src/engine/ecs/terrain/overlay/TerrainOverlay.js +302 -302
  847. package/src/engine/ecs/terrain/tiles/TerrainTile.js +561 -561
  848. package/src/engine/ecs/terrain/tiles/TerrainTileManager.js +896 -896
  849. package/src/engine/ecs/terrain/tiles/tile_geometry_to_meshlets.js +36 -36
  850. package/src/engine/ecs/terrain/util/loadVisibleTerrainTiles.js +129 -129
  851. package/src/engine/ecs/transform/Transform64.js +814 -814
  852. package/src/engine/ecs/transform/t64_copy_from_transform.js +35 -35
  853. package/src/engine/ecs/transform/t64_equals_transform.js +55 -55
  854. package/src/engine/ecs/transform/t64_look_rotation.js +36 -36
  855. package/src/engine/ecs/transform/t64_transform_direction.js +25 -25
  856. package/src/engine/ecs/transform/transform_copy_from_t64.js +28 -28
  857. package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.js +345 -345
  858. package/src/engine/ecs/transform-attachment/transform_attachment_find_descendant_by_name.js +65 -65
  859. package/src/engine/ecs/transform-attachment/transform_attachment_parent_of.js +24 -24
  860. package/src/engine/ecs/util/hideEntityGracefully.js +208 -208
  861. package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +446 -446
  862. package/src/engine/graphics/FULL_SCREEN_QUAD_VERTEX_SHADER.js +14 -14
  863. package/src/engine/graphics/FrameThrottle.js +2 -2
  864. package/src/engine/graphics/ecs/animation/animator/graph/AnimationState.js +207 -207
  865. package/src/engine/graphics/ecs/animation/animator/graph/AnimationTransition.js +151 -151
  866. package/src/engine/graphics/ecs/animation/animator/graph/definition/serialization/AnimationGraphDefinitionAssetLoader.js +22 -22
  867. package/src/engine/graphics/ecs/camera/Camera.js +165 -165
  868. package/src/engine/graphics/ecs/camera/camera_active_frustum.js +25 -25
  869. package/src/engine/graphics/ecs/camera/camera_find_active.js +28 -28
  870. package/src/engine/graphics/ecs/camera/camera_traverse_active.js +18 -18
  871. package/src/engine/graphics/ecs/camera/pp/PerfectPanner.js +170 -170
  872. package/src/engine/graphics/ecs/camera/serialization/CameraSerializationAdapter.js +68 -68
  873. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.js +296 -296
  874. package/src/engine/graphics/ecs/decal/v2/Decal.js +220 -220
  875. package/src/engine/graphics/ecs/decal/v2/DecalSerializationAdapter.js +56 -56
  876. package/src/engine/graphics/ecs/decal/v2/DecalSerializationUpgrader_0_1.js +38 -38
  877. package/src/engine/graphics/ecs/light/shadow/compute_view_frustum_aabb_in_space.js +62 -62
  878. package/src/engine/graphics/ecs/light/shadow/extend_shadow_camera_near_for_casters.js +77 -77
  879. package/src/engine/graphics/ecs/make_bvh_depth_range_computer.js +33 -33
  880. package/src/engine/graphics/ecs/mesh-v2/DeferredBoundsQueue.js +88 -88
  881. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +428 -428
  882. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMesh.js +303 -303
  883. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMeshSystem.d.ts +1 -1
  884. package/src/engine/graphics/ecs/mesh-v2/aggregate/serialization/SGMeshSerializationAdapter.js +39 -39
  885. package/src/engine/graphics/ecs/mesh-v2/sg_hierarchy_compute_bounding_box_via_parent_entity.js +36 -36
  886. package/src/engine/graphics/ecs/path/tube/build/GeometryStream.js +94 -94
  887. package/src/engine/graphics/ecs/path/tube/build/build_stream_catmullrom.js +310 -310
  888. package/src/engine/graphics/ecs/path/tube/build/build_stream_linear.js +73 -73
  889. package/src/engine/graphics/ecs/path/tube/build/computeFrenetFrames.js +199 -199
  890. package/src/engine/graphics/ecs/path/tube/build/makeTubeStream.js +217 -217
  891. package/src/engine/graphics/ecs/path/tube/build/make_cap.js +340 -340
  892. package/src/engine/graphics/ecs/path/tube/build/make_ring_faces.js +40 -40
  893. package/src/engine/graphics/ecs/path/tube/build/make_ring_vertices.js +153 -153
  894. package/src/engine/graphics/ecs/render_layers_compute_depth_range.js +64 -64
  895. package/src/engine/graphics/ecs/trail3d/Trail3D.js +483 -483
  896. package/src/engine/graphics/ecs/trail3d/Trail3DFlags.js +26 -26
  897. package/src/engine/graphics/ecs/trail3d/advance_trail.js +42 -42
  898. package/src/engine/graphics/ecs/trail3d/make_gradient_stroke.js +58 -58
  899. package/src/engine/graphics/ecs/trail3d/seed_trail_stroke.js +90 -90
  900. package/src/engine/graphics/ecs/trail3d/seed_trail_tube.js +75 -75
  901. package/src/engine/graphics/ecs/trail3d/trail_head_position.js +19 -19
  902. package/src/engine/graphics/ecs/water/Water.js +104 -104
  903. package/src/engine/graphics/geometry/AttributeData.js +84 -84
  904. package/src/engine/graphics/geometry/buffered/geometry_compute_vertex_normals_indexed.js +49 -49
  905. package/src/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.js +288 -288
  906. package/src/engine/graphics/geometry/buffered/query/nearest_point_on_triangle_record.js +87 -87
  907. package/src/engine/graphics/geometry/buffered/read_triangle_vertices.js +102 -102
  908. package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_buffered_geometry.js +52 -52
  909. package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_indexed_geometry.js +20 -20
  910. package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_unindexed_geometry.js +19 -19
  911. package/src/engine/graphics/geometry/optimization/geometry_optimize_uv_tension.js +135 -135
  912. package/src/engine/graphics/impostors/voxel/README.md +149 -149
  913. package/src/engine/graphics/impostors/voxel/VoxelImpostorDescription.js +141 -141
  914. package/src/engine/graphics/particles/node-based/codegen/glsl/getTypeByteSize.js +20 -20
  915. package/src/engine/graphics/particles/node-based/nodes/FloatConstant.d.ts +2 -0
  916. package/src/engine/graphics/particles/node-based/nodes/FloatConstant.d.ts.map +1 -1
  917. package/src/engine/graphics/particles/node-based/nodes/ReadFloatUniform.d.ts +2 -0
  918. package/src/engine/graphics/particles/node-based/nodes/ReadFloatUniform.d.ts.map +1 -1
  919. package/src/engine/graphics/particles/node-based/nodes/ReadVelocity.d.ts +2 -0
  920. package/src/engine/graphics/particles/node-based/nodes/ReadVelocity.d.ts.map +1 -1
  921. package/src/engine/graphics/particles/node-based/nodes/ShaderNode.d.ts +1 -2
  922. package/src/engine/graphics/particles/node-based/nodes/ShaderNode.d.ts.map +1 -1
  923. package/src/engine/graphics/particles/node-based/nodes/Vector3Constant.d.ts +2 -0
  924. package/src/engine/graphics/particles/node-based/nodes/Vector3Constant.d.ts.map +1 -1
  925. package/src/engine/graphics/particles/node-based/nodes/Vector3Merge.d.ts +2 -0
  926. package/src/engine/graphics/particles/node-based/nodes/Vector3Merge.d.ts.map +1 -1
  927. package/src/engine/graphics/particles/node-based/nodes/Vector3Split.d.ts +2 -0
  928. package/src/engine/graphics/particles/node-based/nodes/Vector3Split.d.ts.map +1 -1
  929. package/src/engine/graphics/particles/node-based/nodes/WriteVelocity.d.ts +2 -0
  930. package/src/engine/graphics/particles/node-based/nodes/WriteVelocity.d.ts.map +1 -1
  931. package/src/engine/graphics/particles/node-based/nodes/attribute/ReadVector3Attribute.d.ts +2 -0
  932. package/src/engine/graphics/particles/node-based/nodes/attribute/ReadVector3Attribute.d.ts.map +1 -1
  933. package/src/engine/graphics/particles/node-based/nodes/attribute/WriteVector3Attribute.d.ts +2 -0
  934. package/src/engine/graphics/particles/node-based/nodes/attribute/WriteVector3Attribute.d.ts.map +1 -1
  935. package/src/engine/graphics/particles/node-based/nodes/math/AddFloatNode.d.ts +2 -0
  936. package/src/engine/graphics/particles/node-based/nodes/math/AddFloatNode.d.ts.map +1 -1
  937. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Add.d.ts +2 -0
  938. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Add.d.ts.map +1 -1
  939. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Divide.d.ts +2 -0
  940. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Divide.d.ts.map +1 -1
  941. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Multiply.d.ts +2 -0
  942. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Multiply.d.ts.map +1 -1
  943. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Subtract.d.ts +2 -0
  944. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Subtract.d.ts.map +1 -1
  945. package/src/engine/graphics/particles/node-based/nodes/noise/CurlNoiseNode.d.ts +2 -0
  946. package/src/engine/graphics/particles/node-based/nodes/noise/CurlNoiseNode.d.ts.map +1 -1
  947. package/src/engine/graphics/particles/node-based/nodes/particle_data_type_component_count.js +45 -45
  948. package/src/engine/graphics/particles/particular/engine/ParticularEngine.js +229 -229
  949. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.d.ts +2 -10
  950. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.d.ts.map +1 -1
  951. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js +1149 -1149
  952. package/src/engine/graphics/particles/particular/engine/emitter/ParticlePool.js +472 -472
  953. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +2 -2
  954. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTableFlags.js +2 -2
  955. package/src/engine/graphics/particles/particular/engine/parameter/ParameterSet.d.ts.map +1 -1
  956. package/src/engine/graphics/particles/particular/engine/parameter/ParameterSet.js +3 -5
  957. package/src/engine/graphics/particles/particular/engine/shader/ShaderManager.js +135 -135
  958. package/src/engine/graphics/particles/particular/engine/utils/distribute_points_on_indexed_triangles.js +168 -168
  959. package/src/engine/graphics/render/forward_plus/plugin/forwardPlusMaterialMarker.js +18 -18
  960. package/src/engine/graphics/render/forward_plus/read_frustum_corner.js +2 -2
  961. package/src/engine/graphics/render/frame_graph/FRAME_GRAPH_RECOMMENDATIONS.md +219 -219
  962. package/src/engine/graphics/render/frame_graph/FrameGraph.js +900 -900
  963. package/src/engine/graphics/render/frame_graph/FrameGraphScope.js +72 -72
  964. package/src/engine/graphics/render/frame_graph/FrameGraphState.js +39 -39
  965. package/src/engine/graphics/render/frame_graph/ResourceEntry.js +96 -96
  966. package/src/engine/graphics/render/gizmo/GizmoShapeBuffer.js +105 -105
  967. package/src/engine/graphics/render/gizmo/GizmoShapeRenderingInterface.js +162 -162
  968. package/src/engine/graphics/render/layers/RenderLayer.js +95 -95
  969. package/src/engine/graphics/sh3/build_injected_shader.js +56 -56
  970. package/src/engine/graphics/sh3/grid_dilate_average.js +175 -175
  971. package/src/engine/graphics/sh3/path_tracer/BufferedGeometryBVH.js +506 -506
  972. package/src/engine/graphics/sh3/path_tracer/PathTracedMesh.js +161 -161
  973. package/src/engine/graphics/sh3/path_tracer/PathTracedRenderer.js +205 -205
  974. package/src/engine/graphics/sh3/path_tracer/PathTracedScene.js +698 -698
  975. package/src/engine/graphics/sh3/path_tracer/REVIEW_001_ACTION_PLAN.md +490 -490
  976. package/src/engine/graphics/sh3/path_tracer/geometry/compute_triangle_group_aabb3.js +2 -2
  977. package/src/engine/graphics/sh3/path_tracer/make_sky_hosek.js +45 -45
  978. package/src/engine/graphics/sh3/path_tracer/populate_path_traced_scene_from_ecd.js +73 -73
  979. package/src/engine/graphics/sh3/path_tracer/ray_hit_apply_transform.js +32 -32
  980. package/src/engine/graphics/sh3/path_tracer/texture/apply_texture_clamping_to_coordinate.js +28 -28
  981. package/src/engine/graphics/sh3/path_tracer/texture/sample_material.js +142 -142
  982. package/src/engine/graphics/sh3/sky/hosek/render_hosek_sky_to_equirectangular.js +70 -70
  983. package/src/engine/graphics/sh3/sky/hosek/sky_hosek_compute_irradiance_by_direction.js +388 -388
  984. package/src/engine/graphics/shaders/chunks/glsl_octahedral_impostor.js +277 -277
  985. package/src/engine/graphics/shaders/chunks/glsl_voxel_impostor_splat.js +57 -57
  986. package/src/engine/graphics/shadows/vsm.glsl.js +43 -43
  987. package/src/engine/graphics/texture/3d/scs3d_sample_linear3.js +81 -81
  988. package/src/engine/graphics/texture/EnvironmentTextureProjection.js +15 -15
  989. package/src/engine/graphics/texture/channel_count_to_format_prefix.js +26 -26
  990. package/src/engine/graphics/texture/isImageBitmap.js +2 -2
  991. package/src/engine/graphics/texture/reflection/convolve_equirectangular_reflection.js +189 -189
  992. package/src/engine/graphics/texture/reflection/equirectangular_reflection_roughness.js +51 -51
  993. package/src/engine/graphics/texture/sampler/HarmonicDiffusionGrid.js +145 -145
  994. package/src/engine/graphics/texture/sampler/Sampler2DArray.js +172 -172
  995. package/src/engine/graphics/texture/sampler/compare/FLIP_IMPLEMENTATION_PLAN.md +466 -466
  996. package/src/engine/graphics/texture/sampler/compare/flip/FlipParameters.js +18 -18
  997. package/src/engine/graphics/texture/sampler/compare/flip/FlipPooling.js +33 -33
  998. package/src/engine/graphics/texture/sampler/compare/flip/flip_build_feature_kernel.js +147 -147
  999. package/src/engine/graphics/texture/sampler/compare/flip/flip_build_spatial_kernel.js +177 -177
  1000. package/src/engine/graphics/texture/sampler/compare/flip/flip_compute_color_difference.js +104 -104
  1001. package/src/engine/graphics/texture/sampler/compare/flip/flip_compute_feature_difference.js +76 -76
  1002. package/src/engine/graphics/texture/sampler/compare/flip/flip_compute_pixels_per_degree.js +34 -34
  1003. package/src/engine/graphics/texture/sampler/compare/flip/flip_constants.js +77 -77
  1004. package/src/engine/graphics/texture/sampler/compare/flip/flip_filter_feature.js +48 -48
  1005. package/src/engine/graphics/texture/sampler/compare/flip/flip_filter_spatial.js +86 -86
  1006. package/src/engine/graphics/texture/sampler/compare/flip/flip_pool.js +71 -71
  1007. package/src/engine/graphics/texture/sampler/compare/flip/flip_srgb_to_ycxcz.js +55 -55
  1008. package/src/engine/graphics/texture/sampler/compare/flip/sampler2d_flip_ldr.js +80 -80
  1009. package/src/engine/graphics/texture/sampler/filter/SeparableKernel.js +82 -82
  1010. package/src/engine/graphics/texture/sampler/filter/sampler2d_convolve_separable.js +122 -122
  1011. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.js +148 -148
  1012. package/src/engine/graphics/texture/sampler/sampler2d_channel_apply_lut.js +82 -82
  1013. package/src/engine/graphics/texture/sampler/sampler2d_combine.js +67 -67
  1014. package/src/engine/graphics/texture/sampler/sampler2d_linear_f16_to_srgb_u8.js +54 -54
  1015. package/src/engine/graphics/texture/sampler/sampler2d_sample_equirectangular_direction.js +63 -63
  1016. package/src/engine/graphics/texture/sampler/sampler2d_srgb_to_linear.js +33 -33
  1017. package/src/engine/graphics/texture/sampler/sampler2d_srgb_u8_to_linear_f16.js +68 -68
  1018. package/src/engine/graphics/texture/shade_image_preview.js +103 -103
  1019. package/src/engine/graphics/trail/TrailSpawnMode.js +20 -20
  1020. package/src/engine/graphics/trail/tube/TubeX.js +573 -573
  1021. package/src/engine/graphics/trail/tube/TubeXMaterialSpec.js +58 -58
  1022. package/src/engine/graphics/trail/tube/simulator/TubeXFixedPhysicsSimulator.js +34 -34
  1023. package/src/engine/graphics/trail/tube/tube_attributes_spec.js +69 -69
  1024. package/src/engine/graphics/trail/tube/tube_frame.js +83 -83
  1025. package/src/engine/graphics3/AnimationGraphSystem3.js +329 -329
  1026. package/src/engine/graphics3/AnimationSystem3.js +352 -352
  1027. package/src/engine/graphics3/CameraSystem3.js +170 -170
  1028. package/src/engine/graphics3/DecalSystem3.js +441 -441
  1029. package/src/engine/graphics3/FogOfWarSystem3.js +265 -265
  1030. package/src/engine/graphics3/GraphicsEngine3.js +776 -776
  1031. package/src/engine/graphics3/HighlightSystem3.js +241 -241
  1032. package/src/engine/graphics3/LightSystem3.js +211 -211
  1033. package/src/engine/graphics3/MeshSystem3.js +646 -646
  1034. package/src/engine/graphics3/ParticleEmitterSystem3.js +289 -289
  1035. package/src/engine/graphics3/PathDisplaySystem3.js +309 -309
  1036. package/src/engine/graphics3/PickingQuery.js +48 -48
  1037. package/src/engine/graphics3/PickingResult.js +47 -47
  1038. package/src/engine/graphics3/PickingSystem3.js +273 -273
  1039. package/src/engine/graphics3/ShadeCameraAdapter.js +55 -55
  1040. package/src/engine/graphics3/ShadedGeometrySystem3.js +169 -169
  1041. package/src/engine/graphics3/TerrainSystem3.js +566 -566
  1042. package/src/engine/graphics3/TooltipComponentSystem3.js +328 -328
  1043. package/src/engine/graphics3/Trail3DSystem3.js +221 -221
  1044. package/src/engine/graphics3/VolumetricLightMap.d.ts +90 -0
  1045. package/src/engine/graphics3/VolumetricLightMap.d.ts.map +1 -0
  1046. package/src/engine/graphics3/VolumetricLightMap.js +160 -0
  1047. package/src/engine/graphics3/VolumetricLightMapSerializationAdapter.d.ts +32 -0
  1048. package/src/engine/graphics3/VolumetricLightMapSerializationAdapter.d.ts.map +1 -0
  1049. package/src/engine/graphics3/VolumetricLightMapSerializationAdapter.js +67 -0
  1050. package/src/engine/graphics3/VolumetricLightMapSystem3.d.ts +98 -0
  1051. package/src/engine/graphics3/VolumetricLightMapSystem3.d.ts.map +1 -0
  1052. package/src/engine/graphics3/VolumetricLightMapSystem3.js +261 -0
  1053. package/src/engine/graphics3/WaterSystem3.js +293 -293
  1054. package/src/engine/graphics3/animation/ClipPlayback.js +84 -84
  1055. package/src/engine/graphics3/animation/wrap_clip_time.js +23 -23
  1056. package/src/engine/graphics3/animation/write_graph_playback.js +48 -48
  1057. package/src/engine/graphics3/camera_sync_from_transform.js +29 -29
  1058. package/src/engine/graphics3/debug/gizmo_view_from_camera.js +48 -48
  1059. package/src/engine/graphics3/decal/DECAL_CLUSTER.js +61 -61
  1060. package/src/engine/graphics3/decal/DECAL_GPU_RECORD.js +117 -117
  1061. package/src/engine/graphics3/decal/DecalAtlas.js +194 -194
  1062. package/src/engine/graphics3/decal/DecalAtlasFill.js +32 -32
  1063. package/src/engine/graphics3/decal/GPUDecalRenderer.js +360 -360
  1064. package/src/engine/graphics3/decal/chunk_decal_intersects_frustum.js +59 -59
  1065. package/src/engine/graphics3/decal/chunk_decal_sampling_info.js +57 -57
  1066. package/src/engine/graphics3/decal/chunk_decal_surface_frame.js +54 -54
  1067. package/src/engine/graphics3/decal/decal_atlas_border.js +69 -69
  1068. package/src/engine/graphics3/decal/decal_gpu_records.js +120 -120
  1069. package/src/engine/graphics3/decal/decal_material_samplers.js +109 -109
  1070. package/src/engine/graphics3/decal/graph_build_decal_clusters.js +212 -212
  1071. package/src/engine/graphics3/decal/shader_cluster_assign_decals.js +207 -207
  1072. package/src/engine/graphics3/decal/shader_cull_decals_frustum.js +108 -108
  1073. package/src/engine/graphics3/highlight/GPUHighlightRenderer.js +151 -151
  1074. package/src/engine/graphics3/highlight/HIGHLIGHT_OUTLINE.js +23 -23
  1075. package/src/engine/graphics3/highlight/chunk_highlight_lookup.js +53 -53
  1076. package/src/engine/graphics3/highlight/pack_highlight_color.js +44 -44
  1077. package/src/engine/graphics3/highlight/pack_highlight_table.js +74 -74
  1078. package/src/engine/graphics3/highlight/shader_highlight_outline.js +150 -150
  1079. package/src/engine/graphics3/load_cube_environment.js +68 -68
  1080. package/src/engine/graphics3/make_default_environment.js +107 -107
  1081. package/src/engine/graphics3/particles/particle_gpu_records.js +221 -221
  1082. package/src/engine/graphics3/path/build_tube_path_streams.js +98 -98
  1083. package/src/engine/graphics3/path/tube_stream_write_geometry.js +90 -90
  1084. package/src/engine/graphics3/preview/ModelPreviewFraming.js +35 -35
  1085. package/src/engine/graphics3/preview/make_model_preview_scene.js +154 -154
  1086. package/src/engine/graphics3/preview/make_model_thumbnail.js +48 -48
  1087. package/src/engine/graphics3/preview/model_preview_framing.js +70 -70
  1088. package/src/engine/graphics3/shade_bundle_bounds.js +55 -55
  1089. package/src/engine/graphics3/shade_camera_projection_ray.js +77 -77
  1090. package/src/engine/graphics3/shade_node_to_entity_composition.js +84 -84
  1091. package/src/engine/graphics3/terrain/GPUTerrainSplatRenderer.js +481 -481
  1092. package/src/engine/graphics3/terrain/chunk_terrain_grid_overlay.js +61 -61
  1093. package/src/engine/graphics3/terrain/chunk_terrain_splat_mix.js +66 -66
  1094. package/src/engine/graphics3/terrain/pack_terrain_row_table.js +53 -53
  1095. package/src/engine/graphics3/terrain/shader_terrain_splat.js +215 -215
  1096. package/src/engine/graphics3/trail/trail_tube_write_geometry.js +158 -158
  1097. package/src/engine/input/GAMEPAD_API_PROPOSAL.md +717 -717
  1098. package/src/engine/input/analog/apply_radial_dead_zone.js +38 -38
  1099. package/src/engine/input/devices/GamepadDevice.js +466 -466
  1100. package/src/engine/input/devices/ManualInputDevice.js +152 -152
  1101. package/src/engine/input/devices/PointerCoordinates.js +26 -26
  1102. package/src/engine/input/devices/events/GamepadEvents.js +10 -10
  1103. package/src/engine/input/devices/gamepad/GamepadAxes.js +19 -19
  1104. package/src/engine/input/devices/gamepad/GamepadButtons.js +29 -29
  1105. package/src/engine/input/devices/gamepad/GamepadCoordinates.js +17 -17
  1106. package/src/engine/input/devices/gamepad/GamepadDeviceLayout.js +323 -323
  1107. package/src/engine/input/devices/gamepad/GamepadHandle.js +286 -286
  1108. package/src/engine/input/devices/gamepad/GamepadLayout.js +160 -160
  1109. package/src/engine/input/devices/gamepad/GamepadStandardMapping.js +31 -31
  1110. package/src/engine/input/devices/gamepad/GamepadStick.js +169 -169
  1111. package/src/engine/input/devices/gamepad/GamepadStickCalibration.js +119 -119
  1112. package/src/engine/input/devices/gamepad/GamepadStickCalibrator.js +250 -250
  1113. package/src/engine/input/devices/gamepad/gamepad_layout_database.js +144 -144
  1114. package/src/engine/input/devices/gamepad/gamepad_read_hat_axis.js +61 -61
  1115. package/src/engine/input/devices/gamepad/gamepad_write_dpad_vector.js +30 -30
  1116. package/src/engine/input/devices/gamepad/prototypeGamepadTester.js +2124 -2124
  1117. package/src/engine/input/devices/mouse/MouseButtons.js +22 -22
  1118. package/src/engine/input/ecs/components/Input.js +118 -118
  1119. package/src/engine/input/ecs/components/InputController.js +78 -78
  1120. package/src/engine/input/ecs/ism/ISM_DESIGN.md +1523 -1523
  1121. package/src/engine/input/ecs/ism/ISM_IMPLEMENTATION_PLAN.md +627 -627
  1122. package/src/engine/input/ecs/ism/InputActionEvent.js +40 -40
  1123. package/src/engine/input/ecs/ism/InputBinding.js +71 -71
  1124. package/src/engine/input/ecs/ism/InputCoordinateKind.js +25 -25
  1125. package/src/engine/input/ecs/ism/InputCoordinateSource.js +86 -86
  1126. package/src/engine/input/ecs/ism/InputDirection.js +33 -33
  1127. package/src/engine/input/ecs/ism/InputMapProgram.js +236 -236
  1128. package/src/engine/input/ecs/ism/InputMapSystem.js +976 -976
  1129. package/src/engine/input/ecs/ism/InputOcclusion.js +31 -31
  1130. package/src/engine/input/ecs/ism/InputSource.js +67 -67
  1131. package/src/engine/input/ecs/ism/InputSourceTable.js +107 -107
  1132. package/src/engine/input/ecs/ism/coordinate/InputCoordinateChannel.js +93 -93
  1133. package/src/engine/input/ecs/ism/coordinate/InputCoordinateChannelType.js +11 -11
  1134. package/src/engine/input/ecs/ism/coordinate/InputCoordinateDevice.js +153 -153
  1135. package/src/engine/input/ecs/ism/coordinate/InputCoordinateSwitches.js +160 -160
  1136. package/src/engine/input/ecs/ism/device/GAMEPAD_INPUT_DEVICE_ID.js +9 -9
  1137. package/src/engine/input/ecs/ism/device/GamepadInputDeviceAdapter.js +88 -88
  1138. package/src/engine/input/ecs/ism/device/InputDeviceAdapter.js +72 -72
  1139. package/src/engine/input/ecs/ism/device/KEYBOARD_INPUT_DEVICE_ID.js +9 -9
  1140. package/src/engine/input/ecs/ism/device/KeyboardInputDeviceAdapter.js +63 -63
  1141. package/src/engine/input/ecs/ism/device/ManualInputDeviceAdapter.js +55 -55
  1142. package/src/engine/input/ecs/ism/device/POINTER_INPUT_DEVICE_ID.js +9 -9
  1143. package/src/engine/input/ecs/ism/device/PointerInputDeviceAdapter.js +160 -160
  1144. package/src/engine/input/ecs/ism/map/InputBinding.js +88 -88
  1145. package/src/engine/input/ecs/ism/map/InputCoordinateBinding.js +102 -102
  1146. package/src/engine/input/ecs/ism/map/InputLayer.js +220 -220
  1147. package/src/engine/input/ecs/ism/map/InputMap.js +331 -331
  1148. package/src/engine/input/ecs/ism/prototypeInputMap.js +309 -309
  1149. package/src/engine/input/ecs/ism/trigger/InputTrigger.js +148 -148
  1150. package/src/engine/input/ecs/ism/trigger/InputTriggerChord.js +173 -173
  1151. package/src/engine/input/ecs/ism/trigger/InputTriggerGamepadButton.js +37 -37
  1152. package/src/engine/input/ecs/ism/trigger/InputTriggerHold.js +176 -176
  1153. package/src/engine/input/ecs/ism/trigger/InputTriggerKey.js +39 -39
  1154. package/src/engine/input/ecs/ism/trigger/InputTriggerMouseButton.js +38 -38
  1155. package/src/engine/input/ecs/ism/trigger/InputTriggerRelease.js +120 -120
  1156. package/src/engine/input/ecs/ism/trigger/InputTriggerSequence.js +315 -315
  1157. package/src/engine/input/ecs/ism/trigger/InputTriggerSwitch.js +105 -105
  1158. package/src/engine/input/ecs/ism/trigger/InputTriggerType.js +17 -17
  1159. package/src/engine/input/ecs/systems/InputControllerSystem.js +253 -253
  1160. package/src/engine/input/ecs/systems/InputSystem.js +162 -162
  1161. package/src/engine/intelligence/behavior/primitive/FailingBehaviorSerializationAdapter.js +25 -25
  1162. package/src/engine/intelligence/behavior/primitive/SucceedingBehaviorSerializationAdapter.js +26 -26
  1163. package/src/engine/intelligence/behavior/util/AsynchronousDelayAction.js +55 -55
  1164. package/src/engine/interpolation/BinaryInterpolationAdapter.js +56 -56
  1165. package/src/engine/interpolation/Interpoland.js +49 -49
  1166. package/src/engine/interpolation/Interpolated.js +149 -149
  1167. package/src/engine/interpolation/PoseInterpolationAdapter.js +61 -61
  1168. package/src/engine/interpolation/TransformPoseSerializationAdapter.js +57 -57
  1169. package/src/engine/interpolation/pose_interpoland.js +27 -27
  1170. package/src/engine/navigation/ecs/path_following/PathFollower.js +222 -222
  1171. package/src/engine/navigation/mesh/NavigationMesh.js +145 -145
  1172. package/src/engine/navigation/mesh/OVERLAPPING_SURFACES_2026_08_25.md +661 -0
  1173. package/src/engine/navigation/mesh/PATHFINDING_PLAN.md +229 -229
  1174. package/src/engine/navigation/mesh/build/clip_soup_against_overhangs.d.ts.map +1 -1
  1175. package/src/engine/navigation/mesh/build/clip_soup_against_overhangs.js +628 -520
  1176. package/src/engine/network/CONGESTION_CONTROL.md +87 -87
  1177. package/src/engine/network/README.md +52 -52
  1178. package/src/engine/network/adapters/QuaternionInterpolationAdapter.js +43 -43
  1179. package/src/engine/network/adapters/TransformInterpolationAdapter.js +84 -84
  1180. package/src/engine/network/adapters/TransformReplicationAdapter.js +87 -87
  1181. package/src/engine/network/adapters/Vector3InterpolationAdapter.js +46 -46
  1182. package/src/engine/network/convertPathToURL.js +2 -2
  1183. package/src/engine/network/core/MalformedPacketError.js +26 -26
  1184. package/src/engine/network/core/quantize/quantize_float.js +73 -73
  1185. package/src/engine/network/core/quantize/quantize_position.js +65 -65
  1186. package/src/engine/network/core/sequence/ack_bitfield.js +77 -77
  1187. package/src/engine/network/core/sequence/seq16.js +69 -69
  1188. package/src/engine/network/core/sequence/seq32.js +73 -73
  1189. package/src/engine/network/ecs/NetworkSystem.js +84 -84
  1190. package/src/engine/network/ecs/components/NetworkIdentity.js +73 -73
  1191. package/src/engine/network/ecs/owner_authorization.js +55 -55
  1192. package/src/engine/network/ecs/serialization/NetworkIdentitySerializationAdapter.js +64 -64
  1193. package/src/engine/network/replication/ScopeFilter.js +71 -71
  1194. package/src/engine/network/sim/ActionLog.js +152 -152
  1195. package/src/engine/network/sim/SimAction.js +273 -273
  1196. package/src/engine/network/sim/Snapshotter.js +222 -222
  1197. package/src/engine/network/state/FrameBufferRing.js +168 -168
  1198. package/src/engine/network/state/InputRing.js +134 -134
  1199. package/src/engine/network/state/PriorityAccumulator.js +180 -180
  1200. package/src/engine/network/time/TimeDilation.js +62 -62
  1201. package/src/engine/network/transport/Channel.js +336 -336
  1202. package/src/engine/network/transport/Transport.js +203 -203
  1203. package/src/engine/network/transport/adapters/NodeUDPTransport.js +186 -186
  1204. package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.js +105 -105
  1205. package/src/engine/network/transport/fragments/fragment_send.js +147 -147
  1206. package/src/engine/network/transport/fragments/packet_size.js +101 -101
  1207. package/src/engine/network/xhr.js +23 -23
  1208. package/src/engine/physics/BULLET_REVIEW.md +945 -945
  1209. package/src/engine/physics/CANNON_REVIEW.md +1300 -1300
  1210. package/src/engine/physics/CONSTRAINT_SOLVER_BENCH_LOG.md +208 -208
  1211. package/src/engine/physics/CONSTRAINT_SOLVER_IMPROVEMENTS_PLAN.md +364 -364
  1212. package/src/engine/physics/INTEPOLATION_SYSTEM_PLAN.md +287 -287
  1213. package/src/engine/physics/JOLT_REVIEW.md +913 -913
  1214. package/src/engine/physics/PLAN.md +1120 -1094
  1215. package/src/engine/physics/RAPIER_REVIEW.md +934 -934
  1216. package/src/engine/physics/REVIEW_001_ACTION_PLAN.md +642 -642
  1217. package/src/engine/physics/REVIEW_002.md +151 -151
  1218. package/src/engine/physics/REVIEW_003.md +166 -166
  1219. package/src/engine/physics/broadphase/compute_fat_world_aabb.js +97 -97
  1220. package/src/engine/physics/constraint/DofMode.js +35 -35
  1221. package/src/engine/physics/constraint/solve_constraints.js +1 -1
  1222. package/src/engine/physics/contact/combine_material.js +35 -35
  1223. package/src/engine/physics/ecs/BodyKind.js +29 -29
  1224. package/src/engine/physics/ecs/Collider.js +177 -177
  1225. package/src/engine/physics/ecs/ColliderFlags.js +15 -15
  1226. package/src/engine/physics/ecs/ColliderSerializationAdapter.js +37 -37
  1227. package/src/engine/physics/ecs/Joint.js +475 -475
  1228. package/src/engine/physics/ecs/JointSerializationAdapter.js +72 -72
  1229. package/src/engine/physics/ecs/PhysicsSystem.d.ts +3 -0
  1230. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  1231. package/src/engine/physics/ecs/PhysicsSystem.js +7 -2
  1232. package/src/engine/physics/ecs/RigidBodySerializationUpgrader_0_1.js +37 -37
  1233. package/src/engine/physics/ecs/SleepState.js +12 -12
  1234. package/src/engine/physics/ecs/find_non_finite_physics_state.js +76 -76
  1235. package/src/engine/physics/fluid/FluidField.js +867 -867
  1236. package/src/engine/physics/fluid/FluidSimulator.js +832 -832
  1237. package/src/engine/physics/fluid/REVIEW_02_PLAN.md +243 -243
  1238. package/src/engine/physics/fluid/SliceVisualiser.js +190 -190
  1239. package/src/engine/physics/fluid/ecs/FluidComponent.js +239 -239
  1240. package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.js +89 -89
  1241. package/src/engine/physics/fluid/ecs/FluidObstacle.js +97 -97
  1242. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  1243. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.js +348 -348
  1244. package/src/engine/physics/fluid/ecs/FluidSystem.js +142 -142
  1245. package/src/engine/physics/fluid/ecs/FluidWorkerCore.js +123 -123
  1246. package/src/engine/physics/fluid/ecs/WorkerFluidSystem.js +395 -395
  1247. package/src/engine/physics/fluid/ecs/fluid.worker.js +12 -12
  1248. package/src/engine/physics/fluid/ecs/fluid_build_world_to_grid.js +32 -32
  1249. package/src/engine/physics/fluid/ecs/fluid_gather_visible_effectors.js +47 -47
  1250. package/src/engine/physics/fluid/ecs/fluid_reanchor_field.js +85 -85
  1251. package/src/engine/physics/fluid/ecs/fluid_sync_effectors_from_transform.js +16 -16
  1252. package/src/engine/physics/fluid/ecs/fluid_worker_protocol.js +111 -111
  1253. package/src/engine/physics/fluid/ecs/makeFluidWorker.js +18 -18
  1254. package/src/engine/physics/fluid/effector/AbstractFluidEffector.js +81 -81
  1255. package/src/engine/physics/fluid/effector/GlobalFluidEffector.js +202 -202
  1256. package/src/engine/physics/fluid/effector/ImpulseFluidEffector.js +257 -257
  1257. package/src/engine/physics/fluid/effector/WakeFluidEffector.js +405 -405
  1258. package/src/engine/physics/fluid/prototype.js +126 -126
  1259. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_scalar.js +143 -143
  1260. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_velocity.js +162 -162
  1261. package/src/engine/physics/fluid/solver/v3_grid_advect_sl_velocity.js +107 -107
  1262. package/src/engine/physics/fluid/solver/v3_grid_apply_vorticity_confinement.js +131 -131
  1263. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.js +90 -90
  1264. package/src/engine/physics/fluid/solver/v3_grid_limit8_at_indices.js +38 -38
  1265. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_constant.js +77 -77
  1266. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.js +113 -113
  1267. package/src/engine/physics/fluid/solver/v3_grid_sample_scalar_masked.js +92 -92
  1268. package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.js +107 -107
  1269. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.js +135 -135
  1270. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.js +511 -511
  1271. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.js +108 -108
  1272. package/src/engine/physics/fluid/solver/v3_mac_advect_maccormack_velocity.js +317 -317
  1273. package/src/engine/physics/fluid/solver/v3_mac_advect_scalar.js +236 -236
  1274. package/src/engine/physics/fluid/solver/v3_mac_advect_sl_velocity.js +217 -217
  1275. package/src/engine/physics/fluid/solver/v3_mac_apply_vorticity_confinement.js +174 -174
  1276. package/src/engine/physics/fluid/solver/v3_mac_clip_trace.js +95 -95
  1277. package/src/engine/physics/fluid/solver/v3_mac_compute_divergence.js +77 -77
  1278. package/src/engine/physics/fluid/solver/v3_mac_compute_face_solid.js +131 -131
  1279. package/src/engine/physics/fluid/solver/v3_mac_subtract_pressure_gradient.js +104 -104
  1280. package/src/engine/physics/inertia/world_inverse_inertia.js +160 -160
  1281. package/src/engine/physics/integration/integrate_position.js +97 -97
  1282. package/src/engine/physics/narrowphase/box_box_manifold.js +681 -681
  1283. package/src/engine/physics/narrowphase/box_triangle_contact.js +906 -906
  1284. package/src/engine/physics/narrowphase/capsule_triangle_contact.js +395 -395
  1285. package/src/engine/physics/narrowphase/compute_penetration.js +369 -369
  1286. package/src/engine/physics/narrowphase/decomposition/decompose_to_triangles.js +55 -55
  1287. package/src/engine/physics/narrowphase/decomposition/triangle_buffer_layout.js +37 -37
  1288. package/src/engine/physics/narrowphase/mesh_mesh_tet_manifold.js +117 -117
  1289. package/src/engine/physics/narrowphase/narrowphase_step.js +1738 -1738
  1290. package/src/engine/physics/narrowphase/reduce_manifold_contacts.js +74 -74
  1291. package/src/engine/physics/narrowphase/refine_ray_hit.d.ts +12 -11
  1292. package/src/engine/physics/narrowphase/refine_ray_hit.d.ts.map +1 -1
  1293. package/src/engine/physics/narrowphase/refine_ray_hit.js +228 -36
  1294. package/src/engine/physics/narrowphase/sphere_sphere_contact.js +52 -52
  1295. package/src/engine/physics/narrowphase/sphere_triangle_contact.js +138 -138
  1296. package/src/engine/physics/persistence/solver_caches.js +309 -309
  1297. package/src/engine/physics/queries/overlap_shape.js +187 -187
  1298. package/src/engine/physics/queries/raycast.d.ts +7 -4
  1299. package/src/engine/physics/queries/raycast.d.ts.map +1 -1
  1300. package/src/engine/physics/queries/raycast.js +11 -5
  1301. package/src/engine/physics/queries/shape_cast.js +417 -417
  1302. package/src/engine/physics/solver/apply_impulse_to_body.js +86 -86
  1303. package/src/engine/physics/solver/friction_cone.js +37 -37
  1304. package/src/engine/physics/solver/solve_contacts.js +1 -1
  1305. package/src/engine/platform/WebEnginePlatform.d.ts.map +1 -1
  1306. package/src/engine/platform/WebEnginePlatform.js +1 -2
  1307. package/src/engine/scene/SerializedScene.d.ts +2 -2
  1308. package/src/engine/scene/SerializedScene.d.ts.map +1 -1
  1309. package/src/engine/scene/transitionToScene.js +121 -121
  1310. package/src/engine/simulation/Ticker.d.ts.map +1 -1
  1311. package/src/engine/simulation/Ticker.js +33 -0
  1312. package/src/engine/sound/ecs/audio/LiveEmitterSet.js +345 -345
  1313. package/src/engine/sound/ecs/audio/SpatialAudioIndex.js +140 -140
  1314. package/src/engine/sound/simulation/AcousticSimulator.js +646 -646
  1315. package/src/engine/sound/simulation/IMPLEMENTATION_PLAN.md +432 -432
  1316. package/src/engine/sound/simulation/PROBE_PLACEMENT.md +250 -250
  1317. package/src/engine/sound/simulation/PROBE_TRANSFER_RESEARCH.md +322 -322
  1318. package/src/engine/sound/simulation/README.md +277 -277
  1319. package/src/engine/sound/simulation/REFLECTION_IR_PLAN.md +261 -261
  1320. package/src/engine/sound/simulation/VISIBILITY_GRAPH_PLAN.md +121 -121
  1321. package/src/engine/sound/simulation/configureAcousticSimulation.js +48 -48
  1322. package/src/engine/sound/simulation/core/AcousticMedium.js +113 -113
  1323. package/src/engine/sound/simulation/core/AcousticMediumSerializationAdapter.js +27 -27
  1324. package/src/engine/sound/simulation/core/AcousticOccluderIndex.js +312 -312
  1325. package/src/engine/sound/simulation/core/AcousticRegionIndex.js +159 -159
  1326. package/src/engine/sound/simulation/core/AcousticSolution.js +90 -90
  1327. package/src/engine/sound/simulation/core/AcousticSourceState.js +109 -109
  1328. package/src/engine/sound/simulation/core/AcousticVolumeRegion.js +73 -73
  1329. package/src/engine/sound/simulation/core/OcclusionSolver.js +112 -112
  1330. package/src/engine/sound/simulation/core/RayHit.js +50 -50
  1331. package/src/engine/sound/simulation/core/VolumeField.js +149 -149
  1332. package/src/engine/sound/simulation/definition/AcousticDirectivity.js +114 -114
  1333. package/src/engine/sound/simulation/definition/AcousticDirectivitySerializationAdapter.js +30 -30
  1334. package/src/engine/sound/simulation/definition/AcousticMaterial.js +122 -122
  1335. package/src/engine/sound/simulation/definition/AcousticMaterialSerializationAdapter.js +32 -32
  1336. package/src/engine/sound/simulation/ecs/AcousticBody.js +48 -48
  1337. package/src/engine/sound/simulation/ecs/AcousticBodySerializationAdapter.js +34 -34
  1338. package/src/engine/sound/simulation/ecs/AcousticProbeFieldSystem.js +64 -64
  1339. package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.js +75 -75
  1340. package/src/engine/sound/simulation/ecs/AcousticVolume.js +74 -74
  1341. package/src/engine/sound/simulation/ecs/AcousticVolumeSerializationAdapter.js +37 -37
  1342. package/src/engine/sound/simulation/ecs/AcousticVolumeSystem.js +66 -66
  1343. package/src/engine/sound/simulation/probe/AcousticProbeField.js +578 -578
  1344. package/src/engine/sound/simulation/probe/AcousticProbeFieldSerializationAdapter.js +60 -60
  1345. package/src/engine/sound/simulation/probe/ProbeFieldPathingSolution.js +64 -64
  1346. package/src/engine/sound/simulation/probe/ProbeVisibilityRecheck.js +132 -132
  1347. package/src/engine/sound/simulation/probe/acoustic_probe_transfer.js +103 -103
  1348. package/src/engine/sound/simulation/probe/acoustic_trace_energy.js +136 -136
  1349. package/src/engine/sound/simulation/probe/bakeProbeField.js +169 -169
  1350. package/src/engine/sound/simulation/probe/bakeProbeReflectors.js +110 -110
  1351. package/src/engine/sound/simulation/probe/bakeReverbBands.js +110 -110
  1352. package/src/engine/sound/simulation/probe/bakeVisibility.js +148 -148
  1353. package/src/engine/sound/simulation/probe/echogram_band_rt60.js +83 -83
  1354. package/src/engine/sound/simulation/probe/probe_delaunay_edges.js +215 -215
  1355. package/src/engine/sound/simulation/probe/probe_densify_portals.js +140 -140
  1356. package/src/engine/sound/simulation/probe/probe_detect_portals.js +196 -196
  1357. package/src/engine/sound/simulation/probe/probe_edge_key.js +38 -38
  1358. package/src/engine/sound/simulation/probe/probe_edge_visible.js +41 -41
  1359. package/src/engine/sound/simulation/probe/probe_place_sdf_cover.js +82 -82
  1360. package/src/engine/sound/simulation/probe/probe_refine_connectivity.js +181 -181
  1361. package/src/engine/sound/simulation/probe/probe_sdf_grid.js +171 -171
  1362. package/src/engine/sound/simulation/probe/probe_visibility_augment.js +146 -146
  1363. package/src/engine/sound/simulation/probe/probe_visibility_bridge_components.js +167 -167
  1364. package/src/engine/sound/simulation/render/FoaProbeReverbRenderer.js +354 -354
  1365. package/src/engine/sound/simulation/render/ProbeReverbRenderer.js +231 -231
  1366. package/src/engine/sound/simulation/render/foaReverbImpulseResponse.js +105 -105
  1367. package/src/engine/sound/simulation/render/reverbImpulseResponse.js +66 -66
  1368. package/src/engine/sound/simulation/render/reverb_band_tails.js +93 -93
  1369. package/src/engine/sound/simulation/serialization/populateAcousticSerializationRegistry.js +25 -25
  1370. package/src/engine/sound/sopra/README.md +643 -643
  1371. package/src/engine/sound/sopra/SopraEngine.js +432 -432
  1372. package/src/engine/sound/sopra/asset/AssetManagerBufferProvider.js +71 -71
  1373. package/src/engine/sound/sopra/asset/BufferProvider.js +29 -29
  1374. package/src/engine/sound/sopra/asset/StubBufferProvider.js +58 -58
  1375. package/src/engine/sound/sopra/definition/BusDefinition.js +142 -142
  1376. package/src/engine/sound/sopra/definition/BusDefinitionSerializationAdapter.js +54 -54
  1377. package/src/engine/sound/sopra/definition/DuckingRule.js +106 -106
  1378. package/src/engine/sound/sopra/definition/DuckingRuleSerializationAdapter.js +31 -31
  1379. package/src/engine/sound/sopra/definition/EventDescription.js +262 -262
  1380. package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.js +55 -55
  1381. package/src/engine/sound/sopra/definition/MixerSnapshot.js +83 -83
  1382. package/src/engine/sound/sopra/definition/MixerSnapshotSerializationAdapter.js +39 -39
  1383. package/src/engine/sound/sopra/definition/ParameterDefinition.js +117 -117
  1384. package/src/engine/sound/sopra/definition/ParameterDefinitionSerializationAdapter.js +31 -31
  1385. package/src/engine/sound/sopra/definition/VoiceStealMode.js +18 -18
  1386. package/src/engine/sound/sopra/definition/clip/AbstractAudioClip.js +109 -109
  1387. package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClip.js +185 -185
  1388. package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClipSerializationAdapter.js +59 -59
  1389. package/src/engine/sound/sopra/definition/clip/ContainerAudioClip.js +128 -128
  1390. package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClip.js +226 -226
  1391. package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClipSerializationAdapter.js +54 -54
  1392. package/src/engine/sound/sopra/definition/clip/SampleAudioClip.js +191 -191
  1393. package/src/engine/sound/sopra/definition/clip/SampleAudioClipSerializationAdapter.js +39 -39
  1394. package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClip.js +79 -79
  1395. package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClipSerializationAdapter.js +42 -42
  1396. package/src/engine/sound/sopra/definition/clip/SilenceAudioClip.js +77 -77
  1397. package/src/engine/sound/sopra/definition/clip/SilenceAudioClipSerializationAdapter.js +27 -27
  1398. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.d.ts +5 -0
  1399. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.d.ts.map +1 -1
  1400. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.js +125 -125
  1401. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClipSerializationAdapter.js +41 -41
  1402. package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.js +24 -24
  1403. package/src/engine/sound/sopra/definition/effect/CompressorEffect.js +120 -120
  1404. package/src/engine/sound/sopra/definition/effect/CompressorEffectSerializationAdapter.js +31 -31
  1405. package/src/engine/sound/sopra/definition/effect/EqEffect.js +128 -128
  1406. package/src/engine/sound/sopra/definition/effect/EqEffectSerializationAdapter.js +29 -29
  1407. package/src/engine/sound/sopra/definition/effect/ReverbEffect.js +113 -113
  1408. package/src/engine/sound/sopra/definition/effect/ReverbEffectSerializationAdapter.js +25 -25
  1409. package/src/engine/sound/sopra/runtime/BusGraph.js +231 -231
  1410. package/src/engine/sound/sopra/runtime/ParameterStore.js +98 -98
  1411. package/src/engine/sound/sopra/runtime/SopraPlaybackContext.js +68 -68
  1412. package/src/engine/sound/sopra/runtime/Voice.js +145 -145
  1413. package/src/engine/sound/sopra/runtime/VoiceManager.js +136 -136
  1414. package/src/engine/sound/sopra/runtime/VoicePool.js +17 -17
  1415. package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.js +42 -42
  1416. package/src/engine/sound/sopra/serialization/sopraJSON.js +99 -99
  1417. package/src/engine/sound/sopra/serialization/sopraSerializationHarness.js +49 -49
  1418. package/src/engine/sound/sopra/util/MockAudioContext.js +224 -224
  1419. package/src/engine/sound/sopra/util/fadeOutAndStop.js +60 -60
  1420. package/src/engine/ui/DraggableAspect.js +115 -115
  1421. package/src/engine/ui/apply_pointer_tilt_3d.js +50 -50
  1422. package/src/generation/COORDINATES.md +54 -54
  1423. package/src/generation/GridGenerationResource.js +24 -24
  1424. package/src/generation/GridTaskGroup.js +214 -214
  1425. package/src/generation/REVIEW_01_ACTION_PLAN.md +628 -628
  1426. package/src/generation/automata/CaveGeneratorCellularAutomata.js +79 -79
  1427. package/src/generation/automata/CellularAutomata.js +22 -22
  1428. package/src/generation/compute_writes_union.js +25 -25
  1429. package/src/generation/filtering/CellFilter.js +117 -117
  1430. package/src/generation/filtering/core/CellFilterBinaryOperation.js +37 -37
  1431. package/src/generation/filtering/core/CellFilterOperationTertiary.js +43 -43
  1432. package/src/generation/filtering/core/CellFilterUnaryOperation.js +29 -29
  1433. package/src/generation/filtering/numeric/process/computeCellFilterSobel.js +36 -36
  1434. package/src/generation/filtering/numeric/process/computeFilterSurfaceNormal.js +42 -42
  1435. package/src/generation/filtering/numeric/util/populateSampler2DFromCellFilter.js +18 -18
  1436. package/src/generation/filtering/numeric/util/write_cell_filter_to_sampler2d.js +47 -47
  1437. package/src/generation/filtering/util/cell_filter_weights_pick.js +54 -54
  1438. package/src/generation/grid/GridData.js +233 -233
  1439. package/src/generation/grid/coords/grid_to_texel.js +10 -10
  1440. package/src/generation/grid/coords/texel_to_grid.js +10 -10
  1441. package/src/generation/grid/generation/GridTaskApplyActionToCells.js +90 -90
  1442. package/src/generation/grid/generation/GridTaskDensityMarkerDistribution.js +388 -388
  1443. package/src/generation/grid/generation/GridTaskExecuteRuleTimes.js +127 -127
  1444. package/src/generation/grid/generation/GridTaskSequence.js +58 -58
  1445. package/src/generation/grid/generation/NoopGridTaskGenerator.js +12 -12
  1446. package/src/generation/grid/generation/discrete/GridTaskActionRuleSet.js +48 -48
  1447. package/src/generation/grid/generation/discrete/GridTaskCellularAutomata.js +146 -146
  1448. package/src/generation/grid/generation/discrete/GridTaskConnectRooms.js +540 -540
  1449. package/src/generation/grid/generation/discrete/layer/GridTaskBuildSourceDistanceMap.js +222 -222
  1450. package/src/generation/grid/generation/grid/GridTaskAddNodesFixed.js +44 -44
  1451. package/src/generation/grid/generation/road/GridTaskGenerateRoads.js +614 -614
  1452. package/src/generation/markers/GridCellActionPlaceMarker.js +244 -244
  1453. package/src/generation/markers/GridCellActionPlaceMarkerGroup.js +86 -86
  1454. package/src/generation/markers/actions/terrain/MarkerNodeActionPaintTerrain.js +266 -266
  1455. package/src/generation/markers/emitter/MarkerNodeEmitterGridCellAction.js +49 -49
  1456. package/src/generation/placement/GridCellActionTransformNearbyMarkers.js +120 -120
  1457. package/src/generation/placement/action/GridCellAction.js +45 -45
  1458. package/src/generation/placement/action/GridCellActionPlaceTags.js +140 -140
  1459. package/src/generation/placement/action/GridCellActionWriteFilterToLayer.js +89 -89
  1460. package/src/generation/placement/action/random/CellActionSelectRandom.js +69 -69
  1461. package/src/generation/placement/action/random/weighted/CellActionSelectWeightedRandom.js +91 -91
  1462. package/src/generation/placement/action/util/GridCellActionSequence.js +61 -61
  1463. package/src/generation/placement/action/util/GridCellDisplacedAction.js +61 -61
  1464. package/src/generation/rules/cell/CellMatcherRemovalPreservesConnectivity.js +183 -183
  1465. package/src/generation/theme/ThemeEngine.js +666 -666
  1466. package/src/shade/RENDERER_CONTRACT.md +568 -568
  1467. package/src/shade/descriptor/texture/format/gpu_texture_format_info.js +267 -267
  1468. package/src/shade/device/ShadeDeviceFailure.js +104 -104
  1469. package/src/shade/device/ShadeDeviceFailureReason.js +41 -41
  1470. package/src/shade/device/mock/IMPLEMENTATION_PLAN.md +255 -255
  1471. package/src/shade/device/mock/REVIEW_2026_08_22.md +527 -527
  1472. package/src/shade/device/mock/SoftwareGPUBindGroup.js +23 -23
  1473. package/src/shade/device/mock/SoftwareGPUBindGroupLayout.js +22 -22
  1474. package/src/shade/device/mock/SoftwareGPUError.js +63 -63
  1475. package/src/shade/device/mock/SoftwareGPUPipeline.js +75 -75
  1476. package/src/shade/device/mock/SoftwareGPUQuerySet.js +113 -113
  1477. package/src/shade/device/mock/SoftwareGPUSampler.js +30 -30
  1478. package/src/shade/device/mock/SoftwareGPUShaderModule.js +32 -32
  1479. package/src/shade/device/mock/SoftwareGPUTextureView.js +22 -22
  1480. package/src/shade/device/mock/SoftwareGPUUncapturedErrorEvent.js +23 -23
  1481. package/src/shade/device/mock/normalize_dynamic_offsets.js +26 -26
  1482. package/src/shade/device/mock/texture_copy.js +287 -287
  1483. package/src/shade/device/timing/GPUTimer.js +285 -285
  1484. package/src/shade/device/timing/GPUTimerArray.js +205 -205
  1485. package/src/shade/playground/add_random_lights.js +49 -49
  1486. package/src/shade/playground/add_random_meshes.js +83 -83
  1487. package/src/shade/playground/animation_prototype.js +508 -508
  1488. package/src/shade/playground/animation_prototype_skinning.js +647 -647
  1489. package/src/shade/playground/animation_prototype_stress.js +765 -765
  1490. package/src/shade/playground/enable_picker.js +59 -59
  1491. package/src/shade/playground/gltf_skinned_prototype.js +560 -560
  1492. package/src/shade/playground/gltf_skinned_stress_prototype.js +387 -387
  1493. package/src/shade/playground/gltf_viewer.js +282 -282
  1494. package/src/shade/playground/load_default_environment.js +19 -19
  1495. package/src/shade/playground/main.js +2727 -2727
  1496. package/src/shade/playground/make_animated_instances.js +117 -117
  1497. package/src/shade/playground/prototype_virtual_texture.js +274 -274
  1498. package/src/shade/playground/prototype_volumetrics_01.js +206 -206
  1499. package/src/shade/playground/sample.js +234 -234
  1500. package/src/shade/playground/sample_load_gltf.js +102 -102
  1501. package/src/shade/playground/spread_node3d_grid.js +19 -19
  1502. package/src/shade/renderer/Renderer.js +2436 -2436
  1503. package/src/shade/renderer/ShadeIndirectLightingMode.js +14 -14
  1504. package/src/shade/renderer/animation/ShadeAnimationChannel.js +414 -414
  1505. package/src/shade/renderer/animation/compute_skinned_mesh_clip_bounding_sphere.js +531 -531
  1506. package/src/shade/renderer/animation/pose/PosePlayback.js +55 -55
  1507. package/src/shade/renderer/animation/pose/pose_evaluate_local.js +179 -179
  1508. package/src/shade/renderer/animation/pose/pose_evaluate_world.js +76 -76
  1509. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +1024 -1024
  1510. package/src/shade/renderer/animation/skinning/SKINNING_BINDING_STRUCT.js +79 -79
  1511. package/src/shade/renderer/animation/skinning/chunk_skin_blend_mesh_local.js +56 -56
  1512. package/src/shade/renderer/binding/BindGroupManager.js +282 -282
  1513. package/src/shade/renderer/binding/adapt_cache_capacity.js +25 -25
  1514. package/src/shade/renderer/buffer/GPUBufferAllocator.js +116 -116
  1515. package/src/shade/renderer/buffer/buffer_pool_ops.js +123 -123
  1516. package/src/shade/renderer/buffer/table/GPU_DATABASE_PAGE_SIZE.js +9 -9
  1517. package/src/shade/renderer/buffer/table/GPU_DATABASE_UPLOAD_BUFFER_LIMIT.js +8 -8
  1518. package/src/shade/renderer/buffer/table/PageBufferPool.js +71 -71
  1519. package/src/shade/renderer/buffer/table/PageSlotAllocator.js +95 -95
  1520. package/src/shade/renderer/camera/Camera.js +281 -281
  1521. package/src/shade/renderer/camera/GPUCameraContext.js +233 -233
  1522. package/src/shade/renderer/camera/orbital/README.md +84 -84
  1523. package/src/shade/renderer/deferred/shader_composite_volumetrics.js +75 -75
  1524. package/src/shade/renderer/dynamic/DYNAMIC_MESH_VERTEX.js +25 -25
  1525. package/src/shade/renderer/dynamic/GPUDynamicMeshRenderer.js +342 -342
  1526. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.js +167 -167
  1527. package/src/shade/renderer/dynamic/shader_dynamic_mesh.js +170 -170
  1528. package/src/shade/renderer/extension/FrameContext.js +263 -263
  1529. package/src/shade/renderer/extension/FramePhase.js +104 -104
  1530. package/src/shade/renderer/extension/FrameRecord.js +126 -126
  1531. package/src/shade/renderer/extension/GBufferTextures.js +83 -83
  1532. package/src/shade/renderer/extension/PresentTarget.js +34 -34
  1533. package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +918 -918
  1534. package/src/shade/renderer/extension/RenderExtension.js +69 -69
  1535. package/src/shade/renderer/extension/RenderExtensionRegistry.js +319 -319
  1536. package/src/shade/renderer/extension/SceneColor.js +40 -40
  1537. package/src/shade/renderer/extension/ViewTextures.js +78 -78
  1538. package/src/shade/renderer/fow/GPUFogOfWarRenderer.js +182 -182
  1539. package/src/shade/renderer/geometry/Geometry.js +608 -608
  1540. package/src/shade/renderer/geometry/geometry_build_from_meshlet_geometry.js +342 -342
  1541. package/src/shade/renderer/geometry/meshlet_geometry_transfer.js +41 -41
  1542. package/src/shade/renderer/geometry/primitives/make_box_geometry.js +153 -153
  1543. package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.js +240 -240
  1544. package/src/shade/renderer/geometry/primitives/make_plane_geometry.js +145 -145
  1545. package/src/shade/renderer/geometry/primitives/make_polyhedron_geometry.js +327 -327
  1546. package/src/shade/renderer/geometry/primitives/make_torus_geometry.js +107 -107
  1547. package/src/shade/renderer/geometry/primitives/make_torus_knot_geometry.js +165 -165
  1548. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +607 -607
  1549. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.js +66 -66
  1550. package/src/shade/renderer/geometry/virtual/build/VGeoBuildResult.js +32 -32
  1551. package/src/shade/renderer/geometry/virtual/build/VGeoFaceGraph.js +103 -103
  1552. package/src/shade/renderer/geometry/virtual/build/VGeoGatheredFaces.js +25 -25
  1553. package/src/shade/renderer/geometry/virtual/build/VGeoLevel.js +33 -33
  1554. package/src/shade/renderer/geometry/virtual/build/VGeoLevelOptions.js +62 -62
  1555. package/src/shade/renderer/geometry/virtual/build/VGeoLevelSummary.js +49 -49
  1556. package/src/shade/renderer/geometry/virtual/build/VGeoSubmesh.js +20 -20
  1557. package/src/shade/renderer/geometry/virtual/build/VirtualGeometryMesh.js +214 -214
  1558. package/src/shade/renderer/geometry/virtual/build/gltf/GltfByteSource.js +122 -122
  1559. package/src/shade/renderer/geometry/virtual/build/gltf/GltfCollectReport.js +29 -29
  1560. package/src/shade/renderer/geometry/virtual/build/gltf/GltfDocument.js +210 -210
  1561. package/src/shade/renderer/geometry/virtual/build/gltf/GltfGeometry.js +48 -48
  1562. package/src/shade/renderer/geometry/virtual/build/gltf/GltfGeometryInstance.js +25 -25
  1563. package/src/shade/renderer/geometry/virtual/build/gltf/GltfGeometrySelection.js +28 -28
  1564. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_collect_geometries.js +296 -296
  1565. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_open_document.js +166 -166
  1566. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_read_geometry.js +199 -199
  1567. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.js +173 -173
  1568. package/src/shade/renderer/geometry/virtual/build/vgeo_bounding_sphere.js +28 -28
  1569. package/src/shade/renderer/geometry/virtual/build/vgeo_build.js +200 -200
  1570. package/src/shade/renderer/geometry/virtual/build/vgeo_build_levels.js +1786 -1786
  1571. package/src/shade/renderer/geometry/virtual/build/vgeo_build_page_nodes.js +157 -157
  1572. package/src/shade/renderer/geometry/virtual/build/vgeo_build_root_group.js +26 -26
  1573. package/src/shade/renderer/geometry/virtual/build/vgeo_compute_vertex_normals.js +75 -75
  1574. package/src/shade/renderer/geometry/virtual/build/vgeo_compute_vertex_tangents.js +143 -143
  1575. package/src/shade/renderer/geometry/virtual/build/vgeo_containing_sphere.js +44 -44
  1576. package/src/shade/renderer/geometry/virtual/build/vgeo_extract_submesh.js +41 -41
  1577. package/src/shade/renderer/geometry/virtual/build/vgeo_gather_faces.js +71 -71
  1578. package/src/shade/renderer/geometry/virtual/build/vgeo_graph_components.js +123 -123
  1579. package/src/shade/renderer/geometry/virtual/build/vgeo_narrow_indices.js +26 -26
  1580. package/src/shade/renderer/geometry/virtual/build/vgeo_normalize_source.js +112 -112
  1581. package/src/shade/renderer/geometry/virtual/build/vgeo_partition_graph.js +56 -56
  1582. package/src/shade/renderer/geometry/virtual/build/vgeo_sphere_inflate_to_contain.js +70 -70
  1583. package/src/shade/renderer/geometry/virtual/build/vgeo_split_face_set.js +187 -187
  1584. package/src/shade/renderer/geometry/virtual/build/vgeo_split_face_set_packed.js +207 -207
  1585. package/src/shade/renderer/geometry/virtual/format/VGEO_DEFECT.js +18 -18
  1586. package/src/shade/renderer/geometry/virtual/format/VGeoDefect.js +38 -38
  1587. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.js +64 -64
  1588. package/src/shade/renderer/geometry/virtual/format/attribute/VGEO_ATTRIBUTE.js +13 -13
  1589. package/src/shade/renderer/geometry/virtual/format/attribute/VGEO_ATTRIBUTES.js +50 -50
  1590. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attribute_allocate.js +28 -28
  1591. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attribute_mask.js +23 -23
  1592. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attributes_read.js +31 -31
  1593. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_copy_vertex.js +32 -32
  1594. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_declare.js +46 -46
  1595. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_like.js +19 -19
  1596. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_test_fixtures.js +27 -27
  1597. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_asset_id_preimage.js +62 -62
  1598. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_asset_id.js +13 -13
  1599. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_directory_block_checksum.js +41 -41
  1600. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_frame_checksum.js +41 -41
  1601. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_header_checksum.js +25 -25
  1602. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_OFFSET.js +20 -20
  1603. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_RECORD_SIZE.js +5 -5
  1604. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_MAX_CHILD_REF.js +5 -5
  1605. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_MAX_CLUSTER_TRIANGLE_COUNT.js +5 -5
  1606. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_MAX_CLUSTER_VERTEX_COUNT.js +5 -5
  1607. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_NO_CHILD.js +5 -5
  1608. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_NO_GROUP.js +5 -5
  1609. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_SAME_PAGE.js +6 -6
  1610. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.js +81 -81
  1611. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryGroup.js +37 -37
  1612. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryPageNode.js +55 -55
  1613. package/src/shade/renderer/geometry/virtual/format/directory/VGEO_DIRECTORY_BLOCK_RECORDS.js +5 -5
  1614. package/src/shade/renderer/geometry/virtual/format/directory/VGEO_DIRECTORY_FLAG_ROOT_PAGE.js +5 -5
  1615. package/src/shade/renderer/geometry/virtual/format/directory/VGEO_DIRECTORY_RECORD_SIZE.js +5 -5
  1616. package/src/shade/renderer/geometry/virtual/format/directory/vgeo_directory_block_count.js +12 -12
  1617. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CHILD_OFFSET.js +11 -11
  1618. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CHILD_TABLE_ENTRY_SIZE.js +5 -5
  1619. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_LZ4.js +11 -11
  1620. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_RAW.js +5 -5
  1621. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_FRAME_ALIGNMENT.js +5 -5
  1622. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_FRAME_HEADER_SIZE.js +5 -5
  1623. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_FRAME_OFFSET.js +13 -13
  1624. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_PAGE_MAGIC.js +5 -5
  1625. package/src/shade/renderer/geometry/virtual/format/frame/VGeoFrameBlob.js +21 -21
  1626. package/src/shade/renderer/geometry/virtual/format/frame/VGeoFrameExtent.js +59 -59
  1627. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_codec_name.js +27 -27
  1628. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_decode_frame_blob.js +84 -84
  1629. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.js +56 -56
  1630. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_frame_decode_bound.js +35 -35
  1631. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_scan_frames.js +74 -74
  1632. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.js +6 -6
  1633. package/src/shade/renderer/geometry/virtual/format/header/VGEO_HASH_ALGO_XXH3.js +5 -5
  1634. package/src/shade/renderer/geometry/virtual/format/header/VGEO_HEADER_OFFSET.js +31 -31
  1635. package/src/shade/renderer/geometry/virtual/format/header/VGEO_HEADER_SIZE.js +5 -5
  1636. package/src/shade/renderer/geometry/virtual/format/header/VGEO_LEVEL_OFFSET.js +20 -20
  1637. package/src/shade/renderer/geometry/virtual/format/header/VGEO_LEVEL_RECORD_SIZE.js +9 -9
  1638. package/src/shade/renderer/geometry/virtual/format/header/VGEO_MAGIC.js +5 -5
  1639. package/src/shade/renderer/geometry/virtual/format/header/VGEO_MIN_READER_VERSION.js +5 -5
  1640. package/src/shade/renderer/geometry/virtual/format/header/VGEO_PAYLOAD_ENCODING_SHADE_MESHLET_V1.js +5 -5
  1641. package/src/shade/renderer/geometry/virtual/format/header/VGeoLevelRecord.js +41 -41
  1642. package/src/shade/renderer/geometry/virtual/format/page/VGEO_GROUP_RECORD_SIZE.js +5 -5
  1643. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_GROUP_CLUSTER_COUNT.js +6 -6
  1644. package/src/shade/renderer/geometry/virtual/format/page/VGEO_METRIC_OFFSET.js +21 -21
  1645. package/src/shade/renderer/geometry/virtual/format/page/VGEO_METRIC_SIZE.js +5 -5
  1646. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_FANOUT.js +9 -9
  1647. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_FLAG_LEAF.js +5 -5
  1648. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_OFFSET.js +10 -10
  1649. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_RECORD_SIZE.js +5 -5
  1650. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_HEADER_SIZE.js +5 -5
  1651. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET.js +16 -16
  1652. package/src/shade/renderer/geometry/virtual/format/payload/VGEO_ENCODING_FLAGS_MASK.js +6 -6
  1653. package/src/shade/renderer/geometry/virtual/format/payload/VGeoEncodedPayload.js +18 -18
  1654. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_encode_cluster_payload.js +200 -200
  1655. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_payload_attribute_offset.js +39 -39
  1656. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_payload_size.js +20 -20
  1657. package/src/shade/renderer/geometry/virtual/format/prototypeVGEOFormatViewer.js +2063 -2063
  1658. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.js +1622 -1622
  1659. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +485 -485
  1660. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_empty_gpu_structure.d.ts +23 -0
  1661. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_empty_gpu_structure.d.ts.map +1 -0
  1662. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_empty_gpu_structure.js +34 -0
  1663. package/src/shade/renderer/gpu_primitive/sort/ffx/graph_radix_sort.js +115 -115
  1664. package/src/shade/renderer/gpu_primitive/sort/one_sweep/verify_radix_sort_one_sweep.js +110 -110
  1665. package/src/shade/renderer/light/environment/octahedral_resample_kernel.js +50 -50
  1666. package/src/shade/renderer/light/environment/octahedral_uv_to_direction.js +30 -30
  1667. package/src/shade/renderer/light/environment/resample_cube_to_octahedral.js +157 -157
  1668. package/src/shade/renderer/light/make_sunlight.js +35 -35
  1669. package/src/shade/renderer/light/model/io/light_record_point.js +39 -39
  1670. package/src/shade/renderer/loader/gltf/GLTF_PRIMITIVE_MODE.js +23 -23
  1671. package/src/shade/renderer/loader/gltf/MESHOPT_COMPRESSION_PLAN.md +793 -793
  1672. package/src/shade/renderer/loader/gltf/ext/GltfBufferViewExtension.js +54 -54
  1673. package/src/shade/renderer/loader/gltf/ext/GltfBufferViewExtensionSet.js +109 -109
  1674. package/src/shade/renderer/loader/gltf/ext/gltf_apply_buffer_view_extensions.js +69 -69
  1675. package/src/shade/renderer/loader/gltf/ext/gltf_buffer_view_extensions.js +22 -22
  1676. package/src/shade/renderer/loader/gltf/ext/gltf_geometry_extensions.js +39 -39
  1677. package/src/shade/renderer/loader/gltf/ext/meshopt/MeshoptBufferViewExtension.js +301 -301
  1678. package/src/shade/renderer/loader/gltf/gltf_component_type.js +223 -223
  1679. package/src/shade/renderer/loader/gltf/gltf_node_world_matrices.js +137 -137
  1680. package/src/shade/renderer/loader/gltf/gltf_parse_container.js +241 -241
  1681. package/src/shade/renderer/loader/gltf/gltf_read_accessor.js +294 -294
  1682. package/src/shade/renderer/loader/gltf/gltf_used_image_indices.js +49 -49
  1683. package/src/shade/renderer/loader/gltf/load_gltf.js +1253 -1253
  1684. package/src/shade/renderer/loader/gltf/tiny-gltf.js +646 -646
  1685. package/src/shade/renderer/loader/usd/UsdError.js +33 -33
  1686. package/src/shade/renderer/loader/usd/UsdExtensionRegistry.js +69 -69
  1687. package/src/shade/renderer/loader/usd/load_usd.js +226 -226
  1688. package/src/shade/renderer/loader/usd/parse_usda.js +931 -931
  1689. package/src/shade/renderer/loader/usd/unpack_usdz.js +106 -106
  1690. package/src/shade/renderer/loader/usd/usd_build_scene.js +658 -658
  1691. package/src/shade/renderer/loader/usd/usd_compose_transform.js +258 -258
  1692. package/src/shade/renderer/loader/usd/usd_decode_image.js +384 -384
  1693. package/src/shade/renderer/loader/usd/usd_lz4.js +182 -182
  1694. package/src/shade/renderer/loader/usd/usd_triangulate.js +159 -159
  1695. package/src/shade/renderer/material/ShadeMaterial.d.ts +2 -2
  1696. package/src/shade/renderer/material/ShadeMaterial.js +2 -2
  1697. package/src/shade/renderer/material/standard/fragment_gbuffer.js +334 -334
  1698. package/src/shade/renderer/material/standard/fragment_gbuffer_vt.js +169 -169
  1699. package/src/shade/renderer/material/standard/material_gbuffer_vertex.js +45 -45
  1700. package/src/shade/renderer/material/standard_material_to_struct.js +23 -23
  1701. package/src/shade/renderer/particles/prototypeParticleSystem.js +450 -450
  1702. package/src/shade/renderer/particles/runtime/spawn_request_encoding.js +52 -52
  1703. package/src/shade/renderer/pool/TransientResourcePool.js +392 -392
  1704. package/src/shade/renderer/postprocess/bloom/bloom_chain_resolution.js +29 -29
  1705. package/src/shade/renderer/postprocess/bloom/graph_bloom_downsample.js +109 -109
  1706. package/src/shade/renderer/postprocess/bloom/graph_postprocess_bloom.js +155 -155
  1707. package/src/shade/renderer/postprocess/cas/shader_ffx_rcas.js +114 -114
  1708. package/src/shade/renderer/postprocess/dof/DOF_AUTOFOCUS_PARAMS_STRUCT.js +25 -25
  1709. package/src/shade/renderer/postprocess/dof/DOF_FOCUS_STATE_STRUCT.js +23 -23
  1710. package/src/shade/renderer/postprocess/dof/DOF_PRESETS.js +27 -27
  1711. package/src/shade/renderer/postprocess/dof/chunk_dof_coc_band_diameter.js +41 -41
  1712. package/src/shade/renderer/postprocess/dof/chunk_dof_coc_band_radius.js +32 -32
  1713. package/src/shade/renderer/postprocess/dof/chunk_dof_coc_coefficient.js +26 -26
  1714. package/src/shade/renderer/postprocess/dof/compute_dof_autofocus_params.js +64 -64
  1715. package/src/shade/renderer/postprocess/dof/compute_dof_uniform.js +54 -54
  1716. package/src/shade/renderer/postprocess/dof/gather/DOF2_CONFIG.js +91 -91
  1717. package/src/shade/renderer/postprocess/dof/gather/DOF2_PRESETS.js +9 -9
  1718. package/src/shade/renderer/postprocess/dof/gather/DOF2_SETTINGS_STRUCT.js +66 -66
  1719. package/src/shade/renderer/postprocess/dof/gather/DOF2_TEXTURE_FORMAT.js +22 -22
  1720. package/src/shade/renderer/postprocess/dof/gather/DepthOfFieldU.js +292 -292
  1721. package/src/shade/renderer/postprocess/dof/gather/chunk_dof2_coc_to_near_far.js +25 -25
  1722. package/src/shade/renderer/postprocess/dof/gather/chunk_dof2_gather_weight.js +30 -30
  1723. package/src/shade/renderer/postprocess/dof/gather/compute_dof2_uniform.js +54 -54
  1724. package/src/shade/renderer/postprocess/dof/gather/graph_postprocess_dof2.js +194 -194
  1725. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_fill.js +68 -68
  1726. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_far.js +140 -140
  1727. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_near.js +142 -142
  1728. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_recombine.js +99 -99
  1729. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_setup.js +102 -102
  1730. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_tile_dilate.js +75 -75
  1731. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_tile_max.js +73 -73
  1732. package/src/shade/renderer/postprocess/dof/raymarch/DOF_SETTINGS_STRUCT.js +49 -49
  1733. package/src/shade/renderer/postprocess/dof/raymarch/DepthOfField.js +298 -298
  1734. package/src/shade/renderer/postprocess/dof/raymarch/graph_postprocess_dof.js +244 -244
  1735. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_composite.js +91 -91
  1736. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_firefly_cleanup.js +61 -61
  1737. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_prefilter.js +90 -90
  1738. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch_compute.js +267 -267
  1739. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_slice_compute.js +271 -271
  1740. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_tile_dilate.js +70 -70
  1741. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_tile_max.js +72 -72
  1742. package/src/shade/renderer/postprocess/dof/shader_dof_autofocus.js +99 -99
  1743. package/src/shade/renderer/postprocess/gtao/generate_magic_square_noise.js +51 -51
  1744. package/src/shade/renderer/postprocess/motion_blur/MotionBlur.js +56 -56
  1745. package/src/shade/renderer/postprocess/upscale-dither/NOTES.md +78 -78
  1746. package/src/shade/renderer/postprocess/upscale-dither/UpscaleDither.js +95 -95
  1747. package/src/shade/renderer/postprocess/upscale-dither/fragment_shader_upscale_dither.js +204 -204
  1748. package/src/shade/renderer/rasterize/bucket/construct_primitive_state.js +58 -58
  1749. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.js +230 -230
  1750. package/src/shade/renderer/rasterize/native/graph_rasterize_meshes_alpha_tested.js +278 -278
  1751. package/src/shade/renderer/rasterize/native/oit/chunk_material_side_should_draw.js +26 -26
  1752. package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments_ibl.js +178 -178
  1753. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +235 -235
  1754. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +208 -208
  1755. package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.js +206 -206
  1756. package/src/shade/renderer/scene/DynamicMesh.js +70 -70
  1757. package/src/shade/renderer/scene/DynamicMeshBatch.js +90 -90
  1758. package/src/shade/renderer/scene/GPUSceneContext.js +901 -901
  1759. package/src/shade/renderer/scene/SceneNodeBinding.js +56 -56
  1760. package/src/shade/renderer/scene/SkinnedMesh.js +55 -55
  1761. package/src/shade/renderer/scene/TransformAuthority.js +33 -33
  1762. package/src/shade/renderer/scene/optimization/deduplicate_geometries.js +38 -38
  1763. package/src/shade/renderer/scene/optimization/deduplicate_images.js +93 -93
  1764. package/src/shade/renderer/scene/optimization/geometry/internal/anchor_grow_topological.d.ts.map +1 -1
  1765. package/src/shade/renderer/scene/optimization/geometry/internal/anchor_grow_topological.js +12 -3
  1766. package/src/shade/renderer/scene/optimization/geometry/internal/match_refit_validate.js +127 -127
  1767. package/src/shade/renderer/scene/optimization/geometry/internal/match_solve_transform.js +492 -492
  1768. package/src/shade/renderer/scene/optimization/geometry/internal/match_validate_topology.js +3 -3
  1769. package/src/shade/renderer/scene/optimization/geometry/internal/seed_correspondence_from_window.js +3 -3
  1770. package/src/shade/renderer/scene/optimization/optimize_texture_set.js +81 -81
  1771. package/src/shade/renderer/scene/optimization/source_to_sampler2d.js +21 -21
  1772. package/src/shade/renderer/scene/serialization/STANDARD_MATERIAL_SERIALIZED_BYTE_SIZE.js +12 -12
  1773. package/src/shade/renderer/scene/serialization/deserialize_scene.d.ts.map +1 -1
  1774. package/src/shade/renderer/scene/serialization/deserialize_scene.js +0 -2
  1775. package/src/shade/renderer/shader/chunk/geometry/quaternion/dual/chunk_dual_quat_transform_point.js +26 -26
  1776. package/src/shade/renderer/shader/chunk/noise/chunk_interleaved_gradient_noise.js +20 -20
  1777. package/src/shade/renderer/shader/chunk/spherical_harmonics/dering/chunk_sh2_dering_optimize_positive.js +61 -61
  1778. package/src/shade/renderer/shader/chunk/texture/chunk_texture_filter_fxaa_lite.js +225 -225
  1779. package/src/shade/renderer/shader/chunk/texture/dither/chunk_dither_color_8bit_gradient_noise.js +25 -25
  1780. package/src/shade/renderer/shadow/map/DirectionalLightShadowmap.js +384 -384
  1781. package/src/shade/renderer/shadow/map/PointLightShadowmap.js +105 -105
  1782. package/src/shade/renderer/shadow/map/SpotLightShadowmap.js +63 -63
  1783. package/src/shade/renderer/shadow/map/TetrahedronPointLightShadowmap.js +89 -89
  1784. package/src/shade/renderer/shadow/map/shadowmap_update_score.js +232 -232
  1785. package/src/shade/renderer/texture/GPUTextureAllocator.js +85 -85
  1786. package/src/shade/renderer/texture/texture_pool_ops.js +171 -171
  1787. package/src/shade/renderer/texture/virtual/PageTableQuadAllocator.js +253 -253
  1788. package/src/shade/renderer/texture/virtual/README.md +276 -276
  1789. package/src/shade/renderer/texture/virtual/VTPageTable.js +330 -330
  1790. package/src/shade/renderer/texture/virtual/VTPhysicalCache.js +349 -349
  1791. package/src/shade/renderer/texture/virtual/VT_CONSTANTS.js +154 -154
  1792. package/src/shade/renderer/texture/virtual/VT_STACK_INFO_STRUCT.js +20 -20
  1793. package/src/shade/renderer/texture/virtual/VirtualTextureManager.js +1276 -1276
  1794. package/src/shade/renderer/texture/virtual/VirtualTextureStack.js +106 -106
  1795. package/src/shade/renderer/texture/virtual/build_chunk_vt_lookup.js +150 -150
  1796. package/src/shade/renderer/texture/virtual/build_shader_vt_feedback.js +232 -232
  1797. package/src/shade/renderer/texture/virtual/chunk_vt_request_key.js +28 -28
  1798. package/src/shade/renderer/texture/virtual/source/VTSourceImage.js +207 -207
  1799. package/src/shade/renderer/texture/virtual/source/VTSourceProcedural.js +135 -135
  1800. package/src/shade/renderer/texture/virtual/source/VTSourceTiled.js +132 -132
  1801. package/src/shade/renderer/water/GPUWaterRenderer.js +167 -167
  1802. package/src/shade/renderer/water/shader_water.js +246 -246
  1803. package/src/shade/renderer/water/water_height_texture_from_sampler.js +56 -56
  1804. package/src/shade/vitest.setup.mjs +89 -89
  1805. package/src/shade/wgsl/validate_wgsl_source.js +316 -316
  1806. package/src/view/controller/controls/NumericIntervalControl.js +90 -90
  1807. package/src/view/controller/controls/Vector2Control.js +83 -83
  1808. package/src/view/controller/controls/Vector3Control.js +90 -90
  1809. package/src/view/elements/Group.js +56 -56
  1810. package/src/view/elements/drawCheckers.js +33 -33
  1811. package/src/view/elements/windrose/WindRoseDiagram.js +369 -369
  1812. package/src/view/graphics/WebGLContextFailureView.js +76 -76
  1813. package/src/view/layout/DockPanel.js +51 -51
  1814. package/src/view/layout/SplitView.js +365 -365
  1815. package/src/view/layout/show_popup_menu.js +81 -81
  1816. package/src/view/minimap/MinimapCanvasView.js +411 -411
  1817. package/src/view/minimap/MinimapImageCache.js +88 -88
  1818. package/src/view/minimap/MinimapMarkerCollection.d.ts +0 -1
  1819. package/src/view/minimap/MinimapMarkerCollection.d.ts.map +1 -1
  1820. package/src/view/minimap/MinimapMarkerCollection.js +180 -180
  1821. package/src/view/minimap/dom/MinimapCameraView.js +206 -206
  1822. package/src/view/minimap/minimap_focus_area.js +97 -97
  1823. package/editor/process/symbolic/SocketsSymbolicDisplay.js +0 -192
  1824. package/src/core/geom/3d/topology/struct/binary/io/moved_tests.txt +0 -37
  1825. package/src/engine/ecs/attachment/Attachment.d.ts +0 -40
  1826. package/src/engine/ecs/attachment/Attachment.d.ts.map +0 -1
  1827. package/src/engine/ecs/attachment/Attachment.js +0 -57
  1828. package/src/engine/ecs/attachment/AttachmentBinding.d.ts +0 -28
  1829. package/src/engine/ecs/attachment/AttachmentBinding.d.ts.map +0 -1
  1830. package/src/engine/ecs/attachment/AttachmentBinding.js +0 -41
  1831. package/src/engine/ecs/attachment/AttachmentSystem.d.ts +0 -61
  1832. package/src/engine/ecs/attachment/AttachmentSystem.d.ts.map +0 -1
  1833. package/src/engine/ecs/attachment/AttachmentSystem.js +0 -307
  1834. package/src/engine/ecs/attachment/BoneAttachmentBinding.d.ts +0 -27
  1835. package/src/engine/ecs/attachment/BoneAttachmentBinding.d.ts.map +0 -1
  1836. package/src/engine/ecs/attachment/BoneAttachmentBinding.js +0 -69
  1837. package/src/engine/ecs/attachment/TransformAttachmentBinding.d.ts +0 -4
  1838. package/src/engine/ecs/attachment/TransformAttachmentBinding.d.ts.map +0 -1
  1839. package/src/engine/ecs/attachment/TransformAttachmentBinding.js +0 -51
  1840. package/src/engine/ecs/sockets/AttachmentSocket.d.ts +0 -32
  1841. package/src/engine/ecs/sockets/AttachmentSocket.d.ts.map +0 -1
  1842. package/src/engine/ecs/sockets/AttachmentSocket.js +0 -60
  1843. package/src/engine/ecs/sockets/AttachmentSocketType.d.ts +0 -6
  1844. package/src/engine/ecs/sockets/AttachmentSocketType.d.ts.map +0 -1
  1845. package/src/engine/ecs/sockets/AttachmentSocketType.js +0 -8
  1846. package/src/engine/ecs/sockets/AttachmentSockets.d.ts +0 -57
  1847. package/src/engine/ecs/sockets/AttachmentSockets.d.ts.map +0 -1
  1848. package/src/engine/ecs/sockets/AttachmentSockets.js +0 -130
  1849. package/src/engine/ecs/sockets/BoneAttachmentSocket.d.ts +0 -29
  1850. package/src/engine/ecs/sockets/BoneAttachmentSocket.d.ts.map +0 -1
  1851. package/src/engine/ecs/sockets/BoneAttachmentSocket.js +0 -56
  1852. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.d.ts +0 -6
  1853. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.d.ts.map +0 -1
  1854. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.js +0 -19
  1855. package/src/shade/renderer/animation/_dump_resolve.d.mts +0 -2
  1856. package/src/shade/renderer/animation/_dump_resolve.d.mts.map +0 -1
  1857. package/src/shade/renderer/animation/_dump_resolve.mjs +0 -5
  1858. package/src/shade/renderer/scene/optimization/geometry/internal/bt_face_loop_helpers.d.ts +0 -32
  1859. package/src/shade/renderer/scene/optimization/geometry/internal/bt_face_loop_helpers.d.ts.map +0 -1
  1860. package/src/shade/renderer/scene/optimization/geometry/internal/bt_face_loop_helpers.js +0 -77
  1861. package/src/shade/renderer/scene/optimization/geometry/internal/bt_find_edge_between.d.ts +0 -12
  1862. package/src/shade/renderer/scene/optimization/geometry/internal/bt_find_edge_between.d.ts.map +0 -1
  1863. package/src/shade/renderer/scene/optimization/geometry/internal/bt_find_edge_between.js +0 -35
  1864. package/src/shade/renderer/scene/serialization/linear_to_pq.d.ts +0 -2
  1865. package/src/shade/renderer/scene/serialization/linear_to_pq.d.ts.map +0 -1
  1866. package/src/shade/renderer/scene/serialization/linear_to_pq.js +0 -14
  1867. package/src/shade/renderer/scene/serialization/pq_to_linear.d.ts +0 -9
  1868. package/src/shade/renderer/scene/serialization/pq_to_linear.d.ts.map +0 -1
  1869. package/src/shade/renderer/scene/serialization/pq_to_linear.js +0 -30
@@ -1,918 +1,918 @@
1
- # Render extensions — design
2
-
3
- Replaces `Renderer.add_pass` / `remove_pass`, `FramePhase`, `FramePassContext` and
4
- `FramePassRegistry` (MEEP 3, phase 2, item S3).
5
-
6
- Status: **design, not built.** Nothing in §3 through §11 is committed code.
7
-
8
- **Revised 2026-08-24** against the frame-graph work that has landed since the first draft:
9
- `FrameGraphState`, `validate()`, recording scopes, record-time producers, and the `exportToJson`
10
- fix. Those came out of this document's §4 and §13 and are tracked in
11
- `engine/graphics/render/frame_graph/FRAME_GRAPH_RECOMMENDATIONS.md`. §1.2, §3.4, §4, §5 and §13
12
- describe what the graph does now, not what it did — the net effect is that the design leans on the
13
- graph in three more places and asks it for nothing.
14
-
15
- The same revision **withdrew the cull diagnostic** and the engine change it needed, on sponsor
16
- review: culling is what a frame graph is for, and a check that calls it a failure when an extension
17
- is the recorder invents a distinction that does not exist and outlaws the speculative producer.
18
- §5.1 is the argument; the bar it sets — a check may only fire on something that cannot be true —
19
- also took out a provenance check in §3.4.
20
-
21
- ---
22
-
23
- ## 0. Summary
24
-
25
- An extension is a **named object with declarations** — a phase, ordering constraints, the optional
26
- frame products it needs — and one method that records into the frame's graph. Everything it exchanges
27
- with the frame goes through **typed per-frame records** holding frame-graph handles: it reads a
28
- handle out of a record and writes a replacement back. There is no return value and no privileged
29
- resource.
30
-
31
- Three properties follow, and they are the point:
32
-
33
- 1. **Every resource the frame carries is exchangeable**, not just the colour. The G-buffer stops
34
- being a documented special case, depth stops being read-only, and an extension can publish a
35
- record of its own that another extension reads.
36
- 2. **Order is declared**, not emergent from the order in which ECS systems happened to reach their
37
- first `await`.
38
- 3. **The frame can be described without being rendered, and read back attributed once it has been.**
39
- The set of extensions, their order per phase, and the products they force on are data, so
40
- `describe()` prints the pipeline; and the registry records each extension inside its own graph
41
- scope, so a DOT export of the frame groups by who asked for what instead of by whatever the
42
- `graph_*` helpers named things. That pair is what "the frame graph is a first-class construct"
43
- has to mean at this seam.
44
-
45
- Underneath all three, one correction that is not an abstraction: **the upscale is a phase boundary
46
- and the surface says so.** Three phases are before it and two are after, the before case is the
47
- common one, and the size of what an extension is drawing into is derived from the live handle rather
48
- than handed over as a field the renderer fills in once for the whole frame — which is what the
49
- current mechanism does, and gets wrong at two of its five phases (§1.3b).
50
-
51
- The shape is Unity 6 URP's — `ContextContainer` / `ContextItem`, `ScriptableRenderPass`,
52
- `ConfigureInput` — with URP's two worst traits removed (§2).
53
-
54
- ---
55
-
56
- ## 1. What is wrong with `add_pass`
57
-
58
- ### 1.1 One resource is modifiable
59
-
60
- `FramePassRegistry.run` threads exactly one value:
61
-
62
- ```js
63
- const produced = passes[i](context);
64
- if (produced === undefined) { continue; }
65
- context.color = produced;
66
- ```
67
-
68
- A pass's only sanctioned output is a colour handle. Everything else on `FramePassContext` — depth,
69
- previous depth, the four G-buffer targets, the two visibility targets — is an input. The one
70
- exception, the G-buffer being in/out at `AfterGBuffer`, is implemented by letting the pass reach into
71
- `context.gbuffer` and assign, and costs three paragraphs of prose in `FramePassContext` to explain
72
- why replacing beats writing in place.
73
-
74
- What that closes off, concretely: writing depth (terrain and water both rasterize geometry that
75
- should own depth), publishing a resource an extension computed for other extensions to read (fog of
76
- war's visibility grid is exactly this and currently lives outside the graph), and reading anything
77
- the frame builds but the struct does not name — velocity, the Hi-Z pyramid, the TAA history, the
78
- shadow atlas, the light cluster tables.
79
-
80
- The struct is closed by construction: adding a field is an edit to Shade. That is the wrong cost for
81
- "my game needs one more thing from the frame".
82
-
83
- ### 1.2 The graph is an escape hatch, not the mechanism
84
-
85
- `context.graph` hands the pass the `FrameGraph` and steps back. The registry never learns what the
86
- pass read or wrote, so:
87
-
88
- - **It cannot order passes.** It orders by registration order.
89
- - **It cannot attribute anything.** `exportToDot` shows the nodes an extension created with whatever
90
- names its helpers gave them, unrelated to the extension. The graph has since gained recording
91
- scopes, which are exactly the missing mechanism — but they are opt-in and `add_pass` opens none,
92
- so a frame's DOT export is still one flat wall of passes.
93
- - **It cannot validate.** Reading `context.color` at `AfterGBuffer` yields `-1` and fails somewhere
94
- inside a binding builder. Retaining a handle across frames is undetectable. Publishing a stale
95
- handle is now caught, but by the graph at `compile()` and against the *reader* — the pass that
96
- consumed it — so the report names the built-in pass that broke, never the extension that handed
97
- it the bad handle.
98
- - **`AfterGBuffer` has no return channel, so the culling contract cannot be met there.** The rule
99
- itself is the graph's, and it is right everywhere: work nothing consumes is elided. But the only
100
- way this mechanism lets a pass thread its result into the frame is by returning a colour handle,
101
- and at `AfterGBuffer` there is no colour — so a pass whose G-buffer work *should* be consumed
102
- reaches for `make_side_effect()` instead, which does not say "my output is used", it says "run me
103
- anyway". Three paragraphs of `FramePhase` document the workaround. The record model removes the
104
- reason for it (§3.3) and leaves the culling rule alone (§5.1).
105
-
106
- And the injection points themselves are call sites: a phase is wherever `#run_frame_passes` was
107
- typed inside an 800-line method. There are five because five were typed.
108
-
109
- ### 1.3 What this has already produced
110
-
111
- Four findings from reading the current code, each independent of the design that replaces it.
112
-
113
- **(a) Order is an accident, and the code says so.** `TerrainSystem3.startup`:
114
-
115
- > `// before anything is awaited, so that pass order within the phase is the profile's system order —`
116
- > `// the decal composite has to see the textured ground, not precede it`
117
-
118
- An ordering requirement between two extensions is being met by placing a registration call above an
119
- `await`. Adding an `await` to a system's startup silently reorders the frame.
120
-
121
- The same mechanism decides the six-deep chain at `AfterTransparency`, and **it has already produced a
122
- shipped bug**. In profile order that chain is fog of war, particles, path display, highlight, debug
123
- draw, trails — so the fog composites *first* and everything drawn after it is unfogged. Confirmed
124
- with the sponsor: that is not intended. Fog of war conceals, so it belongs over everything it
125
- conceals; particles drawing on top of it defeat what it is for.
126
-
127
- Nobody chose that order. Nothing recorded it. Nothing failed when it turned out wrong. That is the
128
- argument for §3.6 in one paragraph.
129
-
130
- **(b) The one size the context states is wrong at two phases.** `Renderer` fills
131
- `pass_context.resolution` from `resolution_internal.asArray()`, once, for all five phases. But TAA
132
- and NSS upscale to `output_resolution` before `BeforePresent`, and the tonemap writes the canvas at
133
- output resolution — so at `BeforePresent` and `Overlay` the colour is *not* the size the context
134
- reports, whenever TAA is on. With TAA off it is, because the upscale is missing (there is a `TODO`
135
- in `Renderer` saying so). The size of the frame's colour at `BeforePresent` is therefore not
136
- derivable from the context at all; it depends on a renderer feature flag the extension cannot see.
137
-
138
- `probeShadePassInjection` — the gate for the current mechanism — does
139
- `output_resolution: context.resolution` at `BeforePresent`. It passes because the probe runs at 100%
140
- scale. The game ships with dynamic resolution scaling enabled against a 30 fps floor, and at any
141
- scale below 100% that pass produces a cropped, wrongly-scaled frame while the gate still measures a
142
- luminance change and reports green.
143
-
144
- The single field is the tell: the surface was built as though a frame had one resolution. Three of
145
- the five phases are before the upscale and two are after it, and nothing in the surface says which
146
- is which — `FramePhase`'s own text for `BeforePresent` says "still HDR" and never mentions that the
147
- colour has been upscaled by then. §3.5 makes the boundary part of what a phase *is*.
148
-
149
- **(c) `-1` is a sentinel with no guard.** `color` is `-1` at `AfterGBuffer`. Nothing stops a pass
150
- reading it. The house rule is that the common case is the only case and preconditions are asserted,
151
- not encoded as magic values.
152
-
153
- **(d) The G-buffer special case exists only because colour owns the return channel.** Given a
154
- uniform way to publish any handle, "the G-buffer is in/out at one phase" stops being a rule and
155
- becomes an instance of the general one.
156
-
157
- ---
158
-
159
- ## 2. What is borrowed from URP, and what is not
160
-
161
- Borrowed:
162
-
163
- | URP 6 | Here | Why |
164
- | --- | --- | --- |
165
- | `ContextContainer` + `ContextItem` | `FrameContext.get(RecordType)` + frame records | The open, typed resource vocabulary. This is the fix for §1.1, and the reason it is keyed by type rather than by string is that the house rule forbids string-keyed registries. |
166
- | `UniversalResourceData` | `SceneColor`, `GBufferTextures`, `ViewTextures`, `PresentTarget` | Built-in resources are ordinary classes with named fields, carried in the same container as anyone else's. One mechanism, not two. |
167
- | `ScriptableRenderPass` | `RenderExtension` | A declaring object, not a closure. Declarations are what makes ordering, validation and description possible. |
168
- | `ConfigureInput(ScriptableRenderPassInput.Motion)` | `RenderExtension.requires` + `FrameProduct` | An extension states what the frame must produce and the renderer turns it on. This is the answer to "velocity exists, is built, and is unreachable". |
169
- | Renderer feature list, ordered | The registry's resolved order, printable | The pipeline is inspectable before it runs. |
170
-
171
- Not borrowed, deliberately:
172
-
173
- - **`RenderPassEvent` + integer offsets.** URP orders same-event passes by an `int` you add to the
174
- enum. It is the same defect as registration order with an extra step: unreadable, unstable under
175
- insertion, and it makes every ordering question a numerology question. Replaced by explicit
176
- `after` / `before` constraints over extension classes (§3.6).
177
- - **`SetGlobalTexture` / global shader state.** An implicit channel between passes that the graph
178
- cannot see. Records are the channel.
179
- - **`AddUnsafePass`.** URP needs a legacy `CommandBuffer` escape hatch. There is no legacy to carry
180
- here, and adding an unchecked door on day one guarantees it becomes the door.
181
- - **Two-level feature/pass split.** URP splits `ScriptableRendererFeature` from
182
- `ScriptableRenderPass` because a feature is a `ScriptableObject` living on an asset. That reason
183
- does not exist here, so there is one class.
184
-
185
- ---
186
-
187
- ## 3. The model
188
-
189
- ### 3.1 `RenderExtension`
190
-
191
- ```js
192
- export class RenderExtension {
193
- /**
194
- * Stable identity. Used in ordering diagnostics, error decoration and `describe()`.
195
- * @type {string}
196
- */
197
- name = "";
198
-
199
- /** @type {FramePhase} */
200
- phase = FramePhase.AfterTransparency;
201
-
202
- /**
203
- * Extension classes this one records after / before. Constructors, not instances — an
204
- * extension does not need a reference to another system's object to state an order.
205
- * @type {Function[]}
206
- */
207
- after = [];
208
- before = [];
209
-
210
- /**
211
- * Optional frame products this extension reads. A bitmask of {@link FrameProduct}.
212
- * Reading a product nobody required is an assert failure, not a silent `-1`.
213
- * @type {number}
214
- */
215
- requires = 0;
216
-
217
- /**
218
- * Record this extension's work into the frame. Called once per frame, when the phase comes
219
- * round. Returns nothing: everything this produces reaches the rest of the frame by
220
- * publication (§3.4).
221
- *
222
- * @param {FrameContext} frame
223
- */
224
- record(frame) {}
225
- }
226
- ```
227
-
228
- `record` returning `void` is load-bearing. It is what makes colour stop being privileged.
229
-
230
- An extension that has nothing to draw this frame returns without recording; that is the only "off"
231
- switch and there is no `enabled` flag beside it.
232
-
233
- ### 3.2 `FrameContext`
234
-
235
- ```js
236
- export class FrameContext {
237
- /** @type {FrameGraph} the frame's graph — record into this with the `graph_*` helpers */
238
- graph;
239
- /** @type {ViewRenderContext} */
240
- view;
241
- /** @type {FramePhase} */
242
- phase;
243
-
244
- /** @template T @param {new()=>T} type @returns {T} throws if not present at this phase */
245
- get(type) {}
246
-
247
- /** @param {Function} type @returns {boolean} */
248
- has(type) {}
249
-
250
- /** @template T @param {new()=>T} type @returns {T} adds a record this extension owns */
251
- create(type) {}
252
-
253
- /**
254
- * Pixel size of the target this phase carries, derived from the live handle rather than filled
255
- * in by the renderer.
256
- * @returns {number[]}
257
- */
258
- get resolution() {}
259
-
260
- /** @param {number} handle @returns {ResourceDescriptor} size, format and usage of a handle */
261
- describe(handle) {}
262
- }
263
- ```
264
-
265
- Three accessors rather than one `get_or_create`, because "absent" has to stay distinguishable from
266
- "empty" — that is what lets `get(SceneColor)` at `AfterGBuffer` throw with a sentence instead of
267
- handing back `-1`.
268
-
269
- **`resolution` is derived, and that is the whole of the fix for defect (b).** It reads the graph
270
- through the handle this phase's target actually is, so it is right before the upscale, right after
271
- it, right when TAA is off and the upscale does not happen at all, and right at every dynamic
272
- resolution scale. The common case — "how big is the thing I am drawing into" — stays one property
273
- access and cannot be wrong.
274
-
275
- `describe(handle)` is the general form, and it is needed whenever two things in one pass are
276
- different sizes: an extension at `BeforePresent` reading the G-buffer is working across the upscale
277
- boundary and has to ask for both.
278
-
279
- > Both lean on descriptors being trustworthy, which was checked: transient and imported resources
280
- > both carry a real `TextureResourceDescriptor` holding absolute pixels.
281
- > `TextureResourceDescriptor.resolution_domain` says otherwise by default and is vestigial — nothing
282
- > branches on it, only `hash()` folds it in. It stays; it is now documented as vestigial on the field
283
- > itself so the next reader does not take it for a contract.
284
-
285
- ### 3.3 Frame records
286
-
287
- A record is a plain class holding frame-graph handles. The renderer publishes the built-in ones as
288
- the frame reaches the phase where they are meaningful.
289
-
290
- ```js
291
- /** present from AfterGBuffer */
292
- class GBufferTextures { albedo; normal; pbr; emissive; }
293
-
294
- /** present from AfterGBuffer */
295
- class ViewTextures {
296
- depth; depth_previous;
297
- visibility_mesh; visibility_triangle;
298
- velocity; // requires FrameProduct.Velocity
299
- }
300
-
301
- /** present from AfterLighting through BeforePresent */
302
- class SceneColor {
303
- color;
304
- copy; // requires FrameProduct.ColorCopy
305
- }
306
-
307
- /** present at Overlay, and only there */
308
- class PresentTarget { canvas; }
309
- ```
310
-
311
- Presence by phase:
312
-
313
- | phase | records | resolution |
314
- | --- | --- | --- |
315
- | `FrameStart` | — (the view only) | internal |
316
- | `AfterGBuffer` | `GBufferTextures` (writable), `ViewTextures` | internal |
317
- | `AfterLighting` | `GBufferTextures` (frozen), `ViewTextures`, `SceneColor` | internal |
318
- | `AfterTransparency` | as above | internal |
319
- | `BeforePresent` | as above — but `SceneColor` and `GBufferTextures` are now different sizes | output |
320
- | `Overlay` | `PresentTarget` | output |
321
-
322
- Two of those rows are decisions worth naming.
323
-
324
- **`SceneColor` is absent at `Overlay`, and `PresentTarget` is not `SceneColor`.** The current
325
- mechanism hands the tonemapped colour to `Overlay` passes and then documents, at length, that they
326
- must not read it — a texture cannot be a render attachment and a sampled source in the same pass.
327
- That was found by measurement after the fact. Handing back a differently-named record with one field
328
- says the same thing structurally: there is no `color` at `Overlay` to be tempted by, and an
329
- extension that wants the finished image as *input* discovers at `get` time that it belongs at
330
- `BeforePresent`.
331
-
332
- **`GBufferTextures` is present but frozen after `AfterGBuffer`.** Outline and highlight effects
333
- legitimately read the G-buffer and the visibility buffer late. Publishing into it late is
334
- meaningless — shading has run — so the record is frozen and the assert says why (§5). At
335
- `BeforePresent` it is also on the far side of the upscale from the colour (§3.5), so the two are
336
- different sizes; `describe()` is how a pass learns the ratio, and the record's own doc comment says
337
- to expect it.
338
-
339
- Extensions add their own records with `create`:
340
-
341
- ```js
342
- export class FogOfWarVisibility { grid; } // a graph buffer handle
343
-
344
- // producer, at FrameStart
345
- frame.create(FogOfWarVisibility).grid = this.#update_grid(frame.graph);
346
-
347
- // consumer, at AfterTransparency
348
- if (frame.has(FogOfWarVisibility)) { ... }
349
- ```
350
-
351
- Which is the second half of the fix for §1.1: the vocabulary is open, and extending it costs no
352
- edit to Shade.
353
-
354
- ### 3.4 Publication
355
-
356
- A field on a record is an accessor. Writing it is publication:
357
-
358
- ```js
359
- const scene = frame.get(SceneColor);
360
-
361
- const [fogged] = graph_image_pass({
362
- graph: frame.graph,
363
- shader: this.#shader,
364
- output_resolution: frame.describe(scene.color).resolution,
365
- inputs: { input_color: scene.color, input_depth: frame.get(ViewTextures).depth }
366
- });
367
-
368
- scene.color = fogged; // the rest of the frame carries this
369
- ```
370
-
371
- The setter asserts three things, all free in production:
372
-
373
- 1. The record is not frozen (§3.3), and the frame index matches — a handle captured last frame
374
- cannot be published this frame.
375
- 2. `graph.is_valid_resource(handle)` — the handle is the current version of its resource.
376
- 3. The current phase is one where the record is writable.
377
-
378
- Check 2 exists for **attribution**, not detection. The graph catches a superseded handle on its
379
- own: whoever reads it next trips `validate()`'s superseded-read check at `compile()` (§4). But that
380
- report names the *reader* — some built-in pass downstream — and says nothing about which extension
381
- put the bad handle into the record. Checking at the setter fails at the line that caused it, with
382
- the extension's name on it. It forbids nothing: one `ResourceEntry` owns one concrete resource, so
383
- an older node is not a snapshot of older contents and publishing one is wrong in every case.
384
-
385
- **A provenance check was considered here and rejected** — "the handle's producer is a pass recorded
386
- inside this extension's scope", which the record-time producer (§4) made possible. It would have
387
- forbidden a legitimate thing: `import_resource` leaves a node with no producer, so an extension that
388
- imports a texture it owns and publishes it as the frame's colour — a debug view, video playback —
389
- would have failed a check aimed at typos. What it uniquely caught, publishing a handle you read
390
- rather than wrote, surfaces immediately downstream anyway.
391
-
392
- Reading a field asserts frame identity and, for product-gated fields, that the *recording extension*
393
- declared the product (§3.7).
394
-
395
- **Publication is not the dependency edge.** The graph already has the edge: `FramePassBuilder.write`
396
- renames a written resource into a versioned clone and records the read, so "this pass consumed the
397
- colour as it stood and produced a new one" is already a graph fact. Publication is the *naming*
398
- step — which handle currently means "the scene colour". Keeping those two ideas separate is what
399
- lets the record model be this small.
400
-
401
- ### 3.5 Phases
402
-
403
- `FrameStart`, `AfterGBuffer`, `AfterLighting`, `AfterTransparency`, `BeforePresent`, `Overlay`.
404
-
405
- **The upscale is a phase boundary, and saying so is part of what a phase means.** `AfterGBuffer`,
406
- `AfterLighting` and `AfterTransparency` are before it and run at internal resolution; TAA and NSS
407
- upscale to output resolution, so `BeforePresent` and `Overlay` are after it and run at output
408
- resolution.
409
-
410
- **Before the upscale is the common case, and the design leans on it.** An extension drawing into the
411
- scene belongs at `AfterTransparency`: its work is then temporally resolved, upscaled and sharpened
412
- along with everything else, and it is the cheapest place to draw because it draws at internal
413
- resolution. `BeforePresent` is the deliberate other choice — full output resolution, still HDR,
414
- nothing after it but the tonemap — and it is a trade, not an upgrade: work there gets no temporal
415
- history and costs full-resolution pixels. An extension that does not have a reason to be after the
416
- upscale should not be.
417
-
418
- One wrinkle, and it belongs to the renderer rather than to this design: with
419
- `feature_taa_enabled === false` the upscale does not happen at all — there is a `TODO` in `Renderer`
420
- saying exactly that — so in that configuration `BeforePresent` is at internal resolution. A derived
421
- `frame.resolution` (§3.2) is right in both configurations. A documented constant would be wrong in
422
- one, which is how the current mechanism ended up wrong in two.
423
-
424
- Five phases are the existing ones, unchanged in meaning. **`FrameStart` is the one addition**: a point after
425
- the view is updated and before anything is rasterized. It exists because per-frame GPU compute that
426
- later phases depend on currently has nowhere to go — fog of war's grid update, a custom cull, a
427
- procedural buffer build — so it is either bolted onto a draw pass at a later phase, which puts it in
428
- the wrong place in the graph and mis-attributes it in a capture, or done outside the graph entirely,
429
- which is precisely the aliasing-and-lifetime blindness §1.2 is about.
430
-
431
- Considered and rejected: `BeforeGBuffer` (nothing distinguishes it from `FrameStart` for anything an
432
- extension can do), `AfterShadows` (shadow rendering is per-light and interior to
433
- `GPULightCollection`; a phase there would be a lie about what is stable), per-post-effect phases
434
- (URP has seventeen events and their number is a symptom, not a feature).
435
-
436
- ### 3.6 Ordering
437
-
438
- Within a phase, order is the topological order of the `after` / `before` edges. Cycles throw at
439
- registration, naming the cycle. Both directions exist because an extension that must precede one it
440
- cannot edit is exactly the case an extension mechanism is for.
441
-
442
- Unconstrained pairs are broken by `name`, ascending. Stable and reproducible; deliberately *not*
443
- registration order, so that adding an `await` to a system's startup cannot change the picture.
444
-
445
- Name-order is stable, not correct. So the resolver also reports **ambiguity**: two extensions on one
446
- phase that publish the same field of the same record, with no ordering path between them, is an
447
- assert failure naming both and the field. Publication goes through our setters, so the frame knows
448
- who published what — no extra syntax on the author's side. This is the check that would have made
449
- somebody write down what the six-deep `AfterTransparency` chain is supposed to be.
450
-
451
- The ambiguity check is per-frame and assert-only. It costs nothing in production and fires on the
452
- first frame in development.
453
-
454
- ### 3.7 Products
455
-
456
- `FrameProduct` is a bitmask of things the frame *can* build but does not always:
457
-
458
- ```js
459
- export const FrameProduct = {
460
- /** per-object + camera velocity, built even when TAA and motion blur are off */
461
- Velocity: 1,
462
- /** a readable snapshot of the scene colour as it stood when the phase began */
463
- ColorCopy: 2,
464
- };
465
- ```
466
-
467
- The union over registered extensions is computed once per registration change, and the renderer
468
- consults it the way it consults its own feature flags. `ColorCopy` is produced immediately before
469
- the passes of each phase that requires it.
470
-
471
- Two members, because two have a nameable consumer: `Velocity` for any effect an extension wants to
472
- temporally reproject itself (currently built for TAA, unreachable by anyone else), and `ColorCopy`
473
- for refraction — a pass that rasterizes geometry *into* the live colour with a `load` op and must
474
- also sample what is behind it, which is refractive water and distortion particles. A full-screen
475
- pass that reads the colour and writes a new one does not need it and must not ask for it.
476
-
477
- Considered and deferred with reasons in §9: `HiZ`, `PreviousColor`, `SceneDepthPyramid`.
478
-
479
- This is the part of the design with the weakest present-day demand and it ships last (§10).
480
-
481
- ---
482
-
483
- ## 4. What the frame graph does, and what it does not
484
-
485
- Stated plainly, because the design would be dishonest without it.
486
-
487
- `FrameGraph.execute` iterates `__pass_nodes` **in insertion order**. It does not topologically sort,
488
- and there is no plan for it to. What the graph gives is culling (`ref_count` propagation from
489
- unreferenced resources), transient resource lifetime and aliasing, versioned renaming of written
490
- resources, and export.
491
-
492
- So: **the graph does not order extensions; §3.6 does.** Every claim in this document about ordering
493
- is a claim about the resolver, not about the graph.
494
-
495
- **What the graph does instead of sorting is check.** The first draft of this document listed two
496
- implementation constraints the design had to route around. Both are now fixed, and a third thing
497
- landed that the design had assumed away, so the division of labour is different from what §3.6 was
498
- written against. The four that matter here — the full list and its evidence are in
499
- `engine/graphics/render/frame_graph/FRAME_GRAPH_RECOMMENDATIONS.md`:
500
-
501
- - **`validate()` proves the insertion order is a valid topological order**, and `compile()` asserts
502
- on it. It reports a *read before write* (a pass reading a node a later pass produces) and a
503
- *superseded read* (a pass reading a version an earlier pass has already replaced — one
504
- `ResourceEntry` owns one concrete resource, so an older node is not a snapshot). This is the
505
- honest answer to insertion-order execution: not to sort, but to refuse a recording whose order is
506
- wrong. It is asserted, so it costs nothing shipped and fails the frame in development.
507
- - **The lifecycle is one-shot and stated.** `FrameGraphState`: `Recording` → `Compiled` →
508
- `Executed`, monotonic, asserted at every mutating entry point. `compile()` was not idempotent and
509
- `execute()` could not tell whether `compile()` had run — a graph executed uncompiled culls itself
510
- entirely and says nothing. The design's old "the extension layer must never compile the graph
511
- itself" caveat is deleted: the graph says so now.
512
- - **`ResourceNode.producer` is assigned at record time**, by `FramePassBuilder`, rather than in
513
- `compile()`. So "this handle was produced by the pass that is publishing it" is answerable at
514
- publication (§3.4).
515
- - **Recording scopes exist.** `push_scope(name)` / `pop_scope()` stamp every pass and resource node
516
- created inside them, nesting through a parent chain. This supersedes §13's request for a
517
- `pass_count` getter and is what §1.2's attribution complaint was asking for.
518
-
519
- One finding from that work belongs here rather than there, because it is the strongest available
520
- argument for the whole model: `validate()`, on its first run against the live 61-pass `Shading`
521
- graph, found that **Shade's own rasterization was not threading its colour targets.** Depth was
522
- threaded through the two-phase opaque pass and colour was not, so every rasterization pass read
523
- `out_color/0` at version 0 while depth advanced. It was harmless only because those passes write an
524
- imported resource and therefore always execute, and because insertion order happened to give the
525
- right picture — the colour dependency between them was simply not a graph fact. That is what
526
- "working around the graph rather than through it" costs, in the engine's own code, found the day
527
- someone checked.
528
-
529
- What remains true, and what §3.6 rests on: the graph checks that a recording order is *consistent*,
530
- never that it is the one anybody wanted. Two extensions each reading the colour and writing a new
531
- one are valid in either order. Data-order violations are the graph's; visual-order mistakes are
532
- §3.6's, and nothing else will catch them.
533
-
534
- ---
535
-
536
- ## 5. Validation and diagnostics
537
-
538
- All of it under `assert`, which is compiled out of production builds — so the price of every check
539
- here is zero in a shipped game and the checks may be as thorough as they like.
540
-
541
- | check | when | what it catches |
542
- | --- | --- | --- |
543
- | record present at phase | `get` | reading `SceneColor` at `AfterGBuffer` — replaces `-1` |
544
- | record frozen | publish | publishing a G-buffer handle after shading |
545
- | frame identity | read + publish | a handle retained across frames |
546
- | `is_valid_resource` | publish | publishing a superseded handle, attributed to the extension |
547
- | product declared by the recording extension | read | reading `velocity` because *someone else* required it |
548
- | ordering cycle | registration | `after`/`before` cycle, named |
549
- | publication ambiguity | end of phase | two extensions writing one field with no order between them |
550
-
551
- Beneath all of them the graph runs its own `validate()` inside `compile()` (§4), which catches the
552
- data-order failures this layer cannot see.
553
-
554
- Every one of these fires on a **statement that cannot be true** — a superseded handle names one
555
- physical resource holding newer contents, a cycle has no order, an undeclared collision has no
556
- answer. None of them fires on an extension that is behaving correctly. That is the bar; §5.1 is
557
- what happens when a check is written without holding to it.
558
-
559
- ### 5.1 Culling is not an error, and no diagnostic here treats it as one
560
-
561
- An earlier revision of this document asked the graph to report per-scope culling so that "an
562
- extension whose entire recorded work was culled" could be an assert. **That was wrong and it is
563
- removed**, along with the engine change it needed. Three reasons, in increasing order of weight.
564
-
565
- Culling is what a frame graph is *for*. Frostbite's paper is about eliminating work nobody
566
- consumes; that is why the pattern spread. A mechanism cannot adopt the construct and then treat its
567
- central behaviour as a failure.
568
-
569
- The distinction it drew does not exist. "Culled built-in pass: optimisation. Culled extension pass:
570
- bug." Nothing about the recorder changes what culling means, and encoding the split would have made
571
- extensions second-class in the one place the design claims they are not.
572
-
573
- And it forbids the pattern this design exists to enable. §3.3's own worked example is an extension
574
- publishing `FogOfWarVisibility` at `FrameStart` for a consumer at `AfterTransparency`. Take the
575
- consumer out — disable fog — and the producer's work is dead, the graph elides it, and the frame is
576
- correct and cheaper. Under the assert that is a hard error. A speculative producer whose consumer
577
- may or may not be present is the whole point of an open record vocabulary, and the check would have
578
- outlawed it on day one.
579
-
580
- **What replaces it: nothing, because nothing is missing.** `exportToJson` already reports
581
- `culled` per pass and `exportToDot` already greys culled passes out; with the registry's scopes
582
- (§5.2) a culled extension is a grey cluster with its own name on it. An author asking "why did my
583
- pass not run" dumps the graph and sees it. That is a tool, not a tribunal.
584
-
585
- The culling contract itself is stated once, on `RenderExtension.record`, in the same terms it holds
586
- for every other pass in the graph: work whose output nothing consumes is elided; thread your result
587
- into a record and it is consumed; if you want work that runs regardless, `make_side_effect()` says
588
- so, exactly as it does for a built-in pass.
589
-
590
- ### 5.2 Recording scopes
591
-
592
- **The registry opens a recording scope per extension**, named after it, around the `record()` call:
593
-
594
- ```js
595
- graph.push_scope(extension.name);
596
-
597
- try {
598
- extension.record(frame);
599
- } finally {
600
- graph.pop_scope();
601
- }
602
- ```
603
-
604
- The `finally` is not error handling — nothing is caught and nothing is swallowed. It is there
605
- because `compile()` asserts the scope stack came back empty, so an extension that throws while
606
- recording would otherwise fail on an unbalanced scope and bury the real error behind it. The throw
607
- propagates, decorated with the extension's name the way `FrameGraph` already decorates a failing
608
- pass with its own.
609
-
610
- **Scopes are for reading the frame back, not for policing it.** `exportToDot` puts each extension's
611
- passes in its own labelled cluster, nested as the scopes nest, and a graph that opens no scope
612
- exports byte-identically to before. That is the whole of §1.2's attribution complaint, answered by
613
- an API that already exists and that nothing currently calls — and it is what makes §5.1's answer to
614
- culling a real answer rather than a shrug: the grey box in the dump has the extension's name on it.
615
-
616
- No check depends on scopes. The one that did is gone (§5.1), and the provenance check that would
617
- have used `is_within` was rejected on its own merits (§3.4).
618
-
619
- `RenderExtensionRegistry.describe()` returns the resolved pipeline as text: per phase, the extensions
620
- in resolved order, each with the products it required and the records it publishes into. Printable
621
- without a device, which is what makes it testable without one.
622
-
623
- ---
624
-
625
- ## 6. Lifecycle
626
-
627
- Registration is device-free and survives device loss — the current mechanism's one clearly right
628
- decision, kept. `GraphicsEngine3` holds the extension list; a renderer replaced by a restart is
629
- re-populated from it. A system registers once at startup without knowing whether a device exists.
630
-
631
- ```js
632
- graphics.add_extension(extension); // returns the extension
633
- graphics.remove_extension(extension); // returns whether it was registered
634
- ```
635
-
636
- Identity is the object, so the phase no longer has to be passed to removal. Registering or removing
637
- during `record` is an assert failure.
638
-
639
- `GraphicsEngine3` gains no surface it did not have: this replaces `add_pass` / `remove_pass`
640
- one-for-one, so D14's "the facade does not grow" holds. `pass_count(phase)` becomes
641
- `extension_count(phase)`, which the start → stop → start leak gate needs.
642
-
643
- **Views.** There is one injection site today: the primary view inside `render_to_target`. Shadow
644
- views, probe bakes and picking do not run extensions and this design does not change that. When a
645
- second view kind gains injection points, the filter belongs on the registry and the extension gains
646
- a declaration for it; building that now would be inventing a contract for a caller that does not
647
- exist.
648
-
649
- ---
650
-
651
- ## 7. The whole API
652
-
653
- That is the entire surface.
654
-
655
- ```js
656
- // declaration
657
- class RenderExtension { name; phase; after; before; requires; record(frame); }
658
- const FramePhase = { FrameStart, AfterGBuffer, AfterLighting, AfterTransparency, BeforePresent, Overlay };
659
- const FrameProduct = { Velocity, ColorCopy };
660
-
661
- // recording
662
- class FrameContext { graph; view; phase; resolution; get(type); has(type); create(type); describe(handle); }
663
-
664
- // built-in records
665
- class GBufferTextures { albedo; normal; pbr; emissive; }
666
- class ViewTextures { depth; depth_previous; visibility_mesh; visibility_triangle; velocity; }
667
- class SceneColor { color; copy; }
668
- class PresentTarget { canvas; }
669
-
670
- // registration
671
- class RenderExtensionRegistry { add(e); remove(e); count(phase); describe(); run(frame); }
672
- // on GraphicsEngine3 / Renderer
673
- add_extension(e); remove_extension(e); extension_count(phase);
674
- ```
675
-
676
- ---
677
-
678
- ## 8. Migration
679
-
680
- Nine live systems, one probe, one prototype viewer. Every one of them is the same mechanical change:
681
- a closure becomes a class, `context.color` becomes `frame.get(SceneColor).color`, and the return
682
- value becomes a publication.
683
-
684
- | consumer | phase | change beyond the mechanical |
685
- | --- | --- | --- |
686
- | `TerrainSystem3` | `AfterGBuffer` | drops the registration-before-`await` comment; nothing else |
687
- | `DecalSystem3` | `AfterGBuffer` | `after: [TerrainExtension]`, which is the constraint the comment in `TerrainSystem3` was hand-enforcing; stops assigning through `context.gbuffer` |
688
- | `WaterSystem3` | `AfterLighting` | publication instead of return; a candidate first consumer of `FrameProduct.ColorCopy` if refraction is wanted |
689
- | `FogOfWarSystem3` | `AfterTransparency` | the grid update becomes a `FrameStart` extension publishing `FogOfWarVisibility`, and the composite reads it; declares `after` the four content extensions — **this is where §1.3a's shipped bug is fixed** |
690
- | `ParticleEmitterSystem3` | `AfterTransparency` | — (now before the fog, by declaration) |
691
- | `PathDisplaySystem3` | `AfterTransparency` | — |
692
- | `HighlightSystem3` | `AfterTransparency` | reads `ViewTextures.visibility_*`, unchanged in meaning |
693
- | `DebugDrawSystem3` | `AfterTransparency` | `after: [FogOfWarExtension]` |
694
- | `Trail3DSystem3` | `AfterTransparency` | — |
695
- | `probeShadePassInjection` | all | the gate is rewritten and gains the two checks it is currently blind to: a G-buffer replacement, and an order flip |
696
- | `prototypeVGEOFormatViewer` | `AfterTransparency` | prototype; mechanical |
697
-
698
- **The `AfterTransparency` chain is settled, not open.** Fog of war is last among the content
699
- extensions, because it conceals and therefore belongs over everything it is meant to conceal —
700
- particles, trails, path display and the selection highlight all draw before it and are all subject
701
- to it. Debug draw is the single deliberate exception, `after: [FogOfWarExtension]`: developer
702
- geometry that the fog can hide is a debugging tool that stops working exactly where debugging is
703
- needed.
704
-
705
- That is six extensions and two declarations. Written down once, in the two files that care, instead
706
- of being a property of where an `await` sits.
707
-
708
- **The bug does not have to wait for the migration.** Today's ordering is registration order, so
709
- moving `FogOfWarSystem3` below `Trail3DSystem3` in `graphics_profile.js` fixes the picture now — at
710
- the cost of it being another undeclared ordering fact, which is what this design exists to end.
711
-
712
- ---
713
-
714
- ## 9. Non-goals and known limits
715
-
716
- **Shade's own frame is not rewritten into a list of extensions.** URP's real strength is that
717
- built-in and injected passes are the same type. Getting there means restructuring
718
- `Renderer.render_to_target`, and renderer internals are hands-off. The consequence, stated so it is
719
- not discovered later: injection points remain hand-placed call sites, so the phase set is only as
720
- good as the places the renderer publishes records, and an extension cannot insert itself between two
721
- built-in post passes.
722
-
723
- **Extensions cannot participate in OIT.** Work at `AfterTransparency` composites over the resolved
724
- transparency; it cannot interleave with sorted transparents. True today, unchanged, and the honest
725
- reason the phase model has a ceiling.
726
-
727
- **Extensions cannot add to a built-in pass** — no extra material variants in the G-buffer raster, no
728
- extra lights. A new pass is the only unit.
729
-
730
- **No `FrameProduct` for `HiZ` / `PreviousColor` / depth pyramid yet.** Each is built by the renderer
731
- and each would be a one-line addition, and none has a consumer today. Adding them speculatively puts
732
- three untested branches in the renderer's product wiring.
733
-
734
- **No view kinds.** §6.
735
-
736
- **Ordering ambiguity is caught at frame time, not registration time**, because publication is
737
- observed rather than declared. Declaring publications up front would catch it earlier at the cost of
738
- a second declaration that can disagree with the code; observation cannot disagree with the code.
739
-
740
- ---
741
-
742
- ## 10. Delivery
743
-
744
- Three steps, each independently green.
745
-
746
- - **A — the model.** Records, `FrameContext`, publication with all four checks, registry with
747
- ordering, cycle detection and scoped recording. Port the nine systems and the viewer. Delete
748
- `FramePassContext`, `FramePassRegistry` and `add_pass` / `remove_pass`. `FrameStart` and
749
- `PresentTarget` land here, because they are what the fog-of-war split and the `Overlay` rule need.
750
- - **B — diagnostics.** Ambiguity check and `describe()`. Nothing here waits on the engine; scoped
751
- recording lands in A, because it needs nothing that is not already there.
752
- - **C — products.** `FrameProduct.Velocity` and `ColorCopy`, and the renderer wiring that honours
753
- them.
754
-
755
- A is the whole of the user-visible design. B is what makes it hold. C is the part with the weakest
756
- demand and it is separable on purpose.
757
-
758
- ---
759
-
760
- ## 11. Tests and gates
761
-
762
- Device-free (`vitest`, from the moh root), black-box, real objects:
763
-
764
- - resolved order for a set of extensions with `after` / `before`; a cycle throws and names both;
765
- unconstrained pairs resolve by name and the result does not change when registration order does.
766
- - `get` of an absent record throws; `create` twice throws; `has` agrees with both.
767
- - publication of a superseded handle fails; publication into a frozen record fails; a handle from a
768
- previous frame fails. `FrameGraph` and a `SoftwareGPUDevice` are enough for all of these — no real
769
- device, per the standing rule.
770
- - **an extension whose output nothing consumes is culled, and that is not an error** — the frame
771
- renders, no assert fires, and the pass reports `culled` in the JSON export. Pinned as a test
772
- because it is a property somebody will otherwise "fix" (§5.1).
773
- - an extension's passes land inside its own DOT cluster, and a graph recorded with no extensions
774
- exports exactly as it did before. The scope machinery is already specced on the graph; what this
775
- adds is that the registry opens and closes one per extension, including when `record()` throws.
776
- - `describe()` output is stable and contains every registered extension.
777
- - registry survives a simulated renderer replacement with the same extensions in the same order.
778
-
779
- On a device, extending `probeShadePassInjection`:
780
-
781
- - a colour-writing extension at each colour-carrying phase, in and out, restoring to within the
782
- existing 25% bar.
783
- - **a G-buffer-replacing extension at `AfterGBuffer`** — writes a flat albedo, and the lit frame
784
- changes. The current gate has no such check, which is why the in/out G-buffer has never been
785
- exercised outside the decal system.
786
- - **an order flip** — two extensions publishing the colour, with the `after` edge reversed between
787
- runs, producing different frames. This is the property the current mechanism cannot state at all.
788
- - **the upscale boundary, at 60% dynamic resolution scale**: an extension at `AfterTransparency` and
789
- one at `BeforePresent`, each sizing its output from `frame.resolution`, both producing a full,
790
- uncropped frame. They must resolve to *different* sizes. The `BeforePresent` half of this fails on
791
- the current mechanism (§1.3b), and the same check run with `feature_taa_enabled = false` must
792
- still pass, which is what pins `resolution` as derived rather than declared.
793
- - **fog of war over particles** — the `AfterTransparency` chain resolved from declarations, with a
794
- particle emitter inside the concealed region staying concealed. This is §1.3a's bug, as a gate.
795
-
796
- ---
797
-
798
- ## 12. Adversarial review
799
-
800
- The design above is the post-review version. What follows is what was attacked and what changed.
801
-
802
- **"A type-keyed container is a registry, and the house rule forbids registries."** The rule forbids
803
- *string*-keyed factories chosen to save boilerplate. A class is a type; the container is a typed
804
- map. The alternative — a struct with fixed fields — is defect §1.1 restated. *Survived, with the
805
- concession that every built-in record is an ordinary class with named fields, so the container is
806
- the only indirection.*
807
-
808
- **"You claim the graph orders passes. It executes in insertion order."** Correct, and the first
809
- draft leaned on the graph for ordering. **Changed:** §4 now states the execution model outright, and
810
- every ordering claim is attributed to the resolver. The design would have been wrong without this.
811
-
812
- > *Since.* The graph answered this from its own side rather than by being routed around: `validate()`
813
- > now proves that the recorded insertion order is a valid topological order and `compile()` asserts
814
- > on it. The design's position is unchanged — §3.6 still owns ordering — but the failure mode it was
815
- > protecting against narrowed sharply. A recording order that is *inconsistent* is now the graph's
816
- > to reject; §3.6 is left owning the orders that are consistent and still wrong, which is exactly
817
- > the fog-over-particles case (§1.3a) and is the only kind of ordering bug the game actually had.
818
-
819
- **"`scene.color = handle` is untracked mutation — the same side channel you criticised
820
- `context.gbuffer` for being."** Half right. The criticism of `context.gbuffer` was that it was the
821
- *only* extra mutable thing, at *one* phase, invisible in the pass signature. **Changed:** publication
822
- is now uniform across every record and validated at the setter — freeze state, frame identity, and
823
- `is_valid_resource` against the graph. The last of those catches a class of silent wrong-picture bug
824
- that neither the current mechanism nor URP catches at all.
825
-
826
- **"You deleted `resolution` and told every extension to call `describe()`. That is a worse API for
827
- the case everyone has."** Fair, and the first draft did exactly that in reaction to defect (b).
828
- **Changed:** `frame.resolution` came back as a derived getter over the phase's live target handle,
829
- so the common case is one property access *and* correct on both sides of the upscale, with
830
- `describe()` left for the genuinely two-sized case. The lesson from (b) is that the number must not
831
- be a field somebody fills in, not that the number should be hard to get.
832
-
833
- **"Ambiguity detection needs the frame to know who is recording — hidden global state."** One field,
834
- set by the loop that calls `record`. Re-entrant recording is an assert failure. *Survived.*
835
-
836
- **"Alphabetical tie-breaking is arbitrary. Why is arbitrary-by-name better than
837
- arbitrary-by-registration?"** Because it does not change when a system's `startup` gains an `await`.
838
- Reproducibility is the property, not correctness. **Changed:** the ambiguity check was added in the
839
- same pass, so an arbitrary order between two extensions that actually conflict is an error rather
840
- than a silently-chosen order.
841
-
842
- **"`FrameProduct` is a closed enum, so §1.1 is only half fixed."** Concede. The frame's own optional
843
- products are Shade's features and enumerating them is correct; the *open* half is the record
844
- vocabulary, which needs no engine edit. **Changed:** §3.7 says this, the enum was cut to two members
845
- with named consumers, and it was moved to the last delivery step.
846
-
847
- **"An `enabled` flag and an early return from `record` are two ways to do one thing."** Agreed.
848
- **Changed:** the flag was cut.
849
-
850
- **"`get_or_create` is friendlier than three methods."** It is, and it destroys the property that
851
- made `-1` go away: absent has to stay distinguishable from empty. *Rejected.*
852
-
853
- **"Six phases plus a blackboard plus a topological sort, to replace two methods, for nine
854
- consumers."** The two methods currently need four paragraphs of documentation about culling, carry a
855
- wrong resolution at two of five phases, and enforce a documented ordering requirement through the
856
- placement of an `await`. The sort is thirty lines over at most a dozen nodes. *Survived, and it is
857
- the reason §10 splits diagnostics out: if the sort and the records are the value, B and C can be
858
- judged separately.*
859
-
860
- **"`SceneColor` absent at `Overlay` means an extension that wants the tonemapped image just gets a
861
- throw."** Yes, with a message naming `BeforePresent`. That is strictly better than the current
862
- outcome, which is a validation error from inside a binding builder, and it is better than the
863
- documentation-only fix that shipped, which was discovered by measurement after the fact. *Survived.*
864
-
865
- **"The migration makes somebody decide the `AfterTransparency` order, and they may get it wrong."**
866
- It was decided while this document was under review, and the order in the shipped game turned out to
867
- be wrong (§1.3a). That is the argument for declaring it, not a counter to it — a mechanism where the
868
- answer is written down is a mechanism where being wrong is a diff. **Changed:** §8 states the
869
- resolved chain instead of leaving it open.
870
-
871
- **"`describe()` is a feature nobody asked for."** It is the only thing that makes "the frame graph is
872
- a first-class construct" mean something testable at this seam — a pipeline you can print without a
873
- device is a pipeline you can spec without a device. *Survived, in delivery step B.*
874
-
875
- **"Culling is what a frame graph is for. You made it an error for one class of user."** Sponsor, on
876
- the revision that asked the graph to report per-scope culling so a fully-culled extension could
877
- assert. **The objection is correct and the check is gone (§5.1).** Three ways it was wrong, and the
878
- review that produced the rest of this document did not catch any of them:
879
-
880
- - It adopted the construct and then treated its central behaviour as a failure.
881
- - The line it drew — culled built-in pass is optimisation, culled extension pass is a bug — has
882
- nothing behind it. Who recorded a pass does not change what culling means.
883
- - Fatally, it outlawed a pattern this document's own §3.3 puts forward as the reason the record
884
- vocabulary is open: an extension publishing `FogOfWarVisibility` for a consumer that may not be
885
- registered. Disable the consumer and the producer is correctly elided — and the assert would have
886
- called that a hard error. A speculative producer is the point, not an accident.
887
-
888
- Withdrawn with it: `FRAME_GRAPH_RECOMMENDATIONS.md` item 5, which was the last open engine change,
889
- and the provenance check in §3.4, which fell to the same standard once it was applied consistently
890
- — it forbade publishing an imported texture in order to catch a typo. What the argument leaves
891
- standing is a bar the remaining checks are now stated against: **a check may only fire on something
892
- that cannot be true**, never on an extension behaving correctly.
893
-
894
- ---
895
-
896
- ## 13. Engine changes required
897
-
898
- Small, and enumerated so the blast radius is visible. **`FrameGraph` needs nothing.** The graph-side
899
- items this document originally asked for have either landed or been withdrawn — the last of them,
900
- the culling report, was withdrawn on the reasoning in §5.1. Everything below is renderer and facade
901
- work.
902
-
903
- 1. `Renderer` publishes records at six points instead of filling one context at five. The record
904
- objects are built where `#frame_pass_context` is built today.
905
- 2. `Renderer` gains a `FrameStart` call site, and (delivery C) honours the product union when
906
- deciding whether to build velocity and the colour copy.
907
- 3. `GraphicsEngine3` swaps `add_pass`/`remove_pass`/`pass_count` for
908
- `add_extension`/`remove_extension`/`extension_count`. No net surface change.
909
- 4. `src/shade/renderer/pass/` becomes `src/shade/renderer/extension/`. The folder is MEEP 3's, not
910
- Shade's, and "pass" collides with `FramePassNode` — the graph's passes and an extension are
911
- different things and should not share a word.
912
-
913
- Nothing in Shade's frame structure, no pass reordering, no change to how built-in passes record.
914
-
915
- **Already done, and nothing further is needed from them** — `FrameGraphState` and its asserts,
916
- `validate()` with both order checks, `push_scope` / `pop_scope` and DOT clustering,
917
- `ResourceNode.producer` at record time, and the `exportToJson` fix. `getDescriptor`,
918
- `is_valid_resource` and `onExecuted` were already there and the design uses them as they stand.
1
+ # Render extensions — design
2
+
3
+ Replaces `Renderer.add_pass` / `remove_pass`, `FramePhase`, `FramePassContext` and
4
+ `FramePassRegistry` (MEEP 3, phase 2, item S3).
5
+
6
+ Status: **design, not built.** Nothing in §3 through §11 is committed code.
7
+
8
+ **Revised 2026-08-24** against the frame-graph work that has landed since the first draft:
9
+ `FrameGraphState`, `validate()`, recording scopes, record-time producers, and the `exportToJson`
10
+ fix. Those came out of this document's §4 and §13 and are tracked in
11
+ `engine/graphics/render/frame_graph/FRAME_GRAPH_RECOMMENDATIONS.md`. §1.2, §3.4, §4, §5 and §13
12
+ describe what the graph does now, not what it did — the net effect is that the design leans on the
13
+ graph in three more places and asks it for nothing.
14
+
15
+ The same revision **withdrew the cull diagnostic** and the engine change it needed, on sponsor
16
+ review: culling is what a frame graph is for, and a check that calls it a failure when an extension
17
+ is the recorder invents a distinction that does not exist and outlaws the speculative producer.
18
+ §5.1 is the argument; the bar it sets — a check may only fire on something that cannot be true —
19
+ also took out a provenance check in §3.4.
20
+
21
+ ---
22
+
23
+ ## 0. Summary
24
+
25
+ An extension is a **named object with declarations** — a phase, ordering constraints, the optional
26
+ frame products it needs — and one method that records into the frame's graph. Everything it exchanges
27
+ with the frame goes through **typed per-frame records** holding frame-graph handles: it reads a
28
+ handle out of a record and writes a replacement back. There is no return value and no privileged
29
+ resource.
30
+
31
+ Three properties follow, and they are the point:
32
+
33
+ 1. **Every resource the frame carries is exchangeable**, not just the colour. The G-buffer stops
34
+ being a documented special case, depth stops being read-only, and an extension can publish a
35
+ record of its own that another extension reads.
36
+ 2. **Order is declared**, not emergent from the order in which ECS systems happened to reach their
37
+ first `await`.
38
+ 3. **The frame can be described without being rendered, and read back attributed once it has been.**
39
+ The set of extensions, their order per phase, and the products they force on are data, so
40
+ `describe()` prints the pipeline; and the registry records each extension inside its own graph
41
+ scope, so a DOT export of the frame groups by who asked for what instead of by whatever the
42
+ `graph_*` helpers named things. That pair is what "the frame graph is a first-class construct"
43
+ has to mean at this seam.
44
+
45
+ Underneath all three, one correction that is not an abstraction: **the upscale is a phase boundary
46
+ and the surface says so.** Three phases are before it and two are after, the before case is the
47
+ common one, and the size of what an extension is drawing into is derived from the live handle rather
48
+ than handed over as a field the renderer fills in once for the whole frame — which is what the
49
+ current mechanism does, and gets wrong at two of its five phases (§1.3b).
50
+
51
+ The shape is Unity 6 URP's — `ContextContainer` / `ContextItem`, `ScriptableRenderPass`,
52
+ `ConfigureInput` — with URP's two worst traits removed (§2).
53
+
54
+ ---
55
+
56
+ ## 1. What is wrong with `add_pass`
57
+
58
+ ### 1.1 One resource is modifiable
59
+
60
+ `FramePassRegistry.run` threads exactly one value:
61
+
62
+ ```js
63
+ const produced = passes[i](context);
64
+ if (produced === undefined) { continue; }
65
+ context.color = produced;
66
+ ```
67
+
68
+ A pass's only sanctioned output is a colour handle. Everything else on `FramePassContext` — depth,
69
+ previous depth, the four G-buffer targets, the two visibility targets — is an input. The one
70
+ exception, the G-buffer being in/out at `AfterGBuffer`, is implemented by letting the pass reach into
71
+ `context.gbuffer` and assign, and costs three paragraphs of prose in `FramePassContext` to explain
72
+ why replacing beats writing in place.
73
+
74
+ What that closes off, concretely: writing depth (terrain and water both rasterize geometry that
75
+ should own depth), publishing a resource an extension computed for other extensions to read (fog of
76
+ war's visibility grid is exactly this and currently lives outside the graph), and reading anything
77
+ the frame builds but the struct does not name — velocity, the Hi-Z pyramid, the TAA history, the
78
+ shadow atlas, the light cluster tables.
79
+
80
+ The struct is closed by construction: adding a field is an edit to Shade. That is the wrong cost for
81
+ "my game needs one more thing from the frame".
82
+
83
+ ### 1.2 The graph is an escape hatch, not the mechanism
84
+
85
+ `context.graph` hands the pass the `FrameGraph` and steps back. The registry never learns what the
86
+ pass read or wrote, so:
87
+
88
+ - **It cannot order passes.** It orders by registration order.
89
+ - **It cannot attribute anything.** `exportToDot` shows the nodes an extension created with whatever
90
+ names its helpers gave them, unrelated to the extension. The graph has since gained recording
91
+ scopes, which are exactly the missing mechanism — but they are opt-in and `add_pass` opens none,
92
+ so a frame's DOT export is still one flat wall of passes.
93
+ - **It cannot validate.** Reading `context.color` at `AfterGBuffer` yields `-1` and fails somewhere
94
+ inside a binding builder. Retaining a handle across frames is undetectable. Publishing a stale
95
+ handle is now caught, but by the graph at `compile()` and against the *reader* — the pass that
96
+ consumed it — so the report names the built-in pass that broke, never the extension that handed
97
+ it the bad handle.
98
+ - **`AfterGBuffer` has no return channel, so the culling contract cannot be met there.** The rule
99
+ itself is the graph's, and it is right everywhere: work nothing consumes is elided. But the only
100
+ way this mechanism lets a pass thread its result into the frame is by returning a colour handle,
101
+ and at `AfterGBuffer` there is no colour — so a pass whose G-buffer work *should* be consumed
102
+ reaches for `make_side_effect()` instead, which does not say "my output is used", it says "run me
103
+ anyway". Three paragraphs of `FramePhase` document the workaround. The record model removes the
104
+ reason for it (§3.3) and leaves the culling rule alone (§5.1).
105
+
106
+ And the injection points themselves are call sites: a phase is wherever `#run_frame_passes` was
107
+ typed inside an 800-line method. There are five because five were typed.
108
+
109
+ ### 1.3 What this has already produced
110
+
111
+ Four findings from reading the current code, each independent of the design that replaces it.
112
+
113
+ **(a) Order is an accident, and the code says so.** `TerrainSystem3.startup`:
114
+
115
+ > `// before anything is awaited, so that pass order within the phase is the profile's system order —`
116
+ > `// the decal composite has to see the textured ground, not precede it`
117
+
118
+ An ordering requirement between two extensions is being met by placing a registration call above an
119
+ `await`. Adding an `await` to a system's startup silently reorders the frame.
120
+
121
+ The same mechanism decides the six-deep chain at `AfterTransparency`, and **it has already produced a
122
+ shipped bug**. In profile order that chain is fog of war, particles, path display, highlight, debug
123
+ draw, trails — so the fog composites *first* and everything drawn after it is unfogged. Confirmed
124
+ with the sponsor: that is not intended. Fog of war conceals, so it belongs over everything it
125
+ conceals; particles drawing on top of it defeat what it is for.
126
+
127
+ Nobody chose that order. Nothing recorded it. Nothing failed when it turned out wrong. That is the
128
+ argument for §3.6 in one paragraph.
129
+
130
+ **(b) The one size the context states is wrong at two phases.** `Renderer` fills
131
+ `pass_context.resolution` from `resolution_internal.asArray()`, once, for all five phases. But TAA
132
+ and NSS upscale to `output_resolution` before `BeforePresent`, and the tonemap writes the canvas at
133
+ output resolution — so at `BeforePresent` and `Overlay` the colour is *not* the size the context
134
+ reports, whenever TAA is on. With TAA off it is, because the upscale is missing (there is a `TODO`
135
+ in `Renderer` saying so). The size of the frame's colour at `BeforePresent` is therefore not
136
+ derivable from the context at all; it depends on a renderer feature flag the extension cannot see.
137
+
138
+ `probeShadePassInjection` — the gate for the current mechanism — does
139
+ `output_resolution: context.resolution` at `BeforePresent`. It passes because the probe runs at 100%
140
+ scale. The game ships with dynamic resolution scaling enabled against a 30 fps floor, and at any
141
+ scale below 100% that pass produces a cropped, wrongly-scaled frame while the gate still measures a
142
+ luminance change and reports green.
143
+
144
+ The single field is the tell: the surface was built as though a frame had one resolution. Three of
145
+ the five phases are before the upscale and two are after it, and nothing in the surface says which
146
+ is which — `FramePhase`'s own text for `BeforePresent` says "still HDR" and never mentions that the
147
+ colour has been upscaled by then. §3.5 makes the boundary part of what a phase *is*.
148
+
149
+ **(c) `-1` is a sentinel with no guard.** `color` is `-1` at `AfterGBuffer`. Nothing stops a pass
150
+ reading it. The house rule is that the common case is the only case and preconditions are asserted,
151
+ not encoded as magic values.
152
+
153
+ **(d) The G-buffer special case exists only because colour owns the return channel.** Given a
154
+ uniform way to publish any handle, "the G-buffer is in/out at one phase" stops being a rule and
155
+ becomes an instance of the general one.
156
+
157
+ ---
158
+
159
+ ## 2. What is borrowed from URP, and what is not
160
+
161
+ Borrowed:
162
+
163
+ | URP 6 | Here | Why |
164
+ | --- | --- | --- |
165
+ | `ContextContainer` + `ContextItem` | `FrameContext.get(RecordType)` + frame records | The open, typed resource vocabulary. This is the fix for §1.1, and the reason it is keyed by type rather than by string is that the house rule forbids string-keyed registries. |
166
+ | `UniversalResourceData` | `SceneColor`, `GBufferTextures`, `ViewTextures`, `PresentTarget` | Built-in resources are ordinary classes with named fields, carried in the same container as anyone else's. One mechanism, not two. |
167
+ | `ScriptableRenderPass` | `RenderExtension` | A declaring object, not a closure. Declarations are what makes ordering, validation and description possible. |
168
+ | `ConfigureInput(ScriptableRenderPassInput.Motion)` | `RenderExtension.requires` + `FrameProduct` | An extension states what the frame must produce and the renderer turns it on. This is the answer to "velocity exists, is built, and is unreachable". |
169
+ | Renderer feature list, ordered | The registry's resolved order, printable | The pipeline is inspectable before it runs. |
170
+
171
+ Not borrowed, deliberately:
172
+
173
+ - **`RenderPassEvent` + integer offsets.** URP orders same-event passes by an `int` you add to the
174
+ enum. It is the same defect as registration order with an extra step: unreadable, unstable under
175
+ insertion, and it makes every ordering question a numerology question. Replaced by explicit
176
+ `after` / `before` constraints over extension classes (§3.6).
177
+ - **`SetGlobalTexture` / global shader state.** An implicit channel between passes that the graph
178
+ cannot see. Records are the channel.
179
+ - **`AddUnsafePass`.** URP needs a legacy `CommandBuffer` escape hatch. There is no legacy to carry
180
+ here, and adding an unchecked door on day one guarantees it becomes the door.
181
+ - **Two-level feature/pass split.** URP splits `ScriptableRendererFeature` from
182
+ `ScriptableRenderPass` because a feature is a `ScriptableObject` living on an asset. That reason
183
+ does not exist here, so there is one class.
184
+
185
+ ---
186
+
187
+ ## 3. The model
188
+
189
+ ### 3.1 `RenderExtension`
190
+
191
+ ```js
192
+ export class RenderExtension {
193
+ /**
194
+ * Stable identity. Used in ordering diagnostics, error decoration and `describe()`.
195
+ * @type {string}
196
+ */
197
+ name = "";
198
+
199
+ /** @type {FramePhase} */
200
+ phase = FramePhase.AfterTransparency;
201
+
202
+ /**
203
+ * Extension classes this one records after / before. Constructors, not instances — an
204
+ * extension does not need a reference to another system's object to state an order.
205
+ * @type {Function[]}
206
+ */
207
+ after = [];
208
+ before = [];
209
+
210
+ /**
211
+ * Optional frame products this extension reads. A bitmask of {@link FrameProduct}.
212
+ * Reading a product nobody required is an assert failure, not a silent `-1`.
213
+ * @type {number}
214
+ */
215
+ requires = 0;
216
+
217
+ /**
218
+ * Record this extension's work into the frame. Called once per frame, when the phase comes
219
+ * round. Returns nothing: everything this produces reaches the rest of the frame by
220
+ * publication (§3.4).
221
+ *
222
+ * @param {FrameContext} frame
223
+ */
224
+ record(frame) {}
225
+ }
226
+ ```
227
+
228
+ `record` returning `void` is load-bearing. It is what makes colour stop being privileged.
229
+
230
+ An extension that has nothing to draw this frame returns without recording; that is the only "off"
231
+ switch and there is no `enabled` flag beside it.
232
+
233
+ ### 3.2 `FrameContext`
234
+
235
+ ```js
236
+ export class FrameContext {
237
+ /** @type {FrameGraph} the frame's graph — record into this with the `graph_*` helpers */
238
+ graph;
239
+ /** @type {ViewRenderContext} */
240
+ view;
241
+ /** @type {FramePhase} */
242
+ phase;
243
+
244
+ /** @template T @param {new()=>T} type @returns {T} throws if not present at this phase */
245
+ get(type) {}
246
+
247
+ /** @param {Function} type @returns {boolean} */
248
+ has(type) {}
249
+
250
+ /** @template T @param {new()=>T} type @returns {T} adds a record this extension owns */
251
+ create(type) {}
252
+
253
+ /**
254
+ * Pixel size of the target this phase carries, derived from the live handle rather than filled
255
+ * in by the renderer.
256
+ * @returns {number[]}
257
+ */
258
+ get resolution() {}
259
+
260
+ /** @param {number} handle @returns {ResourceDescriptor} size, format and usage of a handle */
261
+ describe(handle) {}
262
+ }
263
+ ```
264
+
265
+ Three accessors rather than one `get_or_create`, because "absent" has to stay distinguishable from
266
+ "empty" — that is what lets `get(SceneColor)` at `AfterGBuffer` throw with a sentence instead of
267
+ handing back `-1`.
268
+
269
+ **`resolution` is derived, and that is the whole of the fix for defect (b).** It reads the graph
270
+ through the handle this phase's target actually is, so it is right before the upscale, right after
271
+ it, right when TAA is off and the upscale does not happen at all, and right at every dynamic
272
+ resolution scale. The common case — "how big is the thing I am drawing into" — stays one property
273
+ access and cannot be wrong.
274
+
275
+ `describe(handle)` is the general form, and it is needed whenever two things in one pass are
276
+ different sizes: an extension at `BeforePresent` reading the G-buffer is working across the upscale
277
+ boundary and has to ask for both.
278
+
279
+ > Both lean on descriptors being trustworthy, which was checked: transient and imported resources
280
+ > both carry a real `TextureResourceDescriptor` holding absolute pixels.
281
+ > `TextureResourceDescriptor.resolution_domain` says otherwise by default and is vestigial — nothing
282
+ > branches on it, only `hash()` folds it in. It stays; it is now documented as vestigial on the field
283
+ > itself so the next reader does not take it for a contract.
284
+
285
+ ### 3.3 Frame records
286
+
287
+ A record is a plain class holding frame-graph handles. The renderer publishes the built-in ones as
288
+ the frame reaches the phase where they are meaningful.
289
+
290
+ ```js
291
+ /** present from AfterGBuffer */
292
+ class GBufferTextures { albedo; normal; pbr; emissive; }
293
+
294
+ /** present from AfterGBuffer */
295
+ class ViewTextures {
296
+ depth; depth_previous;
297
+ visibility_mesh; visibility_triangle;
298
+ velocity; // requires FrameProduct.Velocity
299
+ }
300
+
301
+ /** present from AfterLighting through BeforePresent */
302
+ class SceneColor {
303
+ color;
304
+ copy; // requires FrameProduct.ColorCopy
305
+ }
306
+
307
+ /** present at Overlay, and only there */
308
+ class PresentTarget { canvas; }
309
+ ```
310
+
311
+ Presence by phase:
312
+
313
+ | phase | records | resolution |
314
+ | --- | --- | --- |
315
+ | `FrameStart` | — (the view only) | internal |
316
+ | `AfterGBuffer` | `GBufferTextures` (writable), `ViewTextures` | internal |
317
+ | `AfterLighting` | `GBufferTextures` (frozen), `ViewTextures`, `SceneColor` | internal |
318
+ | `AfterTransparency` | as above | internal |
319
+ | `BeforePresent` | as above — but `SceneColor` and `GBufferTextures` are now different sizes | output |
320
+ | `Overlay` | `PresentTarget` | output |
321
+
322
+ Two of those rows are decisions worth naming.
323
+
324
+ **`SceneColor` is absent at `Overlay`, and `PresentTarget` is not `SceneColor`.** The current
325
+ mechanism hands the tonemapped colour to `Overlay` passes and then documents, at length, that they
326
+ must not read it — a texture cannot be a render attachment and a sampled source in the same pass.
327
+ That was found by measurement after the fact. Handing back a differently-named record with one field
328
+ says the same thing structurally: there is no `color` at `Overlay` to be tempted by, and an
329
+ extension that wants the finished image as *input* discovers at `get` time that it belongs at
330
+ `BeforePresent`.
331
+
332
+ **`GBufferTextures` is present but frozen after `AfterGBuffer`.** Outline and highlight effects
333
+ legitimately read the G-buffer and the visibility buffer late. Publishing into it late is
334
+ meaningless — shading has run — so the record is frozen and the assert says why (§5). At
335
+ `BeforePresent` it is also on the far side of the upscale from the colour (§3.5), so the two are
336
+ different sizes; `describe()` is how a pass learns the ratio, and the record's own doc comment says
337
+ to expect it.
338
+
339
+ Extensions add their own records with `create`:
340
+
341
+ ```js
342
+ export class FogOfWarVisibility { grid; } // a graph buffer handle
343
+
344
+ // producer, at FrameStart
345
+ frame.create(FogOfWarVisibility).grid = this.#update_grid(frame.graph);
346
+
347
+ // consumer, at AfterTransparency
348
+ if (frame.has(FogOfWarVisibility)) { ... }
349
+ ```
350
+
351
+ Which is the second half of the fix for §1.1: the vocabulary is open, and extending it costs no
352
+ edit to Shade.
353
+
354
+ ### 3.4 Publication
355
+
356
+ A field on a record is an accessor. Writing it is publication:
357
+
358
+ ```js
359
+ const scene = frame.get(SceneColor);
360
+
361
+ const [fogged] = graph_image_pass({
362
+ graph: frame.graph,
363
+ shader: this.#shader,
364
+ output_resolution: frame.describe(scene.color).resolution,
365
+ inputs: { input_color: scene.color, input_depth: frame.get(ViewTextures).depth }
366
+ });
367
+
368
+ scene.color = fogged; // the rest of the frame carries this
369
+ ```
370
+
371
+ The setter asserts three things, all free in production:
372
+
373
+ 1. The record is not frozen (§3.3), and the frame index matches — a handle captured last frame
374
+ cannot be published this frame.
375
+ 2. `graph.is_valid_resource(handle)` — the handle is the current version of its resource.
376
+ 3. The current phase is one where the record is writable.
377
+
378
+ Check 2 exists for **attribution**, not detection. The graph catches a superseded handle on its
379
+ own: whoever reads it next trips `validate()`'s superseded-read check at `compile()` (§4). But that
380
+ report names the *reader* — some built-in pass downstream — and says nothing about which extension
381
+ put the bad handle into the record. Checking at the setter fails at the line that caused it, with
382
+ the extension's name on it. It forbids nothing: one `ResourceEntry` owns one concrete resource, so
383
+ an older node is not a snapshot of older contents and publishing one is wrong in every case.
384
+
385
+ **A provenance check was considered here and rejected** — "the handle's producer is a pass recorded
386
+ inside this extension's scope", which the record-time producer (§4) made possible. It would have
387
+ forbidden a legitimate thing: `import_resource` leaves a node with no producer, so an extension that
388
+ imports a texture it owns and publishes it as the frame's colour — a debug view, video playback —
389
+ would have failed a check aimed at typos. What it uniquely caught, publishing a handle you read
390
+ rather than wrote, surfaces immediately downstream anyway.
391
+
392
+ Reading a field asserts frame identity and, for product-gated fields, that the *recording extension*
393
+ declared the product (§3.7).
394
+
395
+ **Publication is not the dependency edge.** The graph already has the edge: `FramePassBuilder.write`
396
+ renames a written resource into a versioned clone and records the read, so "this pass consumed the
397
+ colour as it stood and produced a new one" is already a graph fact. Publication is the *naming*
398
+ step — which handle currently means "the scene colour". Keeping those two ideas separate is what
399
+ lets the record model be this small.
400
+
401
+ ### 3.5 Phases
402
+
403
+ `FrameStart`, `AfterGBuffer`, `AfterLighting`, `AfterTransparency`, `BeforePresent`, `Overlay`.
404
+
405
+ **The upscale is a phase boundary, and saying so is part of what a phase means.** `AfterGBuffer`,
406
+ `AfterLighting` and `AfterTransparency` are before it and run at internal resolution; TAA and NSS
407
+ upscale to output resolution, so `BeforePresent` and `Overlay` are after it and run at output
408
+ resolution.
409
+
410
+ **Before the upscale is the common case, and the design leans on it.** An extension drawing into the
411
+ scene belongs at `AfterTransparency`: its work is then temporally resolved, upscaled and sharpened
412
+ along with everything else, and it is the cheapest place to draw because it draws at internal
413
+ resolution. `BeforePresent` is the deliberate other choice — full output resolution, still HDR,
414
+ nothing after it but the tonemap — and it is a trade, not an upgrade: work there gets no temporal
415
+ history and costs full-resolution pixels. An extension that does not have a reason to be after the
416
+ upscale should not be.
417
+
418
+ One wrinkle, and it belongs to the renderer rather than to this design: with
419
+ `feature_taa_enabled === false` the upscale does not happen at all — there is a `TODO` in `Renderer`
420
+ saying exactly that — so in that configuration `BeforePresent` is at internal resolution. A derived
421
+ `frame.resolution` (§3.2) is right in both configurations. A documented constant would be wrong in
422
+ one, which is how the current mechanism ended up wrong in two.
423
+
424
+ Five phases are the existing ones, unchanged in meaning. **`FrameStart` is the one addition**: a point after
425
+ the view is updated and before anything is rasterized. It exists because per-frame GPU compute that
426
+ later phases depend on currently has nowhere to go — fog of war's grid update, a custom cull, a
427
+ procedural buffer build — so it is either bolted onto a draw pass at a later phase, which puts it in
428
+ the wrong place in the graph and mis-attributes it in a capture, or done outside the graph entirely,
429
+ which is precisely the aliasing-and-lifetime blindness §1.2 is about.
430
+
431
+ Considered and rejected: `BeforeGBuffer` (nothing distinguishes it from `FrameStart` for anything an
432
+ extension can do), `AfterShadows` (shadow rendering is per-light and interior to
433
+ `GPULightCollection`; a phase there would be a lie about what is stable), per-post-effect phases
434
+ (URP has seventeen events and their number is a symptom, not a feature).
435
+
436
+ ### 3.6 Ordering
437
+
438
+ Within a phase, order is the topological order of the `after` / `before` edges. Cycles throw at
439
+ registration, naming the cycle. Both directions exist because an extension that must precede one it
440
+ cannot edit is exactly the case an extension mechanism is for.
441
+
442
+ Unconstrained pairs are broken by `name`, ascending. Stable and reproducible; deliberately *not*
443
+ registration order, so that adding an `await` to a system's startup cannot change the picture.
444
+
445
+ Name-order is stable, not correct. So the resolver also reports **ambiguity**: two extensions on one
446
+ phase that publish the same field of the same record, with no ordering path between them, is an
447
+ assert failure naming both and the field. Publication goes through our setters, so the frame knows
448
+ who published what — no extra syntax on the author's side. This is the check that would have made
449
+ somebody write down what the six-deep `AfterTransparency` chain is supposed to be.
450
+
451
+ The ambiguity check is per-frame and assert-only. It costs nothing in production and fires on the
452
+ first frame in development.
453
+
454
+ ### 3.7 Products
455
+
456
+ `FrameProduct` is a bitmask of things the frame *can* build but does not always:
457
+
458
+ ```js
459
+ export const FrameProduct = {
460
+ /** per-object + camera velocity, built even when TAA and motion blur are off */
461
+ Velocity: 1,
462
+ /** a readable snapshot of the scene colour as it stood when the phase began */
463
+ ColorCopy: 2,
464
+ };
465
+ ```
466
+
467
+ The union over registered extensions is computed once per registration change, and the renderer
468
+ consults it the way it consults its own feature flags. `ColorCopy` is produced immediately before
469
+ the passes of each phase that requires it.
470
+
471
+ Two members, because two have a nameable consumer: `Velocity` for any effect an extension wants to
472
+ temporally reproject itself (currently built for TAA, unreachable by anyone else), and `ColorCopy`
473
+ for refraction — a pass that rasterizes geometry *into* the live colour with a `load` op and must
474
+ also sample what is behind it, which is refractive water and distortion particles. A full-screen
475
+ pass that reads the colour and writes a new one does not need it and must not ask for it.
476
+
477
+ Considered and deferred with reasons in §9: `HiZ`, `PreviousColor`, `SceneDepthPyramid`.
478
+
479
+ This is the part of the design with the weakest present-day demand and it ships last (§10).
480
+
481
+ ---
482
+
483
+ ## 4. What the frame graph does, and what it does not
484
+
485
+ Stated plainly, because the design would be dishonest without it.
486
+
487
+ `FrameGraph.execute` iterates `__pass_nodes` **in insertion order**. It does not topologically sort,
488
+ and there is no plan for it to. What the graph gives is culling (`ref_count` propagation from
489
+ unreferenced resources), transient resource lifetime and aliasing, versioned renaming of written
490
+ resources, and export.
491
+
492
+ So: **the graph does not order extensions; §3.6 does.** Every claim in this document about ordering
493
+ is a claim about the resolver, not about the graph.
494
+
495
+ **What the graph does instead of sorting is check.** The first draft of this document listed two
496
+ implementation constraints the design had to route around. Both are now fixed, and a third thing
497
+ landed that the design had assumed away, so the division of labour is different from what §3.6 was
498
+ written against. The four that matter here — the full list and its evidence are in
499
+ `engine/graphics/render/frame_graph/FRAME_GRAPH_RECOMMENDATIONS.md`:
500
+
501
+ - **`validate()` proves the insertion order is a valid topological order**, and `compile()` asserts
502
+ on it. It reports a *read before write* (a pass reading a node a later pass produces) and a
503
+ *superseded read* (a pass reading a version an earlier pass has already replaced — one
504
+ `ResourceEntry` owns one concrete resource, so an older node is not a snapshot). This is the
505
+ honest answer to insertion-order execution: not to sort, but to refuse a recording whose order is
506
+ wrong. It is asserted, so it costs nothing shipped and fails the frame in development.
507
+ - **The lifecycle is one-shot and stated.** `FrameGraphState`: `Recording` → `Compiled` →
508
+ `Executed`, monotonic, asserted at every mutating entry point. `compile()` was not idempotent and
509
+ `execute()` could not tell whether `compile()` had run — a graph executed uncompiled culls itself
510
+ entirely and says nothing. The design's old "the extension layer must never compile the graph
511
+ itself" caveat is deleted: the graph says so now.
512
+ - **`ResourceNode.producer` is assigned at record time**, by `FramePassBuilder`, rather than in
513
+ `compile()`. So "this handle was produced by the pass that is publishing it" is answerable at
514
+ publication (§3.4).
515
+ - **Recording scopes exist.** `push_scope(name)` / `pop_scope()` stamp every pass and resource node
516
+ created inside them, nesting through a parent chain. This supersedes §13's request for a
517
+ `pass_count` getter and is what §1.2's attribution complaint was asking for.
518
+
519
+ One finding from that work belongs here rather than there, because it is the strongest available
520
+ argument for the whole model: `validate()`, on its first run against the live 61-pass `Shading`
521
+ graph, found that **Shade's own rasterization was not threading its colour targets.** Depth was
522
+ threaded through the two-phase opaque pass and colour was not, so every rasterization pass read
523
+ `out_color/0` at version 0 while depth advanced. It was harmless only because those passes write an
524
+ imported resource and therefore always execute, and because insertion order happened to give the
525
+ right picture — the colour dependency between them was simply not a graph fact. That is what
526
+ "working around the graph rather than through it" costs, in the engine's own code, found the day
527
+ someone checked.
528
+
529
+ What remains true, and what §3.6 rests on: the graph checks that a recording order is *consistent*,
530
+ never that it is the one anybody wanted. Two extensions each reading the colour and writing a new
531
+ one are valid in either order. Data-order violations are the graph's; visual-order mistakes are
532
+ §3.6's, and nothing else will catch them.
533
+
534
+ ---
535
+
536
+ ## 5. Validation and diagnostics
537
+
538
+ All of it under `assert`, which is compiled out of production builds — so the price of every check
539
+ here is zero in a shipped game and the checks may be as thorough as they like.
540
+
541
+ | check | when | what it catches |
542
+ | --- | --- | --- |
543
+ | record present at phase | `get` | reading `SceneColor` at `AfterGBuffer` — replaces `-1` |
544
+ | record frozen | publish | publishing a G-buffer handle after shading |
545
+ | frame identity | read + publish | a handle retained across frames |
546
+ | `is_valid_resource` | publish | publishing a superseded handle, attributed to the extension |
547
+ | product declared by the recording extension | read | reading `velocity` because *someone else* required it |
548
+ | ordering cycle | registration | `after`/`before` cycle, named |
549
+ | publication ambiguity | end of phase | two extensions writing one field with no order between them |
550
+
551
+ Beneath all of them the graph runs its own `validate()` inside `compile()` (§4), which catches the
552
+ data-order failures this layer cannot see.
553
+
554
+ Every one of these fires on a **statement that cannot be true** — a superseded handle names one
555
+ physical resource holding newer contents, a cycle has no order, an undeclared collision has no
556
+ answer. None of them fires on an extension that is behaving correctly. That is the bar; §5.1 is
557
+ what happens when a check is written without holding to it.
558
+
559
+ ### 5.1 Culling is not an error, and no diagnostic here treats it as one
560
+
561
+ An earlier revision of this document asked the graph to report per-scope culling so that "an
562
+ extension whose entire recorded work was culled" could be an assert. **That was wrong and it is
563
+ removed**, along with the engine change it needed. Three reasons, in increasing order of weight.
564
+
565
+ Culling is what a frame graph is *for*. Frostbite's paper is about eliminating work nobody
566
+ consumes; that is why the pattern spread. A mechanism cannot adopt the construct and then treat its
567
+ central behaviour as a failure.
568
+
569
+ The distinction it drew does not exist. "Culled built-in pass: optimisation. Culled extension pass:
570
+ bug." Nothing about the recorder changes what culling means, and encoding the split would have made
571
+ extensions second-class in the one place the design claims they are not.
572
+
573
+ And it forbids the pattern this design exists to enable. §3.3's own worked example is an extension
574
+ publishing `FogOfWarVisibility` at `FrameStart` for a consumer at `AfterTransparency`. Take the
575
+ consumer out — disable fog — and the producer's work is dead, the graph elides it, and the frame is
576
+ correct and cheaper. Under the assert that is a hard error. A speculative producer whose consumer
577
+ may or may not be present is the whole point of an open record vocabulary, and the check would have
578
+ outlawed it on day one.
579
+
580
+ **What replaces it: nothing, because nothing is missing.** `exportToJson` already reports
581
+ `culled` per pass and `exportToDot` already greys culled passes out; with the registry's scopes
582
+ (§5.2) a culled extension is a grey cluster with its own name on it. An author asking "why did my
583
+ pass not run" dumps the graph and sees it. That is a tool, not a tribunal.
584
+
585
+ The culling contract itself is stated once, on `RenderExtension.record`, in the same terms it holds
586
+ for every other pass in the graph: work whose output nothing consumes is elided; thread your result
587
+ into a record and it is consumed; if you want work that runs regardless, `make_side_effect()` says
588
+ so, exactly as it does for a built-in pass.
589
+
590
+ ### 5.2 Recording scopes
591
+
592
+ **The registry opens a recording scope per extension**, named after it, around the `record()` call:
593
+
594
+ ```js
595
+ graph.push_scope(extension.name);
596
+
597
+ try {
598
+ extension.record(frame);
599
+ } finally {
600
+ graph.pop_scope();
601
+ }
602
+ ```
603
+
604
+ The `finally` is not error handling — nothing is caught and nothing is swallowed. It is there
605
+ because `compile()` asserts the scope stack came back empty, so an extension that throws while
606
+ recording would otherwise fail on an unbalanced scope and bury the real error behind it. The throw
607
+ propagates, decorated with the extension's name the way `FrameGraph` already decorates a failing
608
+ pass with its own.
609
+
610
+ **Scopes are for reading the frame back, not for policing it.** `exportToDot` puts each extension's
611
+ passes in its own labelled cluster, nested as the scopes nest, and a graph that opens no scope
612
+ exports byte-identically to before. That is the whole of §1.2's attribution complaint, answered by
613
+ an API that already exists and that nothing currently calls — and it is what makes §5.1's answer to
614
+ culling a real answer rather than a shrug: the grey box in the dump has the extension's name on it.
615
+
616
+ No check depends on scopes. The one that did is gone (§5.1), and the provenance check that would
617
+ have used `is_within` was rejected on its own merits (§3.4).
618
+
619
+ `RenderExtensionRegistry.describe()` returns the resolved pipeline as text: per phase, the extensions
620
+ in resolved order, each with the products it required and the records it publishes into. Printable
621
+ without a device, which is what makes it testable without one.
622
+
623
+ ---
624
+
625
+ ## 6. Lifecycle
626
+
627
+ Registration is device-free and survives device loss — the current mechanism's one clearly right
628
+ decision, kept. `GraphicsEngine3` holds the extension list; a renderer replaced by a restart is
629
+ re-populated from it. A system registers once at startup without knowing whether a device exists.
630
+
631
+ ```js
632
+ graphics.add_extension(extension); // returns the extension
633
+ graphics.remove_extension(extension); // returns whether it was registered
634
+ ```
635
+
636
+ Identity is the object, so the phase no longer has to be passed to removal. Registering or removing
637
+ during `record` is an assert failure.
638
+
639
+ `GraphicsEngine3` gains no surface it did not have: this replaces `add_pass` / `remove_pass`
640
+ one-for-one, so D14's "the facade does not grow" holds. `pass_count(phase)` becomes
641
+ `extension_count(phase)`, which the start → stop → start leak gate needs.
642
+
643
+ **Views.** There is one injection site today: the primary view inside `render_to_target`. Shadow
644
+ views, probe bakes and picking do not run extensions and this design does not change that. When a
645
+ second view kind gains injection points, the filter belongs on the registry and the extension gains
646
+ a declaration for it; building that now would be inventing a contract for a caller that does not
647
+ exist.
648
+
649
+ ---
650
+
651
+ ## 7. The whole API
652
+
653
+ That is the entire surface.
654
+
655
+ ```js
656
+ // declaration
657
+ class RenderExtension { name; phase; after; before; requires; record(frame); }
658
+ const FramePhase = { FrameStart, AfterGBuffer, AfterLighting, AfterTransparency, BeforePresent, Overlay };
659
+ const FrameProduct = { Velocity, ColorCopy };
660
+
661
+ // recording
662
+ class FrameContext { graph; view; phase; resolution; get(type); has(type); create(type); describe(handle); }
663
+
664
+ // built-in records
665
+ class GBufferTextures { albedo; normal; pbr; emissive; }
666
+ class ViewTextures { depth; depth_previous; visibility_mesh; visibility_triangle; velocity; }
667
+ class SceneColor { color; copy; }
668
+ class PresentTarget { canvas; }
669
+
670
+ // registration
671
+ class RenderExtensionRegistry { add(e); remove(e); count(phase); describe(); run(frame); }
672
+ // on GraphicsEngine3 / Renderer
673
+ add_extension(e); remove_extension(e); extension_count(phase);
674
+ ```
675
+
676
+ ---
677
+
678
+ ## 8. Migration
679
+
680
+ Nine live systems, one probe, one prototype viewer. Every one of them is the same mechanical change:
681
+ a closure becomes a class, `context.color` becomes `frame.get(SceneColor).color`, and the return
682
+ value becomes a publication.
683
+
684
+ | consumer | phase | change beyond the mechanical |
685
+ | --- | --- | --- |
686
+ | `TerrainSystem3` | `AfterGBuffer` | drops the registration-before-`await` comment; nothing else |
687
+ | `DecalSystem3` | `AfterGBuffer` | `after: [TerrainExtension]`, which is the constraint the comment in `TerrainSystem3` was hand-enforcing; stops assigning through `context.gbuffer` |
688
+ | `WaterSystem3` | `AfterLighting` | publication instead of return; a candidate first consumer of `FrameProduct.ColorCopy` if refraction is wanted |
689
+ | `FogOfWarSystem3` | `AfterTransparency` | the grid update becomes a `FrameStart` extension publishing `FogOfWarVisibility`, and the composite reads it; declares `after` the four content extensions — **this is where §1.3a's shipped bug is fixed** |
690
+ | `ParticleEmitterSystem3` | `AfterTransparency` | — (now before the fog, by declaration) |
691
+ | `PathDisplaySystem3` | `AfterTransparency` | — |
692
+ | `HighlightSystem3` | `AfterTransparency` | reads `ViewTextures.visibility_*`, unchanged in meaning |
693
+ | `DebugDrawSystem3` | `AfterTransparency` | `after: [FogOfWarExtension]` |
694
+ | `Trail3DSystem3` | `AfterTransparency` | — |
695
+ | `probeShadePassInjection` | all | the gate is rewritten and gains the two checks it is currently blind to: a G-buffer replacement, and an order flip |
696
+ | `prototypeVGEOFormatViewer` | `AfterTransparency` | prototype; mechanical |
697
+
698
+ **The `AfterTransparency` chain is settled, not open.** Fog of war is last among the content
699
+ extensions, because it conceals and therefore belongs over everything it is meant to conceal —
700
+ particles, trails, path display and the selection highlight all draw before it and are all subject
701
+ to it. Debug draw is the single deliberate exception, `after: [FogOfWarExtension]`: developer
702
+ geometry that the fog can hide is a debugging tool that stops working exactly where debugging is
703
+ needed.
704
+
705
+ That is six extensions and two declarations. Written down once, in the two files that care, instead
706
+ of being a property of where an `await` sits.
707
+
708
+ **The bug does not have to wait for the migration.** Today's ordering is registration order, so
709
+ moving `FogOfWarSystem3` below `Trail3DSystem3` in `graphics_profile.js` fixes the picture now — at
710
+ the cost of it being another undeclared ordering fact, which is what this design exists to end.
711
+
712
+ ---
713
+
714
+ ## 9. Non-goals and known limits
715
+
716
+ **Shade's own frame is not rewritten into a list of extensions.** URP's real strength is that
717
+ built-in and injected passes are the same type. Getting there means restructuring
718
+ `Renderer.render_to_target`, and renderer internals are hands-off. The consequence, stated so it is
719
+ not discovered later: injection points remain hand-placed call sites, so the phase set is only as
720
+ good as the places the renderer publishes records, and an extension cannot insert itself between two
721
+ built-in post passes.
722
+
723
+ **Extensions cannot participate in OIT.** Work at `AfterTransparency` composites over the resolved
724
+ transparency; it cannot interleave with sorted transparents. True today, unchanged, and the honest
725
+ reason the phase model has a ceiling.
726
+
727
+ **Extensions cannot add to a built-in pass** — no extra material variants in the G-buffer raster, no
728
+ extra lights. A new pass is the only unit.
729
+
730
+ **No `FrameProduct` for `HiZ` / `PreviousColor` / depth pyramid yet.** Each is built by the renderer
731
+ and each would be a one-line addition, and none has a consumer today. Adding them speculatively puts
732
+ three untested branches in the renderer's product wiring.
733
+
734
+ **No view kinds.** §6.
735
+
736
+ **Ordering ambiguity is caught at frame time, not registration time**, because publication is
737
+ observed rather than declared. Declaring publications up front would catch it earlier at the cost of
738
+ a second declaration that can disagree with the code; observation cannot disagree with the code.
739
+
740
+ ---
741
+
742
+ ## 10. Delivery
743
+
744
+ Three steps, each independently green.
745
+
746
+ - **A — the model.** Records, `FrameContext`, publication with all four checks, registry with
747
+ ordering, cycle detection and scoped recording. Port the nine systems and the viewer. Delete
748
+ `FramePassContext`, `FramePassRegistry` and `add_pass` / `remove_pass`. `FrameStart` and
749
+ `PresentTarget` land here, because they are what the fog-of-war split and the `Overlay` rule need.
750
+ - **B — diagnostics.** Ambiguity check and `describe()`. Nothing here waits on the engine; scoped
751
+ recording lands in A, because it needs nothing that is not already there.
752
+ - **C — products.** `FrameProduct.Velocity` and `ColorCopy`, and the renderer wiring that honours
753
+ them.
754
+
755
+ A is the whole of the user-visible design. B is what makes it hold. C is the part with the weakest
756
+ demand and it is separable on purpose.
757
+
758
+ ---
759
+
760
+ ## 11. Tests and gates
761
+
762
+ Device-free (`vitest`, from the moh root), black-box, real objects:
763
+
764
+ - resolved order for a set of extensions with `after` / `before`; a cycle throws and names both;
765
+ unconstrained pairs resolve by name and the result does not change when registration order does.
766
+ - `get` of an absent record throws; `create` twice throws; `has` agrees with both.
767
+ - publication of a superseded handle fails; publication into a frozen record fails; a handle from a
768
+ previous frame fails. `FrameGraph` and a `SoftwareGPUDevice` are enough for all of these — no real
769
+ device, per the standing rule.
770
+ - **an extension whose output nothing consumes is culled, and that is not an error** — the frame
771
+ renders, no assert fires, and the pass reports `culled` in the JSON export. Pinned as a test
772
+ because it is a property somebody will otherwise "fix" (§5.1).
773
+ - an extension's passes land inside its own DOT cluster, and a graph recorded with no extensions
774
+ exports exactly as it did before. The scope machinery is already specced on the graph; what this
775
+ adds is that the registry opens and closes one per extension, including when `record()` throws.
776
+ - `describe()` output is stable and contains every registered extension.
777
+ - registry survives a simulated renderer replacement with the same extensions in the same order.
778
+
779
+ On a device, extending `probeShadePassInjection`:
780
+
781
+ - a colour-writing extension at each colour-carrying phase, in and out, restoring to within the
782
+ existing 25% bar.
783
+ - **a G-buffer-replacing extension at `AfterGBuffer`** — writes a flat albedo, and the lit frame
784
+ changes. The current gate has no such check, which is why the in/out G-buffer has never been
785
+ exercised outside the decal system.
786
+ - **an order flip** — two extensions publishing the colour, with the `after` edge reversed between
787
+ runs, producing different frames. This is the property the current mechanism cannot state at all.
788
+ - **the upscale boundary, at 60% dynamic resolution scale**: an extension at `AfterTransparency` and
789
+ one at `BeforePresent`, each sizing its output from `frame.resolution`, both producing a full,
790
+ uncropped frame. They must resolve to *different* sizes. The `BeforePresent` half of this fails on
791
+ the current mechanism (§1.3b), and the same check run with `feature_taa_enabled = false` must
792
+ still pass, which is what pins `resolution` as derived rather than declared.
793
+ - **fog of war over particles** — the `AfterTransparency` chain resolved from declarations, with a
794
+ particle emitter inside the concealed region staying concealed. This is §1.3a's bug, as a gate.
795
+
796
+ ---
797
+
798
+ ## 12. Adversarial review
799
+
800
+ The design above is the post-review version. What follows is what was attacked and what changed.
801
+
802
+ **"A type-keyed container is a registry, and the house rule forbids registries."** The rule forbids
803
+ *string*-keyed factories chosen to save boilerplate. A class is a type; the container is a typed
804
+ map. The alternative — a struct with fixed fields — is defect §1.1 restated. *Survived, with the
805
+ concession that every built-in record is an ordinary class with named fields, so the container is
806
+ the only indirection.*
807
+
808
+ **"You claim the graph orders passes. It executes in insertion order."** Correct, and the first
809
+ draft leaned on the graph for ordering. **Changed:** §4 now states the execution model outright, and
810
+ every ordering claim is attributed to the resolver. The design would have been wrong without this.
811
+
812
+ > *Since.* The graph answered this from its own side rather than by being routed around: `validate()`
813
+ > now proves that the recorded insertion order is a valid topological order and `compile()` asserts
814
+ > on it. The design's position is unchanged — §3.6 still owns ordering — but the failure mode it was
815
+ > protecting against narrowed sharply. A recording order that is *inconsistent* is now the graph's
816
+ > to reject; §3.6 is left owning the orders that are consistent and still wrong, which is exactly
817
+ > the fog-over-particles case (§1.3a) and is the only kind of ordering bug the game actually had.
818
+
819
+ **"`scene.color = handle` is untracked mutation — the same side channel you criticised
820
+ `context.gbuffer` for being."** Half right. The criticism of `context.gbuffer` was that it was the
821
+ *only* extra mutable thing, at *one* phase, invisible in the pass signature. **Changed:** publication
822
+ is now uniform across every record and validated at the setter — freeze state, frame identity, and
823
+ `is_valid_resource` against the graph. The last of those catches a class of silent wrong-picture bug
824
+ that neither the current mechanism nor URP catches at all.
825
+
826
+ **"You deleted `resolution` and told every extension to call `describe()`. That is a worse API for
827
+ the case everyone has."** Fair, and the first draft did exactly that in reaction to defect (b).
828
+ **Changed:** `frame.resolution` came back as a derived getter over the phase's live target handle,
829
+ so the common case is one property access *and* correct on both sides of the upscale, with
830
+ `describe()` left for the genuinely two-sized case. The lesson from (b) is that the number must not
831
+ be a field somebody fills in, not that the number should be hard to get.
832
+
833
+ **"Ambiguity detection needs the frame to know who is recording — hidden global state."** One field,
834
+ set by the loop that calls `record`. Re-entrant recording is an assert failure. *Survived.*
835
+
836
+ **"Alphabetical tie-breaking is arbitrary. Why is arbitrary-by-name better than
837
+ arbitrary-by-registration?"** Because it does not change when a system's `startup` gains an `await`.
838
+ Reproducibility is the property, not correctness. **Changed:** the ambiguity check was added in the
839
+ same pass, so an arbitrary order between two extensions that actually conflict is an error rather
840
+ than a silently-chosen order.
841
+
842
+ **"`FrameProduct` is a closed enum, so §1.1 is only half fixed."** Concede. The frame's own optional
843
+ products are Shade's features and enumerating them is correct; the *open* half is the record
844
+ vocabulary, which needs no engine edit. **Changed:** §3.7 says this, the enum was cut to two members
845
+ with named consumers, and it was moved to the last delivery step.
846
+
847
+ **"An `enabled` flag and an early return from `record` are two ways to do one thing."** Agreed.
848
+ **Changed:** the flag was cut.
849
+
850
+ **"`get_or_create` is friendlier than three methods."** It is, and it destroys the property that
851
+ made `-1` go away: absent has to stay distinguishable from empty. *Rejected.*
852
+
853
+ **"Six phases plus a blackboard plus a topological sort, to replace two methods, for nine
854
+ consumers."** The two methods currently need four paragraphs of documentation about culling, carry a
855
+ wrong resolution at two of five phases, and enforce a documented ordering requirement through the
856
+ placement of an `await`. The sort is thirty lines over at most a dozen nodes. *Survived, and it is
857
+ the reason §10 splits diagnostics out: if the sort and the records are the value, B and C can be
858
+ judged separately.*
859
+
860
+ **"`SceneColor` absent at `Overlay` means an extension that wants the tonemapped image just gets a
861
+ throw."** Yes, with a message naming `BeforePresent`. That is strictly better than the current
862
+ outcome, which is a validation error from inside a binding builder, and it is better than the
863
+ documentation-only fix that shipped, which was discovered by measurement after the fact. *Survived.*
864
+
865
+ **"The migration makes somebody decide the `AfterTransparency` order, and they may get it wrong."**
866
+ It was decided while this document was under review, and the order in the shipped game turned out to
867
+ be wrong (§1.3a). That is the argument for declaring it, not a counter to it — a mechanism where the
868
+ answer is written down is a mechanism where being wrong is a diff. **Changed:** §8 states the
869
+ resolved chain instead of leaving it open.
870
+
871
+ **"`describe()` is a feature nobody asked for."** It is the only thing that makes "the frame graph is
872
+ a first-class construct" mean something testable at this seam — a pipeline you can print without a
873
+ device is a pipeline you can spec without a device. *Survived, in delivery step B.*
874
+
875
+ **"Culling is what a frame graph is for. You made it an error for one class of user."** Sponsor, on
876
+ the revision that asked the graph to report per-scope culling so a fully-culled extension could
877
+ assert. **The objection is correct and the check is gone (§5.1).** Three ways it was wrong, and the
878
+ review that produced the rest of this document did not catch any of them:
879
+
880
+ - It adopted the construct and then treated its central behaviour as a failure.
881
+ - The line it drew — culled built-in pass is optimisation, culled extension pass is a bug — has
882
+ nothing behind it. Who recorded a pass does not change what culling means.
883
+ - Fatally, it outlawed a pattern this document's own §3.3 puts forward as the reason the record
884
+ vocabulary is open: an extension publishing `FogOfWarVisibility` for a consumer that may not be
885
+ registered. Disable the consumer and the producer is correctly elided — and the assert would have
886
+ called that a hard error. A speculative producer is the point, not an accident.
887
+
888
+ Withdrawn with it: `FRAME_GRAPH_RECOMMENDATIONS.md` item 5, which was the last open engine change,
889
+ and the provenance check in §3.4, which fell to the same standard once it was applied consistently
890
+ — it forbade publishing an imported texture in order to catch a typo. What the argument leaves
891
+ standing is a bar the remaining checks are now stated against: **a check may only fire on something
892
+ that cannot be true**, never on an extension behaving correctly.
893
+
894
+ ---
895
+
896
+ ## 13. Engine changes required
897
+
898
+ Small, and enumerated so the blast radius is visible. **`FrameGraph` needs nothing.** The graph-side
899
+ items this document originally asked for have either landed or been withdrawn — the last of them,
900
+ the culling report, was withdrawn on the reasoning in §5.1. Everything below is renderer and facade
901
+ work.
902
+
903
+ 1. `Renderer` publishes records at six points instead of filling one context at five. The record
904
+ objects are built where `#frame_pass_context` is built today.
905
+ 2. `Renderer` gains a `FrameStart` call site, and (delivery C) honours the product union when
906
+ deciding whether to build velocity and the colour copy.
907
+ 3. `GraphicsEngine3` swaps `add_pass`/`remove_pass`/`pass_count` for
908
+ `add_extension`/`remove_extension`/`extension_count`. No net surface change.
909
+ 4. `src/shade/renderer/pass/` becomes `src/shade/renderer/extension/`. The folder is MEEP 3's, not
910
+ Shade's, and "pass" collides with `FramePassNode` — the graph's passes and an extension are
911
+ different things and should not share a word.
912
+
913
+ Nothing in Shade's frame structure, no pass reordering, no change to how built-in passes record.
914
+
915
+ **Already done, and nothing further is needed from them** — `FrameGraphState` and its asserts,
916
+ `validate()` with both order checks, `push_scope` / `pop_scope` and DOT clustering,
917
+ `ResourceNode.producer` at record time, and the `exportToJson` fix. `getDescriptor`,
918
+ `is_valid_resource` and `onExecuted` were already there and the design uses them as they stand.