diff options
author | Lukas Stockner <lukas.stockner@freenet.de> | 2019-02-06 16:42:32 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2019-02-06 17:18:38 +0300 |
commit | c183ac73dcfd20d0acf5ca07a2b062deadc4d73a (patch) | |
tree | cde3cca8d7c8cfcaf802e7047f3dd31db9459ba5 | |
parent | 405cacd4cd955552e1f7b50a176ddcdd9baf8d3b (diff) |
Cycles: tweak outlier detection, preparing for animation denoising.
Ref D3889.
-rw-r--r-- | intern/cycles/kernel/filter/filter_prefilter.h | 43 |
1 files changed, 34 insertions, 9 deletions
diff --git a/intern/cycles/kernel/filter/filter_prefilter.h b/intern/cycles/kernel/filter/filter_prefilter.h index 41be4dbea49..e24f4feb28d 100644 --- a/intern/cycles/kernel/filter/filter_prefilter.h +++ b/intern/cycles/kernel/filter/filter_prefilter.h @@ -140,6 +140,7 @@ ccl_device void kernel_filter_detect_outliers(int x, int y, int n = 0; float values[25]; + float pixel_variance, max_variance = 0.0f; for(int y1 = max(y-2, rect.y); y1 < min(y+3, rect.w); y1++) { for(int x1 = max(x-2, rect.x); x1 < min(x+3, rect.z); x1++) { int idx = (y1-rect.y)*buffer_w + (x1-rect.x); @@ -159,15 +160,31 @@ ccl_device void kernel_filter_detect_outliers(int x, int y, /* Insert L. */ values[i] = L; n++; + + float3 pixel_var = make_float3(variance[idx], variance[idx+pass_stride], variance[idx+2*pass_stride]); + float var = average(pixel_var); + if((x1 == x) && (y1 == y)) { + pixel_variance = (pixel_var.x < 0.0f || pixel_var.y < 0.0f || pixel_var.z < 0.0f)? -1.0f : var; + } + else { + max_variance = max(max_variance, var); + } } } + max_variance += 1e-4f; + int idx = (y-rect.y)*buffer_w + (x-rect.x); float3 color = make_float3(image[idx], image[idx+pass_stride], image[idx+2*pass_stride]); color = max(color, make_float3(0.0f, 0.0f, 0.0f)); float L = average(color); float ref = 2.0f*values[(int)(n*0.75f)]; + + /* Slightly offset values to avoid false positives in (almost) black areas. */ + max_variance += 1e-5f; + ref -= 1e-5f; + if(L > ref) { /* The pixel appears to be an outlier. * However, it may just be a legitimate highlight. Therefore, it is checked how likely it is that the pixel @@ -175,16 +192,24 @@ ccl_device void kernel_filter_detect_outliers(int x, int y, * If the reference is within the 3-sigma interval, the pixel is assumed to be a statistical outlier. * Otherwise, it is very unlikely that the pixel should be darker, which indicates a legitimate highlight. */ - float stddev = sqrtf(average(make_float3(variance[idx], variance[idx+pass_stride], variance[idx+2*pass_stride]))); - if(L - 3*stddev < ref) { - /* The pixel is an outlier, so negate the depth value to mark it as one. - * Also, scale its brightness down to the outlier threshold to avoid trouble with the NLM weights. */ + + if(pixel_variance < 0.0f || pixel_variance > 9.0f * max_variance) { depth[idx] = -depth[idx]; - float fac = ref/L; - color *= fac; - variance[idx ] *= fac*fac; - variance[idx + pass_stride] *= fac*fac; - variance[idx+2*pass_stride] *= fac*fac; + color *= ref/L; + variance[idx] = variance[idx + pass_stride] = variance[idx + 2*pass_stride] = max_variance; + } + else { + float stddev = sqrtf(pixel_variance); + if(L - 3*stddev < ref) { + /* The pixel is an outlier, so negate the depth value to mark it as one. + * Also, scale its brightness down to the outlier threshold to avoid trouble with the NLM weights. */ + depth[idx] = -depth[idx]; + float fac = ref/L; + color *= fac; + variance[idx ] *= fac*fac; + variance[idx + pass_stride] *= fac*fac; + variance[idx+2*pass_stride] *= fac*fac; + } } } out[idx ] = color.x; |