Module custom_wave

Module custom_wave 

Source
Expand description

Custom-wave (wavecode_N) pass.

The MD2 wavecode_N block defines up to four user-driven waves that run their own per_frame_init / per_frame / per_point equations. Per frame the engine evaluates each enabled wave’s per-point loop on the CPU, producing a stream of (x, y, r, g, b, a) 6-tuples; this module uploads that stream into a dynamic vertex buffer and dispatches either a line-list or triangle-list draw.

Why CPU-emit vs. GPU-derive: each preset’s per-point equations can reference arbitrary user state (q* channels, the audio buffer, whatever a preset author thought up) — running them on the GPU would require porting the evaluator. The line/dot geometry is tiny enough that uploading expanded vertices each frame is the cheaper path.

Pipeline matrix:

  • Topology is chosen at submit time: LineStrip for b_use_dots = 0 (one strip per wave; segments break at wave boundaries via per-wave draw calls), TriangleList for b_use_dots = 1 (each point expands CPU-side into a small 2-tri quad).
  • Blend is alpha or additive, picked by b_additive.

Dispatch slot: the renderer calls into this pass between the legacy waveform pass and the blur pyramid, so custom waves feed back next frame and contribute to GetBlur*. Same slot the historical waveform pass uses.

Structs§

CustomWaveBatch
One dispatch unit: the slice of the vertex buffer that belongs to a single wavecode_N block, plus its blend/topology flags. The renderer reuses a single growable buffer across all waves and walks the batches to issue one draw call each.
CustomWaveRenderer
Custom-wave GPU pass. Owns one growable vertex buffer + two pipelines (lines and dots topology, alpha and additive blend = 4 combinations, indexed by pipeline_index(dots, additive)).
CustomWaveVertex
One vertex of the custom-wave stream. The shader is pure passthrough — pos is already clip-space [-1, 1], color is the per-point RGBA after r/g/b/a carried through the per-point loop.

Constants§

MAX_CUSTOM_WAVE_VERTICES
Maximum total custom-wave vertices we’ll buffer in a frame. Four waves × 512 samples × (2 lines = 6 verts/segment, dots = 6 verts/point) ≈ 12 288. Round up to 16 384 to leave headroom for the next-sprint custom-shape pass, which will reuse this buffer layout.

Functions§

pipeline_index 🔒
point_to_dot_quad
Expand one MD2 per-point output (x, y, r, g, b, a) into a small screen-space quad (two triangles, six vertices). Used by the dots pipeline. radius_clip is the half-side in clip space — pick 2.0 / height for a single-pixel-equivalent dot at default sizing.
preset_xy_to_clip
Convert MD2 preset-space (x, y) (origin top-left, range [0, 1]) into clip-space (x', y') (origin centre, range [-1, 1], Y-up).
segment_to_thick_quad
Expand two consecutive per-point outputs into a thick-line segment quad — six clip-space vertices forming a screen-space rectangle of thickness_clip perpendicular to the segment direction. Mirrors the line_vertex shape used by waveform_advanced.wgsl for b_wave_thick, so MD2’s “thick custom-wave trail” looks identical to the thick-static-wave path.