ruviz 0.6.0

High-performance 2D plotting library for Rust
Documentation
struct Camera3D {
    view_projection: mat4x4<f32>,
    axis_aspect: vec4<f32>,
    viewport: vec4<f32>,
};

struct PointMaterial3D {
    color: vec4<f32>,
    parameters: vec4<f32>,
};

@group(0) @binding(0)
var<uniform> camera: Camera3D;

@group(1) @binding(0)
var<uniform> material: PointMaterial3D;

struct VertexOutput {
    @builtin(position) clip_position: vec4<f32>,
    @location(0) local: vec2<f32>,
};

/// Smallest homogeneous divisor a billboard may be sized against.
const W_EPSILON: f32 = 1.0e-6;

/// In front of the near plane (z < 0), so the primitive is discarded whole.
const DEGENERATE_POSITION: vec4<f32> = vec4<f32>(0.0, 0.0, -1.0, 1.0);

@vertex
fn vs_main(
    @builtin(vertex_index) vertex_index: u32,
    @location(0) position: vec4<f32>,
) -> VertexOutput {
    let corners = array<vec2<f32>, 4>(
        vec2<f32>(-1.0, -1.0),
        vec2<f32>(-1.0, 1.0),
        vec2<f32>(1.0, -1.0),
        vec2<f32>(1.0, 1.0),
    );
    let corner = corners[vertex_index];
    let center = camera.view_projection * vec4<f32>(
        position.xyz * camera.axis_aspect.xyz,
        1.0,
    );
    var output: VertexOutput;
    // A centre at or behind the eye makes `center.w` useless as a pixel-to-clip
    // scale — the sprite would invert and stretch across the frame. The CPU
    // rasterizer rejects the same billboards on depth alone.
    if !(center.w > W_EPSILON) {
        output.clip_position = DEGENERATE_POSITION;
        output.local = corner;
        return output;
    }
    let ndc_per_pixel = vec2<f32>(2.0 / camera.viewport.x, 2.0 / camera.viewport.y);
    let radius = max(material.parameters.x * camera.viewport.z / 72.0 * 0.5, 0.5);
    let clip_offset = corner * radius * ndc_per_pixel * center.w;
    output.clip_position = vec4<f32>(center.xy + clip_offset, center.z, center.w);
    output.local = corner;
    return output;
}

/// Whether a marker glyph covers `point`, expressed in **y-up** units of the
/// marker radius.
///
/// The same predicate — same constants, same orientation — lives in
/// `software/raster.rs`; `tests/three_d_parity_test.rs` keeps them honest.
fn marker_contains(marker: u32, point: vec2<f32>) -> bool {
    let x = abs(point.x);
    let y = abs(point.y);
    let radial = length(point);
    if marker == 0u {
        return radial <= 1.0;
    }
    if marker == 1u {
        return x <= 1.0 && y <= 1.0;
    }
    if marker == 2u {
        return point.y >= -1.0 && point.y <= 1.0 && x <= (1.0 - point.y) * 0.58;
    }
    if marker == 3u {
        return point.y >= -1.0 && point.y <= 1.0 && x <= (1.0 + point.y) * 0.58;
    }
    if marker == 4u {
        return x + y <= 1.0;
    }
    if marker == 5u {
        return (x <= 0.22 && y <= 1.0) || (y <= 0.22 && x <= 1.0);
    }
    if marker == 6u {
        return x <= 1.0 && y <= 1.0 && abs(x - y) <= 0.28;
    }
    if marker == 7u {
        if radial > 1.0 {
            return false;
        }
        let angle = atan2(point.y, point.x);
        let boundary = 0.58 + 0.42 * abs(cos(angle * 5.0));
        return radial <= boundary;
    }
    if marker == 8u {
        return radial >= 0.62 && radial <= 1.0;
    }
    if marker == 9u {
        return x <= 1.0 && y <= 1.0 && (x >= 0.68 || y >= 0.68);
    }
    if marker == 10u {
        let outer = point.y >= -1.0 && point.y <= 1.0 && x <= (1.0 - point.y) * 0.58;
        let inner = point.y >= -0.48 && point.y <= 0.62 && x <= (0.62 - point.y) * 0.44;
        return outer && !inner;
    }
    let diamond_distance = x + y;
    return diamond_distance >= 0.62 && diamond_distance <= 1.0;
}

@fragment
fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
    let marker = u32(round(material.parameters.y));
    if !marker_contains(marker, input.local) {
        discard;
    }
    // The scene pipelines blend and resolve premultiplied.
    return vec4<f32>(material.color.rgb * material.color.a, material.color.a);
}