From 91c7a7afb8de4aa7322b6a87da3f5e58ea1354b4 Mon Sep 17 00:00:00 2001 From: Lucas Alber Date: Thu, 22 Aug 2024 16:37:16 +0200 Subject: [PATCH] merian-nodes: Accum: Fix reprojection / better extended search --- include/merian-shaders/reprojection.glsl | 4 ++- .../nodes/accumulate/accumulate.comp | 31 +++++++++---------- .../nodes/accumulate/accumulate.cpp | 9 +++--- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/include/merian-shaders/reprojection.glsl b/include/merian-shaders/reprojection.glsl index 3c00c1db..8ccf6fe5 100644 --- a/include/merian-shaders/reprojection.glsl +++ b/include/merian-shaders/reprojection.glsl @@ -17,7 +17,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 + dot(pixel_offset, grad_z) - prev_z + vel_z))); // Similar depth } // Like reprojection_weight but binary @@ -43,11 +43,13 @@ bool reprojection_intersect_border(inout vec2 prev_pos, const vec2 mv, const vec return false; } +// pixel = current_pixel + mv ivec2 reproject_pixel_nearest(const vec2 pixel) { return ivec2(round(pixel)); } // Performs stochastic bilinear interpolation when reprojecting +// pixel = current_pixel + mv ivec2 reproject_pixel_stochastic(const vec2 pixel, const float random) { const vec2 relative_pos = fract(pixel); diff --git a/src/merian-nodes/nodes/accumulate/accumulate.comp b/src/merian-nodes/nodes/accumulate/accumulate.comp index 75eac770..4db16e88 100644 --- a/src/merian-nodes/nodes/accumulate/accumulate.comp +++ b/src/merian-nodes/nodes/accumulate/accumulate.comp @@ -105,24 +105,23 @@ void get_prev_extended_search(const vec2 prev_pos, inout vec2 prev_moments, inout float sum_w) { const ivec2 prev_ipos = ivec2(round(prev_pos)); + uint rng_state = pcg3d16(uvec3(pc.iteration, prev_ipos)); [[unroll]] - for(int yy = -1; yy <= 1; yy++) { - [[unroll]] - for(int xx = -1; xx <= 1; xx++) { - const ivec2 tc = prev_ipos + ivec2(xx, yy); - if(any(greaterThanEqual(tc, textureSize(img_prev_accum, 0))) || any(lessThan(tc, ivec2(0)))) - continue; - - const GBuffer prev_gbuf = prev_gbuffer[gbuffer_index(tc, imageSize(img_accum))]; - const vec3 prev_normal = geo_decode_normal(prev_gbuf.enc_normal); - const float w = reprojection_weight(normal, prev_normal, pc.normal_reject_cos * 0.8, - linear_z, vel_z, ivec2(xx, yy), grad_z, prev_gbuf.linear_z, pc.z_reject_percent * 2.); - - prev_irr_histlen += w * texelFetch(img_prev_accum, tc, 0); - prev_moments += w * texelFetch(img_prev_moments, tc, 0).rg; - sum_w += w; - } + for(int i = 0; i <= 9; i++) { + const ivec2 offset = ivec2(round(XorShift32Vec2(rng_state) * 4)) - 2; + const ivec2 tc = prev_ipos + offset; + if(any(greaterThanEqual(tc, textureSize(img_prev_accum, 0))) || any(lessThan(tc, ivec2(0)))) + continue; + + const GBuffer prev_gbuf = prev_gbuffer[gbuffer_index(tc, imageSize(img_accum))]; + const vec3 prev_normal = geo_decode_normal(prev_gbuf.enc_normal); + const float w = reprojection_weight(normal, prev_normal, pc.normal_reject_cos * 0.8, + linear_z, vel_z, offset, grad_z, prev_gbuf.linear_z, pc.z_reject_percent * 2.); + + prev_irr_histlen += w * texelFetch(img_prev_accum, tc, 0); + prev_moments += w * texelFetch(img_prev_moments, tc, 0).rg; + sum_w += w; } } diff --git a/src/merian-nodes/nodes/accumulate/accumulate.cpp b/src/merian-nodes/nodes/accumulate/accumulate.cpp index f3df8166..00ec5a66 100644 --- a/src/merian-nodes/nodes/accumulate/accumulate.cpp +++ b/src/merian-nodes/nodes/accumulate/accumulate.cpp @@ -186,11 +186,10 @@ Accumulate::NodeStatusFlags Accumulate::properties(Properties& config) { "Reject points with depths farther apart (relative to the max)"); needs_rebuild |= config.config_options("filter mode", filter_mode, {"nearest", "bilinear", "stochastic bilinear"}); - needs_rebuild |= - config.config_bool("extended search", extended_search, - "search in a 3x3 radius with weakened rejection thresholds for valid " - "information if nothing was found. Helps " - "with artifacts at edges"); + needs_rebuild |= config.config_bool( + "extended search", extended_search, + "search randomly in a 4x4 radius with weakened rejection thresholds for valid " + "information if nothing was found."); needs_rebuild |= config.config_bool("reuse border", reuse_border, "Reuse border information (if valid) for pixel where the motion vector "