[Bf-blender-cvs] [ceb68e8] master: Cycles: internal code support for anisotropic Beckmann and GGX reflection

Brecht Van Lommel noreply at git.blender.org
Sat Jun 14 13:55:36 CEST 2014


Commit: ceb68e809edf37ea3fd010692dc3f4367b78cf61
Author: Brecht Van Lommel
Date:   Wed Jun 4 00:39:42 2014 +0200
https://developer.blender.org/rBceb68e809edf37ea3fd010692dc3f4367b78cf61

Cycles: internal code support for anisotropic Beckmann and GGX reflection

Based on:

Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs
E. Heitz, Research Report 2014

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

M	intern/cycles/kernel/closure/bsdf_hair.h
M	intern/cycles/kernel/closure/bsdf_microfacet.h
M	intern/cycles/kernel/kernel_types.h
M	intern/cycles/kernel/osl/osl_closures.cpp
M	intern/cycles/kernel/osl/osl_shader.cpp
M	intern/cycles/kernel/svm/svm_closure.h

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

diff --git a/intern/cycles/kernel/closure/bsdf_hair.h b/intern/cycles/kernel/closure/bsdf_hair.h
index 19cdb77..e0b5454 100644
--- a/intern/cycles/kernel/closure/bsdf_hair.h
+++ b/intern/cycles/kernel/closure/bsdf_hair.h
@@ -63,7 +63,7 @@ ccl_device int bsdf_hair_transmission_setup(ShaderClosure *sc)
 ccl_device float3 bsdf_hair_reflection_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
 #ifdef __HAIR__
-	float offset = sc->offset;
+	float offset = sc->data2;
 	float3 Tg = sc->T;
 #else
 	float offset = 0.0f;
@@ -120,7 +120,7 @@ ccl_device float3 bsdf_hair_reflection_eval_transmit(const ShaderClosure *sc, co
 ccl_device float3 bsdf_hair_transmission_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
 #ifdef __HAIR__
-	float offset = sc->offset;
+	float offset = sc->data2;
 	float3 Tg = sc->T;
 #else
 	float offset = 0.0f;
@@ -166,7 +166,7 @@ ccl_device float3 bsdf_hair_transmission_eval_transmit(const ShaderClosure *sc,
 ccl_device int bsdf_hair_reflection_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
 {
 #ifdef __HAIR__
-	float offset = sc->offset;
+	float offset = sc->data2;
 	float3 Tg = sc->T;
 #else
 	float offset = 0.0f;
@@ -221,7 +221,7 @@ ccl_device int bsdf_hair_reflection_sample(const ShaderClosure *sc, float3 Ng, f
 ccl_device int bsdf_hair_transmission_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
 {
 #ifdef __HAIR__
-	float offset = sc->offset;
+	float offset = sc->data2;
 	float3 Tg = sc->T;
 #else
 	float offset = 0.0f;
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h
index ea0894e..b9b682c 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet.h
@@ -154,18 +154,18 @@ ccl_device float approx_erfinvf_impl(float p, float q)
 
 ccl_device float approx_erfinvf(float z)
 {
-   float p, q, s;
+	float p, q, s;
 
-   if(z < 0) {
+	if(z < 0) {
 	  p = -z;
 	  q = 1 - p;
 	  s = -1;
-   }
-   else {
+	}
+	else {
 	  p = z;
 	  q = 1 - z;
 	  s = 1;
-   }
+	}
 
 	return s * approx_erfinvf_impl(p, q);
 }
@@ -340,11 +340,30 @@ ccl_device_inline float3 microfacet_sample_stretched(const float3 omega_i,
 /* GGX microfacet with Smith shadow-masking from:
  *
  * Microfacet Models for Refraction through Rough Surfaces
- * B. Walter, S. R. Marschner, H. Li, K. E. Torrance, EGSR 2007 */
+ * B. Walter, S. R. Marschner, H. Li, K. E. Torrance, EGSR 2007
+ *
+ * Anisotropic from:
+ *
+ * Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs
+ * E. Heitz, Research Report 2014
+ *
+ * Anisotropy is only supported for reflection currently, but adding it for
+ * tranmission is just a matter of copying code from reflection if needed. */
 
 ccl_device int bsdf_microfacet_ggx_setup(ShaderClosure *sc)
 {
-	sc->data0 = clamp(sc->data0, 0.0f, 1.0f); /* m_ag */
+	sc->data0 = clamp(sc->data0, 0.0f, 1.0f); /* alpha_x */
+	sc->data1 = sc->data0; /* alpha_y */
+	
+	sc->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
+
+	return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
+}
+
+ccl_device int bsdf_microfacet_ggx_aniso_setup(ShaderClosure *sc)
+{
+	sc->data0 = clamp(sc->data0, 0.0f, 1.0f); /* alpha_x */
+	sc->data1 = clamp(sc->data1, 0.0f, 1.0f); /* alpha_y */
 	
 	sc->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
 
@@ -353,7 +372,8 @@ ccl_device int bsdf_microfacet_ggx_setup(ShaderClosure *sc)
 
 ccl_device int bsdf_microfacet_ggx_refraction_setup(ShaderClosure *sc)
 {
-	sc->data0 = clamp(sc->data0, 0.0f, 1.0f); /* m_ag */
+	sc->data0 = clamp(sc->data0, 0.0f, 1.0f); /* alpha_x */
+	sc->data1 = sc->data1; /* alpha_y */
 
 	sc->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
 
@@ -362,16 +382,18 @@ ccl_device int bsdf_microfacet_ggx_refraction_setup(ShaderClosure *sc)
 
 ccl_device void bsdf_microfacet_ggx_blur(ShaderClosure *sc, float roughness)
 {
-	sc->data0 = fmaxf(roughness, sc->data0); /* m_ag */
+	sc->data0 = fmaxf(roughness, sc->data0); /* alpha_x */
+	sc->data1 = fmaxf(roughness, sc->data1); /* alpha_y */
 }
 
 ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
-	float m_ag = max(sc->data0, 1e-4f);
+	float alpha_x = sc->data0;
+	float alpha_y = sc->data1;
 	int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
 	float3 N = sc->N;
 
-	if(m_refractive || m_ag <= 1e-4f)
+	if(m_refractive || fmaxf(alpha_x, alpha_y) <= 1e-4f)
 		return make_float3(0, 0, 0);
 
 	float cosNO = dot(N, I);
@@ -380,18 +402,60 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
 	if(cosNI > 0 && cosNO > 0) {
 		/* get half vector */
 		float3 m = normalize(omega_in + I);
+		float alpha2 = alpha_x * alpha_y;
+		float D, G1o, G1i;
+
+		if(alpha_x == alpha_y) {
+			/* isotropic
+			 * eq. 20: (F*G*D)/(4*in*on)
+			 * eq. 33: first we calculate D(m) */
+			float cosThetaM = dot(N, m);
+			float cosThetaM2 = cosThetaM * cosThetaM;
+			float cosThetaM4 = cosThetaM2 * cosThetaM2;
+			float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
+			D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
+
+			/* eq. 34: now calculate G1(i,m) and G1(o,m) */
+			G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
+			G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); 
+		}
+		else {
+			/* anisotropic */
+			float3 X, Y, Z = N;
+			make_orthonormals_tangent(Z, sc->T, &X, &Y);
+
+			/* distribution */
+			float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
+			float slope_x = -local_m.x/(local_m.z*alpha_x);
+			float slope_y = -local_m.y/(local_m.z*alpha_y);
+			float slope_len = 1 + slope_x*slope_x + slope_y*slope_y;
+
+			float cosThetaM = local_m.z;
+			float cosThetaM2 = cosThetaM * cosThetaM;
+			float cosThetaM4 = cosThetaM2 * cosThetaM2;
+
+			D = 1 / ((slope_len * slope_len) * 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;
+
+			G1o = 2 / (1 + safe_sqrtf(1 + alphaO2 * tanThetaO2));
+
+			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;
+
+			G1i = 2 / (1 + safe_sqrtf(1 + alphaI2 * tanThetaI2));
+		}
 
-		/* eq. 20: (F*G*D)/(4*in*on)
-		 * eq. 33: first we calculate D(m) */
-		float alpha2 = m_ag * m_ag;
-		float cosThetaM = dot(N, m);
-		float cosThetaM2 = cosThetaM * cosThetaM;
-		float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
-		float cosThetaM4 = cosThetaM2 * cosThetaM2;
-		float D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
-		/* eq. 34: now calculate G1(i,m) and G1(o,m) */
-		float G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
-		float G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); 
 		float G = G1o * G1i;
 
 		/* eq. 20 */
@@ -414,12 +478,13 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
 
 ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
 {
-	float m_ag = max(sc->data0, 1e-4f);
-	float m_eta = sc->data1;
+	float alpha_x = sc->data0;
+	float alpha_y = sc->data1;
+	float m_eta = sc->data2;
 	int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
 	float3 N = sc->N;
 
-	if(!m_refractive || m_ag <= 1e-4f)
+	if(!m_refractive || fmaxf(alpha_x, alpha_y) <= 1e-4f)
 		return make_float3(0, 0, 0);
 
 	float cosNO = dot(N, I);
@@ -434,17 +499,20 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, con
 	float cosHO = dot(Ht, I);
 	float cosHI = dot(Ht, omega_in);
 
+	float D, G1o, G1i;
+
 	/* eq. 33: first we calculate D(m) with m=Ht: */
-	float alpha2 = m_ag * m_ag;
+	float alpha2 = alpha_x * alpha_y;
 	float cosThetaM = dot(N, Ht);
 	float cosThetaM2 = cosThetaM * cosThetaM;
 	float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
 	float cosThetaM4 = cosThetaM2 * cosThetaM2;
-	float D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
+	D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
 
 	/* eq. 34: now calculate G1(i,m) and G1(o,m) */
-	float G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
-	float G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); 
+	G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
+	G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); 
+
 	float G = G1o * G1i;
 
 	/* probability */
@@ -464,27 +532,27 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, con
 
 ccl_device int bsdf_microfacet_ggx_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
 {
-	float m_ag = sc->data0;
+	float alpha_x = sc->data0;
+	float alpha_y = sc->data1;
 	int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
 	float3 N = sc->N;
 
 	float cosNO = dot(N, I);
 	if(cosNO > 0) {
 		float3 X, Y, Z = N;
-		make_orthonormals(Z, &X, &Y);
+
+		if(alpha_x == alpha_y)
+			make_orthonormals(Z, &X, &Y);
+		else
+			make_orthonormals_tangent(Z, sc->T, &X, &Y);
 
 		/* importance sampling with distribution of visible normals. vectors are
 		 * transformed to local space before and a

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list