facett-core 0.1.18

facett — visual kernel: render a node/edge Scene into egui (wgpu fast path to come)
Documentation
// ─────────────────────────────────────────────────────────────────────────────
// THE colour-encoded ID pass (GFX_V2 §7 item 8) — the shader half of
// `render::gpu::picking`.
//
// Each pickable primitive carries its `PickId` as a per-vertex `u32`; the fragment
// stage writes that number, unmodified, into an `R32Uint` attachment. A click reads
// one texel back and decodes it with `PickId::from_rgba` — the SAME encoding
// `facett_core::engine::pick`'s CPU lane returns, so the two lanes answer one
// question with one number (LAW #5).
//
// Three properties are load-bearing, and all three are enforced OUTSIDE this file
// so no shader edit can lose them (see `picking.rs`):
//   * `@interpolate(flat)` — an id must never be interpolated. WGSL requires flat
//     for integer inter-stage values, so this is checked by the compiler, but it is
//     spelled explicitly because the failure mode (a blended id = a wrong click on
//     a THIRD object that was never under the cursor) is silent.
//   * the target is `R32Uint`, which WebGPU makes non-filterable, non-blendable and
//     non-multisampleable — the three things that corrupt an id into a neighbour's.
//   * the pass clears to 0 = `PickId::NOTHING`, the reserved miss sentinel that
//     `PickId::new` can never produce for a real (layer, feature).
//
// Needs the shared prelude for `px_to_ndc` — compose with `render::gpu::wgsl()`.
// ─────────────────────────────────────────────────────────────────────────────

struct PickUniforms {
    /// Target size in PHYSICAL pixels — the space `pos_px` is expressed in.
    viewport: vec2<f32>,
    _pad: vec2<f32>,
};
@group(0) @binding(0) var<uniform> pick_u: PickUniforms;

struct PickVertexIn {
    /// Position in physical pixels, origin top-left (the same space the CPU
    /// painter and every other facett GPU lane use).
    @location(0) pos_px: vec2<f32>,
    /// Clip-space depth in `0..1`, 0 = nearest. Lets the pick pass resolve
    /// occlusion the same way the colour pass does, so a 3D click returns the
    /// object a viewer can actually see rather than whichever drew last.
    @location(1) depth: f32,
    /// The encoded `PickId`. Never 0 for a real feature.
    @location(2) id: u32,
};

struct PickVertexOut {
    @builtin(position) clip: vec4<f32>,
    @location(0) @interpolate(flat) id: u32,
};

@vertex
fn pick_vs(v: PickVertexIn) -> PickVertexOut {
    var out: PickVertexOut;
    out.clip = vec4<f32>(px_to_ndc(v.pos_px, pick_u.viewport), v.depth, 1.0);
    out.id = v.id;
    return out;
}

@fragment
fn pick_fs(in: PickVertexOut) -> @location(0) u32 {
    return in.id;
}