@woosh/meep-engine 3.60.4 → 3.60.5
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.
- package/CHANGELOG.md +2602 -0
- package/CONTRIBUTING.md +7 -0
- package/MIGRATION_2_TO_3.md +136 -0
- package/SECURITY.md +4 -0
- package/editor/EditorCameraNavigation.d.ts +2 -1
- package/editor/EditorCameraNavigation.d.ts.map +1 -1
- package/editor/EditorCameraNavigation.js +51 -57
- package/package.json +6 -2
- package/src/engine/EngineHarness.d.ts +3 -9
- package/src/engine/EngineHarness.d.ts.map +1 -1
- package/src/engine/EngineHarness.js +6 -8
- package/src/engine/graphics/camera/makeOrbitalCameraController.d.ts +9 -6
- package/src/engine/graphics/camera/makeOrbitalCameraController.d.ts.map +1 -1
- package/src/engine/graphics/camera/makeOrbitalCameraController.js +44 -71
- package/src/engine/graphics/camera/orbital/MomentumAxis.d.ts +64 -0
- package/src/engine/graphics/camera/orbital/MomentumAxis.d.ts.map +1 -0
- package/src/engine/graphics/camera/orbital/MomentumAxis.js +187 -0
- package/src/engine/graphics/camera/orbital/OrbitalCameraRig.d.ts +86 -0
- package/src/engine/graphics/camera/orbital/OrbitalCameraRig.d.ts.map +1 -0
- package/src/engine/graphics/camera/orbital/OrbitalCameraRig.js +319 -0
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.d.ts +34 -10
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.d.ts.map +1 -1
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.js +116 -30
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts +1 -7
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +1 -37
- package/src/engine/graphics/ecs/water/Water.d.ts +8 -0
- package/src/engine/graphics/ecs/water/Water.d.ts.map +1 -1
- package/src/engine/graphics/ecs/water/Water.js +8 -0
- package/src/engine/graphics3/WaterSystem.d.ts.map +1 -1
- package/src/engine/graphics3/WaterSystem.js +731 -734
- package/src/engine/graphics3/decal/DecalTileShader.d.ts +61 -0
- package/src/engine/graphics3/decal/DecalTileShader.d.ts.map +1 -0
- package/src/engine/graphics3/decal/DecalTileShader.js +138 -0
- package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts +10 -4
- package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts.map +1 -1
- package/src/engine/graphics3/decal/GPUDecalRenderer.js +149 -44
- package/src/engine/graphics3/decal/chunk_decal_tile_vertex.d.ts +25 -0
- package/src/engine/graphics3/decal/chunk_decal_tile_vertex.d.ts.map +1 -0
- package/src/engine/graphics3/decal/chunk_decal_tile_vertex.js +55 -0
- package/src/engine/graphics3/decal/graph_gather_decal_tiles.d.ts +22 -0
- package/src/engine/graphics3/decal/graph_gather_decal_tiles.d.ts.map +1 -0
- package/src/engine/graphics3/decal/graph_gather_decal_tiles.js +70 -0
- package/src/engine/graphics3/decal/shader_decal_composite.d.ts +7 -5
- package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
- package/src/engine/graphics3/decal/shader_decal_composite.js +48 -44
- package/src/engine/graphics3/decal/shader_decal_tile_copy.d.ts +12 -0
- package/src/engine/graphics3/decal/shader_decal_tile_copy.d.ts.map +1 -0
- package/src/engine/graphics3/decal/shader_decal_tile_copy.js +78 -0
- package/src/engine/graphics3/decal/shader_gather_decal_tiles.d.ts +11 -0
- package/src/engine/graphics3/decal/shader_gather_decal_tiles.d.ts.map +1 -0
- package/src/engine/graphics3/decal/shader_gather_decal_tiles.js +80 -0
- package/src/engine/input/devices/mouse/MouseEventButtons.d.ts +13 -0
- package/src/engine/input/devices/mouse/MouseEventButtons.d.ts.map +1 -0
- package/src/engine/input/devices/mouse/MouseEventButtons.js +23 -0
- package/src/engine/input/ecs/controllers/KeyboardCameraController.d.ts +4 -0
- package/src/engine/input/ecs/controllers/KeyboardCameraController.d.ts.map +1 -1
- package/src/engine/input/ecs/controllers/KeyboardCameraController.js +9 -45
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/shade/playground/water_refraction/README.md +5 -6
- package/src/shade/playground/water_refraction/index.html +1 -1
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +7 -5
- package/src/shade/renderer/camera/orbital/OrbitalCameraController.d.ts +40 -80
- package/src/shade/renderer/camera/orbital/OrbitalCameraController.d.ts.map +1 -1
- package/src/shade/renderer/camera/orbital/OrbitalCameraController.js +197 -147
- package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +3 -3
- package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +1 -1
- package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +6 -6
- package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +1 -1
- package/src/shade/renderer/fluid/query/GPUFluidQueries.d.ts +1 -1
- package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +2 -2
- package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +2 -2
- package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts +2 -1
- package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts.map +1 -1
- package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.js +18 -1
- package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.d.ts +31 -0
- package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.js +343 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.d.ts +17 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.js +29 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.js +7 -13
- package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +1 -8
- package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts +5 -5
- package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.js +10 -10
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +1 -4
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +1 -10
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.d.ts +5 -15
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.js +6 -34
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.js +1 -7
- package/src/shade/renderer/hiz/HZBFootprint.d.ts +14 -0
- package/src/shade/renderer/hiz/HZBFootprint.d.ts.map +1 -0
- package/src/shade/renderer/hiz/HZBFootprint.js +16 -0
- package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.d.ts +10 -0
- package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.d.ts.map +1 -0
- package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.js +11 -0
- package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.d.ts +10 -0
- package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.d.ts.map +1 -0
- package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.js +11 -0
- package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts +0 -7
- package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
- package/src/shade/renderer/hiz/HierarchicalZBuffer.js +405 -350
- package/src/shade/renderer/hiz/chunk_hzb_footprint_x.d.ts +12 -0
- package/src/shade/renderer/hiz/chunk_hzb_footprint_x.d.ts.map +1 -0
- package/src/shade/renderer/hiz/chunk_hzb_footprint_x.js +27 -0
- package/src/shade/renderer/hiz/chunk_hzb_footprint_y.d.ts +12 -0
- package/src/shade/renderer/hiz/chunk_hzb_footprint_y.d.ts.map +1 -0
- package/src/shade/renderer/hiz/chunk_hzb_footprint_y.js +27 -0
- package/src/shade/renderer/hiz/hzb_footprint_texels.d.ts +14 -0
- package/src/shade/renderer/hiz/hzb_footprint_texels.d.ts.map +1 -0
- package/src/shade/renderer/hiz/hzb_footprint_texels.js +34 -0
- package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts +0 -5
- package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts.map +1 -1
- package/src/shade/renderer/hiz/shader_hzb_reduce_any.js +37 -57
- package/src/shade/renderer/hiz/shader_hzb_reduce_mip0.d.ts +11 -0
- package/src/shade/renderer/hiz/shader_hzb_reduce_mip0.d.ts.map +1 -0
- package/src/shade/renderer/hiz/{shader_hzb_reduce_mip0_clip.js → shader_hzb_reduce_mip0.js} +120 -111
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
- package/src/shade/renderer/material/GPUMaterialManager.d.ts +7 -0
- package/src/shade/renderer/material/GPUMaterialManager.d.ts.map +1 -1
- package/src/shade/renderer/material/GPUMaterialManager.js +11 -0
- package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts +12 -12
- package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts.map +1 -1
- package/src/shade/renderer/material/resident/GPUResidentMaterialContext.js +17 -118
- package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +7 -2
- package/src/shade/renderer/water/GPUWaterRenderer.d.ts +0 -6
- package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
- package/src/shade/renderer/water/GPUWaterRenderer.js +12 -17
- package/src/shade/renderer/water/medium/graph_water_meshlets.d.ts +35 -0
- package/src/shade/renderer/water/medium/graph_water_meshlets.d.ts.map +1 -0
- package/src/shade/renderer/water/medium/graph_water_meshlets.js +89 -0
- package/src/shade/renderer/water/query/GPUWaterQueries.d.ts +1 -1
- package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
- package/src/shade/renderer/water/shader_water.js +22 -13
- package/src/shade/renderer/water/shader_water_avboit.d.ts.map +1 -1
- package/src/shade/renderer/water/shader_water_avboit.js +7 -7
- package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts +1 -1
- package/src/shade/renderer/water/surface/graph_water_tessellation.js +1 -1
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +9 -1
- package/editor/REWORK_PLAN_2026_08.md +0 -692
- package/src/CODEC_LAYOUT_VERIFICATION.md +0 -419
- package/src/CORRECTNESS_HUNT_2026_07_24.md +0 -142
- package/src/DUPLICATION_AUDIT_2026_08_07/00_core_reuse_surface.md +0 -738
- package/src/DUPLICATION_AUDIT_2026_08_07/A_core_math_geom.md +0 -79
- package/src/DUPLICATION_AUDIT_2026_08_07/B_core_data.md +0 -93
- package/src/DUPLICATION_AUDIT_2026_08_07/C_gfx_render.md +0 -80
- package/src/DUPLICATION_AUDIT_2026_08_07/D_gfx_features.md +0 -164
- package/src/DUPLICATION_AUDIT_2026_08_07/E_physics.md +0 -69
- package/src/DUPLICATION_AUDIT_2026_08_07/F_sound.md +0 -110
- package/src/DUPLICATION_AUDIT_2026_08_07/G_net_save.md +0 -129
- package/src/DUPLICATION_AUDIT_2026_08_07/H_engine_misc.md +0 -72
- package/src/DUPLICATION_AUDIT_2026_08_07/I_generation_view.md +0 -74
- package/src/DUPLICATION_AUDIT_2026_08_07/K_crosscutting.md +0 -169
- package/src/DUPLICATION_AUDIT_2026_08_07.md +0 -254
- package/src/DUPLICATION_AUDIT_REMEDIATION.md +0 -250
- package/src/DUPLICATION_REVIEW_2026_10_24.md +0 -1072
- package/src/REVIEW_2026_08_06/adv-core.md +0 -511
- package/src/REVIEW_2026_08_06/adv-gfx.md +0 -480
- package/src/REVIEW_2026_08_06/adv-view.md +0 -446
- package/src/REVIEW_2026_08_06/api-core.md +0 -296
- package/src/REVIEW_2026_08_06/api-engine.md +0 -195
- package/src/REVIEW_2026_08_06/bvh-phys-sound-net.md +0 -507
- package/src/REVIEW_2026_08_06/core-binary.md +0 -348
- package/src/REVIEW_2026_08_06/core-collection.md +0 -376
- package/src/REVIEW_2026_08_06/core-math.md +0 -221
- package/src/REVIEW_2026_08_06/core-process.md +0 -266
- package/src/REVIEW_2026_08_06/core-science.md +0 -223
- package/src/REVIEW_2026_08_06/engine-ai-nav.md +0 -279
- package/src/REVIEW_2026_08_06/engine-animation.md +0 -167
- package/src/REVIEW_2026_08_06/engine-asset.md +0 -166
- package/src/REVIEW_2026_08_06/engine-ecs.md +0 -920
- package/src/REVIEW_2026_08_06/engine-input.md +0 -197
- package/src/REVIEW_2026_08_06/engine-misc.md +0 -248
- package/src/REVIEW_2026_08_06/engine-terrain.md +0 -52
- package/src/REVIEW_2026_08_06/generation.md +0 -176
- package/src/REVIEW_2026_08_06/geom-2d.md +0 -434
- package/src/REVIEW_2026_08_06/geom-3d.md +0 -117
- package/src/REVIEW_2026_08_06/gfx-gi.md +0 -143
- package/src/REVIEW_2026_08_06/gfx-render.md +0 -740
- package/src/REVIEW_2026_08_06/gfx-texture.md +0 -690
- package/src/REVIEW_2026_08_06/prior-criticals.md +0 -49
- package/src/REVIEW_2026_08_06/prior-highs.md +0 -138
- package/src/REVIEW_2026_08_06/test-gaps.md +0 -364
- package/src/REVIEW_2026_08_06/view.md +0 -667
- package/src/REVIEW_2026_08_06.md +0 -610
- package/src/core/binary/lz4/LZ4_HIGH_COMPRESSION_PLAN_2026_09_14.md +0 -542
- package/src/core/bvh2/bvh3/NOTES.md +0 -2
- package/src/core/bvh8/NOTES.md +0 -63
- package/src/core/cache/wtinylfu/benchmark/CacheWTinylfu.bench.md +0 -243
- package/src/core/color/COLOR_FIX_PLAN_2026_08_28.md +0 -417
- package/src/core/color/COLOR_REVIEW_2026_08_28.md +0 -779
- package/src/core/geom/2d/polygon/TRIANGULATION_DESIGN.md +0 -433
- package/src/core/geom/3d/atlas/ATLAS_PORT_PLAN.md +0 -486
- package/src/core/geom/3d/atlas/BFF_PLAN.md +0 -174
- package/src/core/geom/3d/atlas/REVIEW_02.md +0 -392
- package/src/core/geom/3d/gjk/GJK_REVIEW_NOTES.md +0 -146
- package/src/core/geom/3d/gjk/NOTES.md +0 -8
- package/src/core/geom/3d/topology/TOPO_MESH_RETIREMENT_PLAN.md +0 -135
- package/src/core/geom/GEOMETRY_REVIEW_002_API_ISSUES.md +0 -381
- package/src/core/geom/GEOMETRY_REVIEW_002_NAMING.md +0 -684
- package/src/core/geom/MANIFOLD_COMPARISON_2026_08_01.md +0 -554
- package/src/core/model/reactive/evaluation/PREDICATE_APPLICABILITY_PROPOSAL.md +0 -446
- package/src/engine/REVIEW_2026_07_03.md +0 -211
- package/src/engine/asset/loaders/image/IMAGE_CODEC_REVIEW_2026_08_28.md +0 -815
- package/src/engine/control/first-person/DESIGN.md +0 -658
- package/src/engine/control/first-person/DESIGN_COLLISION.md +0 -382
- package/src/engine/control/first-person/DESIGN_EXTENSIONS.md +0 -563
- package/src/engine/control/first-person/TODO.md +0 -160
- package/src/engine/ecs/ASYNC_SYSTEMS_PROPOSAL.md +0 -531
- package/src/engine/ecs/HIERARCHY_REVIEW.md +0 -717
- package/src/engine/ecs/async/WORKER_SYSTEM_PLAN.md +0 -262
- package/src/engine/ecs/ik/PLAN.md +0 -179
- package/src/engine/ecs/storage/binary/SERIALIZATION_COVERAGE.md +0 -272
- package/src/engine/ecs/storage/binary/object-v2/DESIGN.md +0 -199
- package/src/engine/ecs/transform/TRANSFORM64_MIGRATION_PLAN_2026_09_04.md +0 -521
- package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +0 -463
- package/src/engine/graphics/ecs/camera/pp/NOTES.md +0 -48
- package/src/engine/graphics/render/frame_graph/CORRECTNESS_FIXES_2026_09_04.md +0 -659
- package/src/engine/graphics/render/frame_graph/FRAME_GRAPH_RECOMMENDATIONS.md +0 -235
- package/src/engine/graphics/sh3/path_tracer/REVIEW_001_ACTION_PLAN.md +0 -490
- package/src/engine/graphics/texture/sampler/compare/FLIP_IMPLEMENTATION_PLAN.md +0 -466
- package/src/engine/input/GAMEPAD_API_PROPOSAL.md +0 -717
- package/src/engine/input/ecs/ism/ISM_DESIGN.md +0 -1523
- package/src/engine/input/ecs/ism/ISM_IMPLEMENTATION_PLAN.md +0 -627
- package/src/engine/navigation/mesh/OVERLAPPING_SURFACES_2026_08_25.md +0 -661
- package/src/engine/navigation/mesh/PATHFINDING_PLAN.md +0 -229
- package/src/engine/network/CONGESTION_CONTROL.md +0 -87
- package/src/engine/network/MESSAGE_TRANSPORT.md +0 -364
- package/src/engine/network/SMOOTHNESS_DESIGN.md +0 -400
- package/src/engine/physics/cloth/MEASUREMENTS.md +0 -5304
- package/src/engine/physics/cloth/PLAN.md +0 -3056
- package/src/engine/physics/fluid/GPU_FLUID_CASCADES_PROPOSAL_2026_10_16.md +0 -1382
- package/src/engine/physics/fluid/REVIEW_02_PLAN.md +0 -243
- package/src/engine/physics/fluid/solver/NOTES.md +0 -46
- package/src/engine/sound/SOUND_EMITTER_RETIREMENT_PLAN.md +0 -536
- package/src/engine/sound/simulation/IMPLEMENTATION_PLAN.md +0 -432
- package/src/engine/sound/simulation/PROBE_PLACEMENT.md +0 -250
- package/src/engine/sound/simulation/PROBE_TRANSFER_RESEARCH.md +0 -322
- package/src/engine/sound/simulation/REFLECTION_IR_PLAN.md +0 -261
- package/src/engine/sound/simulation/VISIBILITY_GRAPH_PLAN.md +0 -121
- package/src/engine/sound/sopra/IMPLEMENTATION_PLAN.md +0 -999
- package/src/format/image/avif/DECISIONS.md +0 -545
- package/src/format/image/jpeg/NOTES.md +0 -3
- package/src/format/scene/gltf/MESHOPT_COMPRESSION_PLAN.md +0 -814
- package/src/generation/COORDINATES.md +0 -54
- package/src/generation/REVIEW_01_ACTION_PLAN.md +0 -628
- package/src/generation/foliage/ANNUAL_SHOOTS_BRIEF_2026_10_25.md +0 -220
- package/src/generation/foliage/CROWN_FILLING_BRIEF_2026_10_26.md +0 -172
- package/src/generation/foliage/CROWN_FULLNESS_BRIEF_2026_10_26.md +0 -86
- package/src/generation/foliage/FOLIAGE_DESIGN.md +0 -547
- package/src/generation/foliage/FOLIAGE_PLAN.md +0 -198
- package/src/generation/foliage/LEAF_ARCHITECTURE_BRIEF_2026_10_26.md +0 -158
- package/src/generation/foliage/LOD_REWORK_BRIEF_2026_10_27.md +0 -521
- package/src/generation/foliage/REAL_TIME_TREES_BRIEF_2026_10_27.md +0 -86
- package/src/generation/foliage/SELF_ORGANIZING_FRAMEWORK_BRIEF_2026_10_26.md +0 -347
- package/src/generation/foliage/SHOOT_SYSTEMS_ALL_SPECIES_BRIEF_2026_10_26.md +0 -248
- package/src/generation/foliage/SPEEDTREE_COMPARISON_2026_10_24.md +0 -694
- package/src/generation/foliage/TWO_FRONT_ENDS_BRIEF_2026_10_28.md +0 -552
- package/src/shade/RENDERER_CONTRACT.md +0 -697
- package/src/shade/SHADER_F16_PROPOSAL_2026_10_24.md +0 -263
- package/src/shade/device/IMMEDIATE_DATA_PLAN_2026_08_28.md +0 -569
- package/src/shade/device/PASS_ENCODER_PROPOSAL_2026_08_31.md +0 -755
- package/src/shade/device/mock/EXTENSION_PROPOSAL_2026_08_22.md +0 -458
- package/src/shade/device/mock/IMPLEMENTATION_PLAN.md +0 -255
- package/src/shade/device/mock/REVIEW_2026_08_22.md +0 -527
- package/src/shade/device/timing/GPU_PROFILER_PROPOSAL_2026_08_28.md +0 -894
- package/src/shade/device/timing/profile/SGPT_FORMAT.md +0 -345
- package/src/shade/renderer/NOTES.md +0 -78
- package/src/shade/renderer/PLAN.md +0 -8
- package/src/shade/renderer/animation/ADDITIVE_BLENDING_PLAN.md +0 -145
- package/src/shade/renderer/animation/SKINNING_FRAME_PLAN.md +0 -357
- package/src/shade/renderer/atmosphere/NOTES.md +0 -6
- package/src/shade/renderer/camera/orbital/MomentumAxis.d.ts +0 -76
- package/src/shade/renderer/camera/orbital/MomentumAxis.d.ts.map +0 -1
- package/src/shade/renderer/camera/orbital/MomentumAxis.js +0 -164
- package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.d.ts +0 -45
- package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.d.ts.map +0 -1
- package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.js +0 -66
- package/src/shade/renderer/camera/orbital/OrbitalCameraInput.d.ts +0 -98
- package/src/shade/renderer/camera/orbital/OrbitalCameraInput.d.ts.map +0 -1
- package/src/shade/renderer/camera/orbital/OrbitalCameraInput.js +0 -184
- package/src/shade/renderer/camera/orbital/OrbitalCameraRig.d.ts +0 -175
- package/src/shade/renderer/camera/orbital/OrbitalCameraRig.d.ts.map +0 -1
- package/src/shade/renderer/camera/orbital/OrbitalCameraRig.js +0 -411
- package/src/shade/renderer/camera/orbital/README.md +0 -81
- package/src/shade/renderer/camera/orbital/index.d.ts +0 -6
- package/src/shade/renderer/camera/orbital/index.d.ts.map +0 -1
- package/src/shade/renderer/camera/orbital/index.js +0 -9
- package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +0 -964
- package/src/shade/renderer/fluid/GPU_FLUID_OCCUPANCY_AND_SOTA_REVIEW_2026_10_26.md +0 -361
- package/src/shade/renderer/geometry/bvh/BLAS_REFIT_BATCH_PLAN.md +0 -619
- package/src/shade/renderer/geometry/meshlet/COMPACTION_PLAN_2026_09_16.md +0 -674
- package/src/shade/renderer/geometry/sdf/NOTES.md +0 -6
- package/src/shade/renderer/geometry/virtual/ATTRIBUTE_PLAN_2026_09_18.md +0 -540
- package/src/shade/renderer/geometry/virtual/MICRON_COMPARISON_2026_08_20.md +0 -305
- package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +0 -913
- package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +0 -787
- package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +0 -481
- package/src/shade/renderer/geometry/virtual/VK_LOD_CLUSTERS_COMPARISON_2026_08_20.md +0 -301
- package/src/shade/renderer/geometry/virtual/WEDGE_PLAN_2026_09_18.md +0 -448
- package/src/shade/renderer/geometry/virtual/runtime/CULL_PLAN_2026_09_16.md +0 -385
- package/src/shade/renderer/geometry/virtual/runtime/CUT_PLAN_2026_09_14.md +0 -656
- package/src/shade/renderer/geometry/virtual/runtime/REVIEW_LEDGER.md +0 -308
- package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN.md +0 -657
- package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN_2026_09_14.md +0 -551
- package/src/shade/renderer/geometry/virtual/runtime/SHADOW_PLAN_2026_09_28.md +0 -529
- package/src/shade/renderer/global_illumination/lpv/NOTES.md +0 -3
- package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_CLIPMAP_PROPOSAL_2026_10_27.md +0 -4306
- package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_RAYS_VARIABLE_AND_SORTED_SCOPE_2026_10_30.md +0 -410
- package/src/shade/renderer/global_illumination/sharc/NOTES.md +0 -8
- package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +0 -1369
- package/src/shade/renderer/gpu_primitive/bvh/PHASE1_HANDOVER.md +0 -202
- package/src/shade/renderer/gpu_primitive/indirect/NOTES.md +0 -94
- package/src/shade/renderer/hiz/NOTES.md +0 -3
- package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts +0 -8
- package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts.map +0 -1
- package/src/shade/renderer/light/cluster/NOTES.md +0 -11
- package/src/shade/renderer/light/cluster/PROPOSAL_ALGORITHM_2026_10_16.md +0 -524
- package/src/shade/renderer/light/cluster/PROPOSAL_HIERARCHICAL_2026_10_16.md +0 -1101
- package/src/shade/renderer/material/resident/shader_resident_texture_means.d.ts +0 -24
- package/src/shade/renderer/material/resident/shader_resident_texture_means.d.ts.map +0 -1
- package/src/shade/renderer/material/resident/shader_resident_texture_means.js +0 -120
- package/src/shade/renderer/particles/DESIGN.md +0 -1011
- package/src/shade/renderer/particles/EMITTER_GLOBAL_STATE_PLAN_2026_10_29.md +0 -280
- package/src/shade/renderer/particles/ORIENTATION_PLAN_2026_10_15.md +0 -453
- package/src/shade/renderer/path_tracer/PATH_TRACED_MEDIA_PLAN_2026_10_02.md +0 -520
- package/src/shade/renderer/postprocess/bloom/NOTES.md +0 -6
- package/src/shade/renderer/postprocess/fsr/NOTES.md +0 -4
- package/src/shade/renderer/postprocess/gtao/NOTES.md +0 -6
- package/src/shade/renderer/postprocess/nss/NOTES.md +0 -332
- package/src/shade/renderer/postprocess/perspective/NOTES.md +0 -3
- package/src/shade/renderer/postprocess/sscs/NOTES.md +0 -5
- package/src/shade/renderer/postprocess/ssr/NOTES.md +0 -14
- package/src/shade/renderer/postprocess/ssr/REPROJECTION_PROPOSAL.md +0 -286
- package/src/shade/renderer/postprocess/ssr/prefilter/NOTES.md +0 -39
- package/src/shade/renderer/postprocess/taa/NOTES.md +0 -11
- package/src/shade/renderer/postprocess/upscale-dither/NOTES.md +0 -78
- package/src/shade/renderer/postprocess/vrs/NOTES.md +0 -4
- package/src/shade/renderer/rasterize/native/avboit/AVBOIT_LEDGER.md +0 -1218
- package/src/shade/renderer/rasterize/native/avboit/AVBOIT_PLAN_2026_09_03.md +0 -600
- package/src/shade/renderer/restir/reservoir/NOTES.md +0 -6
- package/src/shade/renderer/shader/chunk/atmosphere/NOTES.md +0 -6
- package/src/shade/renderer/shader/chunk/brdf/FRESNEL_BRIEF_2026_10_16.md +0 -391
- package/src/shade/renderer/shader/chunk/color/tonemap/ACES_TONE_MAPPING_BRIEF_2026_10_17.md +0 -153
- package/src/shade/renderer/shader/chunk/color/tonemap/HDR_TONE_MAPPING_FORMS_BRIEF_2026_10_16.md +0 -322
- package/src/shade/renderer/shader/chunk/color/tonemap/SDR_TONE_MAPPING_BRIEF_2026_10_16.md +0 -247
- package/src/shade/renderer/shader/chunk/fsr/NOTES.md +0 -3
- package/src/shade/renderer/shader/chunk/fsr/spd/NOTES.md +0 -4
- package/src/shade/renderer/shader/chunk/geometry/ray/NOTES.md +0 -4
- package/src/shade/renderer/shader/chunk/material/MULTISCATTER.md +0 -159
- package/src/shade/renderer/shader/chunk/mboit/NOTES.md +0 -38
- package/src/shade/renderer/shader/chunk/spherical_harmonics/l1i/NOTES.md +0 -3
- package/src/shade/renderer/shader/chunk/spherical_harmonics/sampling/NOTES.md +0 -8
- package/src/shade/renderer/shader/compiler/SHADER_SWITCH_PROPOSAL_2026_10_16.md +0 -927
- package/src/shade/renderer/shadow/contact/FINDINGS.md +0 -413
- package/src/shade/renderer/shadow/map/csm/NOTES.md +0 -5
- package/src/shade/renderer/shadow/ray/NOTES.md +0 -31
- package/src/shade/renderer/shadow/sdf/NOTES.md +0 -9
- package/src/shade/renderer/shadow/sdf/brixelizer/NOTES.md +0 -5
- package/src/shade/renderer/shadow/sdf/cascade/NOTES.md +0 -9
- package/src/shade/renderer/shadow/vsm/NOTES.md +0 -12
- package/src/shade/renderer/shadow/vsm/PLAN.md +0 -442
- package/src/shade/renderer/shadow/vsm/REVIEW_LEDGER.md +0 -43
- package/src/shade/renderer/texture/COMPRESSED_TEXTURE_PLAN_2026_09_01.md +0 -2444
- package/src/shade/renderer/texture/mipmaps/NOTES.md +0 -3
- package/src/shade/renderer/volumetrics/NOTES.md +0 -1329
- package/src/shade/renderer/volumetrics/VOLUMETRIC_NOISE_PLAN_2026_10_15.md +0 -336
- package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts +0 -23
- package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts.map +0 -1
- package/src/shade/renderer/water/medium/GPUWaterBodies.js +0 -75
- package/src/shade/wgsl/NOTES.md +0 -4
|
@@ -1,345 +0,0 @@
|
|
|
1
|
-
# The `.sgpt` container — format specification
|
|
2
|
-
|
|
3
|
-
**S**hade **G**PU **P**rofile **T**race, format version 2.
|
|
4
|
-
|
|
5
|
-
This document is the normative description of the file. It is written for somebody outside Company
|
|
6
|
-
Named who wants to read or write one without reading the engine's source. Every integer is
|
|
7
|
-
little-endian and unsigned unless stated otherwise.
|
|
8
|
-
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
## 1. What the format is for, and what it is not
|
|
12
|
-
|
|
13
|
-
A capture holds **what a renderer asked a GPU to do over a run of frames, and how long each piece
|
|
14
|
-
took**: pass timings, the frame graph's structure and dependencies, declared resource sizes, and
|
|
15
|
-
dispatch and draw counts.
|
|
16
|
-
|
|
17
|
-
It deliberately does **not** hold buffer or texture contents, shader source, or anything else that
|
|
18
|
-
scales with the size of the resources it describes. That exclusion is what keeps a frame record in
|
|
19
|
-
the kilobytes and makes an uncapped recording practical.
|
|
20
|
-
|
|
21
|
-
### 1.1 Two properties the layout exists to provide
|
|
22
|
-
|
|
23
|
-
**A truncated capture is a capture.** A recording that ended when the tab did — which is the state
|
|
24
|
-
of every capture of a crash, a device loss, or a hang — must be readable up to the last intact
|
|
25
|
-
record. So every record is self-framed and checksummed, symbols travel inside the record that
|
|
26
|
-
introduces them, and the directory is an index over the stream rather than a prerequisite for
|
|
27
|
-
reading it.
|
|
28
|
-
|
|
29
|
-
**A reader may not understand everything, and must say so rather than fail.** Records carry a type
|
|
30
|
-
and a length; an unrecognised type is skipped by length. This is what lets a newer writer add record
|
|
31
|
-
types without a version bump, and what lets an older reader open the result and report honestly
|
|
32
|
-
which parts it could not show.
|
|
33
|
-
|
|
34
|
-
---
|
|
35
|
-
|
|
36
|
-
## 2. File header
|
|
37
|
-
|
|
38
|
-
Thirty-two bytes at offset 0.
|
|
39
|
-
|
|
40
|
-
| Offset | Size | Field | Notes |
|
|
41
|
-
|---|---|---|---|
|
|
42
|
-
| 0 | 4 | `magic` | `0x54504753` — the ASCII bytes `S`, `G`, `P`, `T` in that order |
|
|
43
|
-
| 4 | 2 | `format_version` | 2 for this document |
|
|
44
|
-
| 6 | 2 | `min_reader_version` | the oldest reader that can read this file correctly |
|
|
45
|
-
| 8 | 4 | `flags` | see below |
|
|
46
|
-
| 12 | 4 | `header_checksum` | CRC-32 over bytes `[0, 8)` **only** |
|
|
47
|
-
| 16 | 8 | `directory_offset` | absolute; **0 when there is no directory** |
|
|
48
|
-
| 24 | 8 | `directory_byte_length` | 0 when absent |
|
|
49
|
-
|
|
50
|
-
Records begin at offset 32.
|
|
51
|
-
|
|
52
|
-
### 2.1 Flags
|
|
53
|
-
|
|
54
|
-
| Bit | Name | Meaning |
|
|
55
|
-
|---|---|---|
|
|
56
|
-
| 0 | `CLOSED` | the writer reached `stop()` and the file is complete as intended |
|
|
57
|
-
|
|
58
|
-
### 2.2 Why the checksum stops at byte 8
|
|
59
|
-
|
|
60
|
-
Everything from `flags` onward is written twice: zeroed when the header is laid down, and patched
|
|
61
|
-
when the session stops. A checksum covering those fields would have to be recomputed at stop — fine
|
|
62
|
-
for a capture that stops, and exactly wrong for one that does not, which would then carry a checksum
|
|
63
|
-
over bytes that were never written and read as corrupt.
|
|
64
|
-
|
|
65
|
-
What remains under the checksum is what a reader must trust before it can do anything at all: *is
|
|
66
|
-
this an `.sgpt`, and can this build read it.* Those never change after the header is written.
|
|
67
|
-
|
|
68
|
-
**A reader must not treat a missing `CLOSED` flag or a zero `directory_offset` as damage.** Both are
|
|
69
|
-
the normal state of an interrupted session, and such a file is fully readable by §3.
|
|
70
|
-
|
|
71
|
-
### 2.3 Version handling
|
|
72
|
-
|
|
73
|
-
A reader **must** refuse a file whose `min_reader_version` exceeds the highest format version it
|
|
74
|
-
implements, and **must** accept anything else. `min_reader_version` is raised only when a change
|
|
75
|
-
would make an older reader produce *wrong* answers rather than incomplete ones — a new record type
|
|
76
|
-
it would skip is incomplete; a reordered field is wrong.
|
|
77
|
-
|
|
78
|
-
Format version 2 keeps `min_reader_version` at 1: it added the `TOPO` record, which a version-1
|
|
79
|
-
reader skips by length, and appended a topology reference to the end of a frame's payload, which a
|
|
80
|
-
version-1 reader stops before.
|
|
81
|
-
|
|
82
|
-
---
|
|
83
|
-
|
|
84
|
-
## 3. Records
|
|
85
|
-
|
|
86
|
-
Every record, whatever its type, is framed identically.
|
|
87
|
-
|
|
88
|
-
| Offset | Size | Field |
|
|
89
|
-
|---|---|---|
|
|
90
|
-
| 0 | 4 | `sync` — `0x43455253`, the ASCII bytes `S`, `R`, `E`, `C` |
|
|
91
|
-
| 4 | 4 | `record_type` — a four-character tag as a u32 |
|
|
92
|
-
| 8 | 4 | `payload_byte_length` |
|
|
93
|
-
| 12 | 4 | `payload_checksum` — CRC-32 over the payload bytes only |
|
|
94
|
-
| 16 | … | payload |
|
|
95
|
-
|
|
96
|
-
`payload_byte_length` is a u32 rather than a u64 because no record describes anything that scales
|
|
97
|
-
with resource size (§1); four gigabytes is not a ceiling anything can approach.
|
|
98
|
-
|
|
99
|
-
### 3.1 Reading, and resynchronising
|
|
100
|
-
|
|
101
|
-
The canonical read is a **forward scan from offset 32**, not a walk of the directory:
|
|
102
|
-
|
|
103
|
-
1. At the current offset, a record is present if — and only if — all four hold: the sync marker
|
|
104
|
-
matches, at least 16 bytes remain, the payload fits within the file, and the payload's CRC-32
|
|
105
|
-
matches `payload_checksum`.
|
|
106
|
-
2. If it does, decode or skip it by type and advance past its payload.
|
|
107
|
-
3. If it does not, scan forward one byte at a time for the next offset where all four hold. Report
|
|
108
|
-
the skipped bytes as damage; do not stop.
|
|
109
|
-
4. If the scan reaches the end without finding another record, the stream was truncated inside a
|
|
110
|
-
record. Report it. Everything already decoded stands.
|
|
111
|
-
|
|
112
|
-
**The sync marker alone is not sufficient and a reader must not treat it as such.** Four bytes of
|
|
113
|
-
payload can spell `SREC` — a pass label could — and resynchronising onto a false positive
|
|
114
|
-
desynchronises everything after it. The length and the checksum are what confirm a candidate.
|
|
115
|
-
|
|
116
|
-
### 3.2 Record types
|
|
117
|
-
|
|
118
|
-
| Tag | u32 | Payload | Cardinality |
|
|
119
|
-
|---|---|---|---|
|
|
120
|
-
| `META` | `0x4154454D` | §4 | 1, immediately after the header |
|
|
121
|
-
| `SYMS` | `0x534D5953` | §5 | 0..n, always before the records referencing them |
|
|
122
|
-
| `TOPO` | `0x4F504F54` | §6 | 0..n |
|
|
123
|
-
| `FRAM` | `0x4D415246` | §7 | 0..n |
|
|
124
|
-
| `CNTR` | `0x52544E43` | reserved | 0..1 |
|
|
125
|
-
| `DIRE` | `0x45524944` | §8 | 0..1, last |
|
|
126
|
-
|
|
127
|
-
An unrecognised tag **must** be skipped using `payload_byte_length`.
|
|
128
|
-
|
|
129
|
-
### 3.3 Primitive encodings
|
|
130
|
-
|
|
131
|
-
- `uintVar` — 7 bits per byte, low group first, high bit set on every byte but the last. Values are
|
|
132
|
-
limited to 2³¹−1.
|
|
133
|
-
- `utf8` — a `uintVar` byte length followed by that many UTF-8 bytes.
|
|
134
|
-
- `f64` — IEEE 754 binary64, little-endian.
|
|
135
|
-
- **Optional index** — a value of −1 meaning "none", written as `uintVar(value + 1)`. Zero means
|
|
136
|
-
none.
|
|
137
|
-
|
|
138
|
-
---
|
|
139
|
-
|
|
140
|
-
## 4. `META`
|
|
141
|
-
|
|
142
|
-
| Field | Type | Notes |
|
|
143
|
-
|---|---|---|
|
|
144
|
-
| `level` | u8 | 0 `TIMING`, 1 `STRUCTURE`, 2 `WORKLOAD`, 3 `VERBOSE` |
|
|
145
|
-
| `wall_clock_start_ms` | f64 | `Date.now()` at session start; for ordering captures, not for timing |
|
|
146
|
-
| `note` | utf8 | free text from whoever captured |
|
|
147
|
-
| `engine_version` | utf8 | |
|
|
148
|
-
| `adapter_vendor` | utf8 | from `GPUAdapterInfo`; empty where the browser withheld it |
|
|
149
|
-
| `adapter_architecture` | utf8 | |
|
|
150
|
-
| `adapter_device` | utf8 | |
|
|
151
|
-
| `adapter_description` | utf8 | |
|
|
152
|
-
| `feature_count` | uintVar | |
|
|
153
|
-
| `features` | utf8 × count | `GPUFeatureName`s the device was created with |
|
|
154
|
-
|
|
155
|
-
### 4.1 On timestamp resolution — a deliberate absence
|
|
156
|
-
|
|
157
|
-
**There is no field here describing the device's timestamp quantum, and adding one is out of
|
|
158
|
-
scope.**
|
|
159
|
-
|
|
160
|
-
Browsers quantize WebGPU timestamps as a timing-attack mitigation; Chrome to 100 µs unless
|
|
161
|
-
`chrome://flags/#enable-webgpu-developer-features` is set. Most passes in a real renderer run below
|
|
162
|
-
that and are reported as exactly zero.
|
|
163
|
-
|
|
164
|
-
Recovering the quantum from the data — a GCD over observed timestamps, or any equivalent — *is* the
|
|
165
|
-
timing attack the mitigation exists to prevent, and doing it imperfectly applies a wrong correction
|
|
166
|
-
to every number in the file. So a capture records what the device reported, zeros included, and says
|
|
167
|
-
nothing further. A reader that wants to present this honestly should aggregate across many frames
|
|
168
|
-
rather than trust any single one, and should say so where the reader will see it.
|
|
169
|
-
|
|
170
|
-
---
|
|
171
|
-
|
|
172
|
-
## 5. `SYMS`
|
|
173
|
-
|
|
174
|
-
| Field | Type |
|
|
175
|
-
|---|---|
|
|
176
|
-
| `first_index` | uintVar |
|
|
177
|
-
| `count` | uintVar |
|
|
178
|
-
| `strings` | utf8 × count |
|
|
179
|
-
|
|
180
|
-
Strings occupy one index space across the whole file; a block declares where its run begins. Every
|
|
181
|
-
later reference is a `uintVar` index into that space.
|
|
182
|
-
|
|
183
|
-
A `SYMS` block **always precedes** the record that references its strings. A writer must not gather
|
|
184
|
-
symbols into one block at the end of the file: a capture truncated before that block would resolve
|
|
185
|
-
no names at all, which is precisely the capture of the crash somebody was trying to record.
|
|
186
|
-
|
|
187
|
-
---
|
|
188
|
-
|
|
189
|
-
## 6. `TOPO` — frame graph structure
|
|
190
|
-
|
|
191
|
-
Present at capture level `STRUCTURE` and above.
|
|
192
|
-
|
|
193
|
-
| Field | Type |
|
|
194
|
-
|---|---|
|
|
195
|
-
| `id` | uintVar — what a frame refers to |
|
|
196
|
-
| `name` | symbol index |
|
|
197
|
-
| `scope_count` | uintVar |
|
|
198
|
-
| **per scope** | `name` (symbol index), `parent` (optional index) |
|
|
199
|
-
| `pass_count` | uintVar |
|
|
200
|
-
| **per pass** | see §6.1 |
|
|
201
|
-
| `resource_count` | uintVar |
|
|
202
|
-
| **per resource** | see §6.2 |
|
|
203
|
-
|
|
204
|
-
A scope's parent always appears at a lower index than the scope itself, so a reader resolves the
|
|
205
|
-
chain in one forward pass.
|
|
206
|
-
|
|
207
|
-
### 6.1 Pass
|
|
208
|
-
|
|
209
|
-
| Field | Type |
|
|
210
|
-
|---|---|
|
|
211
|
-
| `id` | uintVar |
|
|
212
|
-
| `name` | symbol index |
|
|
213
|
-
| `scope` | optional index |
|
|
214
|
-
| `flags` | u8 — bit 0 `CULLED`, bit 1 `HAS_SIDE_EFFECTS` |
|
|
215
|
-
| `ref_count` | uintVar |
|
|
216
|
-
| `reads` | uintVar count, then that many resource **node** ids |
|
|
217
|
-
| `writes` | same |
|
|
218
|
-
| `creates` | same |
|
|
219
|
-
|
|
220
|
-
### 6.2 Resource
|
|
221
|
-
|
|
222
|
-
One entry per resource **node** — that is, per version. A pass records the node it touched rather
|
|
223
|
-
than the underlying resource, so a registry-keyed model would leave every reference past version 0
|
|
224
|
-
dangling.
|
|
225
|
-
|
|
226
|
-
| Field | Type |
|
|
227
|
-
|---|---|
|
|
228
|
-
| `id` | uintVar |
|
|
229
|
-
| `name` | symbol index |
|
|
230
|
-
| `version` | uintVar |
|
|
231
|
-
| `flags` | u8 — bit 2 `TRANSIENT`, bit 3 `IMPORTED` |
|
|
232
|
-
| `producer` | optional index — the pass that produced this version |
|
|
233
|
-
| `kind` | u8 — 0 none, 1 buffer, 2 texture |
|
|
234
|
-
| `usage` | uintVar — `GPUBufferUsage` / `GPUTextureUsage` bitmask |
|
|
235
|
-
| `byte_size` | uintVar — declared bytes, §6.3 |
|
|
236
|
-
| **if buffer** | `size` (uintVar) |
|
|
237
|
-
| **if texture** | `width`, `height`, `depth`, `mip_level_count`, `sample_count` (uintVar each), `format`, `dimension` (symbol indices) |
|
|
238
|
-
|
|
239
|
-
### 6.3 `byte_size` is declared, and is computed by the writer
|
|
240
|
-
|
|
241
|
-
Declared, not allocated: a pooled allocator may serve a larger block, and an aliasing one may serve
|
|
242
|
-
the same block to two resources whose lifetimes do not overlap.
|
|
243
|
-
|
|
244
|
-
For a texture it covers the whole mip chain at the given sample count. **The writer computes it**
|
|
245
|
-
rather than leaving a reader to, because working it out needs the format's block dimensions — so a
|
|
246
|
-
reader never has to carry a copy of that table, and a format the reader has never heard of still
|
|
247
|
-
reports a size. A writer that cannot determine a size **must** write 0.
|
|
248
|
-
|
|
249
|
-
---
|
|
250
|
-
|
|
251
|
-
## 7. `FRAM` — one frame
|
|
252
|
-
|
|
253
|
-
| Field | Type |
|
|
254
|
-
|---|---|
|
|
255
|
-
| `frame_index` | uintVar — the renderer's own counter, not a position in the file |
|
|
256
|
-
| `cpu_begin_ms` | f64 — `performance.now()` when encoding began |
|
|
257
|
-
| `cpu_submit_ms` | f64 — `performance.now()` at submit |
|
|
258
|
-
| `gpu_epoch_ns` | u64 — the earliest GPU timestamp in this frame |
|
|
259
|
-
| `dropped_pass_count` | uintVar — passes that went untimed, §7.2 |
|
|
260
|
-
| `span_count` | uintVar |
|
|
261
|
-
| **per span** | §7.1 |
|
|
262
|
-
| `topology_id` | optional index — **appended last**, absent in a format-1 file |
|
|
263
|
-
|
|
264
|
-
### 7.1 Span
|
|
265
|
-
|
|
266
|
-
| Field | Type |
|
|
267
|
-
|---|---|
|
|
268
|
-
| `label` | symbol index |
|
|
269
|
-
| `kind` | u8 — 0 compute, 1 render |
|
|
270
|
-
| `query_set_id` | u8 — §7.3 |
|
|
271
|
-
| `t_begin_ns` | u32 — nanoseconds from `gpu_epoch_ns` |
|
|
272
|
-
| `duration_ns` | uintVar |
|
|
273
|
-
| `graph_pass_id` | optional index — the frame graph pass that was executing when this pass opened |
|
|
274
|
-
| `has_work` | u8 — 1 if a workload block follows |
|
|
275
|
-
| **if `has_work`** | `dispatch_count`, `indirect_dispatch_count`, `workgroups_x/y/z`, `draw_count`, `indirect_draw_count`, `vertex_count`, `index_count`, `instance_count` (uintVar each), `pipeline` (symbol index), `workgroup_size_x/y/z` (uintVar each) |
|
|
276
|
-
|
|
277
|
-
`t_begin_ns` is a u32 of nanoseconds, holding 4.29 s — three orders of magnitude past any frame, and
|
|
278
|
-
enough to survive a stall rather than wrap. A writer **must** clamp rather than wrap, and **must**
|
|
279
|
-
write a duration of 0 where a device reports an end before its begin.
|
|
280
|
-
|
|
281
|
-
`has_work` is per span rather than per frame because a frame genuinely mixes the two: a pass opened
|
|
282
|
-
before the recorder was attached has no workload record, and a per-frame flag would have to lie
|
|
283
|
-
about one of them.
|
|
284
|
-
|
|
285
|
-
A `workgroup_size` of `[0, 0, 0]` means **unknown** — typically an override-expression size — and is
|
|
286
|
-
not the same as zero work. A reader must not compute an invocation count from it.
|
|
287
|
-
|
|
288
|
-
### 7.2 `dropped_pass_count`
|
|
289
|
-
|
|
290
|
-
Passes the recorder could not time because the frame had more of them than its query set had slots.
|
|
291
|
-
Carried because an untimed pass reads downstream as a free one. A reader should surface a non-zero
|
|
292
|
-
value rather than presenting the frame as complete.
|
|
293
|
-
|
|
294
|
-
### 7.3 `query_set_id`
|
|
295
|
-
|
|
296
|
-
Which of the frame's command contexts produced this span. Timestamps from two different
|
|
297
|
-
`GPUQuerySet`s are not specified to share a clock domain, and a frame ordinarily spans several.
|
|
298
|
-
Carried so that an anomaly following a query-set boundary is visible rather than unfalsifiable.
|
|
299
|
-
|
|
300
|
-
### 7.4 The two clocks are not one clock
|
|
301
|
-
|
|
302
|
-
`cpu_*` come from `performance.now()`; `gpu_epoch_ns` and the spans come from the device. WebGPU
|
|
303
|
-
exposes no calibration between them, and this format carries none. Anything that places the two on
|
|
304
|
-
one axis is anchoring, not synchronising, and should say so.
|
|
305
|
-
|
|
306
|
-
---
|
|
307
|
-
|
|
308
|
-
## 8. `DIRE` — directory
|
|
309
|
-
|
|
310
|
-
| Field | Type |
|
|
311
|
-
|---|---|
|
|
312
|
-
| `record_count` | uintVar |
|
|
313
|
-
| **per record** | `type` (u32), `offset` (u64), `byte_length` (u32) |
|
|
314
|
-
|
|
315
|
-
Written last, and does not index itself.
|
|
316
|
-
|
|
317
|
-
**A reader must not require it, and must not prefer it to the records.** It exists so that a future
|
|
318
|
-
reader can seek instead of scan. A capture that never reached `stop()` has none, and is not thereby
|
|
319
|
-
a lesser capture.
|
|
320
|
-
|
|
321
|
-
---
|
|
322
|
-
|
|
323
|
-
## 9. Conformance summary
|
|
324
|
-
|
|
325
|
-
A conforming **reader**:
|
|
326
|
-
|
|
327
|
-
- refuses a file whose magic does not match or whose `min_reader_version` exceeds its own;
|
|
328
|
-
- reads by scanning records, and does not require a directory or the `CLOSED` flag;
|
|
329
|
-
- validates sync, length and checksum together before accepting a record;
|
|
330
|
-
- resynchronises past damage and reports it, rather than stopping;
|
|
331
|
-
- skips unrecognised record types by length and reports that it did;
|
|
332
|
-
- treats `[0, 0, 0]` workgroup sizes and absent workload blocks as *unknown*, never as zero.
|
|
333
|
-
|
|
334
|
-
A conforming **writer**:
|
|
335
|
-
|
|
336
|
-
- emits `META` first and `DIRE` last, and patches only `flags` and the directory fields;
|
|
337
|
-
- emits a `SYMS` block before any record referencing its strings;
|
|
338
|
-
- never gathers symbols into a single trailing block;
|
|
339
|
-
- clamps rather than wraps out-of-range span times, and writes 0 for an unknown size;
|
|
340
|
-
- records what the device reported, without correcting for timestamp quantization.
|
|
341
|
-
|
|
342
|
-
---
|
|
343
|
-
|
|
344
|
-
*Company Named Limited (c) 2026. The format is documented for interoperability; the engine that
|
|
345
|
-
writes it is proprietary and source-available under its own licence.*
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
the renderer is optimized for large number of instances, and for using PBR shader (`StandardMaterial`)
|
|
2
|
-
|
|
3
|
-
## Normalized Vertex Layout
|
|
4
|
-
|
|
5
|
-
* Geometries that are used with StandardShader are expected to conform to a specific Vertex layout.
|
|
6
|
-
* Tools are to be provided to deal with relevant conversion.
|
|
7
|
-
* Conversion may be done automatically with logged messaged about such, to make the user aware of performance
|
|
8
|
-
penalty
|
|
9
|
-
* Where possible without sacrificing rendering performance - support non-normalized layouts.
|
|
10
|
-
|
|
11
|
-
## GPU-resident renderer architecture
|
|
12
|
-
|
|
13
|
-
* All geometry data (vertex+index) is written into a huge buffer and sits in GPU memory
|
|
14
|
-
* All meshes are represented by a small descriptor that resides on GPU
|
|
15
|
-
* ⚠️*[IMPOSSIBLE]* All draw is indirect draw, indirect draw batches are prepared in a compute shader
|
|
16
|
-
* __Impossible__ on WebGPU, `drawIndirect` as well as `drawIndexedIndirect` only execute 1 draw command from the buffer and not the whole buffer. As a result you're still stuck issuing commands on CPU
|
|
17
|
-
* Culling is done on GPU
|
|
18
|
-
|
|
19
|
-
### references:
|
|
20
|
-
* https://vkguide.dev/docs/gpudriven/draw_indirect/
|
|
21
|
-
* SIGGRAPH-2015 2016 GPU-Driven Rendering Pipelines
|
|
22
|
-
* Anti-Aliasing for specular highlights - really good paper https://blog.selfshadow.com/2011/07/22/specular-showdown/
|
|
23
|
-
|
|
24
|
-
### Unordered References
|
|
25
|
-
Spatio-temporal variance-guided filtering:
|
|
26
|
-
* https://research.nvidia.com/publication/2017-07_spatiotemporal-variance-guided-filtering-real-time-reconstruction-path-traced
|
|
27
|
-
* https://diharaw.github.io/post/adventures_in_hybrid_rendering/
|
|
28
|
-
* https://github.com/diharaw/hybrid-rendering
|
|
29
|
-
* https://github.com/gkjohnson/three-gpu-pathtracer/issues/292
|
|
30
|
-
|
|
31
|
-
### IDEA v2:
|
|
32
|
-
|
|
33
|
-
---
|
|
34
|
-
|
|
35
|
-
### Deferred shading
|
|
36
|
-
|
|
37
|
-
- make use of Visibility Buffer to remove material cost of overdraw and better support GPU-resident rendering (see "The Visibility Buffer: A Cache-Friendly Approach to Deferred Shading", 2013 JCGT)
|
|
38
|
-
- visibility buffer structure: DEPTH, CLUSTER_ID, TRIANGLE_ID (?)
|
|
39
|
-
|
|
40
|
-
#### Geometry Cluster
|
|
41
|
-
- collection of indices (index buffer)
|
|
42
|
-
- references vertex buffer (a geometry) by index
|
|
43
|
-
- A cluster instance also references Mesh that it was produced from
|
|
44
|
-
|
|
45
|
-
**problem**: Vertex shader doesn't allow `STORAGE` type buffers, which can have runt-time defined array length, this means that vertex shader can only accept fixed-sided data. This makes decoding of clusters inside vertex shader impossible, as we don't know ahead of time how many clusters we might have.
|
|
46
|
-
|
|
47
|
-
#### Draw algorithm
|
|
48
|
-
|
|
49
|
-
1. Cull instances, takes list of instances as input, culls against various constraints, produces another, smaller list
|
|
50
|
-
2. Prepare instances for render by breaking them up into fixed chunks of triangles (64/128), to do this:
|
|
51
|
-
1. prepare buffer with clusters
|
|
52
|
-
|
|
53
|
-
### Textures
|
|
54
|
-
|
|
55
|
-
- virtual textures?
|
|
56
|
-
- compressed textures, compression support in-engine
|
|
57
|
-
- AI texture upscaling, enlarge texture by generating in-between data using a neural network
|
|
58
|
-
- Toksvig mapping: https://blog.selfshadow.com/2011/07/22/specular-showdown/
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
### Variable Rate shading
|
|
62
|
-
- Poposal in WebGPU, not in actual standard yet as of 19/05/2024
|
|
63
|
-
- VRS is no good for deferred :(
|
|
64
|
-
- Adaptive Shading possible
|
|
65
|
-
- "Adaptive Undersampling With DACS" https://graphics.geometrian.com/research/dacs.html
|
|
66
|
-
- maybe use a similar technique to post-process by creating N number of render targets of smaller resolution and combining them in the final pass (ala checked-board pattern)
|
|
67
|
-
|
|
68
|
-
### Compute swizzling for better cache usage
|
|
69
|
-
- https://github.com/LouisBavoil/ThreadGroupIDSwizzling/blob/master/ThreadGroupTilingX.hlsl
|
|
70
|
-
- https://developer.nvidia.com/blog/optimizing-compute-shaders-for-l2-locality-using-thread-group-id-swizzling/
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
## Shadow terminator
|
|
74
|
-
* "HACKING THE SHADOW TERMINATOR" by Johannes Hanika ( https://jo.dreggn.org/home/2021_terminator.pdf )
|
|
75
|
-
|
|
76
|
-
## VRS links
|
|
77
|
-
|
|
78
|
-
* https://github.com/GameTechDev/VRS-DoF
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
* Roll back to env-map sampling until GI is ready
|
|
2
|
-
* Implement VRS for shadows
|
|
3
|
-
* see "The Rendering of The Callisto Protocol" by Jorge Jimenez, SIGGRAPH 2023
|
|
4
|
-
* see AMD VRS
|
|
5
|
-
sample: https://github.com/GPUOpen-LibrariesAndSDKs/FidelityFX-SDK/blob/main/sdk/include/FidelityFX/gpu/vrs/ffx_variable_shading.h
|
|
6
|
-
* Clustered lighting
|
|
7
|
-
* Alpha-tested materials ( consider using VT for alpha(?) and as a substitute for bindless in general )
|
|
8
|
-
* TAA at grazing angles messes up textures, need to UNDO jitter during texture sampling
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
# Unified Rest-Anchored Delta Animation Blending
|
|
2
|
-
|
|
3
|
-
**Status:** Approved & Implemented (Zero Runtime Switches / Enums)
|
|
4
|
-
|
|
5
|
-
## 1. Core Insight: Why Bone Masks, Override Layers, and Runtime Blend Enums Are Not Needed
|
|
6
|
-
|
|
7
|
-
In traditional engines where animations are dense full-skeleton arrays, combining a lower-body
|
|
8
|
-
animation with an upper-body or additive animation requires runtime **bone masks**, an explicit
|
|
9
|
-
**override layer mode**, and a runtime **additive vs. absolute clip switch**.
|
|
10
|
-
|
|
11
|
-
`meep-engine` needs none of these:
|
|
12
|
-
1. **`ShadeAnimationClip` is already sparse per-node and per-axis.** A clip's `channels` array only
|
|
13
|
-
contains entries for the specific entities (joints) and axes it keys. An upper-body clip with
|
|
14
|
-
only upper-body channels leaves every lower-body joint untouched. Any per-bone feathering (e.g.
|
|
15
|
-
`Spine_01` moving 30% as much as `Spine_03`) is naturally authored into the keyframe curves.
|
|
16
|
-
2. **Every clip in the runtime is evaluated as a weighted delta from the target joint's Rest Pose
|
|
17
|
-
($V_{\text{rest}}$).**
|
|
18
|
-
Instead of accumulating raw $w_i \cdot V_i(t)$ into a zero-based slot (which collapses
|
|
19
|
-
translation and scale toward zero whenever $\sum w_i < 1$, and ignores partial weights on single
|
|
20
|
-
rotation clips), the apply pass accumulates weighted **deltas from rest**
|
|
21
|
-
$w_i \cdot (V_i(t) - V_{\text{rest}})$ and the resolve pass adds the accumulated delta back onto
|
|
22
|
-
$V_{\text{rest}}$:
|
|
23
|
-
$$V_{\text{final}} = V_{\text{rest}} + \sum_i w_i \cdot \bigl(V_i(t) - V_{\text{rest}}\bigr)$$
|
|
24
|
-
(with $R_{\text{final}} = \text{normalize}(R_{\text{rest}} + \sum_i w_i \cdot (R_i(t) - R_{\text{rest}}))$ for rotation).
|
|
25
|
-
|
|
26
|
-
---
|
|
27
|
-
|
|
28
|
-
## 2. Adversarial Pass on the Zero-Runtime-Switch Design
|
|
29
|
-
|
|
30
|
-
### 2.1. Why Naive "Import-Only Zero-Centered Deltas" Fail on a Zero-Based Accumulator
|
|
31
|
-
Suppose we kept the old zero-based accumulator ($V_{\text{final}} = \sum_i w_i V_i(t)$) and tried to
|
|
32
|
-
bake additive clips at import time as raw zero-centered deltas $\Delta V(t) = V(t) - V_{\text{ref}}$:
|
|
33
|
-
- **Failure 1 (Unkeyed Base Channels / `clip.optimize`):** `load_gltf` calls `clip.optimize(rest)`,
|
|
34
|
-
stripping un-animated channels. In `Michelle.glb`, `SambaDancing` only keys `Translation` on 1 of
|
|
35
|
-
65 bones (`Hips`) and `Rotation` on 52 of 65 bones. If an additive clip keys a bone or axis that
|
|
36
|
-
the base clip does *not* key, the zero-based accumulator receives only $0 + w_{\text{add}} \Delta T$,
|
|
37
|
-
**wiping out the bone's rest translation and scale to zero**.
|
|
38
|
-
- **Failure 2 (Rotation Collapse on Unkeyed Base Bones):** On a bone whose rotation is not keyed by
|
|
39
|
-
the active base clip, a zero-centered quaternion difference $\Delta R = R(t) - R_{\text{ref}}$ has
|
|
40
|
-
$w \approx 0$ for small angles. Normalizing $0 + w_{\text{add}} \Delta R$ without $R_{\text{rest}}$
|
|
41
|
-
normalizes a pure-imaginary chordal vector, **snapping the bone by $90^\circ$**.
|
|
42
|
-
- **Failure 3 (Single Partial-Weight Clip):** On a zero-based accumulator, a single clip fading in
|
|
43
|
-
with weight $w \in (0, 1)$ scales translation and scale toward zero ($w \cdot T$, $w \cdot S$)
|
|
44
|
-
while leaving rotation at 100% full strength ($\text{normalize}(w \cdot R) = R$), then snaps at
|
|
45
|
-
$w = 0$.
|
|
46
|
-
|
|
47
|
-
### 2.2. How Unified Rest-Anchored Delta Accumulation Solves Every Case Without Switches
|
|
48
|
-
Under $V_{\text{final}} = V_{\text{rest}} + \sum_i w_i \cdot (V_i(t) - V_{\text{rest}})$:
|
|
49
|
-
1. **Single clip at $w = 1$:**
|
|
50
|
-
$$V_{\text{rest}} + 1 \cdot (V_1 - V_{\text{rest}}) = V_1$$
|
|
51
|
-
2. **Silent clip at $w = 0$ (fixes D37/E14 at the root for T, R, and S):**
|
|
52
|
-
$$V_{\text{rest}} + 0 \cdot (V_1 - V_{\text{rest}}) = V_{\text{rest}}$$
|
|
53
|
-
A bound clip at weight zero never clobbers non-zero rest translation or scale.
|
|
54
|
-
3. **Single partial-body clip fading $w: 0 \to 1$:**
|
|
55
|
-
$$V_{\text{rest}} + w \cdot (V_1 - V_{\text{rest}}) = (1 - w) V_{\text{rest}} + w V_1$$
|
|
56
|
-
Smoothly interpolates (lerp for T/S, nlerp for R) from the joint's rest pose to $V_1$.
|
|
57
|
-
4. **Two full-body clips crossfading ($w_1 + w_2 = 1$):**
|
|
58
|
-
$$V_{\text{rest}} + w_1(V_1 - V_{\text{rest}}) + w_2(V_2 - V_{\text{rest}}) = w_1 V_1 + w_2 V_2$$
|
|
59
|
-
Even if `clip.optimize` stripped a constant-at-rest channel from clip 1, clip 1's omitted delta
|
|
60
|
-
is identically $0$, so clip 2 still crossfades smoothly against $V_{\text{rest}}$!
|
|
61
|
-
5. **Base clip ($w_{\text{base}} = 1$, or crossfading base clips summing to $1$) + Additive /
|
|
62
|
-
Upper-Body clip ($w_{\text{add}} = w$):**
|
|
63
|
-
$$V_{\text{rest}} + 1 \cdot (V_{\text{base}} - V_{\text{rest}}) + w \cdot (V_{\text{add}} - V_{\text{rest}}) = V_{\text{base}} + w \cdot \Delta V_{\text{add}}$$
|
|
64
|
-
And on any bone/axis that $V_{\text{base}}$ does *not* key, it automatically evaluates to
|
|
65
|
-
$V_{\text{rest}} + w \cdot \Delta V_{\text{add}}$.
|
|
66
|
-
|
|
67
|
-
### 2.3. Adversarial Check: Why Quaternion Hemisphere Alignment Must Happen at Import/Build Time, Not Per-Frame in the Apply Shader
|
|
68
|
-
Suppose a base clip spins a joint past $180^\circ$ so $\text{dot}(R_{\text{base}}(t), R_{\text{rest}})$
|
|
69
|
-
crosses $0$ mid-clip, while an additive clip contributes $w_{\text{add}} \Delta R_{\text{add}}$.
|
|
70
|
-
If the apply shader flipped $R_{\text{base}}(t) \to -R_{\text{base}}(t)$ dynamically when
|
|
71
|
-
$\text{dot}(R_{\text{base}}(t), R_{\text{rest}}) < 0$, then at the crossing frame the sum would flip
|
|
72
|
-
from $+R_{\text{base}} + w_{\text{add}} \Delta R_{\text{add}}$ to
|
|
73
|
-
$-R_{\text{base}} + w_{\text{add}} \Delta R_{\text{add}} = -(R_{\text{base}} - w_{\text{add}} \Delta R_{\text{add}})$,
|
|
74
|
-
inverting the direction of the additive offset mid-animation!
|
|
75
|
-
By keeping sign canonicalization strictly at clip import/creation time (`quat3_canonicalize_sign_run`
|
|
76
|
-
anchored to $R_{\text{rest}}$ at keyframe 0 and continuous across consecutive keyframes), curves
|
|
77
|
-
remain $C^1$-continuous everywhere and the apply shader has zero sign-flip branches.
|
|
78
|
-
|
|
79
|
-
---
|
|
80
|
-
|
|
81
|
-
## 3. Architecture
|
|
82
|
-
|
|
83
|
-
### 3.1. Accumulator Layout ([`POSE_ACCUMULATOR_LAYOUT.js`](./POSE_ACCUMULATOR_LAYOUT.js))
|
|
84
|
-
|
|
85
|
-
Expand each per-row slot in `pose_accumulator` from 16 `u32`s (64 bytes) to 32 `u32`s (128 bytes,
|
|
86
|
-
preserving power-of-two shift indexing) so rest translation and rest scale ride alongside rest
|
|
87
|
-
rotation:
|
|
88
|
-
|
|
89
|
-
```text
|
|
90
|
-
Word Offset Field Description
|
|
91
|
-
──────────────────────────────────────────────────────────────────────────────────────────
|
|
92
|
-
[0..3] translation.xyz Σ w_i * (T_i - rest_T)
|
|
93
|
-
[3..7] rotation.xyzw Σ w_i * (R_i - rest_R)
|
|
94
|
-
[7..10] scale.xyz Σ w_i * (S_i - rest_S)
|
|
95
|
-
[10] dirty_mask Bitmask of touched channels (TX, TY, TZ, R, SX, SY, SZ)
|
|
96
|
-
[11..15] rest_rotation.xyzw Target joint's rest rotation
|
|
97
|
-
[15..18] rest_translation.xyz Target joint's rest translation
|
|
98
|
-
[18..21] rest_scale.xyz Target joint's rest scale
|
|
99
|
-
[21..32] padding Power-of-two slot alignment (32 u32s = 128 bytes)
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### 3.2. Zero-Overhead Binding Rest Value ([`ANIMATION_TRACK_BINDING_STRUCT.js`](./ANIMATION_TRACK_BINDING_STRUCT.js))
|
|
103
|
-
|
|
104
|
-
Each row in `animation_bindings` targets a single `property` (`Translation`, `Rotation`, or `Scale`)
|
|
105
|
-
and already carries a `vec4f` field (`rest_rotation`). By populating that `vec4f` with the target
|
|
106
|
-
entity's rest value for its bound `property`—`[tx, ty, tz, 0]` for Translation, `[sx, sy, sz, 0]`
|
|
107
|
-
for Scale, and `[rx, ry, rz, rw]` for Rotation, both at binding completion and in
|
|
108
|
-
`GPUAnimationManager.#unmute`—the binding struct stays 32 bytes with zero extra memory overhead.
|
|
109
|
-
|
|
110
|
-
### 3.3. GPU Apply & Resolve ([`chunk_pose_accumulator.js`](./chunk_pose_accumulator.js), [`shader_animation_pose_resolve.js`](./shader_animation_pose_resolve.js))
|
|
111
|
-
|
|
112
|
-
- **Apply (`chunk_pose_accumulator`):**
|
|
113
|
-
- `pose_accumulator_add_translation(row, value, mask, weight, rest)`: for each masked axis $a$,
|
|
114
|
-
atomic-adds `value[a] - rest[a] * weight` into `POSE_OFFSET_TRANSLATION + a` and stores
|
|
115
|
-
`rest[a]` into `POSE_OFFSET_REST_TRANSLATION + a`.
|
|
116
|
-
- `pose_accumulator_add_rotation(row, value, mask, weight, rest)`: substitutes `weight` for a
|
|
117
|
-
missing $w$ curve (`let w = select(weight, value.w, (mask & 0x8u) != 0u)`), atomic-adds
|
|
118
|
-
`(value.xyz, w) - rest * weight` into `POSE_OFFSET_ROTATION`, and stores `rest` into
|
|
119
|
-
`POSE_OFFSET_REST_ROTATION`.
|
|
120
|
-
- `pose_accumulator_add_scale(row, value, mask, weight, rest)`: for each masked axis $a$,
|
|
121
|
-
atomic-adds `value[a] - rest[a] * weight` into `POSE_OFFSET_SCALE + a` and stores `rest[a]`
|
|
122
|
-
into `POSE_OFFSET_REST_SCALE + a`.
|
|
123
|
-
- **Resolve (`shader_animation_pose_resolve`):**
|
|
124
|
-
- Translation (per dirty axis $a$): `t[a] = rest_t[a] + delta_t[a]`, then zeroes `delta_t[a]`.
|
|
125
|
-
- Rotation (when `POSE_DIRTY_R` set): `r = rest_r + delta_r`, zeroes `delta_r`, and writes
|
|
126
|
-
`normalize(r)` when `length(r) > 0.0`, else `rest_r`.
|
|
127
|
-
- Scale (per dirty axis $a$): `s[a] = rest_s[a] + delta_s[a]`, then zeroes `delta_s[a]`.
|
|
128
|
-
|
|
129
|
-
### 3.4. CPU Twin Lockstep ([`pose_evaluate_local.js`](./pose/pose_evaluate_local.js))
|
|
130
|
-
|
|
131
|
-
`pose_evaluate_local(result, target, rest, playbacks)` accumulates `(curve.evaluate(time) - rest_comp) * weight`
|
|
132
|
-
into `SUM_TRANSLATION`, `SUM_ROTATION`, and `SUM_SCALE`, and resolves `rest + SUM` (normalizing
|
|
133
|
-
rotation with fallback to `rest.rotation` on zero length), matching the GPU bit-for-bit.
|
|
134
|
-
|
|
135
|
-
### 3.5. Import / Authoring Stage Additive Rebasing ([`ShadeAnimationClip.js`](./ShadeAnimationClip.js))
|
|
136
|
-
|
|
137
|
-
`ShadeAnimationClip.from_additive(source_clip, { reference_clip, reference_time, rest_of, name })`
|
|
138
|
-
rebases a clip authored relative to `reference_clip` at `reference_time` onto each target's rest
|
|
139
|
-
pose `rest_of(target)`:
|
|
140
|
-
- $T_{\text{out}}(t) = T_{\text{rest}} + (T_{\text{src}}(t) - T_{\text{ref}})$
|
|
141
|
-
- $S_{\text{out}}(t) = S_{\text{rest}} + (S_{\text{src}}(t) - S_{\text{ref}})$
|
|
142
|
-
- $R_{\text{out}}(t) = (R_{\text{src}}(t) \otimes R_{\text{ref}}^{-1}) \otimes R_{\text{rest}}$,
|
|
143
|
-
sign-canonicalized against $R_{\text{rest}}$
|
|
144
|
-
- Automatically drops any axis curve or rotation channel whose delta from $V_{\text{ref}}$ is zero
|
|
145
|
-
across all keyframes (within `1e-5`).
|