facett-map3d-flight/src/cdlod_morph.wgsl
// CDLOD terrain vertex height-morph — the crack-closing blend, as a compute pass.
//
// This is the exact op the terrain VERTEX shader runs per vertex (roadmap §6): a
// vertex's height morphs from its own grid value `h` toward the parent (coarser) grid
// value `h_parent` by the node's `morph` factor, so a fine node's shared edge with a
// coarser neighbour collapses onto the coarse edge (no T-junction crack). Running it as
// a compute pass here lets the Rust side read the result back and prove it is the SAME
// function as the CPU `cdlod::morph_height` oracle (the scatter_lut.wgsl parity pattern).
//
// Layout mirrors `MorphParams` / the two storage buffers in `cdlod.rs::gpu`.
struct Params {
morph : f32, // the node's morph factor in [0,1]
count : u32, // number of (h, h_parent) pairs
_pad0 : u32,
_pad1 : u32,
};
@group(0) @binding(0) var<uniform> params : Params;
@group(0) @binding(1) var<storage, read> pairs : array<vec2<f32>>; // [h, h_parent]
@group(0) @binding(2) var<storage, read_write> out : array<f32>; // morphed height
// The crack-closing linear blend: identity at morph 0, the parent grid at morph 1.
fn morph_height(h : f32, h_parent : f32, morph : f32) -> f32 {
return h + clamp(morph, 0.0, 1.0) * (h_parent - h);
}
@compute @workgroup_size(64)
fn cs_morph(@builtin(global_invocation_id) gid : vec3<u32>) {
let i = gid.x;
if (i >= params.count) {
return;
}
let p = pairs[i];
out[i] = morph_height(p.x, p.y, params.morph);
}