Expand description
Custom-shape (shapecode_N) pass.
Up to four user-defined shapes per preset. Each shape spawns
num_inst instances (1..1024) drawn as triangle fans of sides
vertices around (x, y) at radius rad rotated by ang. The
engine runs the shape’s per-frame equations once per instance,
collects the resulting state into a flat storage buffer, and
issues one fill draw call per shape; an optional outline pass
follows for b_thick_outline = 1.
Why a storage buffer + instanced draw (vs. CPU-expanded vertex
stream like custom waves): a single shape with num_inst = 1024 and
sides = 64 would emit 1024 × 64 × 3 ≈ 200K vertices per frame —
the upload bandwidth dominates the work. With instancing the upload
is one struct (~96 bytes) per instance, and the GPU expands the
geometry from (@builtin(vertex_index), @builtin(instance_index)).
Textured mode: instead of a solid colour, the fragment shader
samples prev_texture (the post-warp / post-wave output of the
previous frame) at UV warped by tex_zoom / tex_ang. The output
is multiplied by the centre→edge gradient so the user’s RGB still
tints the result.
Structs§
- Custom
Shape Batch - One dispatch unit: a contiguous run of instances in the storage
buffer that belong to the same shape and share
sides+ blend mode. - Custom
Shape Instance - GPU-side per-instance record.
repr(C)+Podfor directbytemuck::cast_sliceupload to a storage buffer. Each field is avec4-aligned 16-byte block so the WGSLarray<ShapeInstance>layout matches without an explicitalign(16)shim. - Custom
Shape Renderer - GPU pass. Owns the per-frame instance storage buffer + the four pipelines (fill × alpha/additive, outline × alpha/additive). The fragment shader picks textured vs. solid via a per-instance flag bit, so we don’t need a separate textured pipeline.
- Shape
Flags - Per-instance flag bits packed into
CustomShapeInstance::border_flags[1]. Reading side lives incustom_shape.wgsl(flag_bits & 1u, etc.). - Shape
Uniforms 🔒
Constants§
- MAX_
CUSTOM_ SHAPE_ INSTANCES - Hard cap on total instances buffered per frame. 4 shapes × 1024 MD2 max = 4 096; round up to 4 800 for headroom.
- MAX_
SHAPE_ SIDES - MD2 caps
sidesat 100 in the preset format. We clamp to 64 here to keep the per-instance vertex count manageable (64 × 3 = 192 vertices/instance × 1024 instances = ~200K verts max per shape).
Functions§
- additive_
index 🔒 - instance_
from_ md2_ state - Build a
CustomShapeInstancefrom MD2-space eval output.radis converted from preset units (roughly [0, 1] for full-screen) to clip-space half-extent (radius 0.5 = quarter-screen-width before aspect correction). - preset_
xy_ to_ clip - Convert MD2 preset-space
(x, y)(origin top-left, range[0, 1]) to clip-space(x', y')(origin centre, range[-1, 1], Y-up). Same convention ascustom_wave::preset_xy_to_clip.