[Bf-blender-cvs] [d9281a6] master: Cycles: Fix three numerical issues in the fresnel, normal map and Beckmann code

Lukas Stockner noreply at git.blender.org
Sat Jul 16 21:11:21 CEST 2016


Commit: d9281a6332d2273356e0d3d042d64157fb7d06c8
Author: Lukas Stockner
Date:   Sat Jul 16 20:48:12 2016 +0200
Branches: master
https://developer.blender.org/rBd9281a6332d2273356e0d3d042d64157fb7d06c8

Cycles: Fix three numerical issues in the fresnel, normal map and Beckmann code

- In fresnel_dielectric, the differentials calculation sometimes divided by zero.
- When the normal map was (0.5, 0.5, 0.5), the code would try to normalize a zero vector. Now, it just uses the regular normal as a fallback.
- The approximate error function used in Beckmann sampling sometimes overflowed to inf while calculating r^16. The final value is 1 - 1/r^16, however,
  so now it just returns 1 if the computation would overflow otherwise.

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

M	intern/cycles/kernel/closure/bsdf_util.h
M	intern/cycles/kernel/svm/svm_tex_coord.h
M	intern/cycles/util/util_math_fast.h

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

diff --git a/intern/cycles/kernel/closure/bsdf_util.h b/intern/cycles/kernel/closure/bsdf_util.h
index 89b1998..b0c5280 100644
--- a/intern/cycles/kernel/closure/bsdf_util.h
+++ b/intern/cycles/kernel/closure/bsdf_util.h
@@ -80,7 +80,7 @@ ccl_device float fresnel_dielectric(
 		return 1; // total internal reflection
 	}
 	else {
-		float dnp = sqrtf(arg);
+		float dnp = max(sqrtf(arg), 1e-7f);
 		float nK = (neta * cos)- dnp;
 		*T = -(neta * I)+(nK * Nn);
 #ifdef __RAY_DIFFERENTIALS__
diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h
index 27fed89..0bac836 100644
--- a/intern/cycles/kernel/svm/svm_tex_coord.h
+++ b/intern/cycles/kernel/svm/svm_tex_coord.h
@@ -312,7 +312,7 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st
 
 		/* apply normal map */
 		float3 B = sign * cross(normal, tangent);
-		N = normalize(color.x * tangent + color.y * B + color.z * normal);
+		N = safe_normalize(color.x * tangent + color.y * B + color.z * normal);
 
 		/* transform to world space */
 		object_normal_transform(kg, sd, &N);
@@ -330,14 +330,18 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st
 		if(space == NODE_NORMAL_MAP_OBJECT || space == NODE_NORMAL_MAP_BLENDER_OBJECT)
 			object_normal_transform(kg, sd, &N);
 		else
-			N = normalize(N);
+			N = safe_normalize(N);
 	}
 
 	float strength = stack_load_float(stack, strength_offset);
 
 	if(strength != 1.0f) {
 		strength = max(strength, 0.0f);
-		N = normalize(ccl_fetch(sd, N) + (N - ccl_fetch(sd, N))*strength);
+		N = safe_normalize(ccl_fetch(sd, N) + (N - ccl_fetch(sd, N))*strength);
+	}
+
+	if(N == make_float3(0.0f, 0.0f, 0.0f)) {
+		N = ccl_fetch(sd, N);
 	}
 
 	stack_store_float3(stack, normal_offset, N);
diff --git a/intern/cycles/util/util_math_fast.h b/intern/cycles/util/util_math_fast.h
index deb2013..d3960de 100644
--- a/intern/cycles/util/util_math_fast.h
+++ b/intern/cycles/util/util_math_fast.h
@@ -547,6 +547,9 @@ ccl_device_inline float fast_erff(float x)
 	const float a5 = 0.0002765672f;
 	const float a6 = 0.0000430638f;
 	const float a = fabsf(x);
+	if(a >= 12.3f) {
+		return copysignf(1.0f, x);
+	}
 	const float b = 1.0f - (1.0f - a);  /* Crush denormals. */
 	const float r = madd(madd(madd(madd(madd(madd(a6, b, a5), b, a4), b, a3), b, a2), b, a1), b, 1.0f);
 	const float s = r * r;  /* ^2 */




More information about the Bf-blender-cvs mailing list