sophus_renderer 0.14.0

wgpu-based renderer
Documentation
@group(0) @binding(0)
var<uniform> camera: CameraProperties;
@group(0) @binding(1)
var<uniform> zoom: Zoom2d;
@group(0) @binding(2)
var<uniform> pinhole: PinholeModel;

@group(1) @binding(0) var input_texture : texture_2d<f32>;
@group(1) @binding(1) var output_texture : texture_storage_2d<rgba8unorm, write>;
@group(1) @binding(2) var background_texture : texture_2d<f32>;
@group(1) @binding(3) var depth_texture : texture_multisampled_2d<f32>;
@group(1) @binding(4) var distorted_depth_texture : texture_storage_2d<r32float, write>;

 fn distort_pixel(
    view_port_coords_distorted: vec2<u32>,
    image_size: vec2<f32>,
    view_port_size: vec2<u32>,
    background_color: vec4<f32>
) {
    let uv_distorted =  vec2<f32>(view_port_coords_distorted) *  vec2<f32>(image_size) / vec2<f32>(view_port_size);
    let uv_undistorted = undistort(vec2<f32>(uv_distorted), pinhole, camera);
    let view_port_coords_undistorted = uv_undistorted * vec2<f32>(view_port_size) / vec2<f32>(image_size);

    // bi-linear interpolation
    let x0 = floor(view_port_coords_undistorted.x);
    let x1 = ceil(view_port_coords_undistorted.x);
    let y0 = floor(view_port_coords_undistorted.y);
    let y1 = ceil(view_port_coords_undistorted.y);

    let tx = view_port_coords_undistorted.x - x0;
    let ty = view_port_coords_undistorted.y - y0;

    let c00 = textureLoad(input_texture, vec2<u32>(u32(x0), u32(y0)), 0);
    let c10 = textureLoad(input_texture, vec2<u32>(u32(x1), u32(y0)), 0);
    let c01 = textureLoad(input_texture, vec2<u32>(u32(x0), u32(y1)), 0);
    let c11 = textureLoad(input_texture, vec2<u32>(u32(x1), u32(y1)), 0);

    let foreground_color = mix(
        mix(c00, c10, tx),
        mix(c01, c11, tx),
        ty
    );

    // depth lookup without interpolation, and also just the first sample
    // todo: use the correct sample, or min over all samples
    let ndc_z = textureLoad(depth_texture,  vec2<u32>(view_port_coords_undistorted), 0);

    // Use the alpha channel of the foreground for blending
    let alpha = foreground_color.a;

    let mixed = vec4<f32>(
        mix(background_color.rgb, foreground_color.rgb, alpha),
        1.0 // Keep the output fully opaque
    );

    textureStore(distorted_depth_texture, view_port_coords_distorted, ndc_z);
    textureStore(output_texture, view_port_coords_distorted, mixed);
}

@compute @workgroup_size(16, 16)
fn distort(@builtin(global_invocation_id) global_id : vec3<u32>) {
    let view_port_size = textureDimensions(input_texture);
    let coords = vec2<u32>(global_id.xy);

    if (coords.x >= view_port_size.x || coords.y >=  view_port_size.y) {
        return;
    }

    let background_color = vec4<f32>(1.0, 1.0, 1.0, 1.0);
    let image_size = vec2<f32>(camera.camera_image_width, camera.camera_image_height);

    distort_pixel(coords, image_size, view_port_size, background_color);
}

@compute @workgroup_size(16, 16)
fn distort_with_background(@builtin(global_invocation_id) global_id : vec3<u32>) {
    let view_port_size = textureDimensions(input_texture);
    let coords = vec2<u32>(global_id.xy);

    if (coords.x >= view_port_size.x || coords.y >=  view_port_size.y) {
        return;
    }

    let image_size = vec2<f32>(camera.camera_image_width, camera.camera_image_height);
    let image_coords =  vec2<f32>(global_id.xy) *  vec2<f32>(image_size) / vec2<f32>(view_port_size);
    let image_coords_floor = vec2<u32>(image_coords);

    let background_color = textureLoad(background_texture, image_coords_floor, 0);

    distort_pixel(coords, image_size, view_port_size, background_color);
}