Expand description
Warp mesh: a per-vertex UV grid that resamples the previous frame (ADR-0113).
§What it generalizes
ADR-0048 gave the engine one affine transform through which an accumulation
reads its own past: a single zoom, rotation and translation applied
identically to every texel. This scene is that transform per vertex. The
frame is covered by a grid of cells; each of its vertices carries its own
zoom/rot/cx/cy/dx/dy/ sx/sy/warp, and the rasterizer
interpolates between them — so the past can spiral in one corner and drift in
another, which no single affine can express.
Those nine outputs come from a preset’s [per_vertex] table, whose bindings
are evaluated once per vertex per frame with x, y, rad and ang bound
to that vertex’s own position. A preset that declares no such table gets the
scalar params of the same names applied everywhere, which is exactly ADR-0048’s
single shared transform — so the idiom degrades to the one it generalizes.
§The grid is a resolution, not a shape
ADR-0037, and this is the most likely place in the engine to get it wrong,
because here the grid is user-visible: a preset names [mesh] x and [mesh] y, and they are quantized and clamped to a tier capacity. Every
screen-destined coordinate here takes its aspect from the render target — the
rad/ang the per-vertex program reads (computed in vertex_position), and
the isotropic space the source-uv transform works in (computed in the vertex
shader from a uniform the CPU fills with the target’s aspect).
meshx/meshy appear in neither. A f32 aspect derived from the mesh size
would be the bug.
§Three passes
- warp — the mesh is drawn into the write half of a ping-pong field,
sampling the read half through each vertex’s source uv and scaling it by
decay^dt. This is the only pass that is not fullscreen. - deposit — a fullscreen pass adding this frame’s light onto the warped past: a palette-coloured gaussian ring with optional angular arms. It runs after the warp, so the light it lays down is “now” and is warped from the next frame onward.
- present — a fullscreen pass compositing the field over the backdrop,
premultiplied (ADR-0026), scaled by
brightnessandocclude.
All three rates are per second (ADR-0019): decay, zoom, sx, sy are
factors per second and rot/dx/dy/warp/deposit are amounts per second,
so the look is identical at 60 Hz and 144 Hz.
GPU resources are built lazily on first render, for the reason
reaction_diffusion.rs documents: a capture that never activates this scene
never builds this scene’s pipelines, so it cannot perturb another scene’s
render on the DX12 WARP software adapter.
Modules§
- draw
- What MilkDrop draws between the warp and the composite (Plan 0100 Phase 4): the waveform, the custom waves and shapes, the two borders, and the motion-vector grid.
Structs§
- Warp
Mesh Scene - The warp mesh scene (ADR-0113).
Constants§
- COMPOSITE_
PARAMS - MilkDrop’s composite roster, in the order
COMPOSITE_PARAMSdeclares it — the six flags and one multiplier its format carries, reachable from a preset and written by a converted bundle’s per-frame program. - DEFAULT_
MESH - The grid a
[mesh]table’s absent keys mean. Coarse enough to be free on any machine and fine enough that arad-driven program reads as a curve rather than as facets. - MAX_
MESH - The largest grid any tier may name, in cells — the
.milkformat’s own ceiling (meshx <= 128,meshy <= 96), so a converted preset’s requested grid is always representable. - MAX_
SHAPE_ VERTICES - The most vertices the filled-shape buffer holds.
- MILKDROP_
SOFTNESS - The
softnesseverywarp_meshstroke is drawn at — the waveform, every custom wave, every shape outline, both borders and the motion grid, which all reach the line fragment through oneLineRenderer::draw_splitcall. - MIN_
MESH - The smallest grid a
[mesh]table may name, in cells. Below two the mesh is a single quad and the per-vertex program has no interior to interpolate. - PARAMS
- Parameter vocabulary — see
fragment_field::PARAMS. Keep in sync withset_parambelow. - PER_
VERTEX_ PARAMS - The nine outputs a
[per_vertex]table may bind, in the order this scene stores them. Keep in step withPER_VERTEX_DEFAULTSandWarpMeshScene::set_per_vertex.
Functions§
- clamp_
grid - Clamp a preset’s requested grid into what
tierwill carry. - vertex_
count - How many vertices a grid of
meshcells has. One more than the cell count on each axis — the fencepost the whole per-vertex path is sized by. - vertex_
position - The
(x, y, rad, ang)a vertex’s[per_vertex]bindings are evaluated against, for the vertex at columncol, rowrowof ameshgrid, on a render target of aspectaspect.