Expand description
Motion-vector grid pass.
MD2 draws a grid of n_x × n_y short line segments into the warp
output every frame. The renderer is stateless — segments live for
exactly one frame, painted at the same screen-space grid each time
— but because the segments end up inside the feedback loop (we
dispatch between the shape overlays and the blur pyramid), the
warp pulls them into trails. Those trails are the “motion vectors”
the player sees.
The grid is clamped to MD2’s hard cap of 64 × 48; combined with
the 2 vertices per segment that gives MAX_MOTION_VECTOR_SEGMENTS * 2 vertices per frame upload — small enough to keep the buffer at
a static size.
Segment geometry per cell (i, j):
- Anchor:
(x, y) = ((i + 0.5) / n_x + dx, (j + 0.5) / n_y + dy)in MD2 preset space[0, 1](origin top-left), then mapped to clip space withpreset_xy_to_clip. - Tail: anchor +
(length / n_x, 0)— a small horizontal segment.lengthismv_l(MD2 default 0.9) expressed in cells so a value of1.0would span an entire cell, with the visible trail length emerging from how aggressively the feedback warp pulls it.
Structs§
- Motion
Vector Renderer - GPU pass for the MD2 motion-vector grid.
- Motion
Vector Vertex - One vertex of the motion-vector stream. Two per segment (head + tail). Pure passthrough — the shader doesn’t transform or shade, just emits the per-segment colour.
- Warp
Field - Per-vertex warp-displacement field, borrowed from the renderer’s
most recent
update_warp_verticescall.vertices[r * cols + c]matches the warp mesh’s row-major layout; the segment builder recoversuv_origfrompos_clip(inverse of the same mappingWarpMesh::newuses) and reports the displacementuv_warp - uv_origat the grid cell’s nearest mesh vertex.
Constants§
- MAX_
MOTION_ VECTOR_ GRID_ X - Maximum cells along each axis. MD2 caps motion-vector grids at this size in the preset format; the renderer enforces the cap regardless of what the preset declares.
- MAX_
MOTION_ VECTOR_ GRID_ Y - MAX_
MOTION_ VECTOR_ SEGMENTS - Maximum number of segments stored in the GPU buffer.
Functions§
- build_
segments 🔒 - Build the per-frame segment list. Pulled out as a free function so
it can be unit-tested without a GPU device. When
warp_fieldisSome, segments point along the local warp displacement; without it the function falls back to a horizontal stub. - preset_
xy_ 🔒to_ clip - MD2 preset-space → clip-space, identical to the helpers in
custom_wave/custom_shape. Origin moves from top-left at(0, 0)to centre at(0, 0), range[0, 1]becomes[-1, 1], and y is flipped. - sample_
warp_ 🔒displacement - Look up the warp displacement at preset-space position
(x, y)fromfield. Bilinear-interpolates across the four nearest mesh cells so the segment direction stays smooth across the grid boundaries. Returns(dx, dy)in preset-space UV units (uv_warp - uv_orig).