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. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to