pax-gpu 0.39.1

WGPU rendering library for the pax framework
Documentation
struct Paint {
    stops: array<vec4<f32>, 8>,
    axis: vec4<f32>,
    off_axis: vec4<f32>,
    params: vec4<f32>,
};
struct Globals { resolution: vec2<f32>, dpr: vec2<f32>, origin: vec2<f32>, padding: vec2<f32> };
@group(0) @binding(0) var<uniform> globals: Globals;
@group(0) @binding(1) var<uniform> paint_range: vec4<u32>;
@group(0) @binding(2) var<storage, read> paints: array<Paint>;
@group(1) @binding(0) var mesh_paints: texture_2d_array<f32>;
@group(1) @binding(1) var mesh_sampler: sampler;
struct VertexOutput {
    @builtin(position) position: vec4<f32>,
    @location(0) world: vec2<f32>,
};
@vertex fn vs_main(@location(0) point: vec2<f32>) -> VertexOutput {
    var out: VertexOutput;
    let p = (point - globals.origin) / globals.resolution * 2.0 - 1.0;
    out.position = vec4<f32>(p.x, -p.y, 0.0, 1.0);
    out.world = point;
    return out;
}
@fragment fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
    var alpha = 0.0;
    for (var i = 0u; i < paint_range.y; i++) {
        alpha += sample_alpha(paints[paint_range.x + i], in.world);
    }
    return vec4<f32>(clamp(alpha, 0.0, 1.0));
}
fn sample_alpha(paint: Paint, world: vec2<f32>) -> f32 {
    if paint.params.w > 1.5 {
        let delta = world - paint.axis.xy;
        let a = paint.axis.zw;
        let b = paint.off_axis.xy;
        let determinant = a.x*b.y - a.y*b.x;
        if abs(determinant) < 0.000001 { return 0.0; }
        let local = vec2<f32>(delta.x*b.y - delta.y*b.x, a.x*delta.y - a.y*delta.x) / determinant;
        let domain = paint.stops[0];
        let uv = (local - domain.xy) / domain.zw;
        if any(uv < vec2<f32>(0.0)) || any(uv > vec2<f32>(1.0)) { return 0.0; }
        return textureSampleLevel(mesh_paints, mesh_sampler, uv, i32(paint.params.x), 0.0).a * paint.params.y;
    }
    var alpha = paint.params.x;
    let count = u32(paint.params.z);
    if count > 0u {
        let delta = world - paint.axis.xy;
        let axis = paint.axis.zw;
        var coordinate = dot(delta, axis) / max(length(axis), 0.0001);
        let off = paint.off_axis.xy;
        let determinant = axis.x * off.y - axis.y * off.x;
        if paint.params.w < 0.5 && abs(determinant) > 0.0001 {
            coordinate = (delta.x * off.y - delta.y * off.x) / determinant * length(axis);
        }
        if paint.params.w > 0.5 {
            coordinate = radial_coordinate(delta, axis, off, paint.off_axis.zw);
            if coordinate < 0.0 { return 0.0; }
        }
        alpha = paint.stops[0].y;
        for (var i = 1u; i < 8u; i++) {
            if i >= count { break; }
            let a = paint.stops[i - 1u];
            let b = paint.stops[i];
            if coordinate >= b.x { alpha = b.y; }
            else if coordinate > a.x {
                alpha = mix(a.y, b.y, clamp((coordinate - a.x) / max(b.x - a.x, 0.0001), 0.0, 1.0));
                break;
            } else { break; }
        }
    }
    return alpha * paint.params.y;
}