Module custom_shape

Module custom_shape 

Source
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§

CustomShapeBatch
One dispatch unit: a contiguous run of instances in the storage buffer that belong to the same shape and share sides + blend mode.
CustomShapeInstance
GPU-side per-instance record. repr(C) + Pod for direct bytemuck::cast_slice upload to a storage buffer. Each field is a vec4-aligned 16-byte block so the WGSL array<ShapeInstance> layout matches without an explicit align(16) shim.
CustomShapeRenderer
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.
ShapeFlags
Per-instance flag bits packed into CustomShapeInstance::border_flags[1]. Reading side lives in custom_shape.wgsl (flag_bits & 1u, etc.).
ShapeUniforms 🔒

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 sides at 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 CustomShapeInstance from MD2-space eval output. rad is 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 as custom_wave::preset_xy_to_clip.