[Bf-blender-cvs] [5ba78d7] master: Cycles: Deduplicate geometric factor calculation in the Beckmann distribution

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


Commit: 5ba78d76d4836fa2a8f9d8cef6c448ebd792170f
Author: Lukas Stockner
Date:   Sat Jul 16 20:44:28 2016 +0200
Branches: master
https://developer.blender.org/rB5ba78d76d4836fa2a8f9d8cef6c448ebd792170f

Cycles: Deduplicate geometric factor calculation in the Beckmann distribution

Also, this fixes a numerical issue where A would be inf.
Since later G is set to 1 if A is larger than 1.6, the code now checks the reciprocal of A for being smaller than 1/1.6 - same effect, but no inf involved.

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

M	intern/cycles/kernel/closure/bsdf_microfacet.h

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

diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h
index aa21633..7bf7c28 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet.h
@@ -615,6 +615,36 @@ ccl_device void bsdf_microfacet_beckmann_blur(ShaderClosure *sc, float roughness
 	sc->data1 = fmaxf(roughness, sc->data1); /* alpha_y */
 }
 
+ccl_device_inline float bsdf_beckmann_G1(float alpha, float cos_n)
+{
+	cos_n *= cos_n;
+	float invA = alpha * safe_sqrtf((1.0f - cos_n) / cos_n);
+	if(invA < 0.625f) {
+		return 1.0f;
+	}
+
+	float a = 1.0f / invA;
+	return ((2.181f*a + 3.535f)*a) / ((2.577f*a + 2.276f)*a + 1.0f);
+}
+
+ccl_device_inline float bsdf_beckmann_aniso_G1(float alpha_x, float alpha_y, float cos_n, float cos_phi, float sin_phi)
+{
+	cos_n *= cos_n;
+	sin_phi *= sin_phi;
+	cos_phi *= cos_phi;
+	alpha_x *= alpha_x;
+	alpha_y *= alpha_y;
+
+	float alphaO2 = (cos_phi*alpha_x + sin_phi*alpha_y) / (cos_phi + sin_phi);
+	float invA = safe_sqrtf(alphaO2 * (1 - cos_n) / cos_n);
+	if(invA < 0.625f) {
+		return 1.0f;
+	}
+
+	float a = 1.0f / invA;
+	return ((2.181f*a + 3.535f)*a) / ((2.577f*a + 2.276f)*a + 1.0f);
+}
+
 ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
 	float alpha_x = sc->data0;
@@ -646,10 +676,8 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc,
 			D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
 
 			/* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */
-			float ao = 1 / (alpha_x * safe_sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
-			float ai = 1 / (alpha_x * safe_sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI)));
-			G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f;
-			G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f;
+			G1o = bsdf_beckmann_G1(alpha_x, cosNO);
+			G1i = bsdf_beckmann_G1(alpha_x, cosNI);
 		}
 		else {
 			/* anisotropic */
@@ -668,24 +696,8 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc,
 			D = expf(-slope_x*slope_x - slope_y*slope_y) / (M_PI_F * alpha2 * cosThetaM4);
 
 			/* G1(i,m) and G1(o,m) */
-			float tanThetaO2 = (1 - cosNO * cosNO) / (cosNO * cosNO);
-			float cosPhiO = dot(I, X);
-			float sinPhiO = dot(I, Y);
-
-			float alphaO2 = (cosPhiO*cosPhiO)*(alpha_x*alpha_x) + (sinPhiO*sinPhiO)*(alpha_y*alpha_y);
-			alphaO2 /= cosPhiO*cosPhiO + sinPhiO*sinPhiO;
-
-			float tanThetaI2 = (1 - cosNI * cosNI) / (cosNI * cosNI);
-			float cosPhiI = dot(omega_in, X);
-			float sinPhiI = dot(omega_in, Y);
-
-			float alphaI2 = (cosPhiI*cosPhiI)*(alpha_x*alpha_x) + (sinPhiI*sinPhiI)*(alpha_y*alpha_y);
-			alphaI2 /= cosPhiI*cosPhiI + sinPhiI*sinPhiI;
-
-			float ao = 1 / (safe_sqrtf(alphaO2 * tanThetaO2));
-			float ai = 1 / (safe_sqrtf(alphaI2 * tanThetaI2));
-			G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f;
-			G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f;
+			G1o = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNO, dot(I, X), dot(I, Y));
+			G1i = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNI, dot(omega_in, X), dot(omega_in, Y));
 		}
 
 		float G = G1o * G1i;
@@ -740,10 +752,8 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc
 	float D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 *  cosThetaM4);
 
 	/* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */
-	float ao = 1 / (alpha_x * safe_sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
-	float ai = 1 / (alpha_x * safe_sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI)));
-	float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f;
-	float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f;
+	float G1o = bsdf_beckmann_G1(alpha_x, cosNO);
+	float G1i = bsdf_beckmann_G1(alpha_x, cosNI);
 	float G = G1o * G1i;
 
 	/* probability */
@@ -820,8 +830,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderCl
 							float cosNI = dot(N, *omega_in);
 
 							/* eq. 26, 27: now calculate G1(i,m) */
-							float ai = 1 / (alpha_x * safe_sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI)));
-							G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f;
+							G1i = bsdf_beckmann_G1(alpha_x, cosNI);
 						}
 						else {
 							/* anisotropic distribution */
@@ -836,16 +845,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderCl
 							D = expf(-slope_x*slope_x - slope_y*slope_y) / (M_PI_F * alpha2 * cosThetaM4);
 
 							/* G1(i,m) */
-							float cosNI = dot(N, *omega_in);
-							float tanThetaI2 = (1 - cosNI * cosNI) / (cosNI * cosNI);
-							float cosPhiI = dot(*omega_in, X);
-							float sinPhiI = dot(*omega_in, Y);
-
-							float alphaI2 = (cosPhiI*cosPhiI)*(alpha_x*alpha_x) + (sinPhiI*sinPhiI)*(alpha_y*alpha_y);
-							alphaI2 /= cosPhiI*cosPhiI + sinPhiI*sinPhiI;
-
-							float ai = 1 / (safe_sqrtf(alphaI2 * tanThetaI2));
-							G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f;
+							G1i = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, dot(*omega_in, N), dot(*omega_in, X), dot(*omega_in, Y));
 						}
 
 						float G = G1o * G1i;
@@ -906,8 +906,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderCl
 					float cosNI = dot(N, *omega_in);
 
 					/* eq. 26, 27: now calculate G1(i,m) */
-					float ai = 1 / (alpha_x * safe_sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI)));
-					float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f;
+					float G1i = bsdf_beckmann_G1(alpha_x, cosNI);
 					float G = G1o * G1i;
 
 					/* eq. 21 */




More information about the Bf-blender-cvs mailing list