// Apply warp field with bicubic sampling
// This shader is currently a passthrough since warping is done in warp_field.wgsl
struct Metadata {
width: u32,
height: u32,
levels: u32,
_padding: u32,
}
@group(0) @binding(0) var<storage, read> warp_data: array<u32>;
@group(0) @binding(1) var<uniform> metadata: Metadata;
@group(0) @binding(2) var<storage, read_write> output: array<u32>;
// Bicubic kernel weight
fn cubic_weight(x: f32) -> f32 {
let abs_x = abs(x);
if (abs_x <= 1.0) {
return 1.5 * abs_x * abs_x * abs_x - 2.5 * abs_x * abs_x + 1.0;
} else if (abs_x <= 2.0) {
return -0.5 * abs_x * abs_x * abs_x + 2.5 * abs_x * abs_x - 4.0 * abs_x + 2.0;
}
return 0.0;
}
// Bicubic sampling
fn sample_bicubic(img: ptr<storage, array<u32>, read>, x: f32, y: f32, w: u32, h: u32) -> vec3<f32> {
let x0 = floor(x);
let y0 = floor(y);
let dx = x - x0;
let dy = y - y0;
var color = vec3<f32>(0.0);
var weight_sum = 0.0;
// 4x4 bicubic kernel
for (var j = -1; j <= 2; j++) {
for (var i = -1; i <= 2; i++) {
let sx = u32(clamp(x0 + f32(i), 0.0, f32(w - 1u)));
let sy = u32(clamp(y0 + f32(j), 0.0, f32(h - 1u)));
let pixel = img[sy * w + sx];
let r = f32(pixel & 0xFFu);
let g = f32((pixel >> 8u) & 0xFFu);
let b = f32((pixel >> 16u) & 0xFFu);
let wx = cubic_weight(dx - f32(i));
let wy = cubic_weight(dy - f32(j));
let weight = wx * wy;
color += vec3<f32>(r, g, b) * weight;
weight_sum += weight;
}
}
if (weight_sum > 0.0) {
color /= weight_sum;
}
return color;
}
@compute @workgroup_size(8, 8, 1)
fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
let x = global_id.x;
let y = global_id.y;
if (x >= metadata.width || y >= metadata.height) {
return;
}
let idx = y * metadata.width + x;
// Passthrough for now (warping already done in previous pass)
output[idx] = output[idx];
}