kludgine 0.11.0

A wgpu-powered 2d graphics library with optional windowing support
Documentation
struct PushConstants {
    flags: i32,
    scale: f32,
    rotation: f32,
    opacity: f32,
    translation_x: i32,
    translation_y: i32,
}
var<push_constant> pc: PushConstants;

struct VertexInput {
    @location(0) position: vec2<i32>,
    @location(1) uv: vec2<u32>,
    @location(2) color: u32,
}

struct VertexOutput {
    @builtin(position) position: vec4<f32>,
    @location(0) color: vec4<f32>,
    @location(1) uv: vec2<f32>,
}

struct Uniforms {
    ortho: mat4x4<f32>,
    dips_scale: u32,
}

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

struct Fraction {
    div_by: i32,
    mul_by: i32,
}

fn ratio(raio: u32) -> Fraction {
    var ratio: Fraction;
    ratio.div_by = i32(uniforms.dips_scale >> u32(16));
    ratio.mul_by = i32(uniforms.dips_scale & u32(0xFFFF));
    return ratio;
}

fn ratio_to_f32(ratio: Fraction) -> f32 {
    return f32(ratio.mul_by) / f32(ratio.div_by);
}

fn int_scale(value: i32, ratio: Fraction) -> i32 {
    return value * ratio.mul_by / ratio.div_by;
}

fn dips_to_pixels(value: i32, ratio: Fraction) -> i32 {
    return (int_scale(value, ratio) * i32(96 * 4) + 91439) / i32(182880);
}

fn int_to_rgba(color: u32) -> vec4<f32> {
    let r = color >> u32(24);
    let g = (color >> u32(16)) & u32(0xFF);
    let b = (color >> u32(8)) & u32(0xFF);
    let a = color & u32(0xFF);

    return vec4<f32>(f32(r) / 255.0, f32(g) / 255.0, f32(b) / 255.0, f32(a) / 255.0);
}

@vertex
fn vertex(input: VertexInput) -> VertexOutput {
    let flag_dips = u32(1);
    let flag_scale = flag_dips << u32(1);
    let flag_rotation = flag_dips << u32(2);
    let flag_translate = flag_dips << u32(3);

    let flags = u32(pc.flags);

    var dips_scale = ratio(uniforms.dips_scale);
    var outval: VertexOutput;
    var position: vec2<f32>;
    if (flags & flag_dips) != u32(0) {
        position = vec2<f32>(
            f32(dips_to_pixels(input.position.x, dips_scale)),
            f32(dips_to_pixels(input.position.y, dips_scale)),
        );
    } else {
        position = vec2<f32>(
            f32(input.position.x),
            f32(input.position.y),
        );
    }
    if (flags & flag_rotation) != u32(0) {
        var angle_cos = cos(pc.rotation);
        var angle_sin = sin(pc.rotation);
        position = position * mat2x2<f32>(angle_cos, -angle_sin, angle_sin, angle_cos);
    }
    if (flags & flag_scale) != u32(0) {
        position = position * pc.scale;
    }
    if (flags & flag_translate) != u32(0) {
        position = position + vec2<f32>(
            f32(pc.translation_x),
            f32(pc.translation_y)
        );
    }
    outval.position = uniforms.ortho * vec4<f32>(position / 4., 0., 1.0);
    outval.color = int_to_rgba(input.color);
    outval.color.a = pc.opacity * outval.color.a;
    outval.uv = vec2<f32>(input.uv) / vec2<f32>(textureDimensions(r_texture));
    return outval;
}

struct FragmentInput {
    @location(0) color: vec4<f32>,
    @location(1) uv: vec2<f32>,
}

@group(0)
@binding(1)
var r_texture: texture_2d<f32>;
@group(0)
@binding(2)
var r_sampler: sampler;

@fragment
fn fragment(fragment: FragmentInput) -> @location(0) vec4<f32> {
    let flag_textured = u32(1) << u32(4);
    let flag_masked = u32(1) << u32(5);

    var color = fragment.color;

    let flags = u32(pc.flags);
    if (flags & flag_textured) != u32(0) {
        let sample = textureSample(r_texture, r_sampler, fragment.uv / 4.);
        if (flags & flag_masked) != u32(0) {
            return vec4<f32>(color.x, color.y, color.z, sample.x * color.w);
        }

        return sample * color;
    }

    return color;
}