@woosh/meep-engine 3.0.2 → 3.2.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 (1823) hide show
  1. package/LICENSE +188 -188
  2. package/README.md +152 -145
  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/core/binary/BitImage2.js +246 -246
  134. package/src/core/binary/align_32.js +21 -21
  135. package/src/core/binary/data_view/DataType2DataViewReaders.js +23 -23
  136. package/src/core/binary/data_view/DataType2DataViewWriters.js +25 -25
  137. package/src/core/binary/hash/XXH128Hash.js +55 -55
  138. package/src/core/binary/hash/XXH3_SECRET.js +25 -25
  139. package/src/core/binary/hash/xxh3_128.js +341 -341
  140. package/src/core/binary/hash/xxh3_64.js +241 -241
  141. package/src/core/binary/hash/xxh3_common.js +476 -476
  142. package/src/core/binary/lz4/LZ4_MAX_INPUT_SIZE.js +9 -9
  143. package/src/core/binary/lz4/lz4_compress_block.js +385 -385
  144. package/src/core/binary/lz4/lz4_compress_bound.js +25 -25
  145. package/src/core/binary/lz4/lz4_decompress_block.js +139 -139
  146. package/src/core/binary/lz4/lz4_decompress_bound.js +30 -30
  147. package/src/core/binary/meshopt/MESHOPT_GROUP_SIZE.js +18 -18
  148. package/src/core/binary/meshopt/MeshoptCompressionFilter.js +30 -30
  149. package/src/core/binary/meshopt/MeshoptCompressionMode.js +21 -21
  150. package/src/core/binary/meshopt/__meshopt_test_streams.js +237 -237
  151. package/src/core/binary/meshopt/meshopt_decode.js +73 -73
  152. package/src/core/binary/meshopt/meshopt_decode_byte_group.js +67 -67
  153. package/src/core/binary/meshopt/meshopt_decode_data_block.js +59 -59
  154. package/src/core/binary/meshopt/meshopt_decode_filter_color.js +69 -69
  155. package/src/core/binary/meshopt/meshopt_decode_filter_exponential.js +43 -43
  156. package/src/core/binary/meshopt/meshopt_decode_filter_octahedral.js +60 -60
  157. package/src/core/binary/meshopt/meshopt_decode_filter_quaternion.js +71 -71
  158. package/src/core/binary/meshopt/meshopt_decode_index_buffer.js +294 -294
  159. package/src/core/binary/meshopt/meshopt_decode_index_sequence.js +115 -115
  160. package/src/core/binary/meshopt/meshopt_decode_vertex_buffer.js +381 -381
  161. package/src/core/binary/meshopt/meshopt_read_uint_var.js +59 -59
  162. package/src/core/binary/reinterpret_float32_as_uint32.js +13 -13
  163. package/src/core/binary/reinterpret_uint32_as_float32.js +14 -14
  164. package/src/core/binary/type/DataType2TypedArrayConstructorMapping.js +35 -35
  165. package/src/core/bvh2/bvh3/ebvh_geometry_query_any_triangle_ray.js +149 -149
  166. package/src/core/bvh2/bvh3/ebvh_sort_for_traversal_depth_first.js +96 -96
  167. package/src/core/bvh2/bvh3/query/bvh_query_depth_range_in_frustum.js +101 -101
  168. package/src/core/bvh2/bvh3/query/bvh_query_leaves_generic.js +77 -77
  169. package/src/core/bvh2/bvh3/query/bvh_query_leaves_ray.js +90 -90
  170. package/src/core/bvh2/bvh3/query/bvh_query_leaves_ray_segment.js +94 -94
  171. package/src/core/bvh2/bvh3/query/bvh_query_user_data_generic.js +86 -86
  172. package/src/core/bvh2/bvh3/query/bvh_query_user_data_intersects_capsule.js +101 -101
  173. package/src/core/bvh2/bvh3/query/bvh_query_user_data_intersects_sphere.js +92 -92
  174. package/src/core/bvh2/bvh3/query/bvh_query_user_data_ray.js +96 -96
  175. package/src/core/bvh2/bvh3/query/bvh_query_user_data_ray_segment.js +100 -100
  176. package/src/core/bvh2/visual/BVHGeometry.js +131 -131
  177. package/src/core/bvh8/BVH8.js +436 -436
  178. package/src/core/bvh8/aabb3_round_to_float32.js +22 -22
  179. package/src/core/bvh8/build/BVH8Converter.js +588 -588
  180. package/src/core/bvh8/build/TriangleCluster.js +122 -122
  181. package/src/core/bvh8/build/aabb3_compute_merge_cost.js +28 -28
  182. package/src/core/bvh8/build/aabb3_from_triangle_by_index.js +17 -17
  183. package/src/core/bvh8/build/bvh8_build_for_geometry.js +303 -303
  184. package/src/core/bvh8/build/bvh8_from_proxy.js +256 -256
  185. package/src/core/bvh8/build/byte.js +9 -9
  186. package/src/core/bvh8/build/encode_bounds_e.js +11 -11
  187. package/src/core/bvh8/bvh8_convert_to_dot.js +132 -132
  188. package/src/core/bvh8/bvh8_count_primitives.js +98 -98
  189. package/src/core/bvh8/bvh8_geometry_validate.js +138 -138
  190. package/src/core/bvh8/bvh8_geometry_validate_indirect.js +166 -166
  191. package/src/core/bvh8/bvh8_get_node_bounds.js +34 -34
  192. package/src/core/bvh8/bvh8_get_node_child_bounds.js +52 -52
  193. package/src/core/bvh8/bvh8_node_child_surface_area.js +18 -18
  194. package/src/core/bvh8/bvh8_node_count_triangles.js +27 -27
  195. package/src/core/bvh8/bvh8_quality.js +72 -72
  196. package/src/core/bvh8/bvh8_validate_structure.js +87 -87
  197. package/src/core/clipboard/obtainClipBoard.js +29 -29
  198. package/src/core/clipboard/safeClipboardReadText.js +55 -55
  199. package/src/core/clipboard/safeClipboardWriteText.js +23 -23
  200. package/src/core/collection/array/typed/typed_array_value_denormalize.js +52 -52
  201. package/src/core/collection/array/typed/typed_array_value_normalize.js +51 -51
  202. package/src/core/collection/union-find/union_find.js +79 -79
  203. package/src/core/color/YCoCg/rgb_to_ycocg.js +20 -20
  204. package/src/core/color/YCoCg/ycocg_to_rgb.js +17 -17
  205. package/src/core/color/colormap/MAGMA_LUT.js +26 -26
  206. package/src/core/color/illuminant/D65_TRISTIMULUS_XYZ.js +19 -19
  207. package/src/core/color/lab/lab_apply_hunt_adjustment.js +27 -27
  208. package/src/core/color/lab/lab_distance_hyab.js +23 -23
  209. package/src/core/color/lab/xyz_to_lab.js +62 -62
  210. package/src/core/color/operations/color_darken.js +24 -24
  211. package/src/core/color/operations/color_desaturate.js +24 -24
  212. package/src/core/color/operations/color_lighten.js +24 -24
  213. package/src/core/color/operations/color_saturate.js +24 -24
  214. package/src/core/color/operations/color_scale_okhsv_channel.js +45 -45
  215. package/src/core/color/tonemap/tonemap_aces.js +41 -41
  216. package/src/core/color/ycxcz/xyz_to_ycxcz.js +28 -28
  217. package/src/core/color/ycxcz/ycxcz_to_xyz.js +19 -19
  218. package/src/core/dom/isImageBitmap.js +12 -12
  219. package/src/core/function/frameThrottle.js +23 -23
  220. package/src/core/geom/2d/aabb/aabb2_array_combine.js +7 -7
  221. package/src/core/geom/2d/aabb/aabb2_compute_area.js +7 -7
  222. package/src/core/geom/2d/aabb/aabb2_compute_center_from_multiple.js +7 -7
  223. package/src/core/geom/2d/aabb/aabb2_compute_overlap.js +7 -7
  224. package/src/core/geom/2d/aabb/aabb2_from_v2_array.js +7 -7
  225. package/src/core/geom/2d/aabb/aabb2_intersects_point.js +7 -7
  226. package/src/core/geom/2d/aabb/aabb2_overlap_exists.js +7 -7
  227. package/src/core/geom/2d/circle/circle_compute_circle_intersection.js +7 -7
  228. package/src/core/geom/2d/circle/circle_compute_circle_penetration.js +7 -7
  229. package/src/core/geom/2d/circle/circle_intersects_point.js +7 -7
  230. package/src/core/geom/2d/compute_polygon_area_2d.js +7 -7
  231. package/src/core/geom/2d/convex-hull/fixed_convex_hull_humus.js +7 -7
  232. package/src/core/geom/2d/convex-hull/fixed_convex_hull_relaxation.js +7 -7
  233. package/src/core/geom/2d/convex-hull/orientation3_array.js +7 -7
  234. package/src/core/geom/2d/intersect_ray_2d.js +7 -7
  235. package/src/core/geom/2d/line/line2_distance_to_point_sqr.js +7 -7
  236. package/src/core/geom/2d/line/line2_segment_intersection_fraction_2d.js +44 -44
  237. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_2d.js +7 -7
  238. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_array_2d.js +7 -7
  239. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_vectors_2d.js +7 -7
  240. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_vectors_array_2d.js +7 -7
  241. package/src/core/geom/2d/line/line_segment_intersection_fraction_2d.js +7 -7
  242. package/src/core/geom/2d/line/line_segment_line_segment_intersection_exists_2d.js +7 -7
  243. package/src/core/geom/2d/line/segment2_intersects_segment2_2d.js +25 -25
  244. package/src/core/geom/2d/line/segment2_segment_compute_intersection_array_2d.js +46 -46
  245. package/src/core/geom/2d/line/segment2_segment_intersection_fractions.js +52 -52
  246. package/src/core/geom/2d/oriented-box/min_area_rect_2d.js +69 -69
  247. package/src/core/geom/2d/polygon/TRIANGULATION_DESIGN.md +433 -433
  248. package/src/core/geom/2d/polygon/polygon2_clip_axis_halfplane.js +51 -51
  249. package/src/core/geom/2d/polygon/polygon2_clip_halfplane.js +50 -50
  250. package/src/core/geom/2d/polygon/polygon2_is_counter_clockwise.js +84 -84
  251. package/src/core/geom/2d/polygon/polygon2_signed_area.js +52 -52
  252. package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.js +86 -86
  253. package/src/core/geom/2d/polygon/polygon2_triangulate.js +1280 -1280
  254. package/src/core/geom/2d/polygon/polygon2_triangulation_deviation.js +77 -77
  255. package/src/core/geom/2d/quad-tree/qt_collect_by_circle.js +39 -39
  256. package/src/core/geom/2d/quad-tree/qt_match_data_by_circle.js +101 -101
  257. package/src/core/geom/2d/quad-tree/qt_query_data_nearest_to_point.js +7 -7
  258. package/src/core/geom/2d/rectangle_to_aabb.js +7 -7
  259. package/src/core/geom/2d/spline_bezier2_2d.js +7 -7
  260. package/src/core/geom/2d/triangle/tri2_rasterize_conservative.js +99 -99
  261. package/src/core/geom/2d/triangle/tri2_signed_area.js +35 -35
  262. package/src/core/geom/2d/triangle2d_compute_area.js +7 -7
  263. package/src/core/geom/2d/triangle2d_contains_point.js +7 -7
  264. package/src/core/geom/2d/triangle2d_get_barycentric.js +7 -7
  265. package/src/core/geom/2d/v2_morton_encode.js +23 -23
  266. package/src/core/geom/3d/aabb/aabb3_array_intersects_frustum_degree.js +7 -7
  267. package/src/core/geom/3d/aabb/aabb3_box_surface_area_2.js +7 -7
  268. package/src/core/geom/3d/aabb/aabb3_build_frustum.js +5 -5
  269. package/src/core/geom/3d/aabb/aabb3_closest_point_on_surface.js +57 -57
  270. package/src/core/geom/3d/aabb/aabb3_combined_surface_area.js +7 -7
  271. package/src/core/geom/3d/aabb/aabb3_compute_half_surface_area.js +7 -7
  272. package/src/core/geom/3d/aabb/aabb3_compute_projected_area.js +7 -7
  273. package/src/core/geom/3d/aabb/aabb3_compute_surface_area.js +7 -7
  274. package/src/core/geom/3d/aabb/aabb3_detailed_volume_intersection.js +7 -7
  275. package/src/core/geom/3d/aabb/aabb3_estimate_projected_area2.js +7 -7
  276. package/src/core/geom/3d/aabb/aabb3_from_threejs_geometry.js +7 -7
  277. package/src/core/geom/3d/aabb/aabb3_from_triangle_group.js +46 -46
  278. package/src/core/geom/3d/aabb/aabb3_intersects_frustum_degree.js +7 -7
  279. package/src/core/geom/3d/aabb/aabb3_intersects_line_segment.js +7 -7
  280. package/src/core/geom/3d/aabb/aabb3_near_distance_to_intersection_ray_segment.js +7 -7
  281. package/src/core/geom/3d/aabb/aabb3_nearest_point_on_surface.js +7 -7
  282. package/src/core/geom/3d/aabb/aabb3_ray_segment_entry_distance.js +95 -95
  283. package/src/core/geom/3d/aabb/aabb3_raycast.js +7 -7
  284. package/src/core/geom/3d/aabb/aabb3_transform_oriented.js +93 -93
  285. package/src/core/geom/3d/aabb/aabb3_transform_oriented_inverse.js +82 -82
  286. package/src/core/geom/3d/aabb/compute_aabb_from_points.js +7 -7
  287. package/src/core/geom/3d/aabb/compute_triangle_group_aabb3.js +7 -7
  288. package/src/core/geom/3d/atlas/ATLAS_PORT_PLAN.md +486 -486
  289. package/src/core/geom/3d/atlas/BFF_PLAN.md +174 -174
  290. package/src/core/geom/3d/atlas/Chart.js +77 -77
  291. package/src/core/geom/3d/atlas/REVIEW_02.md +392 -392
  292. package/src/core/geom/3d/atlas/atlas_bench_lib.js +315 -315
  293. package/src/core/geom/3d/atlas/atlas_chart_type.js +16 -16
  294. package/src/core/geom/3d/atlas/atlas_compute_charts.js +188 -188
  295. package/src/core/geom/3d/atlas/atlas_extract_chart.js +107 -107
  296. package/src/core/geom/3d/atlas/atlas_generate.js +50 -50
  297. package/src/core/geom/3d/atlas/atlas_test_fixtures.js +266 -266
  298. package/src/core/geom/3d/atlas/atlas_write_chart_uvs.js +36 -36
  299. package/src/core/geom/3d/atlas/data/atlas_build_edge_dihedrals.js +62 -62
  300. package/src/core/geom/3d/atlas/data/atlas_build_edge_lengths.js +33 -33
  301. package/src/core/geom/3d/atlas/data/atlas_build_face_areas.js +50 -50
  302. package/src/core/geom/3d/atlas/io/atlas_mesh_weld_colocals.js +39 -39
  303. package/src/core/geom/3d/atlas/io/bt_loop_uv.js +35 -35
  304. package/src/core/geom/3d/atlas/pack/ChartPlacement.js +46 -46
  305. package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_bff.js +269 -269
  306. package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_lscm.js +209 -209
  307. package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_ortho.js +38 -38
  308. package/src/core/geom/3d/atlas/param/atlas_chart_stretch_metric.js +86 -86
  309. package/src/core/geom/3d/atlas/param/atlas_piecewise_resegment.js +183 -183
  310. package/src/core/geom/3d/atlas/param/fit_plane_basis.js +66 -66
  311. package/src/core/geom/3d/atlas/segment/RegionGraph.js +40 -40
  312. package/src/core/geom/3d/atlas/segment/atlas_build_region_graph.js +136 -136
  313. package/src/core/geom/3d/atlas/segment/atlas_chart_roundness_delta.js +30 -30
  314. package/src/core/geom/3d/atlas/segment/atlas_compute_planar_regions.js +77 -77
  315. package/src/core/geom/3d/atlas/segment/atlas_merge_charts.js +116 -116
  316. package/src/core/geom/3d/atlas/segment/atlas_segment_charts.js +271 -271
  317. package/src/core/geom/3d/atlas/segment/atlas_segment_charts_atomic.js +191 -191
  318. package/src/core/geom/3d/box/box3_projected_half_extent.js +35 -35
  319. package/src/core/geom/3d/capsule/capsule_intersects_aabb3_closed.js +67 -67
  320. package/src/core/geom/3d/capsule/capsule_intersects_aabb3_iterative.js +137 -137
  321. package/src/core/geom/3d/compute_circle_bounding_box.js +7 -7
  322. package/src/core/geom/3d/cone/computeConeBoundingBox.js +7 -7
  323. package/src/core/geom/3d/cone/computeConePlaneSide.js +7 -7
  324. package/src/core/geom/3d/cone/compute_bounding_cone_of_2_cones.js +7 -7
  325. package/src/core/geom/3d/cylinder/cylinder3_raycast.d.ts +38 -0
  326. package/src/core/geom/3d/cylinder/cylinder3_raycast.d.ts.map +1 -0
  327. package/src/core/geom/3d/cylinder/cylinder3_raycast.js +105 -0
  328. package/src/core/geom/3d/equirectangular/equirectangular_direction_to_uv.js +18 -18
  329. package/src/core/geom/3d/equirectangular/equirectangular_uv_to_direction.js +24 -24
  330. package/src/core/geom/3d/frustum/clipping_volume_matrix4_project.js +7 -7
  331. package/src/core/geom/3d/frustum/frustum3_computeNearestPointToPoint.js +7 -7
  332. package/src/core/geom/3d/frustum/frustum3_compute_closest_point.js +117 -117
  333. package/src/core/geom/3d/frustum/frustum_matrix4_project.js +7 -7
  334. package/src/core/geom/3d/frustum/hexahedron_from_aabb.js +7 -7
  335. package/src/core/geom/3d/frustum/read_frustum_corner.js +17 -17
  336. package/src/core/geom/3d/frustum/read_three_planes_to_array.js +7 -7
  337. package/src/core/geom/3d/frustum/slice_frustum_linear_to_points.js +7 -7
  338. package/src/core/geom/3d/gjk/GJK_REVIEW_NOTES.md +146 -146
  339. package/src/core/geom/3d/gjk/gjk.js +430 -430
  340. package/src/core/geom/3d/gjk/gjk_epa_penetration.js +520 -520
  341. package/src/core/geom/3d/gjk/minkowski_support.js +71 -71
  342. package/src/core/geom/3d/gjk/mpr.js +368 -368
  343. package/src/core/geom/3d/line/line3_closest_points_segment_segment.js +7 -7
  344. package/src/core/geom/3d/line/line3_compute_nearest_point_to_point.js +7 -7
  345. package/src/core/geom/3d/line/line3_compute_point_segment_point_distance_unfolded.js +64 -64
  346. package/src/core/geom/3d/line/line3_compute_segment_closest_point_to_aabb3_t.js +153 -153
  347. package/src/core/geom/3d/line/line3_compute_segment_nearest_point_to_aabb3_t.js +7 -7
  348. package/src/core/geom/3d/line/line3_compute_segment_nearest_point_to_point_t.js +7 -7
  349. package/src/core/geom/3d/line/line3_compute_segment_segment_closest_points.js +88 -88
  350. package/src/core/geom/3d/line/line3_segment_segment_closest_point_pair.js +71 -71
  351. package/src/core/geom/3d/line/segment3_point_distance_to_segments.js +25 -25
  352. package/src/core/geom/3d/mat4/allocate_m4.js +7 -7
  353. package/src/core/geom/3d/mat4/apply_mat4_transform_to_direction_v3_array.js +7 -7
  354. package/src/core/geom/3d/mat4/apply_mat4_transform_to_v3_array.js +7 -7
  355. package/src/core/geom/3d/mat4/compose_matrix4_array.js +7 -7
  356. package/src/core/geom/3d/mat4/decompose_matrix_4_array.js +7 -7
  357. package/src/core/geom/3d/mat4/eulerAnglesFromMatrix.js +7 -7
  358. package/src/core/geom/3d/mat4/m4_compose.js +22 -22
  359. package/src/core/geom/3d/mat4/m4_compute_normal_matrix3.js +7 -7
  360. package/src/core/geom/3d/mat4/m4_decompose.js +64 -64
  361. package/src/core/geom/3d/mat4/m4_decompose_array.js +157 -157
  362. package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale.js +32 -32
  363. package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale_scalar.js +67 -67
  364. package/src/core/geom/3d/mat4/m4_linear_matrix3.js +29 -29
  365. package/src/core/geom/3d/mat4/m4_look_at.js +96 -96
  366. package/src/core/geom/3d/mat4/m4_make_rotation_x.js +47 -47
  367. package/src/core/geom/3d/mat4/m4_make_rotation_y.js +47 -47
  368. package/src/core/geom/3d/mat4/m4_make_rotation_z.js +47 -47
  369. package/src/core/geom/3d/mat4/m4_normal_matrix3.js +39 -39
  370. package/src/core/geom/3d/mat4/m4_perspective.js +66 -66
  371. package/src/core/geom/3d/mat4/m4_transpose.js +48 -48
  372. package/src/core/geom/3d/morton/mortonEncode_LUT.js +7 -7
  373. package/src/core/geom/3d/morton/mortonEncode_magicbits.js +7 -7
  374. package/src/core/geom/3d/normal/hemioct/encode_unit3_hemioct.js +5 -5
  375. package/src/core/geom/3d/normal/hemioct/encode_unit_to_hemioct.js +28 -28
  376. package/src/core/geom/3d/normal/lambert_azimuth/decode_azimuth_to_unit.js +30 -30
  377. package/src/core/geom/3d/normal/lambert_azimuth/encode_unit_to_azimuth.js +19 -19
  378. package/src/core/geom/3d/normal/spherical/decode_spheremap_to_unit.js +38 -38
  379. package/src/core/geom/3d/normal/spherical/encode_unit_to_spheremap.js +30 -30
  380. package/src/core/geom/3d/plane/is_point_within_planes.js +7 -7
  381. package/src/core/geom/3d/plane/orient3d_fast_point.js +47 -47
  382. package/src/core/geom/3d/plane/plane3_compute_convex_3_plane_intersection.js +7 -7
  383. package/src/core/geom/3d/plane/plane3_compute_plane_intersection.js +7 -7
  384. package/src/core/geom/3d/plane/plane3_intersect_plane.js +7 -7
  385. package/src/core/geom/3d/plane/plane3_three_compute_convex_3_plane_intersection.js +7 -7
  386. package/src/core/geom/3d/point/point3_raycast.d.ts +33 -0
  387. package/src/core/geom/3d/point/point3_raycast.d.ts.map +1 -0
  388. package/src/core/geom/3d/point/point3_raycast.js +47 -0
  389. package/src/core/geom/3d/polygon/polygon3_compute_normal.js +60 -60
  390. package/src/core/geom/3d/polygon/polygon3_triangulate.js +94 -94
  391. package/src/core/geom/3d/polyhedron/convex_polyhedron3_raycast.d.ts +40 -0
  392. package/src/core/geom/3d/polyhedron/convex_polyhedron3_raycast.d.ts.map +1 -0
  393. package/src/core/geom/3d/polyhedron/convex_polyhedron3_raycast.js +94 -0
  394. package/src/core/geom/3d/quadric/QUADRIC3_SIZE.js +14 -14
  395. package/src/core/geom/3d/quadric/Quadric3.js +282 -282
  396. package/src/core/geom/3d/quadric/quadric3_add.js +33 -33
  397. package/src/core/geom/3d/quadric/quadric3_clear.js +25 -25
  398. package/src/core/geom/3d/quadric/quadric3_copy.js +27 -27
  399. package/src/core/geom/3d/quadric/quadric3_distance.js +36 -36
  400. package/src/core/geom/3d/quadric/quadric3_evaluate.js +25 -25
  401. package/src/core/geom/3d/quadric/quadric3_optimize.js +45 -45
  402. package/src/core/geom/3d/quadric/quadric3_scale.js +32 -32
  403. package/src/core/geom/3d/quadric/quadric3_set_from_plane_through_point.js +30 -30
  404. package/src/core/geom/3d/quadric/quadric3_set_from_vector4.js +35 -35
  405. package/src/core/geom/3d/quadric/quadric3_sub.js +36 -36
  406. package/src/core/geom/3d/quadric/quadric3_to_tensor_m3.js +28 -28
  407. package/src/core/geom/3d/quadric/quadric3_to_tensor_m3_inverse.js +56 -56
  408. package/src/core/geom/3d/quadric/quadric3_to_vector3.js +19 -19
  409. package/src/core/geom/3d/quaternion/quat3_createFromAxisAngle.js +7 -7
  410. package/src/core/geom/3d/quaternion/quat3_integrate.js +62 -62
  411. package/src/core/geom/3d/quaternion/quat3_multiply.js +31 -31
  412. package/src/core/geom/3d/quaternion/quat3_nlerp.js +72 -72
  413. package/src/core/geom/3d/quaternion/quat3_to_matrix3.js +69 -69
  414. package/src/core/geom/3d/quaternion/quat_decode_from_uint32.js +7 -7
  415. package/src/core/geom/3d/quaternion/quat_encode_to_uint32.js +7 -7
  416. package/src/core/geom/3d/ray/ray3_array_compose.js +7 -7
  417. package/src/core/geom/3d/ray/ray3_compute_nearest_point_to_point.js +7 -7
  418. package/src/core/geom/3d/ray/ray3_distance_to_point.js +7 -7
  419. package/src/core/geom/3d/ray/ray3_shift_origin_along_direction.js +7 -7
  420. package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts +17 -0
  421. package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts.map +1 -1
  422. package/src/core/geom/3d/shape/ConvexHullShape3D.js +43 -0
  423. package/src/core/geom/3d/shape/CylinderShape3D.d.ts +1 -0
  424. package/src/core/geom/3d/shape/CylinderShape3D.d.ts.map +1 -1
  425. package/src/core/geom/3d/shape/CylinderShape3D.js +21 -0
  426. package/src/core/geom/3d/shape/PointShape3D.d.ts +7 -0
  427. package/src/core/geom/3d/shape/PointShape3D.d.ts.map +1 -1
  428. package/src/core/geom/3d/shape/PointShape3D.js +88 -63
  429. package/src/core/geom/3d/shape/PosedShape3D.d.ts +6 -0
  430. package/src/core/geom/3d/shape/PosedShape3D.d.ts.map +1 -1
  431. package/src/core/geom/3d/shape/PosedShape3D.js +27 -0
  432. package/src/core/geom/3d/shape/TransformedShape3D.d.ts +10 -0
  433. package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
  434. package/src/core/geom/3d/shape/TransformedShape3D.js +13 -0
  435. package/src/core/geom/3d/shape/Triangle3D.d.ts +1 -0
  436. package/src/core/geom/3d/shape/Triangle3D.d.ts.map +1 -1
  437. package/src/core/geom/3d/shape/Triangle3D.js +26 -0
  438. package/src/core/geom/3d/shape/UnionShape3D.d.ts +6 -0
  439. package/src/core/geom/3d/shape/UnionShape3D.d.ts.map +1 -1
  440. package/src/core/geom/3d/shape/UnionShape3D.js +7 -0
  441. package/src/core/geom/3d/shape/UnitCubeShape3D.js +45 -45
  442. package/src/core/geom/3d/shape/UnitSphereShape3D.js +44 -44
  443. package/src/core/geom/3d/shape/shape3_mesh_from_geometry.js +64 -64
  444. package/src/core/geom/3d/shape/shape_mesh_from_geometry.js +7 -7
  445. package/src/core/geom/3d/shape/util/compute_signed_distance_gradient_by_sampling.js +51 -51
  446. package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.js +7 -7
  447. package/src/core/geom/3d/sphere/compute_bounding_sphere_of_2_spheres.js +7 -7
  448. package/src/core/geom/3d/sphere/harmonics/sh3_convolve_with_zh.js +53 -53
  449. package/src/core/geom/3d/sphere/harmonics/sh3_ggx_zh.js +30 -30
  450. package/src/core/geom/3d/sphere/harmonics/sh3_rotate_bl.js +7 -7
  451. package/src/core/geom/3d/sphere/harmonics/sh_compute_K.js +7 -7
  452. package/src/core/geom/3d/sphere/sphere_array_intersects_point.js +7 -7
  453. package/src/core/geom/3d/sphere/sphere_array_intersects_ray.js +7 -7
  454. package/src/core/geom/3d/sphere/sphere_intersects_point.js +7 -7
  455. package/src/core/geom/3d/sphere/sphere_matrix4_transform.js +5 -5
  456. package/src/core/geom/3d/sphere/sphere_projected_sphere_radius_sqr.js +7 -7
  457. package/src/core/geom/3d/sphere/sphere_radius_sqr_from_v3_array_transformed.js +7 -7
  458. package/src/core/geom/3d/sphere/spherical_from_cartesian.js +7 -7
  459. package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.js +174 -174
  460. package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.js +7 -7
  461. package/src/core/geom/3d/tetrahedra/compute_tetrahedron_volume.js +7 -7
  462. package/src/core/geom/3d/tetrahedra/delaunay/fill_in_a_cavity.js +7 -7
  463. package/src/core/geom/3d/tetrahedra/graphics/build_tetrahedral_mesh_geometry.js +39 -39
  464. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_build_vertex_to_tets_map.js +48 -48
  465. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.js +173 -173
  466. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_compute_tet_quality.js +22 -22
  467. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.js +146 -146
  468. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.js +232 -232
  469. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.js +255 -255
  470. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.js +387 -387
  471. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.js +140 -140
  472. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_tet_get_neighbours.js +7 -7
  473. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.js +97 -97
  474. package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.js +66 -66
  475. package/src/core/geom/3d/tetrahedra/triangle/triangle_decode_depth.js +59 -59
  476. package/src/core/geom/3d/tetrahedra/triangle/triangle_rasterized_depth_sample_index.js +54 -54
  477. package/src/core/geom/3d/tetrahedra/validate_neighbour.js +70 -70
  478. package/src/core/geom/3d/topology/struct/binary/BinaryDataBlock.js +314 -314
  479. package/src/core/geom/3d/topology/struct/binary/BinaryDataLayer.js +364 -364
  480. package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.js +567 -567
  481. package/src/core/geom/3d/topology/struct/binary/BinaryTopology.js +1085 -1085
  482. package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.js +73 -73
  483. package/src/core/geom/3d/topology/struct/binary/io/bt_loop_kill.js +35 -35
  484. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_append.js +119 -119
  485. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.js +84 -84
  486. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.js +172 -172
  487. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_face_normals.js +56 -56
  488. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_vertex_quadratics.js +7 -7
  489. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_vertex_quadrics.js +227 -227
  490. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_decouple.js +161 -161
  491. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_island_erode.js +490 -490
  492. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.js +120 -120
  493. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_from_indexed_geometry.js +120 -120
  494. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_collapse.js +52 -52
  495. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_create.js +115 -115
  496. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_flip.js +142 -142
  497. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_get_or_create.js +21 -21
  498. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.js +92 -92
  499. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_split.js +179 -179
  500. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_swap_vertex_slots.js +28 -28
  501. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_kill_only_edge.js +8 -8
  502. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_fuse_duplicate_edges.js +83 -83
  503. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.js +89 -89
  504. package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_kill.js +25 -25
  505. package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_poke.js +127 -127
  506. package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_triangulate.js +268 -268
  507. package/src/core/geom/3d/topology/struct/binary/io/face/bt_kill_only_face.js +8 -8
  508. package/src/core/geom/3d/topology/struct/binary/io/face/bt_mesh_kill_degenerate_faces.js +72 -72
  509. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_kill_only_vert.js +7 -7
  510. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_merge_verts_by_distance.js +7 -7
  511. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_mesh_relative_merge_distance.js +48 -48
  512. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_mesh_split_pinched_vertices.js +256 -256
  513. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_mesh_vertex_merge_distance.js +77 -77
  514. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vert_fuse_duplicate_edges.js +7 -7
  515. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vert_kill.js +7 -7
  516. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_fuse_duplicate_edges.js +148 -148
  517. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_kill_only.js +7 -7
  518. package/src/core/geom/3d/topology/struct/binary/query/bt_collect_boundary_segments.js +29 -29
  519. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_collapse_breaks_link_condition.js +107 -107
  520. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_flip_is_legal.js +41 -41
  521. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_flip_would_fold.js +120 -120
  522. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.js +42 -42
  523. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_is_boundary.js +20 -20
  524. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_read_diamond.js +96 -96
  525. package/src/core/geom/3d/topology/struct/binary/query/bt_face_compute_newell_normal.js +72 -72
  526. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_attached_faces.js +7 -7
  527. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_edge_adjacent_faces.js +39 -39
  528. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_edge_adjacent_faces_weighted.js +93 -93
  529. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_neighbour_faces.js +7 -7
  530. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_shared_loop.js +48 -48
  531. package/src/core/geom/3d/topology/struct/binary/query/bt_face_island_flood_fill.js +45 -45
  532. package/src/core/geom/3d/topology/struct/binary/query/bt_face_read_triangle.js +66 -66
  533. package/src/core/geom/3d/topology/struct/binary/query/bt_faces_shared_loop.js +7 -7
  534. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_assert_valid.js +44 -44
  535. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_build_boundary_euclidean_distance_field.js +32 -32
  536. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_compute_face_islands.js +53 -53
  537. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path.js +703 -703
  538. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.js +181 -181
  539. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_segment_penetrates_surface.js +133 -133
  540. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_surface_ray_parity.js +82 -82
  541. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_validate.js +599 -599
  542. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.js +108 -108
  543. package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.js +7 -7
  544. package/src/core/geom/3d/triangle/computeTriangleClosestPointToPointBarycentric.js +7 -7
  545. package/src/core/geom/3d/triangle/computeTriangleRayIntersection.js +7 -7
  546. package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentric.js +7 -7
  547. package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentricEdge.js +7 -7
  548. package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentricGeometry.js +7 -7
  549. package/src/core/geom/3d/triangle/compute_triangle_area_3d.js +7 -7
  550. package/src/core/geom/3d/triangle/compute_triangle_normal.js +7 -7
  551. package/src/core/geom/3d/triangle/rayTriangleIntersection.js +7 -7
  552. package/src/core/geom/3d/triangle/tri3_closest_point.js +65 -65
  553. package/src/core/geom/3d/triangle/tri3_closest_point_barycentric.js +171 -171
  554. package/src/core/geom/3d/triangle/tri3_flatten_isometric.js +79 -79
  555. package/src/core/geom/3d/triangle/tri3_ray_intersection.js +160 -160
  556. package/src/core/geom/3d/triangle/tri3_ray_intersection_barycentric.js +96 -96
  557. package/src/core/geom/3d/triangle/tri3_raycast.d.ts +42 -0
  558. package/src/core/geom/3d/triangle/tri3_raycast.d.ts.map +1 -0
  559. package/src/core/geom/3d/triangle/tri3_raycast.js +94 -0
  560. package/src/core/geom/3d/triangle/triangle3_incenter.js +7 -7
  561. package/src/core/geom/3d/triangle/triangle_compute_plane_side.js +7 -7
  562. package/src/core/geom/3d/triangle/triangle_compute_signed_volume.js +7 -7
  563. package/src/core/geom/3d/triangle/triangle_intersects_clipping_volume.js +7 -7
  564. package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.js +7 -7
  565. package/src/core/geom/3d/triangle/v3_compute_triangle_normal.js +7 -7
  566. package/src/core/geom/3d/util/make_justified_point_grid.js +7 -7
  567. package/src/core/geom/GEOMETRY_REVIEW_002_API_ISSUES.md +381 -381
  568. package/src/core/geom/GEOMETRY_REVIEW_002_NAMING.md +684 -684
  569. package/src/core/geom/MANIFOLD_COMPARISON_2026_08_01.md +554 -554
  570. package/src/core/geom/mat3/m3_cm_from_translation.js +7 -7
  571. package/src/core/geom/mat3/m3_cm_invert.js +7 -7
  572. package/src/core/geom/mat3/m3_make_rotation.js +5 -5
  573. package/src/core/geom/mat3/m3_make_rotation_TBN.js +31 -31
  574. package/src/core/geom/mat3/m3_multiply_vec3.js +7 -7
  575. package/src/core/geom/packing/computeBoundingSphereOfSpheres.js +7 -7
  576. package/src/core/geom/packing/max-rect/cost/costByBestShortSide.js +7 -7
  577. package/src/core/geom/packing/max-rect/cost/costByRemainingArea.js +7 -7
  578. package/src/core/geom/packing/max-rect/cutArea.js +7 -7
  579. package/src/core/geom/packing/max-rect/findBestContainer.js +7 -7
  580. package/src/core/geom/packing/max-rect/packMaxRectangles.js +7 -7
  581. package/src/core/geom/packing/max-rect/packOneBox.js +7 -7
  582. package/src/core/geom/packing/max-rect/removeRedundantBoxes.js +7 -7
  583. package/src/core/geom/packing/max-rect/removeRedundantBoxesArray.js +7 -7
  584. package/src/core/geom/random/randomPointInBox.js +7 -7
  585. package/src/core/geom/random/randomPointInCircle.js +7 -7
  586. package/src/core/geom/random/randomPointInPoint.js +7 -7
  587. package/src/core/geom/random/randomPointInSphere.js +7 -7
  588. package/src/core/geom/random/randomPointOnBox.js +7 -7
  589. package/src/core/geom/random/randomPointOnSphere.js +7 -7
  590. package/src/core/geom/random/random_orthonormal_basis.js +31 -31
  591. package/src/core/geom/vec/vector_axpy.js +15 -15
  592. package/src/core/geom/vec/vector_axpy_offset.js +20 -20
  593. package/src/core/geom/vec/vector_copy.js +7 -7
  594. package/src/core/geom/vec/vector_dot_offset.js +25 -25
  595. package/src/core/geom/vec/vector_scale_array.js +7 -7
  596. package/src/core/geom/vec2/v2_rotate.js +21 -21
  597. package/src/core/geom/vec2/v2_rotate_cos_sin.js +21 -21
  598. package/src/core/geom/vec3/v3_angle_atan2_between.js +7 -7
  599. package/src/core/geom/vec3/v3_angle_between.js +7 -7
  600. package/src/core/geom/vec3/v3_angle_cos_between.js +7 -7
  601. package/src/core/geom/vec3/v3_array_add_in_place.js +7 -7
  602. package/src/core/geom/vec3/v3_array_centroid.js +7 -7
  603. package/src/core/geom/vec3/v3_array_copy.js +7 -7
  604. package/src/core/geom/vec3/v3_array_displace_in_direction.js +7 -7
  605. package/src/core/geom/vec3/v3_array_equals.js +7 -7
  606. package/src/core/geom/vec3/v3_array_immediate_add.js +7 -7
  607. package/src/core/geom/vec3/v3_array_matrix4_rotate.js +7 -7
  608. package/src/core/geom/vec3/v3_array_normalize.js +7 -7
  609. package/src/core/geom/vec3/v3_array_scale.js +7 -7
  610. package/src/core/geom/vec3/v3_compute_interior_angle.js +7 -7
  611. package/src/core/geom/vec3/v3_cotangent.js +33 -33
  612. package/src/core/geom/vec3/v3_dot_array_array.js +7 -7
  613. package/src/core/geom/vec3/v3_matrix3_multiply.js +30 -30
  614. package/src/core/geom/vec3/v3_matrix3_rotate.js +49 -49
  615. package/src/core/geom/vec3/v3_matrix4_rotate.js +7 -7
  616. package/src/core/geom/vec3/v3_multiply.js +23 -23
  617. package/src/core/geom/vec3/v3_multiply_scalar.js +7 -7
  618. package/src/core/geom/vec3/v3_orthonormal_matrix_from_normal.js +49 -49
  619. package/src/core/geom/vec3/v3_quat3_apply.js +7 -7
  620. package/src/core/geom/vec3/v3_quat3_apply_inverse.js +7 -7
  621. package/src/core/geom/vec3/v3_quaternion_apply.js +39 -39
  622. package/src/core/geom/vec3/v3_quaternion_apply_inverse.js +41 -41
  623. package/src/core/geom/vec3/v3_reflect.js +24 -24
  624. package/src/core/geom/vec3/v3_scale_array.js +18 -18
  625. package/src/core/geom/vec3/v3_triple_cross.js +45 -45
  626. package/src/core/geom/vec3/v3_triple_cross_product.js +7 -7
  627. package/src/core/geom/vec3/v3_uniform_sample_cone.js +21 -21
  628. package/src/core/geom/vec4/v4_multiply_mat4.js +7 -7
  629. package/src/core/graph/csr/csr_graph_build_distance_field.js +112 -112
  630. package/src/core/graph/csr/csr_graph_find_edge.js +25 -25
  631. package/src/core/graph/csr/csr_graph_find_shortest_path.js +105 -105
  632. package/src/core/graph/csr/csr_graph_from_undirected_edge_list.js +94 -94
  633. package/src/core/graph/graph_k_means_cluster.js +250 -250
  634. package/src/core/graph/layout/CircleLayout.js +1 -1
  635. package/src/core/graph/layout/box/BoxLayouter.js +1 -1
  636. package/src/core/graph/layout/graph_peel_topological_layer.js +45 -45
  637. package/src/core/graph/metis/BinaryTopologyFaceGraph.js +49 -49
  638. package/src/core/graph/metis/bt_mesh_build_face_graph.js +111 -111
  639. package/src/core/graph/metis/cluster_mesh_metis.js +137 -137
  640. package/src/core/graph/metis/native/bisection/bisect_graph.js +100 -100
  641. package/src/core/graph/metis/native/bisection/compute_2way_params.js +86 -86
  642. package/src/core/graph/metis/native/bisection/fm_2way.js +297 -297
  643. package/src/core/graph/metis/native/bisection/grow_bisection.js +137 -137
  644. package/src/core/graph/metis/native/bisection/split_graph_two_way.js +119 -119
  645. package/src/core/graph/metis/native/coarsen/coarsen_graph.js +94 -94
  646. package/src/core/graph/metis/native/coarsen/create_coarse_graph.js +158 -158
  647. package/src/core/graph/metis/native/coarsen/match_shem.js +175 -175
  648. package/src/core/graph/metis/native/initial/initial_kway_bfs.js +122 -122
  649. package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.js +170 -170
  650. package/src/core/graph/metis/native/metis_partition_kway.js +126 -126
  651. package/src/core/graph/metis/native/refine/RefinementScratch.js +53 -53
  652. package/src/core/graph/metis/native/refine/fm_kway.js +487 -487
  653. package/src/core/graph/metis/native/refine/project_kway.js +43 -43
  654. package/src/core/graph/metis/native/refine/refine_kway.js +43 -43
  655. package/src/core/lang/reactive/pegjs/parser.js +3458 -3458
  656. package/src/core/math/complex/complex_horner_eval.js +31 -31
  657. package/src/core/math/computeWholeDivisorLow.js +33 -33
  658. package/src/core/math/f32_next_down.js +24 -24
  659. package/src/core/math/f32_next_up.js +27 -27
  660. package/src/core/math/hash/hash_mix2.js +22 -22
  661. package/src/core/math/hash/hash_mix3.js +19 -19
  662. package/src/core/math/linalg/cg/cg_solve.js +106 -106
  663. package/src/core/math/linalg/cg/cg_solve_normal_equations.js +59 -59
  664. package/src/core/math/linalg/cubic_residual_times_derivative_accumulate.js +43 -43
  665. package/src/core/math/linalg/eigen/matrix_householder_in_place.js +122 -122
  666. package/src/core/math/linalg/eigen/matrix_qr_in_place.js +190 -190
  667. package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.js +117 -117
  668. package/src/core/math/linalg/givens/givens_apply_rows.js +28 -28
  669. package/src/core/math/linalg/givens/givens_apply_rows_offset.js +30 -30
  670. package/src/core/math/linalg/givens/givens_rotation_coefficients.js +39 -39
  671. package/src/core/math/linalg/lu_factor_linear_system.js +108 -108
  672. package/src/core/math/linalg/lu_solve_linear_system.js +53 -53
  673. package/src/core/math/linalg/polynomial_add_into.js +29 -29
  674. package/src/core/math/linalg/polynomial_complex_roots_aberth_ehrlich.js +159 -159
  675. package/src/core/math/linalg/polynomial_cubic_derivative_eval.js +16 -16
  676. package/src/core/math/linalg/polynomial_cubic_horner_eval.js +19 -19
  677. package/src/core/math/linalg/polynomial_cubic_second_derivative_eval.js +14 -14
  678. package/src/core/math/linalg/polynomial_multiply.js +41 -41
  679. package/src/core/math/linalg/polynomial_real_roots_in_interval.js +211 -211
  680. package/src/core/math/linalg/polynomial_root_bound_cauchy.js +30 -30
  681. package/src/core/math/linalg/polynomial_scale_into.js +17 -17
  682. package/src/core/math/linalg/polynomial_sub_into.js +29 -29
  683. package/src/core/math/linalg/solve_linear_system_GEPP_2x2.js +96 -96
  684. package/src/core/math/linalg/sor_optimal_omega.js +42 -42
  685. package/src/core/math/linalg/sparse/SparseMatrixCSR.js +88 -88
  686. package/src/core/math/linalg/sparse/spm_matvec.js +22 -22
  687. package/src/core/math/linalg/sparse/spm_matvec_transpose.js +29 -29
  688. package/src/core/math/lookup/LUT_HEATMAP.js +30 -30
  689. package/src/core/math/lookup/ParameterLookupTable.js +495 -495
  690. package/src/core/math/lookup/ParameterLookupTableFlags.js +6 -6
  691. package/src/core/math/noise/curl_noise_3d.js +18 -18
  692. package/src/core/math/physics/brdf/cone_cosine_from_roughness.js +28 -28
  693. package/src/core/math/physics/brdf/reflection_sample_weight.js +48 -48
  694. package/src/core/math/physics/kinematics/computeInterceptPoint.js +79 -79
  695. package/src/core/math/random/randomSeed.js +16 -16
  696. package/src/core/math/random/random_pick_weighted_index.js +26 -26
  697. package/src/core/math/round_half_away_from_zero.js +13 -13
  698. package/src/core/math/spline/spline3_hermite_apply_transform.js +107 -107
  699. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_1d.js +125 -125
  700. package/src/core/math/spline/spline3_hermite_intersects_spline3_hermite.js +50 -50
  701. package/src/core/math/spline/spline3_hermite_reverse.js +49 -49
  702. package/src/core/math/spline/spline3_hermite_to_monomial.js +37 -37
  703. package/src/core/math/statistics/hammersley_sequence.js +53 -53
  704. package/src/core/model/reactive/model/util/createRandomReactiveExpression.js +185 -185
  705. package/src/core/path/convertPathToURL.js +107 -107
  706. package/src/core/process/delay.js +16 -16
  707. package/src/core/science/units/MEASUREMENT_UNITS_SCIENTIFIC.js +87 -87
  708. package/src/core/science/units/MEASUREMENT_UNITS_SI.js +17 -17
  709. package/src/core/science/units/NamedUnit.js +48 -48
  710. package/src/core/science/units/UNIT_DIMENSION_MAPPING.js +29 -29
  711. package/src/core/science/units/UnitDimension.js +28 -28
  712. package/src/core/science/units/format_quantity.js +74 -74
  713. package/src/core/science/units/magnitude_prefix.js +127 -127
  714. package/src/core/science/units/si/AMPERE.js +13 -13
  715. package/src/core/science/units/si/CANDELA.js +13 -13
  716. package/src/core/science/units/si/DIMENSIONLESS.js +14 -14
  717. package/src/core/science/units/si/KELVIN.js +13 -13
  718. package/src/core/science/units/si/KILOGRAM.js +13 -13
  719. package/src/core/science/units/si/METER.js +13 -13
  720. package/src/core/science/units/si/MOLE.js +13 -13
  721. package/src/core/science/units/si/SECOND.js +13 -13
  722. package/src/core/science/units/si/derived/BECQUEREL.js +16 -16
  723. package/src/core/science/units/si/derived/COULOMB.js +13 -13
  724. package/src/core/science/units/si/derived/FARAD.js +13 -13
  725. package/src/core/science/units/si/derived/GRAY.js +16 -16
  726. package/src/core/science/units/si/derived/HENRY.js +13 -13
  727. package/src/core/science/units/si/derived/HERTZ.js +16 -16
  728. package/src/core/science/units/si/derived/JOULE.js +13 -13
  729. package/src/core/science/units/si/derived/KATAL.js +13 -13
  730. package/src/core/science/units/si/derived/LUMEN.js +14 -14
  731. package/src/core/science/units/si/derived/LUX.js +13 -13
  732. package/src/core/science/units/si/derived/NEWTON.js +13 -13
  733. package/src/core/science/units/si/derived/OHM.js +13 -13
  734. package/src/core/science/units/si/derived/PASCAL.js +13 -13
  735. package/src/core/science/units/si/derived/SIEMENS.js +13 -13
  736. package/src/core/science/units/si/derived/SIEVERT.js +16 -16
  737. package/src/core/science/units/si/derived/TESLA.js +13 -13
  738. package/src/core/science/units/si/derived/VOLT.js +13 -13
  739. package/src/core/science/units/si/derived/WATT.js +13 -13
  740. package/src/core/science/units/si/derived/WEBER.js +13 -13
  741. package/src/core/science/units/unit_matrix_to_string.js +403 -403
  742. package/src/engine/Engine.js +726 -726
  743. package/src/engine/EngineHarness.js +590 -590
  744. package/src/engine/REVIEW_2026_07_03.md +211 -211
  745. package/src/engine/animation/AnimatedActions.js +81 -81
  746. package/src/engine/animation/AnimationUtils.js +252 -252
  747. package/src/engine/animation/async/TimeSeries.js +300 -300
  748. package/src/engine/animation/curve/animation_curve_binary_codec.js +60 -60
  749. package/src/engine/animation/curve/draw/canvas_point_to_curve.js +22 -22
  750. package/src/engine/animation/curve/draw/curve_point_to_canvas.js +38 -38
  751. package/src/engine/animation/curve/draw/position_canvas_to_curve.js +22 -22
  752. package/src/engine/animation/curve/draw/position_curve_to_canvas.js +22 -22
  753. package/src/engine/asset/GameAssetType.d.ts +0 -1
  754. package/src/engine/asset/GameAssetType.js +0 -1
  755. package/src/engine/asset/load_model_scene_bundle.js +27 -27
  756. package/src/engine/asset/loaders/font/FontAsset.js +21 -21
  757. package/src/engine/asset/loaders/font/FontAssetLoader.js +20 -20
  758. package/src/engine/asset/loaders/gltf_test_fixtures.js +358 -358
  759. package/src/engine/asset/loaders/image/ImageBitmapAssetLoader.js +52 -52
  760. package/src/engine/asset/loaders/image/ImageRGBADataLoader.js +94 -94
  761. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterAverage.js +59 -59
  762. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterNone.js +55 -55
  763. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterPaeth.js +74 -74
  764. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterSub.js +34 -34
  765. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterUp.js +46 -46
  766. package/src/engine/control/first-person/DESIGN.md +640 -640
  767. package/src/engine/control/first-person/DESIGN_EXTENSIONS.md +563 -563
  768. package/src/engine/control/first-person/FirstPersonMotionPhase.js +134 -134
  769. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +2045 -2045
  770. package/src/engine/control/first-person/mastery/DecisionPoint.js +30 -30
  771. package/src/engine/control/first-person/math/Spring.js +71 -71
  772. package/src/engine/control/first-person/math/computeJumpFromApex.js +23 -23
  773. package/src/engine/control/first-person/math/computeLRCBreathRate.js +41 -41
  774. package/src/engine/control/first-person/math/computeMassRatios.js +44 -44
  775. package/src/engine/control/first-person/math/criticallyDampedSpring.js +34 -34
  776. package/src/engine/control/first-person/math/dampedSpringStep.js +72 -72
  777. package/src/engine/control/first-person/math/jumpDynamics.js +108 -108
  778. package/src/engine/control/first-person/math/stepTowards.js +20 -20
  779. package/src/engine/control/first-person/pose/FirstPersonPose.js +137 -137
  780. package/src/engine/control/first-person/pose/FirstPersonPosture.js +27 -27
  781. package/src/engine/control/first-person/test/buildTestPlayer.js +36 -36
  782. package/src/engine/ecs/ASYNC_SYSTEMS_PROPOSAL.md +531 -531
  783. package/src/engine/ecs/EntityManager.d.ts +7 -3
  784. package/src/engine/ecs/EntityManager.d.ts.map +1 -1
  785. package/src/engine/ecs/EntityManager.js +10 -5
  786. package/src/engine/ecs/HIERARCHY_REVIEW.md +717 -717
  787. package/src/engine/ecs/async/SystemWorkerHost.js +329 -329
  788. package/src/engine/ecs/async/SystemWorkerLoopback.js +143 -143
  789. package/src/engine/ecs/async/WORKER_SYSTEM_PLAN.md +246 -246
  790. package/src/engine/ecs/async/WorkerSystem.js +702 -702
  791. package/src/engine/ecs/async/WorkerSystemProtocol.js +150 -150
  792. package/src/engine/ecs/fow/FogOfWar.js +707 -707
  793. package/src/engine/ecs/fow/FogOfWarEdgeMode.js +40 -40
  794. package/src/engine/ecs/fow/fog_of_war_mask_world_bounds.js +24 -24
  795. package/src/engine/ecs/fow/fog_of_war_uv_transform.js +30 -30
  796. package/src/engine/ecs/gui/hud/testHudEdgeStick.js +132 -134
  797. package/src/engine/ecs/hierarchy/EntityChildIndex.js +140 -140
  798. package/src/engine/ecs/ik/IKProblem.js +42 -42
  799. package/src/engine/ecs/ik/InverseKinematicsSystem.js +193 -193
  800. package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.js +134 -134
  801. package/src/engine/ecs/ik/TwoBoneInverseKinematicsSolver.js +97 -97
  802. package/src/engine/ecs/ik/ik_bone_chain.js +85 -85
  803. package/src/engine/ecs/ik/ik_probe_terrain_contact.js +119 -119
  804. package/src/engine/ecs/parent/EntityNode.d.ts +1 -1
  805. package/src/engine/ecs/parent/EntityNode.js +2 -2
  806. package/src/engine/ecs/parent/ParentEntitySystem.js +255 -255
  807. package/src/engine/ecs/speaker/VoiceSystem.d.ts +2 -2
  808. package/src/engine/ecs/speaker/VoiceSystem.d.ts.map +1 -1
  809. package/src/engine/ecs/speaker/VoiceSystem.js +13 -7
  810. package/src/engine/ecs/storage/binary/SERIALIZATION_COVERAGE.md +269 -269
  811. package/src/engine/ecs/storage/binary/object-v2/BinaryObjectDeSerializer.js +315 -315
  812. package/src/engine/ecs/storage/binary/object-v2/BinaryObjectSerializer.js +331 -331
  813. package/src/engine/ecs/storage/binary/object-v2/DESIGN.md +199 -199
  814. package/src/engine/ecs/storage/binary/object-v2/ObjectBinaryFormat.js +57 -57
  815. package/src/engine/ecs/storage/binary/object-v2/ObjectSerializationAdapter.js +56 -56
  816. package/src/engine/ecs/storage/binary/object-v2/README.md +110 -110
  817. package/src/engine/ecs/storage/binary/object-v2/objectStringCodec.js +48 -48
  818. package/src/engine/ecs/storage/binary/object-v2/serializerTestHarness.js +44 -44
  819. package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +265 -265
  820. package/src/engine/ecs/terrain/TerrainClouds.js +97 -97
  821. package/src/engine/ecs/terrain/ecs/StubTerrainBuildWorker.js +65 -65
  822. package/src/engine/ecs/terrain/ecs/Terrain.d.ts +4 -0
  823. package/src/engine/ecs/terrain/ecs/Terrain.d.ts.map +1 -1
  824. package/src/engine/ecs/terrain/ecs/Terrain.js +790 -790
  825. package/src/engine/ecs/terrain/ecs/TerrainSystem.js +209 -209
  826. package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.js +316 -316
  827. package/src/engine/ecs/terrain/ecs/layers/TerrainLayers.js +416 -416
  828. package/src/engine/ecs/terrain/ecs/splat/SplatMapping.js +525 -525
  829. package/src/engine/ecs/terrain/overlay/TerrainOverlay.js +302 -302
  830. package/src/engine/ecs/terrain/tiles/TerrainTile.js +561 -561
  831. package/src/engine/ecs/terrain/tiles/TerrainTileManager.js +896 -896
  832. package/src/engine/ecs/terrain/tiles/tile_geometry_to_meshlets.js +36 -36
  833. package/src/engine/ecs/terrain/util/loadVisibleTerrainTiles.js +129 -129
  834. package/src/engine/ecs/transform/Transform64.js +814 -814
  835. package/src/engine/ecs/transform/t64_copy_from_transform.js +35 -35
  836. package/src/engine/ecs/transform/t64_equals_transform.js +55 -55
  837. package/src/engine/ecs/transform/t64_look_rotation.js +36 -36
  838. package/src/engine/ecs/transform/t64_transform_direction.js +25 -25
  839. package/src/engine/ecs/transform/transform_copy_from_t64.js +28 -28
  840. package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.js +345 -345
  841. package/src/engine/ecs/transform-attachment/transform_attachment_find_descendant_by_name.js +65 -65
  842. package/src/engine/ecs/transform-attachment/transform_attachment_parent_of.js +24 -24
  843. package/src/engine/ecs/util/hideEntityGracefully.js +208 -208
  844. package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +446 -446
  845. package/src/engine/graphics/FULL_SCREEN_QUAD_VERTEX_SHADER.js +14 -14
  846. package/src/engine/graphics/FrameThrottle.js +2 -2
  847. package/src/engine/graphics/ecs/animation/animator/graph/AnimationState.js +207 -207
  848. package/src/engine/graphics/ecs/animation/animator/graph/AnimationTransition.js +151 -151
  849. package/src/engine/graphics/ecs/animation/animator/graph/definition/serialization/AnimationGraphDefinitionAssetLoader.js +22 -22
  850. package/src/engine/graphics/ecs/camera/Camera.js +165 -165
  851. package/src/engine/graphics/ecs/camera/camera_active_frustum.js +25 -25
  852. package/src/engine/graphics/ecs/camera/camera_find_active.js +28 -28
  853. package/src/engine/graphics/ecs/camera/camera_traverse_active.js +18 -18
  854. package/src/engine/graphics/ecs/camera/pp/PerfectPanner.js +170 -170
  855. package/src/engine/graphics/ecs/camera/serialization/CameraSerializationAdapter.js +68 -68
  856. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.js +296 -296
  857. package/src/engine/graphics/ecs/decal/v2/Decal.js +220 -220
  858. package/src/engine/graphics/ecs/decal/v2/DecalSerializationAdapter.js +56 -56
  859. package/src/engine/graphics/ecs/decal/v2/DecalSerializationUpgrader_0_1.js +38 -38
  860. package/src/engine/graphics/ecs/light/shadow/compute_view_frustum_aabb_in_space.js +62 -62
  861. package/src/engine/graphics/ecs/light/shadow/extend_shadow_camera_near_for_casters.js +77 -77
  862. package/src/engine/graphics/ecs/make_bvh_depth_range_computer.js +33 -33
  863. package/src/engine/graphics/ecs/mesh-v2/DeferredBoundsQueue.js +88 -88
  864. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +428 -428
  865. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMesh.js +303 -303
  866. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMeshSystem.d.ts +1 -1
  867. package/src/engine/graphics/ecs/mesh-v2/aggregate/serialization/SGMeshSerializationAdapter.js +39 -39
  868. package/src/engine/graphics/ecs/mesh-v2/sg_hierarchy_compute_bounding_box_via_parent_entity.js +36 -36
  869. package/src/engine/graphics/ecs/path/tube/build/GeometryStream.js +94 -94
  870. package/src/engine/graphics/ecs/path/tube/build/build_stream_catmullrom.js +310 -310
  871. package/src/engine/graphics/ecs/path/tube/build/build_stream_linear.js +73 -73
  872. package/src/engine/graphics/ecs/path/tube/build/computeFrenetFrames.js +199 -199
  873. package/src/engine/graphics/ecs/path/tube/build/makeTubeStream.js +217 -217
  874. package/src/engine/graphics/ecs/path/tube/build/make_cap.js +340 -340
  875. package/src/engine/graphics/ecs/path/tube/build/make_ring_faces.js +40 -40
  876. package/src/engine/graphics/ecs/path/tube/build/make_ring_vertices.js +153 -153
  877. package/src/engine/graphics/ecs/render_layers_compute_depth_range.js +64 -64
  878. package/src/engine/graphics/ecs/trail3d/Trail3D.js +483 -483
  879. package/src/engine/graphics/ecs/trail3d/Trail3DFlags.js +26 -26
  880. package/src/engine/graphics/ecs/trail3d/advance_trail.js +42 -42
  881. package/src/engine/graphics/ecs/trail3d/make_gradient_stroke.js +58 -58
  882. package/src/engine/graphics/ecs/trail3d/seed_trail_stroke.js +90 -90
  883. package/src/engine/graphics/ecs/trail3d/seed_trail_tube.js +75 -75
  884. package/src/engine/graphics/ecs/trail3d/trail_head_position.js +19 -19
  885. package/src/engine/graphics/ecs/water/Water.js +104 -104
  886. package/src/engine/graphics/geometry/AttributeData.js +84 -84
  887. package/src/engine/graphics/geometry/buffered/geometry_compute_vertex_normals_indexed.js +49 -49
  888. package/src/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.js +288 -288
  889. package/src/engine/graphics/geometry/buffered/query/nearest_point_on_triangle_record.js +87 -87
  890. package/src/engine/graphics/geometry/buffered/read_triangle_vertices.js +102 -102
  891. package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_buffered_geometry.js +52 -52
  892. package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_indexed_geometry.js +20 -20
  893. package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_unindexed_geometry.js +19 -19
  894. package/src/engine/graphics/geometry/optimization/geometry_optimize_uv_tension.js +135 -135
  895. package/src/engine/graphics/impostors/voxel/README.md +149 -149
  896. package/src/engine/graphics/impostors/voxel/VoxelImpostorDescription.js +141 -141
  897. package/src/engine/graphics/particles/node-based/codegen/glsl/getTypeByteSize.js +20 -20
  898. package/src/engine/graphics/particles/node-based/nodes/FloatConstant.d.ts +2 -0
  899. package/src/engine/graphics/particles/node-based/nodes/FloatConstant.d.ts.map +1 -1
  900. package/src/engine/graphics/particles/node-based/nodes/ReadFloatUniform.d.ts +2 -0
  901. package/src/engine/graphics/particles/node-based/nodes/ReadFloatUniform.d.ts.map +1 -1
  902. package/src/engine/graphics/particles/node-based/nodes/ReadVelocity.d.ts +2 -0
  903. package/src/engine/graphics/particles/node-based/nodes/ReadVelocity.d.ts.map +1 -1
  904. package/src/engine/graphics/particles/node-based/nodes/ShaderNode.d.ts +1 -2
  905. package/src/engine/graphics/particles/node-based/nodes/ShaderNode.d.ts.map +1 -1
  906. package/src/engine/graphics/particles/node-based/nodes/Vector3Constant.d.ts +2 -0
  907. package/src/engine/graphics/particles/node-based/nodes/Vector3Constant.d.ts.map +1 -1
  908. package/src/engine/graphics/particles/node-based/nodes/Vector3Merge.d.ts +2 -0
  909. package/src/engine/graphics/particles/node-based/nodes/Vector3Merge.d.ts.map +1 -1
  910. package/src/engine/graphics/particles/node-based/nodes/Vector3Split.d.ts +2 -0
  911. package/src/engine/graphics/particles/node-based/nodes/Vector3Split.d.ts.map +1 -1
  912. package/src/engine/graphics/particles/node-based/nodes/WriteVelocity.d.ts +2 -0
  913. package/src/engine/graphics/particles/node-based/nodes/WriteVelocity.d.ts.map +1 -1
  914. package/src/engine/graphics/particles/node-based/nodes/attribute/ReadVector3Attribute.d.ts +2 -0
  915. package/src/engine/graphics/particles/node-based/nodes/attribute/ReadVector3Attribute.d.ts.map +1 -1
  916. package/src/engine/graphics/particles/node-based/nodes/attribute/WriteVector3Attribute.d.ts +2 -0
  917. package/src/engine/graphics/particles/node-based/nodes/attribute/WriteVector3Attribute.d.ts.map +1 -1
  918. package/src/engine/graphics/particles/node-based/nodes/math/AddFloatNode.d.ts +2 -0
  919. package/src/engine/graphics/particles/node-based/nodes/math/AddFloatNode.d.ts.map +1 -1
  920. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Add.d.ts +2 -0
  921. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Add.d.ts.map +1 -1
  922. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Divide.d.ts +2 -0
  923. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Divide.d.ts.map +1 -1
  924. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Multiply.d.ts +2 -0
  925. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Multiply.d.ts.map +1 -1
  926. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Subtract.d.ts +2 -0
  927. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Subtract.d.ts.map +1 -1
  928. package/src/engine/graphics/particles/node-based/nodes/noise/CurlNoiseNode.d.ts +2 -0
  929. package/src/engine/graphics/particles/node-based/nodes/noise/CurlNoiseNode.d.ts.map +1 -1
  930. package/src/engine/graphics/particles/node-based/nodes/particle_data_type_component_count.js +45 -45
  931. package/src/engine/graphics/particles/particular/engine/ParticularEngine.js +229 -229
  932. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.d.ts +2 -10
  933. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.d.ts.map +1 -1
  934. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js +1149 -1149
  935. package/src/engine/graphics/particles/particular/engine/emitter/ParticlePool.js +472 -472
  936. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +2 -2
  937. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTableFlags.js +2 -2
  938. package/src/engine/graphics/particles/particular/engine/parameter/ParameterSet.d.ts.map +1 -1
  939. package/src/engine/graphics/particles/particular/engine/parameter/ParameterSet.js +3 -5
  940. package/src/engine/graphics/particles/particular/engine/shader/ShaderManager.js +135 -135
  941. package/src/engine/graphics/particles/particular/engine/utils/distribute_points_on_indexed_triangles.js +168 -168
  942. package/src/engine/graphics/render/forward_plus/plugin/forwardPlusMaterialMarker.js +18 -18
  943. package/src/engine/graphics/render/forward_plus/read_frustum_corner.js +2 -2
  944. package/src/engine/graphics/render/frame_graph/FRAME_GRAPH_RECOMMENDATIONS.md +219 -219
  945. package/src/engine/graphics/render/frame_graph/FrameGraph.js +900 -900
  946. package/src/engine/graphics/render/frame_graph/FrameGraphScope.js +72 -72
  947. package/src/engine/graphics/render/frame_graph/FrameGraphState.js +39 -39
  948. package/src/engine/graphics/render/frame_graph/ResourceEntry.js +96 -96
  949. package/src/engine/graphics/render/gizmo/GizmoShapeBuffer.js +105 -105
  950. package/src/engine/graphics/render/gizmo/GizmoShapeRenderingInterface.js +162 -162
  951. package/src/engine/graphics/render/layers/RenderLayer.js +95 -95
  952. package/src/engine/graphics/sh3/build_injected_shader.js +56 -56
  953. package/src/engine/graphics/sh3/grid_dilate_average.js +175 -175
  954. package/src/engine/graphics/sh3/path_tracer/BufferedGeometryBVH.js +506 -506
  955. package/src/engine/graphics/sh3/path_tracer/PathTracedMesh.js +161 -161
  956. package/src/engine/graphics/sh3/path_tracer/PathTracedRenderer.js +205 -205
  957. package/src/engine/graphics/sh3/path_tracer/PathTracedScene.js +698 -698
  958. package/src/engine/graphics/sh3/path_tracer/REVIEW_001_ACTION_PLAN.md +490 -490
  959. package/src/engine/graphics/sh3/path_tracer/geometry/compute_triangle_group_aabb3.js +2 -2
  960. package/src/engine/graphics/sh3/path_tracer/make_sky_hosek.js +45 -45
  961. package/src/engine/graphics/sh3/path_tracer/populate_path_traced_scene_from_ecd.js +73 -73
  962. package/src/engine/graphics/sh3/path_tracer/ray_hit_apply_transform.js +32 -32
  963. package/src/engine/graphics/sh3/path_tracer/texture/apply_texture_clamping_to_coordinate.js +28 -28
  964. package/src/engine/graphics/sh3/path_tracer/texture/sample_material.js +142 -142
  965. package/src/engine/graphics/sh3/sky/hosek/render_hosek_sky_to_equirectangular.js +70 -70
  966. package/src/engine/graphics/sh3/sky/hosek/sky_hosek_compute_irradiance_by_direction.js +388 -388
  967. package/src/engine/graphics/shaders/chunks/glsl_octahedral_impostor.js +277 -277
  968. package/src/engine/graphics/shaders/chunks/glsl_voxel_impostor_splat.js +57 -57
  969. package/src/engine/graphics/shadows/vsm.glsl.js +43 -43
  970. package/src/engine/graphics/texture/3d/scs3d_sample_linear3.js +81 -81
  971. package/src/engine/graphics/texture/EnvironmentTextureProjection.js +15 -15
  972. package/src/engine/graphics/texture/channel_count_to_format_prefix.js +26 -26
  973. package/src/engine/graphics/texture/isImageBitmap.js +2 -2
  974. package/src/engine/graphics/texture/reflection/convolve_equirectangular_reflection.js +189 -189
  975. package/src/engine/graphics/texture/reflection/equirectangular_reflection_roughness.js +51 -51
  976. package/src/engine/graphics/texture/sampler/HarmonicDiffusionGrid.js +145 -145
  977. package/src/engine/graphics/texture/sampler/Sampler2DArray.js +172 -172
  978. package/src/engine/graphics/texture/sampler/compare/FLIP_IMPLEMENTATION_PLAN.md +466 -466
  979. package/src/engine/graphics/texture/sampler/compare/flip/FlipParameters.js +18 -18
  980. package/src/engine/graphics/texture/sampler/compare/flip/FlipPooling.js +33 -33
  981. package/src/engine/graphics/texture/sampler/compare/flip/flip_build_feature_kernel.js +147 -147
  982. package/src/engine/graphics/texture/sampler/compare/flip/flip_build_spatial_kernel.js +177 -177
  983. package/src/engine/graphics/texture/sampler/compare/flip/flip_compute_color_difference.js +104 -104
  984. package/src/engine/graphics/texture/sampler/compare/flip/flip_compute_feature_difference.js +76 -76
  985. package/src/engine/graphics/texture/sampler/compare/flip/flip_compute_pixels_per_degree.js +34 -34
  986. package/src/engine/graphics/texture/sampler/compare/flip/flip_constants.js +77 -77
  987. package/src/engine/graphics/texture/sampler/compare/flip/flip_filter_feature.js +48 -48
  988. package/src/engine/graphics/texture/sampler/compare/flip/flip_filter_spatial.js +86 -86
  989. package/src/engine/graphics/texture/sampler/compare/flip/flip_pool.js +71 -71
  990. package/src/engine/graphics/texture/sampler/compare/flip/flip_srgb_to_ycxcz.js +55 -55
  991. package/src/engine/graphics/texture/sampler/compare/flip/sampler2d_flip_ldr.js +80 -80
  992. package/src/engine/graphics/texture/sampler/filter/SeparableKernel.js +82 -82
  993. package/src/engine/graphics/texture/sampler/filter/sampler2d_convolve_separable.js +122 -122
  994. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.js +148 -148
  995. package/src/engine/graphics/texture/sampler/sampler2d_channel_apply_lut.js +82 -82
  996. package/src/engine/graphics/texture/sampler/sampler2d_combine.js +67 -67
  997. package/src/engine/graphics/texture/sampler/sampler2d_linear_f16_to_srgb_u8.js +54 -54
  998. package/src/engine/graphics/texture/sampler/sampler2d_sample_equirectangular_direction.js +63 -63
  999. package/src/engine/graphics/texture/sampler/sampler2d_srgb_to_linear.js +33 -33
  1000. package/src/engine/graphics/texture/sampler/sampler2d_srgb_u8_to_linear_f16.js +68 -68
  1001. package/src/engine/graphics/texture/shade_image_preview.js +103 -103
  1002. package/src/engine/graphics/trail/TrailSpawnMode.js +20 -20
  1003. package/src/engine/graphics/trail/tube/TubeX.js +573 -573
  1004. package/src/engine/graphics/trail/tube/TubeXMaterialSpec.js +58 -58
  1005. package/src/engine/graphics/trail/tube/simulator/TubeXFixedPhysicsSimulator.js +34 -34
  1006. package/src/engine/graphics/trail/tube/tube_attributes_spec.js +69 -69
  1007. package/src/engine/graphics/trail/tube/tube_frame.js +83 -83
  1008. package/src/engine/graphics3/AnimationGraphSystem3.js +329 -329
  1009. package/src/engine/graphics3/AnimationSystem3.js +352 -352
  1010. package/src/engine/graphics3/CameraSystem3.js +170 -170
  1011. package/src/engine/graphics3/DecalSystem3.js +441 -441
  1012. package/src/engine/graphics3/FogOfWarSystem3.js +265 -265
  1013. package/src/engine/graphics3/GraphicsEngine3.js +776 -776
  1014. package/src/engine/graphics3/HighlightSystem3.js +241 -241
  1015. package/src/engine/graphics3/LightSystem3.js +211 -211
  1016. package/src/engine/graphics3/MeshSystem3.js +646 -646
  1017. package/src/engine/graphics3/ParticleEmitterSystem3.js +289 -289
  1018. package/src/engine/graphics3/PathDisplaySystem3.js +309 -309
  1019. package/src/engine/graphics3/PickingQuery.js +48 -48
  1020. package/src/engine/graphics3/PickingResult.js +47 -47
  1021. package/src/engine/graphics3/PickingSystem3.js +273 -273
  1022. package/src/engine/graphics3/ShadeCameraAdapter.js +55 -55
  1023. package/src/engine/graphics3/ShadedGeometrySystem3.js +169 -169
  1024. package/src/engine/graphics3/TerrainSystem3.js +566 -566
  1025. package/src/engine/graphics3/TooltipComponentSystem3.js +328 -328
  1026. package/src/engine/graphics3/Trail3DSystem3.js +221 -221
  1027. package/src/engine/graphics3/WaterSystem3.js +293 -293
  1028. package/src/engine/graphics3/animation/ClipPlayback.js +84 -84
  1029. package/src/engine/graphics3/animation/wrap_clip_time.js +23 -23
  1030. package/src/engine/graphics3/animation/write_graph_playback.js +48 -48
  1031. package/src/engine/graphics3/camera_sync_from_transform.js +29 -29
  1032. package/src/engine/graphics3/debug/gizmo_view_from_camera.js +48 -48
  1033. package/src/engine/graphics3/decal/DECAL_CLUSTER.js +61 -61
  1034. package/src/engine/graphics3/decal/DECAL_GPU_RECORD.js +117 -117
  1035. package/src/engine/graphics3/decal/DecalAtlas.js +194 -194
  1036. package/src/engine/graphics3/decal/DecalAtlasFill.js +32 -32
  1037. package/src/engine/graphics3/decal/GPUDecalRenderer.js +360 -360
  1038. package/src/engine/graphics3/decal/chunk_decal_intersects_frustum.js +59 -59
  1039. package/src/engine/graphics3/decal/chunk_decal_sampling_info.js +57 -57
  1040. package/src/engine/graphics3/decal/chunk_decal_surface_frame.js +54 -54
  1041. package/src/engine/graphics3/decal/decal_atlas_border.js +69 -69
  1042. package/src/engine/graphics3/decal/decal_gpu_records.js +120 -120
  1043. package/src/engine/graphics3/decal/decal_material_samplers.js +109 -109
  1044. package/src/engine/graphics3/decal/graph_build_decal_clusters.js +212 -212
  1045. package/src/engine/graphics3/decal/shader_cluster_assign_decals.js +207 -207
  1046. package/src/engine/graphics3/decal/shader_cull_decals_frustum.js +108 -108
  1047. package/src/engine/graphics3/highlight/GPUHighlightRenderer.js +151 -151
  1048. package/src/engine/graphics3/highlight/HIGHLIGHT_OUTLINE.js +23 -23
  1049. package/src/engine/graphics3/highlight/chunk_highlight_lookup.js +53 -53
  1050. package/src/engine/graphics3/highlight/pack_highlight_color.js +44 -44
  1051. package/src/engine/graphics3/highlight/pack_highlight_table.js +74 -74
  1052. package/src/engine/graphics3/highlight/shader_highlight_outline.js +150 -150
  1053. package/src/engine/graphics3/load_cube_environment.js +68 -68
  1054. package/src/engine/graphics3/make_default_environment.js +107 -107
  1055. package/src/engine/graphics3/particles/particle_gpu_records.js +221 -221
  1056. package/src/engine/graphics3/path/build_tube_path_streams.js +98 -98
  1057. package/src/engine/graphics3/path/tube_stream_write_geometry.js +90 -90
  1058. package/src/engine/graphics3/preview/ModelPreviewFraming.js +35 -35
  1059. package/src/engine/graphics3/preview/make_model_preview_scene.js +154 -154
  1060. package/src/engine/graphics3/preview/make_model_thumbnail.js +48 -48
  1061. package/src/engine/graphics3/preview/model_preview_framing.js +70 -70
  1062. package/src/engine/graphics3/shade_bundle_bounds.js +55 -55
  1063. package/src/engine/graphics3/shade_camera_projection_ray.js +77 -77
  1064. package/src/engine/graphics3/shade_node_to_entity_composition.js +84 -84
  1065. package/src/engine/graphics3/terrain/GPUTerrainSplatRenderer.js +481 -481
  1066. package/src/engine/graphics3/terrain/chunk_terrain_grid_overlay.js +61 -61
  1067. package/src/engine/graphics3/terrain/chunk_terrain_splat_mix.js +66 -66
  1068. package/src/engine/graphics3/terrain/pack_terrain_row_table.js +53 -53
  1069. package/src/engine/graphics3/terrain/shader_terrain_splat.js +215 -215
  1070. package/src/engine/graphics3/trail/trail_tube_write_geometry.js +158 -158
  1071. package/src/engine/grid/grid2transform/GridPosition2TransformSystem.d.ts +2 -2
  1072. package/src/engine/grid/grid2transform/GridPosition2TransformSystem.d.ts.map +1 -1
  1073. package/src/engine/input/GAMEPAD_API_PROPOSAL.md +717 -717
  1074. package/src/engine/input/analog/apply_radial_dead_zone.js +38 -38
  1075. package/src/engine/input/devices/GamepadDevice.js +466 -466
  1076. package/src/engine/input/devices/ManualInputDevice.js +152 -152
  1077. package/src/engine/input/devices/PointerCoordinates.js +26 -26
  1078. package/src/engine/input/devices/events/GamepadEvents.js +10 -10
  1079. package/src/engine/input/devices/gamepad/GamepadAxes.js +19 -19
  1080. package/src/engine/input/devices/gamepad/GamepadButtons.js +29 -29
  1081. package/src/engine/input/devices/gamepad/GamepadCoordinates.js +17 -17
  1082. package/src/engine/input/devices/gamepad/GamepadDeviceLayout.js +323 -323
  1083. package/src/engine/input/devices/gamepad/GamepadHandle.js +286 -286
  1084. package/src/engine/input/devices/gamepad/GamepadLayout.js +160 -160
  1085. package/src/engine/input/devices/gamepad/GamepadStandardMapping.js +31 -31
  1086. package/src/engine/input/devices/gamepad/GamepadStick.js +169 -169
  1087. package/src/engine/input/devices/gamepad/GamepadStickCalibration.js +119 -119
  1088. package/src/engine/input/devices/gamepad/GamepadStickCalibrator.js +250 -250
  1089. package/src/engine/input/devices/gamepad/gamepad_layout_database.js +144 -144
  1090. package/src/engine/input/devices/gamepad/gamepad_read_hat_axis.js +61 -61
  1091. package/src/engine/input/devices/gamepad/gamepad_write_dpad_vector.js +30 -30
  1092. package/src/engine/input/devices/gamepad/prototypeGamepadTester.js +2124 -2124
  1093. package/src/engine/input/devices/mouse/MouseButtons.js +22 -22
  1094. package/src/engine/input/ecs/components/Input.js +118 -118
  1095. package/src/engine/input/ecs/components/InputController.js +78 -78
  1096. package/src/engine/input/ecs/ism/ISM_DESIGN.md +1523 -1523
  1097. package/src/engine/input/ecs/ism/ISM_IMPLEMENTATION_PLAN.md +627 -627
  1098. package/src/engine/input/ecs/ism/InputActionEvent.js +40 -40
  1099. package/src/engine/input/ecs/ism/InputBinding.js +71 -71
  1100. package/src/engine/input/ecs/ism/InputCoordinateKind.js +25 -25
  1101. package/src/engine/input/ecs/ism/InputCoordinateSource.js +86 -86
  1102. package/src/engine/input/ecs/ism/InputDirection.js +33 -33
  1103. package/src/engine/input/ecs/ism/InputMapProgram.js +236 -236
  1104. package/src/engine/input/ecs/ism/InputMapSystem.js +976 -976
  1105. package/src/engine/input/ecs/ism/InputOcclusion.js +31 -31
  1106. package/src/engine/input/ecs/ism/InputSource.js +67 -67
  1107. package/src/engine/input/ecs/ism/InputSourceTable.js +107 -107
  1108. package/src/engine/input/ecs/ism/coordinate/InputCoordinateChannel.js +93 -93
  1109. package/src/engine/input/ecs/ism/coordinate/InputCoordinateChannelType.js +11 -11
  1110. package/src/engine/input/ecs/ism/coordinate/InputCoordinateDevice.js +153 -153
  1111. package/src/engine/input/ecs/ism/coordinate/InputCoordinateSwitches.js +160 -160
  1112. package/src/engine/input/ecs/ism/device/GAMEPAD_INPUT_DEVICE_ID.js +9 -9
  1113. package/src/engine/input/ecs/ism/device/GamepadInputDeviceAdapter.js +88 -88
  1114. package/src/engine/input/ecs/ism/device/InputDeviceAdapter.js +72 -72
  1115. package/src/engine/input/ecs/ism/device/KEYBOARD_INPUT_DEVICE_ID.js +9 -9
  1116. package/src/engine/input/ecs/ism/device/KeyboardInputDeviceAdapter.js +63 -63
  1117. package/src/engine/input/ecs/ism/device/ManualInputDeviceAdapter.js +55 -55
  1118. package/src/engine/input/ecs/ism/device/POINTER_INPUT_DEVICE_ID.js +9 -9
  1119. package/src/engine/input/ecs/ism/device/PointerInputDeviceAdapter.js +160 -160
  1120. package/src/engine/input/ecs/ism/map/InputBinding.js +88 -88
  1121. package/src/engine/input/ecs/ism/map/InputCoordinateBinding.js +102 -102
  1122. package/src/engine/input/ecs/ism/map/InputLayer.js +220 -220
  1123. package/src/engine/input/ecs/ism/map/InputMap.js +331 -331
  1124. package/src/engine/input/ecs/ism/prototypeInputMap.js +309 -309
  1125. package/src/engine/input/ecs/ism/trigger/InputTrigger.js +148 -148
  1126. package/src/engine/input/ecs/ism/trigger/InputTriggerChord.js +173 -173
  1127. package/src/engine/input/ecs/ism/trigger/InputTriggerGamepadButton.js +37 -37
  1128. package/src/engine/input/ecs/ism/trigger/InputTriggerHold.js +176 -176
  1129. package/src/engine/input/ecs/ism/trigger/InputTriggerKey.js +39 -39
  1130. package/src/engine/input/ecs/ism/trigger/InputTriggerMouseButton.js +38 -38
  1131. package/src/engine/input/ecs/ism/trigger/InputTriggerRelease.js +120 -120
  1132. package/src/engine/input/ecs/ism/trigger/InputTriggerSequence.js +315 -315
  1133. package/src/engine/input/ecs/ism/trigger/InputTriggerSwitch.js +105 -105
  1134. package/src/engine/input/ecs/ism/trigger/InputTriggerType.js +17 -17
  1135. package/src/engine/input/ecs/systems/InputControllerSystem.js +253 -253
  1136. package/src/engine/input/ecs/systems/InputSystem.js +162 -162
  1137. package/src/engine/intelligence/behavior/primitive/FailingBehaviorSerializationAdapter.js +25 -25
  1138. package/src/engine/intelligence/behavior/primitive/SucceedingBehaviorSerializationAdapter.js +26 -26
  1139. package/src/engine/intelligence/behavior/util/AsynchronousDelayAction.js +55 -55
  1140. package/src/engine/interpolation/BinaryInterpolationAdapter.js +56 -56
  1141. package/src/engine/interpolation/Interpoland.js +49 -49
  1142. package/src/engine/interpolation/Interpolated.js +149 -149
  1143. package/src/engine/interpolation/PoseInterpolationAdapter.js +61 -61
  1144. package/src/engine/interpolation/TransformPoseSerializationAdapter.js +57 -57
  1145. package/src/engine/interpolation/pose_interpoland.js +27 -27
  1146. package/src/engine/navigation/ecs/path_following/PathFollower.js +222 -222
  1147. package/src/engine/navigation/mesh/NavigationMesh.js +145 -145
  1148. package/src/engine/navigation/mesh/OVERLAPPING_SURFACES_2026_08_25.md +661 -0
  1149. package/src/engine/navigation/mesh/PATHFINDING_PLAN.md +229 -229
  1150. package/src/engine/navigation/mesh/build/clip_soup_against_overhangs.d.ts.map +1 -1
  1151. package/src/engine/navigation/mesh/build/clip_soup_against_overhangs.js +628 -520
  1152. package/src/engine/network/CONGESTION_CONTROL.md +87 -87
  1153. package/src/engine/network/README.md +52 -52
  1154. package/src/engine/network/adapters/QuaternionInterpolationAdapter.js +43 -43
  1155. package/src/engine/network/adapters/TransformInterpolationAdapter.js +84 -84
  1156. package/src/engine/network/adapters/TransformReplicationAdapter.js +87 -87
  1157. package/src/engine/network/adapters/Vector3InterpolationAdapter.js +46 -46
  1158. package/src/engine/network/convertPathToURL.js +2 -2
  1159. package/src/engine/network/core/MalformedPacketError.js +26 -26
  1160. package/src/engine/network/core/quantize/quantize_float.js +73 -73
  1161. package/src/engine/network/core/quantize/quantize_position.js +65 -65
  1162. package/src/engine/network/core/sequence/ack_bitfield.js +77 -77
  1163. package/src/engine/network/core/sequence/seq16.js +69 -69
  1164. package/src/engine/network/core/sequence/seq32.js +73 -73
  1165. package/src/engine/network/ecs/NetworkSystem.js +84 -84
  1166. package/src/engine/network/ecs/components/NetworkIdentity.js +73 -73
  1167. package/src/engine/network/ecs/owner_authorization.js +55 -55
  1168. package/src/engine/network/ecs/serialization/NetworkIdentitySerializationAdapter.js +64 -64
  1169. package/src/engine/network/replication/ScopeFilter.js +71 -71
  1170. package/src/engine/network/sim/ActionLog.js +152 -152
  1171. package/src/engine/network/sim/SimAction.js +273 -273
  1172. package/src/engine/network/sim/Snapshotter.js +222 -222
  1173. package/src/engine/network/state/FrameBufferRing.js +168 -168
  1174. package/src/engine/network/state/InputRing.js +134 -134
  1175. package/src/engine/network/state/PriorityAccumulator.js +180 -180
  1176. package/src/engine/network/time/TimeDilation.js +62 -62
  1177. package/src/engine/network/transport/Channel.js +336 -336
  1178. package/src/engine/network/transport/Transport.js +203 -203
  1179. package/src/engine/network/transport/adapters/NodeUDPTransport.js +186 -186
  1180. package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.js +105 -105
  1181. package/src/engine/network/transport/fragments/fragment_send.js +147 -147
  1182. package/src/engine/network/transport/fragments/packet_size.js +101 -101
  1183. package/src/engine/network/xhr.js +23 -23
  1184. package/src/engine/physics/BULLET_REVIEW.md +945 -945
  1185. package/src/engine/physics/CANNON_REVIEW.md +1300 -1300
  1186. package/src/engine/physics/CONSTRAINT_SOLVER_BENCH_LOG.md +208 -208
  1187. package/src/engine/physics/CONSTRAINT_SOLVER_IMPROVEMENTS_PLAN.md +364 -364
  1188. package/src/engine/physics/INTEPOLATION_SYSTEM_PLAN.md +287 -287
  1189. package/src/engine/physics/JOLT_REVIEW.md +913 -913
  1190. package/src/engine/physics/PLAN.md +1120 -1094
  1191. package/src/engine/physics/RAPIER_REVIEW.md +934 -934
  1192. package/src/engine/physics/REVIEW_001_ACTION_PLAN.md +642 -642
  1193. package/src/engine/physics/REVIEW_002.md +151 -151
  1194. package/src/engine/physics/REVIEW_003.md +166 -166
  1195. package/src/engine/physics/broadphase/compute_fat_world_aabb.js +97 -97
  1196. package/src/engine/physics/constraint/DofMode.js +35 -35
  1197. package/src/engine/physics/constraint/solve_constraints.js +1 -1
  1198. package/src/engine/physics/contact/combine_material.js +35 -35
  1199. package/src/engine/physics/ecs/BodyKind.js +29 -29
  1200. package/src/engine/physics/ecs/Collider.js +177 -177
  1201. package/src/engine/physics/ecs/ColliderFlags.js +15 -15
  1202. package/src/engine/physics/ecs/ColliderSerializationAdapter.js +37 -37
  1203. package/src/engine/physics/ecs/Joint.js +475 -475
  1204. package/src/engine/physics/ecs/JointSerializationAdapter.js +72 -72
  1205. package/src/engine/physics/ecs/PhysicsSystem.d.ts +3 -0
  1206. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  1207. package/src/engine/physics/ecs/PhysicsSystem.js +7 -2
  1208. package/src/engine/physics/ecs/RigidBodySerializationUpgrader_0_1.js +37 -37
  1209. package/src/engine/physics/ecs/SleepState.js +12 -12
  1210. package/src/engine/physics/ecs/find_non_finite_physics_state.js +76 -76
  1211. package/src/engine/physics/fluid/FluidField.js +867 -867
  1212. package/src/engine/physics/fluid/FluidSimulator.js +832 -832
  1213. package/src/engine/physics/fluid/REVIEW_02_PLAN.md +243 -243
  1214. package/src/engine/physics/fluid/SliceVisualiser.js +190 -190
  1215. package/src/engine/physics/fluid/ecs/FluidComponent.js +239 -239
  1216. package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.js +89 -89
  1217. package/src/engine/physics/fluid/ecs/FluidObstacle.js +97 -97
  1218. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.js +348 -348
  1219. package/src/engine/physics/fluid/ecs/FluidSystem.js +142 -142
  1220. package/src/engine/physics/fluid/ecs/FluidWorkerCore.js +123 -123
  1221. package/src/engine/physics/fluid/ecs/WorkerFluidSystem.js +395 -395
  1222. package/src/engine/physics/fluid/ecs/fluid.worker.js +12 -12
  1223. package/src/engine/physics/fluid/ecs/fluid_build_world_to_grid.js +32 -32
  1224. package/src/engine/physics/fluid/ecs/fluid_gather_visible_effectors.js +47 -47
  1225. package/src/engine/physics/fluid/ecs/fluid_reanchor_field.js +85 -85
  1226. package/src/engine/physics/fluid/ecs/fluid_sync_effectors_from_transform.js +16 -16
  1227. package/src/engine/physics/fluid/ecs/fluid_worker_protocol.js +111 -111
  1228. package/src/engine/physics/fluid/ecs/makeFluidWorker.js +18 -18
  1229. package/src/engine/physics/fluid/effector/AbstractFluidEffector.js +81 -81
  1230. package/src/engine/physics/fluid/effector/GlobalFluidEffector.js +202 -202
  1231. package/src/engine/physics/fluid/effector/ImpulseFluidEffector.js +257 -257
  1232. package/src/engine/physics/fluid/effector/WakeFluidEffector.js +405 -405
  1233. package/src/engine/physics/fluid/prototype.js +126 -126
  1234. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_scalar.js +143 -143
  1235. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_velocity.js +162 -162
  1236. package/src/engine/physics/fluid/solver/v3_grid_advect_sl_velocity.js +107 -107
  1237. package/src/engine/physics/fluid/solver/v3_grid_apply_vorticity_confinement.js +131 -131
  1238. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.js +90 -90
  1239. package/src/engine/physics/fluid/solver/v3_grid_limit8_at_indices.js +38 -38
  1240. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_constant.js +77 -77
  1241. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.js +113 -113
  1242. package/src/engine/physics/fluid/solver/v3_grid_sample_scalar_masked.js +92 -92
  1243. package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.js +107 -107
  1244. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.js +135 -135
  1245. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.js +511 -511
  1246. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.js +108 -108
  1247. package/src/engine/physics/fluid/solver/v3_mac_advect_maccormack_velocity.js +317 -317
  1248. package/src/engine/physics/fluid/solver/v3_mac_advect_scalar.js +236 -236
  1249. package/src/engine/physics/fluid/solver/v3_mac_advect_sl_velocity.js +217 -217
  1250. package/src/engine/physics/fluid/solver/v3_mac_apply_vorticity_confinement.js +174 -174
  1251. package/src/engine/physics/fluid/solver/v3_mac_clip_trace.js +95 -95
  1252. package/src/engine/physics/fluid/solver/v3_mac_compute_divergence.js +77 -77
  1253. package/src/engine/physics/fluid/solver/v3_mac_compute_face_solid.js +131 -131
  1254. package/src/engine/physics/fluid/solver/v3_mac_subtract_pressure_gradient.js +104 -104
  1255. package/src/engine/physics/inertia/world_inverse_inertia.js +160 -160
  1256. package/src/engine/physics/integration/integrate_position.js +97 -97
  1257. package/src/engine/physics/narrowphase/box_box_manifold.js +681 -681
  1258. package/src/engine/physics/narrowphase/box_triangle_contact.js +906 -906
  1259. package/src/engine/physics/narrowphase/capsule_triangle_contact.js +395 -395
  1260. package/src/engine/physics/narrowphase/compute_penetration.js +369 -369
  1261. package/src/engine/physics/narrowphase/decomposition/decompose_to_triangles.js +55 -55
  1262. package/src/engine/physics/narrowphase/decomposition/triangle_buffer_layout.js +37 -37
  1263. package/src/engine/physics/narrowphase/mesh_mesh_tet_manifold.js +117 -117
  1264. package/src/engine/physics/narrowphase/narrowphase_step.js +1738 -1738
  1265. package/src/engine/physics/narrowphase/reduce_manifold_contacts.js +74 -74
  1266. package/src/engine/physics/narrowphase/refine_ray_hit.d.ts +12 -11
  1267. package/src/engine/physics/narrowphase/refine_ray_hit.d.ts.map +1 -1
  1268. package/src/engine/physics/narrowphase/refine_ray_hit.js +228 -36
  1269. package/src/engine/physics/narrowphase/sphere_sphere_contact.js +52 -52
  1270. package/src/engine/physics/narrowphase/sphere_triangle_contact.js +138 -138
  1271. package/src/engine/physics/persistence/solver_caches.js +309 -309
  1272. package/src/engine/physics/queries/overlap_shape.js +187 -187
  1273. package/src/engine/physics/queries/raycast.d.ts +7 -4
  1274. package/src/engine/physics/queries/raycast.d.ts.map +1 -1
  1275. package/src/engine/physics/queries/raycast.js +11 -5
  1276. package/src/engine/physics/queries/shape_cast.js +417 -417
  1277. package/src/engine/physics/solver/apply_impulse_to_body.js +86 -86
  1278. package/src/engine/physics/solver/friction_cone.js +37 -37
  1279. package/src/engine/physics/solver/solve_contacts.js +1 -1
  1280. package/src/engine/platform/WebEnginePlatform.d.ts.map +1 -1
  1281. package/src/engine/platform/WebEnginePlatform.js +1 -2
  1282. package/src/engine/scene/SerializedScene.d.ts +2 -2
  1283. package/src/engine/scene/SerializedScene.d.ts.map +1 -1
  1284. package/src/engine/scene/transitionToScene.js +121 -121
  1285. package/src/engine/simulation/Ticker.d.ts.map +1 -1
  1286. package/src/engine/simulation/Ticker.js +33 -0
  1287. package/src/engine/sound/ecs/audio/LiveEmitterSet.js +345 -345
  1288. package/src/engine/sound/ecs/audio/SpatialAudioIndex.js +140 -140
  1289. package/src/engine/sound/simulation/AcousticSimulator.js +646 -646
  1290. package/src/engine/sound/simulation/IMPLEMENTATION_PLAN.md +432 -432
  1291. package/src/engine/sound/simulation/PROBE_PLACEMENT.md +250 -250
  1292. package/src/engine/sound/simulation/PROBE_TRANSFER_RESEARCH.md +322 -322
  1293. package/src/engine/sound/simulation/README.md +277 -277
  1294. package/src/engine/sound/simulation/REFLECTION_IR_PLAN.md +261 -261
  1295. package/src/engine/sound/simulation/VISIBILITY_GRAPH_PLAN.md +121 -121
  1296. package/src/engine/sound/simulation/configureAcousticSimulation.js +48 -48
  1297. package/src/engine/sound/simulation/core/AcousticMedium.js +113 -113
  1298. package/src/engine/sound/simulation/core/AcousticMediumSerializationAdapter.js +27 -27
  1299. package/src/engine/sound/simulation/core/AcousticOccluderIndex.js +312 -312
  1300. package/src/engine/sound/simulation/core/AcousticRegionIndex.js +159 -159
  1301. package/src/engine/sound/simulation/core/AcousticSolution.js +90 -90
  1302. package/src/engine/sound/simulation/core/AcousticSourceState.js +109 -109
  1303. package/src/engine/sound/simulation/core/AcousticVolumeRegion.js +73 -73
  1304. package/src/engine/sound/simulation/core/OcclusionSolver.js +112 -112
  1305. package/src/engine/sound/simulation/core/RayHit.js +50 -50
  1306. package/src/engine/sound/simulation/core/VolumeField.js +149 -149
  1307. package/src/engine/sound/simulation/definition/AcousticDirectivity.js +114 -114
  1308. package/src/engine/sound/simulation/definition/AcousticDirectivitySerializationAdapter.js +30 -30
  1309. package/src/engine/sound/simulation/definition/AcousticMaterial.js +122 -122
  1310. package/src/engine/sound/simulation/definition/AcousticMaterialSerializationAdapter.js +32 -32
  1311. package/src/engine/sound/simulation/ecs/AcousticBody.js +48 -48
  1312. package/src/engine/sound/simulation/ecs/AcousticBodySerializationAdapter.js +34 -34
  1313. package/src/engine/sound/simulation/ecs/AcousticProbeFieldSystem.js +64 -64
  1314. package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.js +75 -75
  1315. package/src/engine/sound/simulation/ecs/AcousticVolume.js +74 -74
  1316. package/src/engine/sound/simulation/ecs/AcousticVolumeSerializationAdapter.js +37 -37
  1317. package/src/engine/sound/simulation/ecs/AcousticVolumeSystem.js +66 -66
  1318. package/src/engine/sound/simulation/probe/AcousticProbeField.js +578 -578
  1319. package/src/engine/sound/simulation/probe/AcousticProbeFieldSerializationAdapter.js +60 -60
  1320. package/src/engine/sound/simulation/probe/ProbeFieldPathingSolution.js +64 -64
  1321. package/src/engine/sound/simulation/probe/ProbeVisibilityRecheck.js +132 -132
  1322. package/src/engine/sound/simulation/probe/acoustic_probe_transfer.js +103 -103
  1323. package/src/engine/sound/simulation/probe/acoustic_trace_energy.js +136 -136
  1324. package/src/engine/sound/simulation/probe/bakeProbeField.js +169 -169
  1325. package/src/engine/sound/simulation/probe/bakeProbeReflectors.js +110 -110
  1326. package/src/engine/sound/simulation/probe/bakeReverbBands.js +110 -110
  1327. package/src/engine/sound/simulation/probe/bakeVisibility.js +148 -148
  1328. package/src/engine/sound/simulation/probe/echogram_band_rt60.js +83 -83
  1329. package/src/engine/sound/simulation/probe/probe_delaunay_edges.js +215 -215
  1330. package/src/engine/sound/simulation/probe/probe_densify_portals.js +140 -140
  1331. package/src/engine/sound/simulation/probe/probe_detect_portals.js +196 -196
  1332. package/src/engine/sound/simulation/probe/probe_edge_key.js +38 -38
  1333. package/src/engine/sound/simulation/probe/probe_edge_visible.js +41 -41
  1334. package/src/engine/sound/simulation/probe/probe_place_sdf_cover.js +82 -82
  1335. package/src/engine/sound/simulation/probe/probe_refine_connectivity.js +181 -181
  1336. package/src/engine/sound/simulation/probe/probe_sdf_grid.js +171 -171
  1337. package/src/engine/sound/simulation/probe/probe_visibility_augment.js +146 -146
  1338. package/src/engine/sound/simulation/probe/probe_visibility_bridge_components.js +167 -167
  1339. package/src/engine/sound/simulation/render/FoaProbeReverbRenderer.js +354 -354
  1340. package/src/engine/sound/simulation/render/ProbeReverbRenderer.js +231 -231
  1341. package/src/engine/sound/simulation/render/foaReverbImpulseResponse.js +105 -105
  1342. package/src/engine/sound/simulation/render/reverbImpulseResponse.js +66 -66
  1343. package/src/engine/sound/simulation/render/reverb_band_tails.js +93 -93
  1344. package/src/engine/sound/simulation/serialization/populateAcousticSerializationRegistry.js +25 -25
  1345. package/src/engine/sound/sopra/README.md +643 -643
  1346. package/src/engine/sound/sopra/SopraEngine.js +432 -432
  1347. package/src/engine/sound/sopra/asset/AssetManagerBufferProvider.js +71 -71
  1348. package/src/engine/sound/sopra/asset/BufferProvider.js +29 -29
  1349. package/src/engine/sound/sopra/asset/StubBufferProvider.js +58 -58
  1350. package/src/engine/sound/sopra/definition/BusDefinition.js +142 -142
  1351. package/src/engine/sound/sopra/definition/BusDefinitionSerializationAdapter.js +54 -54
  1352. package/src/engine/sound/sopra/definition/DuckingRule.js +106 -106
  1353. package/src/engine/sound/sopra/definition/DuckingRuleSerializationAdapter.js +31 -31
  1354. package/src/engine/sound/sopra/definition/EventDescription.js +262 -262
  1355. package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.js +55 -55
  1356. package/src/engine/sound/sopra/definition/MixerSnapshot.js +83 -83
  1357. package/src/engine/sound/sopra/definition/MixerSnapshotSerializationAdapter.js +39 -39
  1358. package/src/engine/sound/sopra/definition/ParameterDefinition.js +117 -117
  1359. package/src/engine/sound/sopra/definition/ParameterDefinitionSerializationAdapter.js +31 -31
  1360. package/src/engine/sound/sopra/definition/VoiceStealMode.js +18 -18
  1361. package/src/engine/sound/sopra/definition/clip/AbstractAudioClip.js +109 -109
  1362. package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClip.js +185 -185
  1363. package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClipSerializationAdapter.js +59 -59
  1364. package/src/engine/sound/sopra/definition/clip/ContainerAudioClip.js +128 -128
  1365. package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClip.js +226 -226
  1366. package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClipSerializationAdapter.js +54 -54
  1367. package/src/engine/sound/sopra/definition/clip/SampleAudioClip.js +191 -191
  1368. package/src/engine/sound/sopra/definition/clip/SampleAudioClipSerializationAdapter.js +39 -39
  1369. package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClip.js +79 -79
  1370. package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClipSerializationAdapter.js +42 -42
  1371. package/src/engine/sound/sopra/definition/clip/SilenceAudioClip.js +77 -77
  1372. package/src/engine/sound/sopra/definition/clip/SilenceAudioClipSerializationAdapter.js +27 -27
  1373. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.d.ts +5 -0
  1374. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.d.ts.map +1 -1
  1375. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.js +125 -125
  1376. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClipSerializationAdapter.js +41 -41
  1377. package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.js +24 -24
  1378. package/src/engine/sound/sopra/definition/effect/CompressorEffect.js +120 -120
  1379. package/src/engine/sound/sopra/definition/effect/CompressorEffectSerializationAdapter.js +31 -31
  1380. package/src/engine/sound/sopra/definition/effect/EqEffect.js +128 -128
  1381. package/src/engine/sound/sopra/definition/effect/EqEffectSerializationAdapter.js +29 -29
  1382. package/src/engine/sound/sopra/definition/effect/ReverbEffect.js +113 -113
  1383. package/src/engine/sound/sopra/definition/effect/ReverbEffectSerializationAdapter.js +25 -25
  1384. package/src/engine/sound/sopra/runtime/BusGraph.js +231 -231
  1385. package/src/engine/sound/sopra/runtime/ParameterStore.js +98 -98
  1386. package/src/engine/sound/sopra/runtime/SopraPlaybackContext.js +68 -68
  1387. package/src/engine/sound/sopra/runtime/Voice.js +145 -145
  1388. package/src/engine/sound/sopra/runtime/VoiceManager.js +136 -136
  1389. package/src/engine/sound/sopra/runtime/VoicePool.js +17 -17
  1390. package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.js +42 -42
  1391. package/src/engine/sound/sopra/serialization/sopraJSON.js +99 -99
  1392. package/src/engine/sound/sopra/serialization/sopraSerializationHarness.js +49 -49
  1393. package/src/engine/sound/sopra/util/MockAudioContext.js +224 -224
  1394. package/src/engine/sound/sopra/util/fadeOutAndStop.js +60 -60
  1395. package/src/engine/ui/DraggableAspect.js +115 -115
  1396. package/src/engine/ui/apply_pointer_tilt_3d.js +50 -50
  1397. package/src/generation/COORDINATES.md +54 -54
  1398. package/src/generation/GridGenerationResource.js +24 -24
  1399. package/src/generation/GridTaskGroup.js +214 -214
  1400. package/src/generation/REVIEW_01_ACTION_PLAN.md +628 -628
  1401. package/src/generation/automata/CaveGeneratorCellularAutomata.js +79 -79
  1402. package/src/generation/automata/CellularAutomata.js +22 -22
  1403. package/src/generation/compute_writes_union.js +25 -25
  1404. package/src/generation/filtering/CellFilter.js +117 -117
  1405. package/src/generation/filtering/core/CellFilterBinaryOperation.js +37 -37
  1406. package/src/generation/filtering/core/CellFilterOperationTertiary.js +43 -43
  1407. package/src/generation/filtering/core/CellFilterUnaryOperation.js +29 -29
  1408. package/src/generation/filtering/numeric/process/computeCellFilterSobel.js +36 -36
  1409. package/src/generation/filtering/numeric/process/computeFilterSurfaceNormal.js +42 -42
  1410. package/src/generation/filtering/numeric/util/populateSampler2DFromCellFilter.js +18 -18
  1411. package/src/generation/filtering/numeric/util/write_cell_filter_to_sampler2d.js +47 -47
  1412. package/src/generation/filtering/util/cell_filter_weights_pick.js +54 -54
  1413. package/src/generation/grid/GridData.js +233 -233
  1414. package/src/generation/grid/coords/grid_to_texel.js +10 -10
  1415. package/src/generation/grid/coords/texel_to_grid.js +10 -10
  1416. package/src/generation/grid/generation/GridTaskApplyActionToCells.js +90 -90
  1417. package/src/generation/grid/generation/GridTaskDensityMarkerDistribution.js +388 -388
  1418. package/src/generation/grid/generation/GridTaskExecuteRuleTimes.js +127 -127
  1419. package/src/generation/grid/generation/GridTaskSequence.js +58 -58
  1420. package/src/generation/grid/generation/NoopGridTaskGenerator.js +12 -12
  1421. package/src/generation/grid/generation/discrete/GridTaskActionRuleSet.js +48 -48
  1422. package/src/generation/grid/generation/discrete/GridTaskCellularAutomata.js +146 -146
  1423. package/src/generation/grid/generation/discrete/GridTaskConnectRooms.js +540 -540
  1424. package/src/generation/grid/generation/discrete/layer/GridTaskBuildSourceDistanceMap.js +222 -222
  1425. package/src/generation/grid/generation/grid/GridTaskAddNodesFixed.js +44 -44
  1426. package/src/generation/grid/generation/road/GridTaskGenerateRoads.js +614 -614
  1427. package/src/generation/markers/GridCellActionPlaceMarker.js +244 -244
  1428. package/src/generation/markers/GridCellActionPlaceMarkerGroup.js +86 -86
  1429. package/src/generation/markers/actions/terrain/MarkerNodeActionPaintTerrain.js +266 -266
  1430. package/src/generation/markers/emitter/MarkerNodeEmitterGridCellAction.js +49 -49
  1431. package/src/generation/placement/GridCellActionTransformNearbyMarkers.js +120 -120
  1432. package/src/generation/placement/action/GridCellAction.js +45 -45
  1433. package/src/generation/placement/action/GridCellActionPlaceTags.js +140 -140
  1434. package/src/generation/placement/action/GridCellActionWriteFilterToLayer.js +89 -89
  1435. package/src/generation/placement/action/random/CellActionSelectRandom.js +69 -69
  1436. package/src/generation/placement/action/random/weighted/CellActionSelectWeightedRandom.js +91 -91
  1437. package/src/generation/placement/action/util/GridCellActionSequence.js +61 -61
  1438. package/src/generation/placement/action/util/GridCellDisplacedAction.js +61 -61
  1439. package/src/generation/rules/cell/CellMatcherRemovalPreservesConnectivity.js +183 -183
  1440. package/src/generation/theme/ThemeEngine.js +666 -666
  1441. package/src/shade/RENDERER_CONTRACT.md +568 -0
  1442. package/src/shade/descriptor/texture/format/gpu_texture_format_info.js +267 -267
  1443. package/src/shade/device/ShadeDeviceFailure.js +104 -104
  1444. package/src/shade/device/ShadeDeviceFailureReason.js +41 -41
  1445. package/src/shade/device/mock/IMPLEMENTATION_PLAN.md +255 -255
  1446. package/src/shade/device/mock/REVIEW_2026_08_22.md +527 -527
  1447. package/src/shade/device/mock/SoftwareGPUBindGroup.js +23 -23
  1448. package/src/shade/device/mock/SoftwareGPUBindGroupLayout.js +22 -22
  1449. package/src/shade/device/mock/SoftwareGPUError.js +63 -63
  1450. package/src/shade/device/mock/SoftwareGPUPipeline.js +75 -75
  1451. package/src/shade/device/mock/SoftwareGPUQuerySet.js +113 -113
  1452. package/src/shade/device/mock/SoftwareGPUSampler.js +30 -30
  1453. package/src/shade/device/mock/SoftwareGPUShaderModule.js +32 -32
  1454. package/src/shade/device/mock/SoftwareGPUTextureView.js +22 -22
  1455. package/src/shade/device/mock/SoftwareGPUUncapturedErrorEvent.js +23 -23
  1456. package/src/shade/device/mock/normalize_dynamic_offsets.js +26 -26
  1457. package/src/shade/device/mock/texture_copy.js +287 -287
  1458. package/src/shade/device/timing/GPUTimer.js +285 -285
  1459. package/src/shade/device/timing/GPUTimerArray.js +205 -205
  1460. package/src/shade/playground/add_random_lights.js +49 -49
  1461. package/src/shade/playground/add_random_meshes.js +83 -83
  1462. package/src/shade/playground/animation_prototype.js +508 -508
  1463. package/src/shade/playground/animation_prototype_skinning.js +647 -647
  1464. package/src/shade/playground/animation_prototype_stress.js +765 -765
  1465. package/src/shade/playground/enable_picker.js +59 -59
  1466. package/src/shade/playground/gltf_skinned_prototype.js +560 -560
  1467. package/src/shade/playground/gltf_skinned_stress_prototype.js +387 -387
  1468. package/src/shade/playground/gltf_viewer.js +282 -282
  1469. package/src/shade/playground/load_default_environment.js +19 -19
  1470. package/src/shade/playground/main.js +2727 -2727
  1471. package/src/shade/playground/make_animated_instances.js +117 -117
  1472. package/src/shade/playground/prototype_virtual_texture.js +274 -274
  1473. package/src/shade/playground/prototype_volumetrics_01.js +206 -206
  1474. package/src/shade/playground/sample.js +234 -234
  1475. package/src/shade/playground/sample_load_gltf.js +102 -102
  1476. package/src/shade/playground/spread_node3d_grid.js +19 -19
  1477. package/src/shade/renderer/Renderer.js +2436 -2436
  1478. package/src/shade/renderer/ShadeIndirectLightingMode.js +14 -14
  1479. package/src/shade/renderer/animation/ShadeAnimationChannel.js +414 -414
  1480. package/src/shade/renderer/animation/compute_skinned_mesh_clip_bounding_sphere.js +531 -531
  1481. package/src/shade/renderer/animation/pose/PosePlayback.js +55 -55
  1482. package/src/shade/renderer/animation/pose/pose_evaluate_local.js +179 -179
  1483. package/src/shade/renderer/animation/pose/pose_evaluate_world.js +76 -76
  1484. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +1024 -1024
  1485. package/src/shade/renderer/animation/skinning/SKINNING_BINDING_STRUCT.js +79 -79
  1486. package/src/shade/renderer/animation/skinning/chunk_skin_blend_mesh_local.js +56 -56
  1487. package/src/shade/renderer/binding/BindGroupManager.js +282 -282
  1488. package/src/shade/renderer/binding/adapt_cache_capacity.js +25 -25
  1489. package/src/shade/renderer/buffer/GPUBufferAllocator.js +116 -116
  1490. package/src/shade/renderer/buffer/buffer_pool_ops.js +123 -123
  1491. package/src/shade/renderer/buffer/table/GPU_DATABASE_PAGE_SIZE.js +9 -9
  1492. package/src/shade/renderer/buffer/table/GPU_DATABASE_UPLOAD_BUFFER_LIMIT.js +8 -8
  1493. package/src/shade/renderer/buffer/table/PageBufferPool.js +71 -71
  1494. package/src/shade/renderer/buffer/table/PageSlotAllocator.js +95 -95
  1495. package/src/shade/renderer/camera/Camera.js +281 -281
  1496. package/src/shade/renderer/camera/GPUCameraContext.js +233 -233
  1497. package/src/shade/renderer/camera/orbital/README.md +84 -84
  1498. package/src/shade/renderer/deferred/shader_composite_volumetrics.js +75 -75
  1499. package/src/shade/renderer/dynamic/DYNAMIC_MESH_VERTEX.js +25 -25
  1500. package/src/shade/renderer/dynamic/GPUDynamicMeshRenderer.js +342 -342
  1501. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.js +167 -167
  1502. package/src/shade/renderer/dynamic/shader_dynamic_mesh.js +170 -170
  1503. package/src/shade/renderer/extension/FrameContext.js +263 -263
  1504. package/src/shade/renderer/extension/FramePhase.js +104 -104
  1505. package/src/shade/renderer/extension/FrameRecord.js +126 -126
  1506. package/src/shade/renderer/extension/GBufferTextures.js +83 -83
  1507. package/src/shade/renderer/extension/PresentTarget.js +34 -34
  1508. package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +918 -918
  1509. package/src/shade/renderer/extension/RenderExtension.js +69 -69
  1510. package/src/shade/renderer/extension/RenderExtensionRegistry.js +319 -319
  1511. package/src/shade/renderer/extension/SceneColor.js +40 -40
  1512. package/src/shade/renderer/extension/ViewTextures.js +78 -78
  1513. package/src/shade/renderer/fow/GPUFogOfWarRenderer.js +182 -182
  1514. package/src/shade/renderer/geometry/Geometry.js +608 -608
  1515. package/src/shade/renderer/geometry/geometry_build_from_meshlet_geometry.js +342 -342
  1516. package/src/shade/renderer/geometry/meshlet_geometry_transfer.js +41 -41
  1517. package/src/shade/renderer/geometry/primitives/make_box_geometry.js +153 -153
  1518. package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.js +240 -240
  1519. package/src/shade/renderer/geometry/primitives/make_plane_geometry.js +145 -145
  1520. package/src/shade/renderer/geometry/primitives/make_polyhedron_geometry.js +327 -327
  1521. package/src/shade/renderer/geometry/primitives/make_torus_geometry.js +107 -107
  1522. package/src/shade/renderer/geometry/primitives/make_torus_knot_geometry.js +165 -165
  1523. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +607 -607
  1524. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.js +66 -66
  1525. package/src/shade/renderer/geometry/virtual/build/VGeoBuildResult.js +32 -32
  1526. package/src/shade/renderer/geometry/virtual/build/VGeoFaceGraph.js +103 -103
  1527. package/src/shade/renderer/geometry/virtual/build/VGeoGatheredFaces.js +25 -25
  1528. package/src/shade/renderer/geometry/virtual/build/VGeoLevel.js +33 -33
  1529. package/src/shade/renderer/geometry/virtual/build/VGeoLevelOptions.js +62 -62
  1530. package/src/shade/renderer/geometry/virtual/build/VGeoLevelSummary.js +49 -49
  1531. package/src/shade/renderer/geometry/virtual/build/VGeoSubmesh.js +20 -20
  1532. package/src/shade/renderer/geometry/virtual/build/VirtualGeometryMesh.js +214 -214
  1533. package/src/shade/renderer/geometry/virtual/build/gltf/GltfByteSource.js +122 -122
  1534. package/src/shade/renderer/geometry/virtual/build/gltf/GltfCollectReport.js +29 -29
  1535. package/src/shade/renderer/geometry/virtual/build/gltf/GltfDocument.js +210 -210
  1536. package/src/shade/renderer/geometry/virtual/build/gltf/GltfGeometry.js +48 -48
  1537. package/src/shade/renderer/geometry/virtual/build/gltf/GltfGeometryInstance.js +25 -25
  1538. package/src/shade/renderer/geometry/virtual/build/gltf/GltfGeometrySelection.js +28 -28
  1539. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_collect_geometries.js +296 -296
  1540. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_open_document.js +166 -166
  1541. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_read_geometry.js +199 -199
  1542. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.js +173 -173
  1543. package/src/shade/renderer/geometry/virtual/build/vgeo_bounding_sphere.js +28 -28
  1544. package/src/shade/renderer/geometry/virtual/build/vgeo_build.js +200 -200
  1545. package/src/shade/renderer/geometry/virtual/build/vgeo_build_levels.js +1786 -1786
  1546. package/src/shade/renderer/geometry/virtual/build/vgeo_build_page_nodes.js +157 -157
  1547. package/src/shade/renderer/geometry/virtual/build/vgeo_build_root_group.js +26 -26
  1548. package/src/shade/renderer/geometry/virtual/build/vgeo_compute_vertex_normals.js +75 -75
  1549. package/src/shade/renderer/geometry/virtual/build/vgeo_compute_vertex_tangents.js +143 -143
  1550. package/src/shade/renderer/geometry/virtual/build/vgeo_containing_sphere.js +44 -44
  1551. package/src/shade/renderer/geometry/virtual/build/vgeo_extract_submesh.js +41 -41
  1552. package/src/shade/renderer/geometry/virtual/build/vgeo_gather_faces.js +71 -71
  1553. package/src/shade/renderer/geometry/virtual/build/vgeo_graph_components.js +123 -123
  1554. package/src/shade/renderer/geometry/virtual/build/vgeo_narrow_indices.js +26 -26
  1555. package/src/shade/renderer/geometry/virtual/build/vgeo_normalize_source.js +112 -112
  1556. package/src/shade/renderer/geometry/virtual/build/vgeo_partition_graph.js +56 -56
  1557. package/src/shade/renderer/geometry/virtual/build/vgeo_sphere_inflate_to_contain.js +70 -70
  1558. package/src/shade/renderer/geometry/virtual/build/vgeo_split_face_set.js +187 -187
  1559. package/src/shade/renderer/geometry/virtual/build/vgeo_split_face_set_packed.js +207 -207
  1560. package/src/shade/renderer/geometry/virtual/format/VGEO_DEFECT.js +18 -18
  1561. package/src/shade/renderer/geometry/virtual/format/VGeoDefect.js +38 -38
  1562. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.js +64 -64
  1563. package/src/shade/renderer/geometry/virtual/format/attribute/VGEO_ATTRIBUTE.js +13 -13
  1564. package/src/shade/renderer/geometry/virtual/format/attribute/VGEO_ATTRIBUTES.js +50 -50
  1565. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attribute_allocate.js +28 -28
  1566. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attribute_mask.js +23 -23
  1567. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attributes_read.js +31 -31
  1568. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_copy_vertex.js +32 -32
  1569. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_declare.js +46 -46
  1570. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_like.js +19 -19
  1571. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_test_fixtures.js +27 -27
  1572. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_asset_id_preimage.js +62 -62
  1573. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_asset_id.js +13 -13
  1574. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_directory_block_checksum.js +41 -41
  1575. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_frame_checksum.js +41 -41
  1576. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_header_checksum.js +25 -25
  1577. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_OFFSET.js +20 -20
  1578. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_RECORD_SIZE.js +5 -5
  1579. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_MAX_CHILD_REF.js +5 -5
  1580. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_MAX_CLUSTER_TRIANGLE_COUNT.js +5 -5
  1581. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_MAX_CLUSTER_VERTEX_COUNT.js +5 -5
  1582. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_NO_CHILD.js +5 -5
  1583. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_NO_GROUP.js +5 -5
  1584. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_SAME_PAGE.js +6 -6
  1585. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.js +81 -81
  1586. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryGroup.js +37 -37
  1587. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryPageNode.js +55 -55
  1588. package/src/shade/renderer/geometry/virtual/format/directory/VGEO_DIRECTORY_BLOCK_RECORDS.js +5 -5
  1589. package/src/shade/renderer/geometry/virtual/format/directory/VGEO_DIRECTORY_FLAG_ROOT_PAGE.js +5 -5
  1590. package/src/shade/renderer/geometry/virtual/format/directory/VGEO_DIRECTORY_RECORD_SIZE.js +5 -5
  1591. package/src/shade/renderer/geometry/virtual/format/directory/vgeo_directory_block_count.js +12 -12
  1592. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CHILD_OFFSET.js +11 -11
  1593. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CHILD_TABLE_ENTRY_SIZE.js +5 -5
  1594. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_LZ4.js +11 -11
  1595. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_RAW.js +5 -5
  1596. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_FRAME_ALIGNMENT.js +5 -5
  1597. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_FRAME_HEADER_SIZE.js +5 -5
  1598. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_FRAME_OFFSET.js +13 -13
  1599. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_PAGE_MAGIC.js +5 -5
  1600. package/src/shade/renderer/geometry/virtual/format/frame/VGeoFrameBlob.js +21 -21
  1601. package/src/shade/renderer/geometry/virtual/format/frame/VGeoFrameExtent.js +59 -59
  1602. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_codec_name.js +27 -27
  1603. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_decode_frame_blob.js +84 -84
  1604. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.js +56 -56
  1605. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_frame_decode_bound.js +35 -35
  1606. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_scan_frames.js +74 -74
  1607. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.js +6 -6
  1608. package/src/shade/renderer/geometry/virtual/format/header/VGEO_HASH_ALGO_XXH3.js +5 -5
  1609. package/src/shade/renderer/geometry/virtual/format/header/VGEO_HEADER_OFFSET.js +31 -31
  1610. package/src/shade/renderer/geometry/virtual/format/header/VGEO_HEADER_SIZE.js +5 -5
  1611. package/src/shade/renderer/geometry/virtual/format/header/VGEO_LEVEL_OFFSET.js +20 -20
  1612. package/src/shade/renderer/geometry/virtual/format/header/VGEO_LEVEL_RECORD_SIZE.js +9 -9
  1613. package/src/shade/renderer/geometry/virtual/format/header/VGEO_MAGIC.js +5 -5
  1614. package/src/shade/renderer/geometry/virtual/format/header/VGEO_MIN_READER_VERSION.js +5 -5
  1615. package/src/shade/renderer/geometry/virtual/format/header/VGEO_PAYLOAD_ENCODING_SHADE_MESHLET_V1.js +5 -5
  1616. package/src/shade/renderer/geometry/virtual/format/header/VGeoLevelRecord.js +41 -41
  1617. package/src/shade/renderer/geometry/virtual/format/page/VGEO_GROUP_RECORD_SIZE.js +5 -5
  1618. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_GROUP_CLUSTER_COUNT.js +6 -6
  1619. package/src/shade/renderer/geometry/virtual/format/page/VGEO_METRIC_OFFSET.js +21 -21
  1620. package/src/shade/renderer/geometry/virtual/format/page/VGEO_METRIC_SIZE.js +5 -5
  1621. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_FANOUT.js +9 -9
  1622. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_FLAG_LEAF.js +5 -5
  1623. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_OFFSET.js +10 -10
  1624. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_RECORD_SIZE.js +5 -5
  1625. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_HEADER_SIZE.js +5 -5
  1626. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET.js +16 -16
  1627. package/src/shade/renderer/geometry/virtual/format/payload/VGEO_ENCODING_FLAGS_MASK.js +6 -6
  1628. package/src/shade/renderer/geometry/virtual/format/payload/VGeoEncodedPayload.js +18 -18
  1629. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_encode_cluster_payload.js +200 -200
  1630. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_payload_attribute_offset.js +39 -39
  1631. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_payload_size.js +20 -20
  1632. package/src/shade/renderer/geometry/virtual/format/prototypeVGEOFormatViewer.js +2063 -2063
  1633. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.js +1622 -1622
  1634. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +485 -485
  1635. package/src/shade/renderer/gpu_primitive/sort/ffx/graph_radix_sort.js +115 -115
  1636. package/src/shade/renderer/gpu_primitive/sort/one_sweep/verify_radix_sort_one_sweep.js +110 -110
  1637. package/src/shade/renderer/light/environment/octahedral_resample_kernel.js +50 -50
  1638. package/src/shade/renderer/light/environment/octahedral_uv_to_direction.js +30 -30
  1639. package/src/shade/renderer/light/environment/resample_cube_to_octahedral.js +157 -157
  1640. package/src/shade/renderer/light/make_sunlight.js +35 -35
  1641. package/src/shade/renderer/light/model/io/light_record_point.js +39 -39
  1642. package/src/shade/renderer/loader/gltf/GLTF_PRIMITIVE_MODE.js +23 -23
  1643. package/src/shade/renderer/loader/gltf/MESHOPT_COMPRESSION_PLAN.md +793 -793
  1644. package/src/shade/renderer/loader/gltf/ext/GltfBufferViewExtension.js +54 -54
  1645. package/src/shade/renderer/loader/gltf/ext/GltfBufferViewExtensionSet.js +109 -109
  1646. package/src/shade/renderer/loader/gltf/ext/gltf_apply_buffer_view_extensions.js +69 -69
  1647. package/src/shade/renderer/loader/gltf/ext/gltf_buffer_view_extensions.js +22 -22
  1648. package/src/shade/renderer/loader/gltf/ext/gltf_geometry_extensions.js +39 -39
  1649. package/src/shade/renderer/loader/gltf/ext/meshopt/MeshoptBufferViewExtension.js +301 -301
  1650. package/src/shade/renderer/loader/gltf/gltf_component_type.js +223 -223
  1651. package/src/shade/renderer/loader/gltf/gltf_node_world_matrices.js +137 -137
  1652. package/src/shade/renderer/loader/gltf/gltf_parse_container.js +241 -241
  1653. package/src/shade/renderer/loader/gltf/gltf_read_accessor.js +294 -294
  1654. package/src/shade/renderer/loader/gltf/gltf_used_image_indices.js +49 -49
  1655. package/src/shade/renderer/loader/gltf/load_gltf.js +1253 -1253
  1656. package/src/shade/renderer/loader/gltf/tiny-gltf.js +646 -646
  1657. package/src/shade/renderer/loader/usd/UsdError.js +33 -33
  1658. package/src/shade/renderer/loader/usd/UsdExtensionRegistry.js +69 -69
  1659. package/src/shade/renderer/loader/usd/load_usd.js +226 -226
  1660. package/src/shade/renderer/loader/usd/parse_usda.js +931 -931
  1661. package/src/shade/renderer/loader/usd/unpack_usdz.js +106 -106
  1662. package/src/shade/renderer/loader/usd/usd_build_scene.js +658 -658
  1663. package/src/shade/renderer/loader/usd/usd_compose_transform.js +258 -258
  1664. package/src/shade/renderer/loader/usd/usd_decode_image.js +384 -384
  1665. package/src/shade/renderer/loader/usd/usd_lz4.js +182 -182
  1666. package/src/shade/renderer/loader/usd/usd_triangulate.js +159 -159
  1667. package/src/shade/renderer/material/ShadeMaterial.d.ts +2 -2
  1668. package/src/shade/renderer/material/ShadeMaterial.js +2 -2
  1669. package/src/shade/renderer/material/standard/fragment_gbuffer.js +334 -334
  1670. package/src/shade/renderer/material/standard/fragment_gbuffer_vt.js +169 -169
  1671. package/src/shade/renderer/material/standard/material_gbuffer_vertex.js +45 -45
  1672. package/src/shade/renderer/material/standard_material_to_struct.js +23 -23
  1673. package/src/shade/renderer/particles/prototypeParticleSystem.js +450 -450
  1674. package/src/shade/renderer/particles/runtime/spawn_request_encoding.js +52 -52
  1675. package/src/shade/renderer/pool/TransientResourcePool.js +392 -392
  1676. package/src/shade/renderer/postprocess/bloom/bloom_chain_resolution.js +29 -29
  1677. package/src/shade/renderer/postprocess/bloom/graph_bloom_downsample.js +109 -109
  1678. package/src/shade/renderer/postprocess/bloom/graph_postprocess_bloom.js +155 -155
  1679. package/src/shade/renderer/postprocess/cas/shader_ffx_rcas.js +114 -114
  1680. package/src/shade/renderer/postprocess/dof/DOF_AUTOFOCUS_PARAMS_STRUCT.js +25 -25
  1681. package/src/shade/renderer/postprocess/dof/DOF_FOCUS_STATE_STRUCT.js +23 -23
  1682. package/src/shade/renderer/postprocess/dof/DOF_PRESETS.js +27 -27
  1683. package/src/shade/renderer/postprocess/dof/chunk_dof_coc_band_diameter.js +41 -41
  1684. package/src/shade/renderer/postprocess/dof/chunk_dof_coc_band_radius.js +32 -32
  1685. package/src/shade/renderer/postprocess/dof/chunk_dof_coc_coefficient.js +26 -26
  1686. package/src/shade/renderer/postprocess/dof/compute_dof_autofocus_params.js +64 -64
  1687. package/src/shade/renderer/postprocess/dof/compute_dof_uniform.js +54 -54
  1688. package/src/shade/renderer/postprocess/dof/gather/DOF2_CONFIG.js +91 -91
  1689. package/src/shade/renderer/postprocess/dof/gather/DOF2_PRESETS.js +9 -9
  1690. package/src/shade/renderer/postprocess/dof/gather/DOF2_SETTINGS_STRUCT.js +66 -66
  1691. package/src/shade/renderer/postprocess/dof/gather/DOF2_TEXTURE_FORMAT.js +22 -22
  1692. package/src/shade/renderer/postprocess/dof/gather/DepthOfFieldU.js +292 -292
  1693. package/src/shade/renderer/postprocess/dof/gather/chunk_dof2_coc_to_near_far.js +25 -25
  1694. package/src/shade/renderer/postprocess/dof/gather/chunk_dof2_gather_weight.js +30 -30
  1695. package/src/shade/renderer/postprocess/dof/gather/compute_dof2_uniform.js +54 -54
  1696. package/src/shade/renderer/postprocess/dof/gather/graph_postprocess_dof2.js +194 -194
  1697. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_fill.js +68 -68
  1698. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_far.js +140 -140
  1699. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_near.js +142 -142
  1700. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_recombine.js +99 -99
  1701. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_setup.js +102 -102
  1702. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_tile_dilate.js +75 -75
  1703. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_tile_max.js +73 -73
  1704. package/src/shade/renderer/postprocess/dof/raymarch/DOF_SETTINGS_STRUCT.js +49 -49
  1705. package/src/shade/renderer/postprocess/dof/raymarch/DepthOfField.js +298 -298
  1706. package/src/shade/renderer/postprocess/dof/raymarch/graph_postprocess_dof.js +244 -244
  1707. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_composite.js +91 -91
  1708. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_firefly_cleanup.js +61 -61
  1709. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_prefilter.js +90 -90
  1710. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch_compute.js +267 -267
  1711. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_slice_compute.js +271 -271
  1712. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_tile_dilate.js +70 -70
  1713. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_tile_max.js +72 -72
  1714. package/src/shade/renderer/postprocess/dof/shader_dof_autofocus.js +99 -99
  1715. package/src/shade/renderer/postprocess/gtao/generate_magic_square_noise.js +51 -51
  1716. package/src/shade/renderer/postprocess/motion_blur/MotionBlur.js +56 -56
  1717. package/src/shade/renderer/postprocess/upscale-dither/NOTES.md +78 -78
  1718. package/src/shade/renderer/postprocess/upscale-dither/UpscaleDither.js +95 -95
  1719. package/src/shade/renderer/postprocess/upscale-dither/fragment_shader_upscale_dither.js +204 -204
  1720. package/src/shade/renderer/rasterize/bucket/construct_primitive_state.js +58 -58
  1721. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.js +230 -230
  1722. package/src/shade/renderer/rasterize/native/graph_rasterize_meshes_alpha_tested.js +278 -278
  1723. package/src/shade/renderer/rasterize/native/oit/chunk_material_side_should_draw.js +26 -26
  1724. package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments_ibl.js +178 -178
  1725. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +235 -235
  1726. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +208 -208
  1727. package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.js +206 -206
  1728. package/src/shade/renderer/scene/DynamicMesh.js +70 -70
  1729. package/src/shade/renderer/scene/DynamicMeshBatch.js +90 -90
  1730. package/src/shade/renderer/scene/GPUSceneContext.js +901 -901
  1731. package/src/shade/renderer/scene/SceneNodeBinding.js +56 -56
  1732. package/src/shade/renderer/scene/SkinnedMesh.js +55 -55
  1733. package/src/shade/renderer/scene/TransformAuthority.js +33 -33
  1734. package/src/shade/renderer/scene/optimization/deduplicate_geometries.js +38 -38
  1735. package/src/shade/renderer/scene/optimization/deduplicate_images.js +93 -93
  1736. package/src/shade/renderer/scene/optimization/geometry/internal/match_refit_validate.js +127 -127
  1737. package/src/shade/renderer/scene/optimization/geometry/internal/match_solve_transform.js +492 -492
  1738. package/src/shade/renderer/scene/optimization/optimize_texture_set.js +81 -81
  1739. package/src/shade/renderer/scene/optimization/source_to_sampler2d.js +21 -21
  1740. package/src/shade/renderer/scene/serialization/STANDARD_MATERIAL_SERIALIZED_BYTE_SIZE.js +12 -12
  1741. package/src/shade/renderer/shader/chunk/geometry/quaternion/dual/chunk_dual_quat_transform_point.js +26 -26
  1742. package/src/shade/renderer/shader/chunk/noise/chunk_interleaved_gradient_noise.js +20 -20
  1743. package/src/shade/renderer/shader/chunk/spherical_harmonics/dering/chunk_sh2_dering_optimize_positive.js +61 -61
  1744. package/src/shade/renderer/shader/chunk/texture/chunk_texture_filter_fxaa_lite.js +225 -225
  1745. package/src/shade/renderer/shader/chunk/texture/dither/chunk_dither_color_8bit_gradient_noise.js +25 -25
  1746. package/src/shade/renderer/shadow/map/DirectionalLightShadowmap.js +384 -384
  1747. package/src/shade/renderer/shadow/map/PointLightShadowmap.js +105 -105
  1748. package/src/shade/renderer/shadow/map/SpotLightShadowmap.js +63 -63
  1749. package/src/shade/renderer/shadow/map/TetrahedronPointLightShadowmap.js +89 -89
  1750. package/src/shade/renderer/shadow/map/shadowmap_update_score.js +232 -232
  1751. package/src/shade/renderer/texture/GPUTextureAllocator.js +85 -85
  1752. package/src/shade/renderer/texture/texture_pool_ops.js +171 -171
  1753. package/src/shade/renderer/texture/virtual/PageTableQuadAllocator.js +253 -253
  1754. package/src/shade/renderer/texture/virtual/README.md +276 -276
  1755. package/src/shade/renderer/texture/virtual/VTPageTable.js +330 -330
  1756. package/src/shade/renderer/texture/virtual/VTPhysicalCache.js +349 -349
  1757. package/src/shade/renderer/texture/virtual/VT_CONSTANTS.js +154 -154
  1758. package/src/shade/renderer/texture/virtual/VT_STACK_INFO_STRUCT.js +20 -20
  1759. package/src/shade/renderer/texture/virtual/VirtualTextureManager.js +1276 -1276
  1760. package/src/shade/renderer/texture/virtual/VirtualTextureStack.js +106 -106
  1761. package/src/shade/renderer/texture/virtual/build_chunk_vt_lookup.js +150 -150
  1762. package/src/shade/renderer/texture/virtual/build_shader_vt_feedback.js +232 -232
  1763. package/src/shade/renderer/texture/virtual/chunk_vt_request_key.js +28 -28
  1764. package/src/shade/renderer/texture/virtual/source/VTSourceImage.js +207 -207
  1765. package/src/shade/renderer/texture/virtual/source/VTSourceProcedural.js +135 -135
  1766. package/src/shade/renderer/texture/virtual/source/VTSourceTiled.js +132 -132
  1767. package/src/shade/renderer/water/GPUWaterRenderer.js +167 -167
  1768. package/src/shade/renderer/water/shader_water.js +246 -246
  1769. package/src/shade/renderer/water/water_height_texture_from_sampler.js +56 -56
  1770. package/src/shade/vitest.setup.mjs +89 -89
  1771. package/src/shade/wgsl/validate_wgsl_source.js +316 -316
  1772. package/src/view/controller/controls/NumericIntervalControl.js +90 -90
  1773. package/src/view/controller/controls/Vector2Control.js +83 -83
  1774. package/src/view/controller/controls/Vector3Control.js +90 -90
  1775. package/src/view/elements/Group.js +56 -56
  1776. package/src/view/elements/drawCheckers.js +33 -33
  1777. package/src/view/elements/windrose/WindRoseDiagram.js +369 -369
  1778. package/src/view/graphics/WebGLContextFailureView.js +76 -76
  1779. package/src/view/layout/DockPanel.js +51 -51
  1780. package/src/view/layout/SplitView.js +365 -365
  1781. package/src/view/layout/show_popup_menu.js +81 -81
  1782. package/src/view/minimap/MinimapCanvasView.js +411 -411
  1783. package/src/view/minimap/MinimapImageCache.js +88 -88
  1784. package/src/view/minimap/MinimapMarkerCollection.d.ts +0 -1
  1785. package/src/view/minimap/MinimapMarkerCollection.d.ts.map +1 -1
  1786. package/src/view/minimap/MinimapMarkerCollection.js +180 -180
  1787. package/src/view/minimap/dom/MinimapCameraView.js +206 -206
  1788. package/src/view/minimap/minimap_focus_area.js +97 -97
  1789. package/editor/process/symbolic/SocketsSymbolicDisplay.js +0 -192
  1790. package/src/core/geom/3d/topology/struct/binary/io/moved_tests.txt +0 -37
  1791. package/src/engine/ecs/attachment/Attachment.d.ts +0 -40
  1792. package/src/engine/ecs/attachment/Attachment.d.ts.map +0 -1
  1793. package/src/engine/ecs/attachment/Attachment.js +0 -57
  1794. package/src/engine/ecs/attachment/AttachmentBinding.d.ts +0 -28
  1795. package/src/engine/ecs/attachment/AttachmentBinding.d.ts.map +0 -1
  1796. package/src/engine/ecs/attachment/AttachmentBinding.js +0 -41
  1797. package/src/engine/ecs/attachment/AttachmentSystem.d.ts +0 -61
  1798. package/src/engine/ecs/attachment/AttachmentSystem.d.ts.map +0 -1
  1799. package/src/engine/ecs/attachment/AttachmentSystem.js +0 -307
  1800. package/src/engine/ecs/attachment/BoneAttachmentBinding.d.ts +0 -27
  1801. package/src/engine/ecs/attachment/BoneAttachmentBinding.d.ts.map +0 -1
  1802. package/src/engine/ecs/attachment/BoneAttachmentBinding.js +0 -69
  1803. package/src/engine/ecs/attachment/TransformAttachmentBinding.d.ts +0 -4
  1804. package/src/engine/ecs/attachment/TransformAttachmentBinding.d.ts.map +0 -1
  1805. package/src/engine/ecs/attachment/TransformAttachmentBinding.js +0 -51
  1806. package/src/engine/ecs/sockets/AttachmentSocket.d.ts +0 -32
  1807. package/src/engine/ecs/sockets/AttachmentSocket.d.ts.map +0 -1
  1808. package/src/engine/ecs/sockets/AttachmentSocket.js +0 -60
  1809. package/src/engine/ecs/sockets/AttachmentSocketType.d.ts +0 -6
  1810. package/src/engine/ecs/sockets/AttachmentSocketType.d.ts.map +0 -1
  1811. package/src/engine/ecs/sockets/AttachmentSocketType.js +0 -8
  1812. package/src/engine/ecs/sockets/AttachmentSockets.d.ts +0 -57
  1813. package/src/engine/ecs/sockets/AttachmentSockets.d.ts.map +0 -1
  1814. package/src/engine/ecs/sockets/AttachmentSockets.js +0 -130
  1815. package/src/engine/ecs/sockets/BoneAttachmentSocket.d.ts +0 -29
  1816. package/src/engine/ecs/sockets/BoneAttachmentSocket.d.ts.map +0 -1
  1817. package/src/engine/ecs/sockets/BoneAttachmentSocket.js +0 -56
  1818. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.d.ts +0 -6
  1819. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.d.ts.map +0 -1
  1820. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.js +0 -19
  1821. package/src/shade/renderer/animation/_dump_resolve.d.mts +0 -2
  1822. package/src/shade/renderer/animation/_dump_resolve.d.mts.map +0 -1
  1823. package/src/shade/renderer/animation/_dump_resolve.mjs +0 -5
@@ -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.