[Bf-blender-cvs] [bf1dc396797] master: Fix T53567: Negative pixel values causing artifacts with denoising

Lukas Stockner noreply at git.blender.org
Thu Dec 21 14:37:29 CET 2017


Commit: bf1dc3967971c882a9179d31a36f03702cbc8e0f
Author: Lukas Stockner
Date:   Thu Dec 21 14:24:23 2017 +0100
Branches: master
https://developer.blender.org/rBbf1dc3967971c882a9179d31a36f03702cbc8e0f

Fix T53567: Negative pixel values causing artifacts with denoising

Now negative color values are clamped to zero before the actual denoising.

===================================================================

M	intern/cycles/kernel/filter/filter_prefilter.h

===================================================================

diff --git a/intern/cycles/kernel/filter/filter_prefilter.h b/intern/cycles/kernel/filter/filter_prefilter.h
index eefcbfea230..4af209341f6 100644
--- a/intern/cycles/kernel/filter/filter_prefilter.h
+++ b/intern/cycles/kernel/filter/filter_prefilter.h
@@ -117,61 +117,58 @@ ccl_device void kernel_filter_detect_outliers(int x, int y,
 {
 	int buffer_w = align_up(rect.z - rect.x, 4);
 
-	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]);
-
-	float fac = 1.0f;
-	if(color.x < 0.0f || color.y < 0.0f || color.z < 0.0f) {
-		depth[idx] = -depth[idx];
-		fac = 0.0f;
-	}
-	else {
-		float L = average(color);
-		int n = 0;
-		float values[25];
-		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);
-				float L = average(make_float3(image[idx], image[idx+pass_stride], image[idx+2*pass_stride]));
-
-				/* Find the position of L. */
-				int i;
-				for(i = 0; i < n; i++) {
-					if(values[i] > L) break;
-				}
-				/* Make space for L by shifting all following values to the right. */
-				for(int j = n; j > i; j--) {
-					values[j] = values[j-1];
-				}
-				/* Insert L. */
-				values[i] = L;
-				n++;
+	int n = 0;
+	float values[25];
+	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);
+			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);
+
+			/* Find the position of L. */
+			int i;
+			for(i = 0; i < n; i++) {
+				if(values[i] > L) break;
+			}
+			/* Make space for L by shifting all following values to the right. */
+			for(int j = n; j > i; j--) {
+				values[j] = values[j-1];
 			}
+			/* Insert L. */
+			values[i] = L;
+			n++;
 		}
+	}
 
-		float ref = 2.0f*values[(int)(n*0.75f)];
-		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
-			 * should actually be at the reference value:
-			 * 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. */
-				depth[idx] = -depth[idx];
-				fac = ref/L;
-				variance[idx              ] *= fac*fac;
-				variance[idx + pass_stride] *= fac*fac;
-				variance[idx+2*pass_stride] *= fac*fac;
-			}
+	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)];
+	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
+		 * should actually be at the reference value:
+		 * 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. */
+			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              ] = fac*image[idx];
-	out[idx + pass_stride] = fac*image[idx + pass_stride];
-	out[idx+2*pass_stride] = fac*image[idx+2*pass_stride];
+	out[idx              ] = color.x;
+	out[idx + pass_stride] = color.y;
+	out[idx+2*pass_stride] = color.z;
 }
 
 /* Combine A/B buffers.



More information about the Bf-blender-cvs mailing list