lumen-engine 0.2.1

Core composition model and rendering orchestration for Lumen.
Documentation
struct BooleanParams {
    values: vec4<f32>,
}

@group(0) @binding(0) var a_tex: texture_2d<f32>;
@group(0) @binding(1) var b_tex: texture_2d<f32>;
@group(0) @binding(2) var<uniform> params: BooleanParams;
@group(0) @binding(3) var output_tex: texture_storage_2d<rgba8unorm, write>;

fn sample_or_transparent(tex: texture_2d<f32>, pixel: vec2<u32>) -> vec4<f32> {
    let size = textureDimensions(tex);
    if (pixel.x >= size.x || pixel.y >= size.y) {
        return vec4<f32>(0.0);
    }
    return textureLoad(tex, vec2<i32>(pixel), 0);
}

@compute @workgroup_size(8, 8, 1)
fn cs_main(@builtin(global_invocation_id) id: vec3<u32>) {
    let size = textureDimensions(output_tex);
    if (id.x >= size.x || id.y >= size.y) {
        return;
    }

    let a = sample_or_transparent(a_tex, id.xy);
    let b = sample_or_transparent(b_tex, id.xy);
    let operation = u32(params.values.x);
    let threshold = clamp(params.values.y, 0.0, 1.0);
    let aa = select(a.a, 1.0, a.a > threshold);
    let ba = select(b.a, 1.0, b.a > threshold);
    var alpha = max(aa, ba);
    if (operation == 1u) {
        alpha = min(aa, ba);
    } else if (operation == 2u) {
        alpha = aa * (1.0 - ba);
    } else if (operation == 3u) {
        alpha = abs(aa - ba);
    }
    let rgb = select(b.rgb, a.rgb, aa >= ba);
    textureStore(output_tex, vec2<i32>(id.xy), vec4<f32>(rgb * alpha, alpha));
}