cranpose-render-wgpu 0.1.164

WGPU renderer backend for Cranpose
Documentation
use super::*;

fn plain_card() -> RuntimeShader {
    let mut shader = RuntimeShader::new("fn main() {}");
    shader.set_float2(CONTAINER_UNIFORM, 300.0, 120.0);
    shader.set_float2(CENTER_UNIFORM, 150.0, 60.0);
    shader.set_float2(SIZE_UNIFORM, 300.0, 120.0);
    shader.set_float(CORNER_RADIUS_UNIFORM, 20.0);
    shader.set_float(REFRACTION_DEPTH_UNIFORM, 0.58);
    for flag in PLAIN_SDF_FLAGS {
        shader.set_override(flag, 1.0);
    }
    shader
}

#[test]
fn a_plain_card_splits_into_an_inset_interior_and_four_rim_bands_around_a_hole() {
    let shader = plain_card();
    let rect = [10.0, 20.0, 600.0, 240.0];
    let bounds = (0, 0, 720, 480);
    let split =
        split_scissors(&shader, (30.0, 40.0), rect, bounds).expect("a plain rounded rect splits");
    let interior = split.interior.expect("the card has an interior");
    assert!(
        interior.0 > 40 && interior.1 > 60,
        "the interior is inset from the card"
    );
    assert!(
        interior.0 + interior.2 < 640 && interior.1 + interior.3 < 300,
        "the interior stays inside the card: {interior:?}"
    );
    let bands: Vec<Scissor> = split.rim.iter().flatten().copied().collect();
    assert_eq!(bands.len(), 4, "the rim is four bands around the hole");
    let hole_x = bands[2].0 + bands[2].2;
    let hole_y = bands[0].1 + bands[0].3;
    assert!(
        hole_x > interior.0 && hole_y > interior.1,
        "the hole is inset further than the interior by the corner radius"
    );
    let covered: u32 = bands.iter().map(|(_, _, w, h)| w * h).sum();
    let hole_area = bands[3].0.saturating_sub(hole_x) * bands[1].1.saturating_sub(hole_y);
    assert_eq!(
        covered + hole_area,
        720 * 480,
        "bands and hole tile the bounds exactly"
    );
}

fn rounded_rect_distance(p: (f32, f32), half: (f32, f32), radius: f32) -> f32 {
    let q = (p.0.abs() - (half.0 - radius), p.1.abs() - (half.1 - radius));
    let outside = (q.0.max(0.0).powi(2) + q.1.max(0.0).powi(2)).sqrt();
    outside + q.0.max(q.1).min(0.0) - radius
}

#[test]
fn the_rim_hole_lies_deeper_than_the_rim_reach_even_for_a_wide_corner() {
    let mut shader = plain_card();
    shader.set_float2(CONTAINER_UNIFORM, 300.0, 200.0);
    shader.set_float2(CENTER_UNIFORM, 150.0, 100.0);
    shader.set_float2(SIZE_UNIFORM, 300.0, 200.0);
    shader.set_float(CORNER_RADIUS_UNIFORM, 60.0);
    let rect = [0.0, 0.0, 600.0, 400.0];
    let reach = reach(&shader, (0.0, 0.0), rect);
    let split = split_scissors(&shader, (0.0, 0.0), rect, (0, 0, 600, 400))
        .expect("a wide-cornered card splits");
    let bands: Vec<Scissor> = split.rim.iter().flatten().copied().collect();
    assert_eq!(bands.len(), 4);
    assert_hole_corners_beyond_the_rim(&reach, &bands);
}

fn hole(bands: &[Scissor]) -> (u32, u32, u32, u32) {
    (
        bands[2].0 + bands[2].2,
        bands[0].1 + bands[0].3,
        bands[3].0,
        bands[1].1,
    )
}

fn assert_hole_corners_beyond_the_rim(reach: &Reach, bands: &[Scissor]) {
    let (hx0, hy0, hx1, hy1) = hole(bands);
    let half = (reach.width * 0.5, reach.height * 0.5);
    let center = (reach.inner_x + half.0, reach.inner_y + half.1);
    for (x, y) in [
        (hx0, hy0),
        (hx1 - 1, hy0),
        (hx0, hy1 - 1),
        (hx1 - 1, hy1 - 1),
    ] {
        let p = (x as f32 + 0.5 - center.0, y as f32 + 0.5 - center.1);
        let d = rounded_rect_distance(p, half, reach.corner);
        assert!(
            d <= -reach.rim_high,
            "hole corner ({x}, {y}) sits at d = {d:.1}, within the rim's reach of \
             {:.1}: the hole must exclude only fragments the rim draw discards",
            reach.rim_high
        );
    }
}

#[test]
fn a_short_wide_cornered_card_keeps_a_hole_whose_corners_lie_beyond_the_rim_reach() {
    let mut shader = plain_card();
    shader.set_float2(CONTAINER_UNIFORM, 200.0, 70.0);
    shader.set_float2(CENTER_UNIFORM, 100.0, 35.0);
    shader.set_float2(SIZE_UNIFORM, 200.0, 70.0);
    shader.set_float(CORNER_RADIUS_UNIFORM, 25.0);
    let rect = [0.0, 0.0, 445.0, 156.0];
    let reach = reach(&shader, (0.0, 0.0), rect);
    let whole_corner_hole = reach.height - 2.0 * (reach.rim_high + reach.corner);
    assert!(
        whole_corner_hole < 16.0,
        "the case is a card whose hole inset by the whole corner is a sliver: {} px of {}",
        whole_corner_hole,
        reach.height
    );
    let split =
        split_scissors(&shader, (0.0, 0.0), rect, (0, 0, 445, 156)).expect("a plain card splits");
    let bands: Vec<Scissor> = split.rim.iter().flatten().copied().collect();
    assert_eq!(
        bands.len(),
        4,
        "the tangent inset leaves a hole: {:?}",
        split.rim
    );
    let (hx0, hy0, hx1, hy1) = hole(&bands);
    assert!(
        (hx1 - hx0) * (hy1 - hy0) > 445 * 156 / 3,
        "the hole covers a third of the card: {}x{}",
        hx1 - hx0,
        hy1 - hy0
    );
    assert_hole_corners_beyond_the_rim(&reach, &bands);
}

#[test]
fn a_material_with_scene_shapes_or_wobble_or_strain_keeps_whole_quads() {
    for flag in PLAIN_SDF_FLAGS {
        let mut shader = plain_card();
        shader.clear_override(flag);
        assert!(
            split_scissors(
                &shader,
                (0.0, 0.0),
                [0.0, 0.0, 100.0, 50.0],
                (0, 0, 100, 50)
            )
            .is_none(),
            "{flag} lowered means the SDF is not the plain rounded rect"
        );
    }
}

#[test]
fn a_tiny_card_has_no_hole_and_the_rim_is_the_whole_bounds() {
    let shader = plain_card();
    let split = split_scissors(&shader, (0.0, 0.0), [0.0, 0.0, 30.0, 12.0], (0, 0, 30, 12))
        .expect("a plain card splits");
    assert_eq!(split.rim, [Some((0, 0, 30, 12)), None, None, None]);
}

#[test]
fn a_card_whose_hole_and_interior_lie_outside_the_bounds_keeps_the_rim_over_the_bounds() {
    let shader = plain_card();
    let bounds = (0, 0, 720, 70);
    let split = split_scissors(&shader, (30.0, 40.0), [10.0, 20.0, 600.0, 240.0], bounds)
        .expect("a plain card splits");
    assert_eq!(
        split.interior, None,
        "no interior pixel is inside the bounds"
    );
    assert_eq!(split.rim, [Some(bounds), None, None, None]);
}