simvx.graphics.renderer.velocity_pass¶
How it works¶
A dedicated RG16F render target (with its own depth) is re-drawn from the same
opaque instances the forward pass submitted. velocity.vert reads two parallel
model-matrix SSBOs keyed by gl_InstanceIndex (current + previous frame) and,
together with the UNJITTERED current/previous view-projection (from
PostProcessPass.taa_cur_vp / taa_prev_vp), emits NDC-space motion vectors.
Previous-frame transforms are kept on the CPU side: each frame the renderer hands
this pass the column-major model matrices it already computed for the main
transform SSBO. We upload them as “current”, and roll last frame’s into “previous”.
On the first frame – or whenever the scene tree structure changes (instance row
indices may shift) – prev is forced equal to current, yielding zero velocity (no
spike), mirroring the camera-VP first-frame guard in update_taa_matrices.
Background / sky pixels keep the render pass’s clear sentinel (-2, -2) (outside
any legitimate NDC-delta range) so the resolve can fall back to depth-based camera
reprojection there.
SCOPE: opaque mesh instances only. Skinned meshes and GPU particles have no prev-joint / prev-particle state at this boundary and are intentionally NOT drawn here – they keep the resolve’s camera-only depth-reproject behaviour (mild self-motion ghosting, no regression). Per-object velocity for those is a flagged follow-up.
Per-object motion-vector (velocity) pass for TAA (desktop Vulkan).
Foundation stage for per-object TAA: produces a per-pixel velocity buffer for
opaque MESH INSTANCES so a moving mesh stops ghosting once the resolve samples
it (the resolve hookup is a separate stage). Purely additive and gated on
taa_enabled: nothing here is allocated, uploaded, or recorded when TAA is
off, so the no-TAA frame stays byte-identical.
Module Contents¶
Classes¶
Re-draws opaque mesh instances into an RG16F per-object velocity target. |
Data¶
API¶
- simvx.graphics.renderer.velocity_pass.__all__¶
[‘VelocityPass’]
- simvx.graphics.renderer.velocity_pass.log¶
‘getLogger(…)’
- class simvx.graphics.renderer.velocity_pass.VelocityPass(engine: Any, max_objects: int)[source]¶
Re-draws opaque mesh instances into an RG16F per-object velocity target.
Initialization
- property velocity_view: Any[source]¶
RG16F colour view the resolve samples (SHADER_READ_ONLY after the pass).
- setup(width: int, height: int) None[source]¶
Allocate the velocity target, prev/cur model SSBOs, UBO, descriptors, pipelines.
Called lazily by the renderer only when TAA is first enabled, so the no-TAA path never touches any of this.
- set_frame_matrices(cur_vp: numpy.ndarray, prev_vp: numpy.ndarray) None[source]¶
Stash the UNJITTERED current + previous view-projection for this frame.
- upload_models(models_col_major: numpy.ndarray, structure_changed: bool) None[source]¶
Upload current model matrices and roll the previous-frame copy.
models_col_majoris the (N, 4, 4) column-major (GLSL-ready) model matrices the renderer already computed for the main transform SSBO – the same row order, sogl_InstanceIndexpairs current<->previous correctly.On the first frame (no cached prior models) or after a tree-structure change (row indices may have shifted -> a stale prev would spike), prev is set equal to current so velocity is zero that frame.
- render(cmd: Any, scene_renderer: Any) None[source]¶
Re-draw opaque instances into the velocity target. No-op when not ready.
Reuses the scene content renderer’s opaque draw path with this pass’s pipeline/layout/descriptor overrides, so culling + grouping + the indirect batch are shared with the forward pass (no second Python draw loop).