Skip to content

Commit

Permalink
Search temporal reprojection in a quad of pixels
Browse files Browse the repository at this point in the history
  • Loading branch information
kvark committed Oct 28, 2023
1 parent cbb66b0 commit 61db6b9
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 12 deletions.
40 changes: 31 additions & 9 deletions blade-render/code/blur.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ var input: texture_2d<f32>;
var prev_input: texture_2d<f32>;
var output: texture_storage_2d<rgba16float, write>;

fn get_projected_pixel_quad(cp: CameraParams, point: vec3<f32>) -> array<vec2<i32>, 4> {
let pixel = get_projected_pixel_float(cp, point);
return array<vec2<i32>, 4>(
vec2<i32>(vec2<f32>(pixel.x - 0.5, pixel.y - 0.5)),
vec2<i32>(vec2<f32>(pixel.x + 0.5, pixel.y - 0.5)),
vec2<i32>(vec2<f32>(pixel.x + 0.5, pixel.y + 0.5)),
vec2<i32>(vec2<f32>(pixel.x - 0.5, pixel.y + 0.5)),
);
}

fn read_surface(pixel: vec2<i32>) -> Surface {
var surface = Surface();
surface.flat_normal = normalize(textureLoad(t_flat_normal, pixel, 0).xyz);
Expand All @@ -44,17 +54,29 @@ fn temporal_accum(@builtin(global_invocation_id) global_id: vec3<u32>) {
let cur_radiance = textureLoad(input, pixel, 0).xyz;
let surface = read_surface(pixel);
let pos_world = camera.position + surface.depth * get_ray_direction(camera, pixel);
let prev_pixel = get_projected_pixel(prev_camera, pos_world);
// considering all samples in 2x2 quad, to help with edges
var prev_pixels = get_projected_pixel_quad(prev_camera, pos_world);
var best_index = 0;
var best_weight = 0.0;
for (var i = 0; i < 4; i += 1) {
let prev_pixel = prev_pixels[i];
if (all(prev_pixel >= vec2<i32>(0)) && all(prev_pixel < params.extent)) {
let prev_surface = read_prev_surface(prev_pixel);
let projected_distance = length(pos_world - prev_camera.position);
let weight = compare_flat_normals(surface.flat_normal, prev_surface.flat_normal)
* compare_depths(surface.depth, projected_distance);
if (weight > best_weight) {
best_index = i;
best_weight = weight;
}
}
}

var prev_radiance = cur_radiance;
var history_weight = 1.0 - params.temporal_weight;
if (all(prev_pixel >= vec2<i32>(0)) && all(prev_pixel < params.extent)) {
prev_radiance = textureLoad(prev_input, prev_pixel, 0).xyz;
let prev_surface = read_prev_surface(prev_pixel);
let projected_distance = length(pos_world - prev_camera.position);
history_weight *= compare_flat_normals(surface.flat_normal, prev_surface.flat_normal);
history_weight *= compare_depths(surface.depth, projected_distance);
if (best_weight > 0.01) {
prev_radiance = textureLoad(prev_input, prev_pixels[best_index], 0).xyz;
}
let radiance = mix(cur_radiance, prev_radiance, history_weight);
let radiance = mix(cur_radiance, prev_radiance, best_weight * (1.0 - params.temporal_weight));
textureStore(output, global_id.xy, vec4<f32>(radiance, 0.0));
}

Expand Down
10 changes: 7 additions & 3 deletions blade-render/code/camera.inc.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,16 @@ fn get_ray_direction(cp: CameraParams, pixel: vec2<i32>) -> vec3<f32> {
return normalize(qrot(cp.orientation, local_dir));
}

fn get_projected_pixel(cp: CameraParams, point: vec3<f32>) -> vec2<i32> {
fn get_projected_pixel_float(cp: CameraParams, point: vec3<f32>) -> vec2<f32> {
let local_dir = qrot(qinv(cp.orientation), point - cp.position);
if local_dir.z >= 0.0 {
return vec2<i32>(-1);
return vec2<f32>(-1.0);
}
let ndc = local_dir.xy / (-local_dir.z * tan(0.5 * cp.fov));
let half_size = 0.5 * vec2<f32>(cp.target_size);
return vec2<i32>((ndc + vec2<f32>(1.0)) * half_size);
return (ndc + vec2<f32>(1.0)) * half_size;
}

fn get_projected_pixel(cp: CameraParams, point: vec3<f32>) -> vec2<i32> {
return vec2<i32>(get_projected_pixel_float(cp, point));
}

0 comments on commit 61db6b9

Please sign in to comment.