facett-map/src/gpu/blit.wgsl
// Blit the map's offscreen colour into egui's render pass.
//
// The offscreen target is the WHOLE SURFACE (the vertices are in whole-surface
// coordinates), while egui has already set the pass viewport to the callback's own
// pane rect. So the quad covers the full NDC of that viewport and samples the PANE's
// sub-rectangle of the texture — `uv_min`/`uv_max` in 0..1 surface space. Getting this
// backwards draws the whole window shrunk into the pane, which is the same failure the
// lane's own `paint` note records from 2026-08-03.
struct Blit {
uv_min: vec2<f32>,
uv_max: vec2<f32>,
};
@group(0) @binding(0) var src: texture_2d<f32>;
@group(0) @binding(1) var samp: sampler;
@group(0) @binding(2) var<uniform> b: Blit;
struct VsOut {
@builtin(position) pos: vec4<f32>,
@location(0) uv: vec2<f32>,
};
// A full-viewport triangle, not a quad: three vertices, no index buffer, no seam
// down the diagonal.
@vertex
fn vs_main(@builtin(vertex_index) i: u32) -> VsOut {
let xy = array<vec2<f32>, 3>(
vec2<f32>(-1.0, -1.0),
vec2<f32>( 3.0, -1.0),
vec2<f32>(-1.0, 3.0),
);
let p = xy[i];
// NDC -> 0..1, with Y flipped: NDC +Y is up, texture V is down.
let t = vec2<f32>((p.x + 1.0) * 0.5, (1.0 - p.y) * 0.5);
let uv = b.uv_min + t * (b.uv_max - b.uv_min);
return VsOut(vec4<f32>(p, 0.0, 1.0), uv);
}
@fragment
fn fs_main(in: VsOut) -> @location(0) vec4<f32> {
return textureSample(src, samp, in.uv);
}