fidget-wgpu 0.5.1

WGPU backend for Fidget
Documentation
//! Pass to compute per-pixel color based on pixel indices

struct Config {
    /// Screen-to-model transform matrix, converting pixels to model space
    mat: mat3x3f,

    /// Mapping from X, Y, Z to input indices
    axes: vec3u,

    // Z height at which to evaluate
    z: f32,

    /// Image size, in pixels
    image_size: vec2u,

    /// Only compute color for filled pixels when this is non-zero
    only_filled: u32,

    // manual alignment
    _pad: array<u32, 3>,

    /// Tape data, tightly packed per-tile (flexible array member)
    tape_data: array<TapeWord>,
}

@group(0) @binding(0) var<storage, read> config: Config;
@group(0) @binding(1) var<storage, read> shape_start: array<u32>;

/// Array of values for (non-xyz) variables
@group(0) @binding(2) var<storage, read> var_values: array<f32>;

@group(1) @binding(0) var<storage, read> distance: array<RawDistancePixel>;
/// Image buffer, which is shape index going in and color going out
@group(1) @binding(1) var<storage, read_write> color: array<u32>;

@compute @workgroup_size(8, 8)
fn color_main(
    @builtin(global_invocation_id) global_id: vec3u
) {
    // Clamp to image size
    if global_id.x >= config.image_size.x ||
       global_id.y >= config.image_size.y
    {
        return;
    }

    // Shape indices are in the color buffer; we'll overwrite them here
    var i = global_id.x + config.image_size.x * global_id.y;
    let d = distance[i];

    // Store alpha; early exit if we only care about color for filled pixels
    var alpha = 0u;
    if distance_pixel_is_inside(d) {
        alpha = 0xFF;
    } else if config.only_filled != 0 {
        color[i] = 0x00000000;
        return;
    }

    let tag = color[i];
    if tag >= arrayLength(&shape_start) {
        color[i] = 0xFF0000FF; // corrupt, fill with red
        return;
    }

    // Compute input values
    let m_xy = transformed_inputs(
        Value(f32(global_id.x)),
        Value(f32(global_id.y)),
    );
    let m = array(m_xy[0], m_xy[1], build_imm(config.z));

    let raw_start = shape_start[tag];
    let index = raw_start & 0x7FFFFFFF;
    let is_hsl = (raw_start & (1u << 31)) != 0;
    var stack = Stack(); // dummy value

    // Color channel tapes are packed together
    let out_0 = run_tape(index, m, &stack);
    let out_1 = run_tape(out_0.pos, m, &stack);
    let out_2 = run_tape(out_1.pos, m, &stack);
    let out = vec3f(
        clamp(out_0.value.v, 0.0, 1.0),
        clamp(out_1.value.v, 0.0, 1.0),
        clamp(out_2.value.v, 0.0, 1.0)
    );

    var channels: vec3f;
    if is_hsl {
        channels = hsl_to_rgb(out);
    } else {
        channels = out;
    }

    let u = vec3u(channels * 255.0);
    color[i] = (alpha << 24) | (u[2] << 16) | (u[1] << 8) | u[0];
}