facett-core 0.1.19

facett — visual kernel: render a node/edge Scene into egui (wgpu fast path to come)
Documentation
// **The GPU label draw** — instanced glyph quads whose instance count comes from the
// collision pass's `atomicAdd`, consumed by `draw_indirect` (GFX_V2 item 4).
//
// One instance per glyph-tap: `label_collide.wgsl` expands each glyph into 4 halo taps
// plus the ink pass, contiguously per label, so within a label the halo rasterises
// under the ink. Across labels order does not matter — not drawing two labels on the
// same pixels is the entire point of the pass upstream.
//
// ── Why this is not `msdf.wgsl` ─────────────────────────────────────────────────
//
// The atlas here is epaint's own font atlas — an 8-bit COVERAGE field premultiplied
// into RGBA, the same texture egui's text pass samples. Reusing egui's atlas is what
// makes a GPU-drawn street name identical to the CPU-painted one, so the fail-safe
// lane and the device lane letter the map the same way (and no font rasteriser,
// offline `msdf-atlas-gen` step or second copy of the glyph cache enters the tree).
//
// A coverage atlas has no signed distance to reconstruct, so `msdf_fs`'s median-of-
// three-channels and its `px_range` slope would be arithmetic over a field that is not
// there — `median3(a,a,a) - 0.5` on a coverage value is not a distance, and scaling it
// by a pixel range would harden the antialiasing egui already resolved. Sampling
// `.a` and letting the bilinear filter do the edge is the correct reconstruction for
// this texture. `MsdfText` remains the right pipeline for a real MSDF atlas.

struct LabelDrawU {
    // x,y = viewport size in px (the space the collision pass emitted rects in)
    vp: vec4<f32>,
};

@group(0) @binding(0) var<uniform> U: LabelDrawU;
@group(1) @binding(0) var atlas_tex: texture_2d<f32>;
@group(1) @binding(1) var atlas_smp: sampler;

struct GlyphIn {
    @location(0) rect_min: vec2<f32>,
    @location(1) rect_max: vec2<f32>,
    @location(2) uv_min: vec2<f32>,
    @location(3) uv_max: vec2<f32>,
    @location(4) color: vec4<f32>,
};

struct VOut {
    @builtin(position) clip: vec4<f32>,
    @location(0) uv: vec2<f32>,
    @location(1) color: vec4<f32>,
};

@vertex
fn label_vs(@builtin(vertex_index) vi: u32, g: GlyphIn) -> VOut {
    var corners = array<vec2<f32>, 6>(
        vec2<f32>(0.0, 0.0), vec2<f32>(1.0, 0.0), vec2<f32>(0.0, 1.0),
        vec2<f32>(0.0, 1.0), vec2<f32>(1.0, 0.0), vec2<f32>(1.0, 1.0),
    );
    let c = corners[vi];
    let px = mix(g.rect_min, g.rect_max, c);
    let uv = mix(g.uv_min, g.uv_max, c);
    // Pixel rect -> NDC, y down in pixel space.
    let ndc = vec2<f32>(px.x / U.vp.x * 2.0 - 1.0, 1.0 - px.y / U.vp.y * 2.0);
    var out: VOut;
    out.clip = vec4<f32>(ndc, 0.0, 1.0);
    out.uv = uv;
    out.color = g.color;
    return out;
}

@fragment
fn label_fs(in: VOut) -> @location(0) vec4<f32> {
    // epaint writes each glyph as white premultiplied by its coverage, so alpha IS the
    // coverage and the colour channels carry no glyph information of their own.
    let cov = textureSample(atlas_tex, atlas_smp, in.uv).a;
    let a = cov * in.color.a;
    return vec4<f32>(in.color.rgb * a, a);  // premultiplied source-over
}