facett-core 0.1.12

facett — visual kernel: render a node/edge Scene into egui (wgpu fast path to come)
Documentation
//! **INJECT-ASSERT (CONS-CORE §6)** — the L0 SDF coverage kernel: inject N circle /
//! ring / marker instances and assert the CPU coverage buffer lights pixels **only
//! inside `radius ± aa`**, that coverage is **monotone** across the AA band, that a
//! **ring has a hole**, and that **each marker shape's geometry matches**. Per LAW
//! #3 the cases are a **parameter sweep** over radius × AA, not a single case.

use facett_core::render::cpu::sdf;
use facett_core::render::prim::{shape, CircleInstance, MarkerInstance, QuadInstance, RingInstance};
use facett_core::render::{Camera, Canvas, CpuCanvas};

/// Pixel at `(x,y)` of a straight-RGBA8 frame's alpha channel.
fn alpha(rgba: &[u8], w: u32, x: u32, y: u32) -> u8 {
    rgba[((y * w + x) * 4 + 3) as usize]
}

#[test]
fn circle_coverage_lit_only_inside_radius_band_swept() {
    // SWEEP radius × aa (LAW #3: a grid, not one case).
    for &radius in &[3.0f32, 6.0, 12.0, 24.0, 48.0] {
        for &aa in &[0.0f32, 0.5, 1.0, 2.0, 4.0] {
            let c = CircleInstance { center: [0.0, 0.0], radius, color: [1.0; 4], aa };
            let q = c.lower();
            // The centre is the most-lit point. It reaches full opacity once the AA
            // band is no wider than the radius; when aa ≥ radius the disc is all
            // fringe, so we only require it be substantially lit + the field maximum.
            let centre = sdf::quad_coverage(&q, 0.0, 0.0);
            if aa < radius {
                assert!(centre > 0.99, "centre fully lit r={radius} aa={aa}");
            } else {
                assert!(centre > 0.5, "centre substantially lit (aa≥r) r={radius} aa={aa}");
            }
            assert!(centre >= sdf::quad_coverage(&q, radius * 0.5, 0.0) - 1e-6, "centre is the max");
            // Just outside the band is dark.
            let outside = radius + aa + 1.0;
            assert!(
                sdf::quad_coverage(&q, outside, 0.0) < 0.01,
                "beyond band dark r={radius} aa={aa}"
            );
            // No coverage anywhere past radius+aa, in any of 16 directions.
            for k in 0..16 {
                let ang = std::f32::consts::TAU * k as f32 / 16.0;
                let d = radius + aa + 0.5;
                let cov = sdf::quad_coverage(&q, d * ang.cos(), d * ang.sin());
                assert!(cov < 0.05, "no ink outside radius+aa (dir {k}) r={radius} aa={aa}");
            }
        }
    }
}

#[test]
fn circle_alpha_is_monotone_non_increasing_across_the_band() {
    for &radius in &[8.0f32, 16.0, 32.0] {
        for &aa in &[1.0f32, 2.0, 4.0] {
            let q = CircleInstance { center: [0.0, 0.0], radius, color: [1.0; 4], aa }.lower();
            // Walk radially outward; coverage must never increase.
            let mut prev = 1.01;
            let mut d = 0.0;
            while d <= radius + aa + 2.0 {
                let cov = sdf::quad_coverage(&q, d, 0.0);
                assert!(cov <= prev + 1e-5, "monotone at d={d} r={radius} aa={aa}");
                prev = cov;
                d += 0.25;
            }
            // The exact edge sits near half coverage.
            assert!((sdf::quad_coverage(&q, radius, 0.0) - 0.5).abs() < 0.06, "edge≈0.5");
        }
    }
}

#[test]
fn ring_has_a_hole_swept() {
    for &outer in &[10.0f32, 20.0, 40.0] {
        for &frac in &[0.3f32, 0.5, 0.7] {
            let inner = outer * frac;
            let aa = 1.0;
            let q = RingInstance { center: [0.0; 2], radius: outer, inner, color: [1.0; 4], aa }.lower();
            // Centre is a hole.
            assert!(sdf::quad_coverage(&q, 0.0, 0.0) < 0.02, "hole o={outer} f={frac}");
            // The band midpoint is lit.
            let mid = (outer + inner) * 0.5;
            assert!(sdf::quad_coverage(&q, mid, 0.0) > 0.95, "band lit o={outer} f={frac}");
            // Beyond outer is dark.
            assert!(sdf::quad_coverage(&q, outer + aa + 1.0, 0.0) < 0.02, "outside dark");
            // Just inside the hole edge is dark, just outside it lit (the hole is real).
            assert!(sdf::quad_coverage(&q, inner - aa - 0.5, 0.0) < 0.05, "inside hole dark");
        }
    }
}

#[test]
fn marker_shapes_match_their_geometry() {
    let half = 12.0;
    let aa = 0.5;
    let mk = |shp: u32| MarkerInstance { center: [0.0; 2], radius: half, corner: 0.0, color: [1.0; 4], aa, shape: shp }.lower();
    let square = mk(shape::SQUARE);
    let diamond = mk(shape::DIAMOND);
    let triangle = mk(shape::TRIANGLE);

    // The box corner (just inside ±half): inside the SQUARE, outside the DIAMOND.
    let corner = half - 1.0;
    assert!(sdf::quad_coverage(&square, corner, corner) > 0.9, "square fills corner");
    assert!(sdf::quad_coverage(&diamond, corner, corner) < 0.1, "diamond cuts the corner");

    // Diamond lit on its axes (|x|+|y| small), e.g. on +x axis well inside.
    assert!(sdf::quad_coverage(&diamond, half - 2.0, 0.0) > 0.9, "diamond axis lit");

    // Triangle: apex up (y negative is up here). Base-centre lit, top corners cut.
    assert!(sdf::quad_coverage(&triangle, 0.0, half - 2.0) > 0.9, "triangle base lit");
    assert!(sdf::quad_coverage(&triangle, half - 1.0, -(half - 1.0)) < 0.1, "triangle top-corner cut");

    // Centre lit for all three.
    for q in [&square, &diamond, &triangle] {
        assert!(sdf::quad_coverage(q, 0.0, 0.0) > 0.9, "marker centre lit");
    }
}

#[test]
fn cpu_canvas_rasters_a_lit_circle_inside_the_band_only() {
    // End-to-end through the CpuCanvas (vello_cpu pixmap target): a centred circle
    // lights an interior pixel, leaves the corners background, and the lit region
    // is bounded by radius+aa.
    let w = 80;
    let h = 80;
    let radius = 20.0;
    let aa = 1.5;
    let mut canvas = CpuCanvas::new(w, h, Camera::default(), [0, 0, 0, 0]);
    let q: QuadInstance =
        CircleInstance { center: [40.0, 40.0], radius, color: [1.0, 0.2, 0.1, 1.0], aa }.lower();
    canvas.push_quads(&[q]);
    let frame = canvas.rasterize();

    assert!(alpha(&frame.rgba, w, 40, 40) > 250, "centre fully opaque");
    assert_eq!(alpha(&frame.rgba, w, 0, 0), 0, "corner is transparent background");
    // Every lit pixel sits within radius+aa of the centre.
    let lim = (radius + aa + 1.0).powi(2);
    for y in 0..h {
        for x in 0..w {
            if alpha(&frame.rgba, w, x, y) > 4 {
                let dx = x as f32 + 0.5 - 40.0;
                let dy = y as f32 + 0.5 - 40.0;
                assert!(dx * dx + dy * dy <= lim, "lit pixel ({x},{y}) inside radius+aa");
            }
        }
    }
    assert!(frame.lit_px() > 100, "the disc lit a real region, got {}", frame.lit_px());
}