pierro 0.1.0

An immediate mode UI library for Rust
Documentation

struct VertexOutput {
    @builtin(position) clip_pos: vec4<f32>,
    @location(0)  color: vec4<f32>,
    @location(1)  uv: vec2<f32>,
    @location(2)  tex: u32,
    @location(3)  pos: vec2<f32>,
    @location(4)  clip_min: vec2<f32>,
    @location(5)  clip_max: vec2<f32>,
    @location(6)  rect_center: vec2<f32>,
    @location(7)  rect_half_size: vec2<f32>,
    @location(8)  rounding: f32,
    @location(9)  stroke_color: vec4<f32>,
    @location(10) stroke_width: f32
};

struct RectData {
    @location(0)  min: vec2<f32>,
    @location(1)  size: vec2<f32>,
    @location(2)  uv_min: vec2<f32>,
    @location(3)  uv_size: vec2<f32>,
    @location(4)  color: vec4<f32>,
    @location(5)  tex: u32,
    @location(6)  clip_min: vec2<f32>,
    @location(7)  clip_max: vec2<f32>,
    @location(8)  rounding: f32,
    @location(9)  stroke_color: vec4<f32>,
    @location(10) stroke_width: f32
}

struct Uniforms {
    screen_size: vec2<f32>
}

@group(0) @binding(1)
var<uniform> uniforms: Uniforms;

@vertex
fn vs_main(
    @builtin(vertex_index) vert_id: u32,
    rect: RectData
) -> VertexOutput {
    var out: VertexOutput;

    var RECT_SIZE_SCALE = array(
        vec2(0.0,  0.0),
        vec2(0.0,  1.0),
        vec2(1.0,  0.0),

        vec2(0.0,  1.0),
        vec2(1.0,  1.0),
        vec2(1.0,  0.0),
    );

    let pos = rect.min + RECT_SIZE_SCALE[vert_id] * rect.size; 
    out.clip_pos = vec4<f32>(2.0 * pos.x / uniforms.screen_size.x - 1.0, -2.0 * pos.y / uniforms.screen_size.y + 1.0, 0.0, 1.0);
    out.color = rect.color;
    out.uv = rect.uv_min + RECT_SIZE_SCALE[vert_id] * rect.uv_size;
    out.tex = rect.tex;
    out.pos = pos;
    out.clip_min = rect.clip_min;
    out.clip_max = rect.clip_max;
    out.rect_center = rect.min + rect.size * 0.5;
    out.rect_half_size = rect.size * 0.5;
    out.rounding = rect.rounding;
    out.stroke_color = rect.stroke_color;
    out.stroke_width = rect.stroke_width;
    return out;
}

@group(0) @binding(0)
var s: sampler;
@group(0) @binding(2)
var tex1: texture_2d<f32>;
@group(0) @binding(3)
var tex2: texture_2d<f32>;
@group(0) @binding(4)
var tex3: texture_2d<f32>;
@group(0) @binding(5)
var tex4: texture_2d<f32>;
@group(0) @binding(6)
var tex5: texture_2d<f32>;
@group(0) @binding(7)
var tex6: texture_2d<f32>;
@group(0) @binding(8)
var tex7: texture_2d<f32>;
@group(0) @binding(9)
var tex8: texture_2d<f32>;

fn sample(uv: vec2<f32>, tex: u32) -> vec4<f32> {
    switch(tex) {
        case 0u, default: {
            return vec4(1.0, 1.0, 1.0, 1.0); 
        }
        case 1u: {
            return textureSample(tex1, s, uv);
        }
        case 2u: {
            return textureSample(tex2, s, uv);
        }
        case 3u: {
            return textureSample(tex3, s, uv);
        }
        case 4u: {
            return textureSample(tex4, s, uv);
        }
        case 5u: {
            return textureSample(tex5, s, uv);
        }
        case 6u: {
            return textureSample(tex6, s, uv);
        }
        case 7u: {
            return textureSample(tex7, s, uv);
        }
        case 8u: {
            return textureSample(tex8, s, uv);
        }
    }
}

fn rounded_rect_sdf(pos: vec2<f32>, rect_center: vec2<f32>, rect_half_size: vec2<f32>, r: f32) -> f32 {
    let d2 = abs(rect_center - pos) - rect_half_size + vec2(r, r);
    return min(max(d2.x, d2.y), 0.0) + length(max(d2, vec2(0.0, 0.0))) - r;
}

@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
    if
        in.pos.x < in.clip_min.x ||
        in.pos.y < in.clip_min.y ||
        in.pos.x > in.clip_max.x ||
        in.pos.y > in.clip_max.y
    {
        discard;         
    }
    
    let outer_sdf = rounded_rect_sdf(in.pos, in.rect_center, in.rect_half_size, in.rounding);
    let rounding_factor = vec4(1.0, 1.0, 1.0, 1.0 - smoothstep(0.0, 1.0, outer_sdf));

    var color = in.color;
    if in.stroke_width > 0.0 {
        let inner_half_size = in.rect_half_size - vec2(in.stroke_width, in.stroke_width);
        let inner_rounding = max(in.rounding - 2.0 * in.stroke_width, 0.0);
        let inner_sdf = rounded_rect_sdf(in.pos, in.rect_center, inner_half_size, inner_rounding);
        let stroke_fac = smoothstep(-0.5, 0.5, inner_sdf);
        color = mix(color, in.stroke_color, stroke_fac);
    }
    
    return color * sample(in.uv, in.tex) * rounding_factor;
}