diff --git a/include/merian-shaders/reprojection.glsl b/include/merian-shaders/reprojection.glsl index 993c951..60b1dd2 100644 --- a/include/merian-shaders/reprojection.glsl +++ b/include/merian-shaders/reprojection.glsl @@ -7,7 +7,7 @@ float reprojection_weight(const vec3 curr_normal, const vec3 prev_normal, const return smoothstep(normal_reject_cos, 1.0, dot(curr_normal, prev_normal)) // Similar normals // move vel_z outside of abs to reject less - * (1.0 - smoothstep(0.0, z_reject_percent * max(curr_z, prev_z), abs(curr_z - prev_z + vel_z))); // Similar depth + * (1.0 - smoothstep(0.0, z_reject_percent * max(curr_z, prev_z), abs(curr_z - prev_z + vel_z))); // Similar depth } float reprojection_weight(const vec3 curr_normal, const vec3 prev_normal, const float normal_reject_cos, @@ -15,7 +15,7 @@ float reprojection_weight(const vec3 curr_normal, const vec3 prev_normal, const const float prev_z, const float z_reject_percent) { return smoothstep(normal_reject_cos, 1.0, dot(curr_normal, prev_normal)) // Similar normals - * (1.0 - smoothstep(0.0, z_reject_percent * max(curr_z, prev_z), abs(curr_z - prev_z + vel_z) - dot(pixel_offset, grad_z))); // Similar depth + * (1.0 - smoothstep(0.0, z_reject_percent * max(curr_z, prev_z), abs(curr_z - prev_z + vel_z) - dot(pixel_offset, grad_z))); // Similar depth } // Like reprojection_weight but binary @@ -25,3 +25,18 @@ bool reprojection_valid(const vec3 curr_normal, const vec3 prev_normal, const fl return normal_reject_cos <= dot(curr_normal, prev_normal) // Similar normals && abs(curr_z - prev_z) <= z_reject_percent * max(curr_z, prev_z); // Similar depth } + +// Intersects the motion vector with the image borders. +// +// Returns true if prev pos was outside the image borders. +// prev_pos = pos + mv +bool reprojection_intersect_border(inout vec2 prev_pos, const vec2 mv, const vec2 image_size_minus_one) { + if (any(greaterThan(round(prev_pos), image_size_minus_one)) || any(lessThan(round(prev_pos), vec2(0)))) { + // Intersect motion vector with image: + const float tmin = max(min(prev_pos.x / mv.x, (prev_pos.x - image_size_minus_one.x) / mv.x), + min(prev_pos.y / mv.y, (prev_pos.y - image_size_minus_one.y) / mv.y)); + prev_pos = prev_pos - mv * tmin; + return true; + } + return false; +} diff --git a/src/merian-nodes/nodes/accumulate/accumulate.comp b/src/merian-nodes/nodes/accumulate/accumulate.comp index 2a33e75..865b237 100644 --- a/src/merian-nodes/nodes/accumulate/accumulate.comp +++ b/src/merian-nodes/nodes/accumulate/accumulate.comp @@ -165,12 +165,7 @@ void main() { // Attemp to reuse information at the image border. // This results in minor smearing but looks a lot better than // noise / SVGF blotches. - const vec2 bmax = imageSize(img_accum) - 1; - if (any(greaterThan(round(prev_pos), bmax)) || any(lessThan(round(prev_pos), vec2(0)))) { - // Intersect motion vector with image: - float tmin = min(prev_pos.x / mv.x, (prev_pos.x - bmax.x) / mv.x); - tmin = max(tmin, min(prev_pos.y / mv.y, (prev_pos.y - bmax.y) / mv.y)); - prev_pos = prev_pos - mv * tmin; + if (reprojection_intersect_border(prev_pos, mv, imageSize(img_accum) - 1)) { // reset history to converge faster max_history = 2.0; }