xgpui-wgpu 1.0.2

wgpu rendering backend, texture atlas, and text support for xgpui
Documentation
struct Params { bounds: vec4<f32>, mask: vec4<f32>, radii: vec4<f32>, viewport: vec4<f32>, color_r: vec4<f32>, color_g: vec4<f32>, color_b: vec4<f32>, vignette: vec4<f32>, linear: vec4<f32> }
@group(0) @binding(0) var<uniform> p: Params;
@group(0) @binding(1) var paint_sampler: sampler;
@group(0) @binding(2) var image: texture_2d<f32>;
@group(0) @binding(3) var shape_mask: texture_2d<f32>;
struct Vertex { @builtin(position) position: vec4<f32>, @location(0) uv: vec2<f32> }
@vertex fn custom_vertex(@builtin(vertex_index) id: u32) -> Vertex {
    let vertices = array<vec2<f32>,6>(vec2(0.,0.),vec2(1.,0.),vec2(0.,1.),vec2(0.,1.),vec2(1.,0.),vec2(1.,1.));
    let uv = vertices[id];
    let xy = p.bounds.xy + uv * p.bounds.zw;
    return Vertex(vec4(xy.x / p.viewport.x * 2. - 1., 1. - xy.y / p.viewport.y * 2., 0., 1.), uv);
}
fn decode_srgb(c: f32) -> f32 {
    return select(c / 12.92, pow((c + 0.055) / 1.055, 2.4), c > 0.04045);
}
fn encode_srgb(c: f32) -> f32 {
    return select(12.92 * c, 1.055 * pow(c, 1.0 / 2.4) - 0.055, c > 0.0031308);
}
fn p3_to_srgb(c: vec3<f32>) -> vec3<f32> {
    return vec3(dot(c,vec3(1.22494018,-0.22494018,0.)),dot(c,vec3(-0.04205695,1.04205695,0.)),dot(c,vec3(-0.01963755,-0.07863605,1.09827360)));
}
fn srgb_to_p3(c: vec3<f32>) -> vec3<f32> {
    return vec3(dot(c,vec3(0.82246197,0.17753803,0.)),dot(c,vec3(0.03319420,0.96680580,0.)),dot(c,vec3(0.01708263,0.07239744,0.91051993)));
}
// Linear SDR Rec.2020 -> P3; retain extended channels until preview mapping.
fn rec2020_to_p3(c: vec3<f32>) -> vec3<f32> {
    return vec3(dot(c,vec3(1.343578253,-0.282179671,-0.061398582)),dot(c,vec3(-0.065297453,1.075787916,-0.010490463)),dot(c,vec3(0.002821787,-0.019598495,1.016776707)));
}
@fragment fn custom_fragment(in: Vertex) -> @location(0) vec4<f32> {
    if any(in.position.xy < p.mask.xy) || any(in.position.xy >= p.mask.xy + p.mask.zw) { discard; }
    let local = in.uv * p.bounds.zw;
    let right = local.x > p.bounds.z * 0.5;
    let bottom = local.y > p.bounds.w * 0.5;
    let r = select(select(p.radii.x, p.radii.y, right), select(p.radii.w, p.radii.z, right), bottom);
    let q = abs(local - p.bounds.zw * 0.5) - p.bounds.zw * 0.5 + r;
    let distance = length(max(q, vec2(0.))) + min(max(q.x,q.y),0.) - r;
    var coverage = clamp(0.5 - distance,0.,1.);
    if (u32(p.viewport.w) & 1u) != 0u { coverage = textureSample(shape_mask,paint_sampler,in.uv).r; }
    var color = textureSample(image,paint_sampler,in.uv);
    if p.linear.y > 2.5 { color = vec4(rec2020_to_p3(color.rgb), color.a); }
    if p.viewport.w > 1.5 && color.a > 0. { color = vec4(color.rgb / color.a, color.a); }
    let processing = p.linear.x > 0.5 || p.linear.y > 0.5;
    var rgb = color.rgb;
    if p.linear.y > 0.5 {
        rgb = vec3(0.);
        if color.a > 0. { rgb = color.rgb / color.a; }
        if p.linear.z < 0.5 { rgb = p3_to_srgb(rgb); }
    } else if processing {
        let c = clamp(rgb, vec3(0.), vec3(1.));
        rgb = vec3(decode_srgb(c.r), decode_srgb(c.g), decode_srgb(c.b));
        if p.linear.z > 0.5 { rgb = srgb_to_p3(rgb); }
    }
    color = vec4(rgb, color.a);
    let rgb1 = vec4(color.rgb, 1.);
    color = vec4(dot(p.color_r,rgb1), dot(p.color_g,rgb1), dot(p.color_b,rgb1), color.a);
    if processing {
        let dims = vec2<f32>(textureDimensions(image, 0));
        let q = in.uv * 2. - vec2(1.);
        let ellipse = length(q);
        let circle = length(q * dims / min(dims.x, dims.y));
        let d = mix(ellipse, circle, p.vignette.w);
        let t = clamp((d - p.vignette.y) / p.vignette.z, 0., 1.);
        let factor = 1. - p.vignette.x * t * t * (3. - 2. * t);
        rgb = color.rgb * factor;
        if p.linear.z > 0.5 { rgb = p3_to_srgb(rgb); }
        let c = clamp(rgb, vec3(0.), vec3(1.));
        color = vec4(encode_srgb(c.r), encode_srgb(c.g), encode_srgb(c.b), color.a);
        if color.a == 0. { color = vec4(0.); }
    }
    return vec4(color.rgb, color.a * coverage * p.viewport.z);
}