Blender V2.61 - r43446

bsdf_microfacet.h

Go to the documentation of this file.
00001 /* 
00002  * Adapted from Open Shading Language with this license: 
00003  * 
00004  * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. 
00005  * All Rights Reserved. 
00006  * 
00007  * Modifications Copyright 2011, Blender Foundation. 
00008  *  
00009  * Redistribution and use in source and binary forms, with or without 
00010  * modification, are permitted provided that the following conditions are 
00011  * met: 
00012  * * Redistributions of source code must retain the above copyright 
00013  *   notice, this list of conditions and the following disclaimer. 
00014  * * Redistributions in binary form must reproduce the above copyright 
00015  *   notice, this list of conditions and the following disclaimer in the 
00016  *   documentation and/or other materials provided with the distribution. 
00017  * * Neither the name of Sony Pictures Imageworks nor the names of its 
00018  *   contributors may be used to endorse or promote products derived from 
00019  *   this software without specific prior written permission. 
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
00021  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
00022  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
00023  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
00024  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
00025  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
00026  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
00027  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
00028  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
00029  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
00030  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00031 */
00032 
00033 #ifndef __BSDF_MICROFACET_H__
00034 #define __BSDF_MICROFACET_H__
00035 
00036 CCL_NAMESPACE_BEGIN
00037 
00038 /* GGX */
00039 
00040 typedef struct BsdfMicrofacetGGXClosure {
00041     //float3 m_N;
00042     float m_ag;
00043     float m_eta;
00044 } BsdfMicrofacetGGXClosure;
00045 
00046 __device void bsdf_microfacet_ggx_setup(ShaderData *sd, ShaderClosure *sc, float ag, float eta, bool refractive)
00047 {
00048     float m_ag = clamp(ag, 1e-4f, 1.0f);
00049     float m_eta = eta;
00050 
00051     sc->data0 = m_ag;
00052     sc->data1 = m_eta;
00053 
00054     if(refractive)
00055         sc->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
00056     else
00057         sc->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
00058 
00059     sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
00060 }
00061 
00062 __device void bsdf_microfacet_ggx_blur(ShaderClosure *sc, float roughness)
00063 {
00064     float m_ag = sc->data0;
00065     m_ag = fmaxf(roughness, m_ag);
00066     sc->data0 = m_ag;
00067 }
00068 
00069 __device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
00070 {
00071     float m_ag = sc->data0;
00072     //float m_eta = sc->data1;
00073     int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
00074     float3 m_N = sd->N;
00075 
00076     if(m_refractive) return make_float3 (0, 0, 0);
00077     float cosNO = dot(m_N, I);
00078     float cosNI = dot(m_N, omega_in);
00079     if(cosNI > 0 && cosNO > 0) {
00080         // get half vector
00081         float3 Hr = normalize(omega_in + I);
00082         // eq. 20: (F*G*D)/(4*in*on)
00083         // eq. 33: first we calculate D(m) with m=Hr:
00084         float alpha2 = m_ag * m_ag;
00085         float cosThetaM = dot(m_N, Hr);
00086         float cosThetaM2 = cosThetaM * cosThetaM;
00087         float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
00088         float cosThetaM4 = cosThetaM2 * cosThetaM2;
00089         float D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
00090         // eq. 34: now calculate G1(i,m) and G1(o,m)
00091         float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
00092         float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); 
00093         float G = G1o * G1i;
00094         float out = (G * D) * 0.25f / cosNO;
00095         // eq. 24
00096         float pm = D * cosThetaM;
00097         // convert into pdf of the sampled direction
00098         // eq. 38 - but see also:
00099         // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
00100         *pdf = pm * 0.25f / dot(Hr, I);
00101         return make_float3 (out, out, out);
00102     }
00103     return make_float3 (0, 0, 0);
00104 }
00105 
00106 __device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
00107 {
00108     float m_ag = sc->data0;
00109     float m_eta = sc->data1;
00110     int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
00111     float3 m_N = sd->N;
00112 
00113     if(!m_refractive) return make_float3 (0, 0, 0);
00114     float cosNO = dot(m_N, I);
00115     float cosNI = dot(m_N, omega_in);
00116     if(cosNO <= 0 || cosNI >= 0)
00117         return make_float3 (0, 0, 0); // vectors on same side -- not possible
00118     // compute half-vector of the refraction (eq. 16)
00119     float3 ht = -(m_eta * omega_in + I);
00120     float3 Ht = normalize(ht);
00121     float cosHO = dot(Ht, I);
00122 
00123     float cosHI = dot(Ht, omega_in);
00124     // eq. 33: first we calculate D(m) with m=Ht:
00125     float alpha2 = m_ag * m_ag;
00126     float cosThetaM = dot(m_N, Ht);
00127     float cosThetaM2 = cosThetaM * cosThetaM;
00128     float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
00129     float cosThetaM4 = cosThetaM2 * cosThetaM2;
00130     float D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
00131     // eq. 34: now calculate G1(i,m) and G1(o,m)
00132     float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
00133     float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); 
00134     float G = G1o * G1i;
00135     // probability
00136     float invHt2 = 1 / dot(ht, ht);
00137     *pdf = D * fabsf(cosThetaM) * (fabsf(cosHI) * (m_eta * m_eta)) * invHt2;
00138     float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D) * invHt2) / cosNO;
00139     return make_float3 (out, out, out);
00140 }
00141 
00142 __device float bsdf_microfacet_ggx_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
00143 {
00144     return 1.0f;
00145 }
00146 
00147 __device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
00148 {
00149     float m_ag = sc->data0;
00150     float m_eta = sc->data1;
00151     int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
00152     float3 m_N = sd->N;
00153 
00154     float cosNO = dot(m_N, sd->I);
00155     if(cosNO > 0) {
00156         float3 X, Y, Z = m_N;
00157         make_orthonormals(Z, &X, &Y);
00158         // generate a random microfacet normal m
00159         // eq. 35,36:
00160         // we take advantage of cos(atan(x)) == 1/sqrt(1+x^2)
00161         //tttt  and sin(atan(x)) == x/sqrt(1+x^2)
00162         float alpha2 = m_ag * m_ag;
00163         float tanThetaM2 = alpha2 * randu / (1 - randu);
00164         float cosThetaM  = 1 / sqrtf(1 + tanThetaM2);
00165         float sinThetaM  = cosThetaM * sqrtf(tanThetaM2);
00166         float phiM = 2 * M_PI_F * randv;
00167         float3 m = (cosf(phiM) * sinThetaM) * X +
00168                  (sinf(phiM) * sinThetaM) * Y +
00169                                cosThetaM  * Z;
00170         if(!m_refractive) {
00171             float cosMO = dot(m, sd->I);
00172             if(cosMO > 0) {
00173                 // eq. 39 - compute actual reflected direction
00174                 *omega_in = 2 * cosMO * m - sd->I;
00175                 if(dot(sd->Ng, *omega_in) > 0) {
00176                     // microfacet normal is visible to this ray
00177                     // eq. 33
00178                     float cosThetaM2 = cosThetaM * cosThetaM;
00179                     float cosThetaM4 = cosThetaM2 * cosThetaM2;
00180                     float D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
00181                     // eq. 24
00182                     float pm = D * cosThetaM;
00183                     // convert into pdf of the sampled direction
00184                     // eq. 38 - but see also:
00185                     // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
00186                     *pdf = pm * 0.25f / cosMO;
00187                     // eval BRDF*cosNI
00188                     float cosNI = dot(m_N, *omega_in);
00189                     // eq. 34: now calculate G1(i,m) and G1(o,m)
00190                     float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
00191                     float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); 
00192                     float G = G1o * G1i;
00193                     // eq. 20: (F*G*D)/(4*in*on)
00194                     float out = (G * D) * 0.25f / cosNO;
00195                     *eval = make_float3(out, out, out);
00196 #ifdef __RAY_DIFFERENTIALS__
00197                     *domega_in_dx = (2 * dot(m, sd->dI.dx)) * m - sd->dI.dx;
00198                     *domega_in_dy = (2 * dot(m, sd->dI.dy)) * m - sd->dI.dy;
00199                     // Since there is some blur to this reflection, make the
00200                     // derivatives a bit bigger. In theory this varies with the
00201                     // roughness but the exact relationship is complex and
00202                     // requires more ops than are practical.
00203                     *domega_in_dx *= 10.0f;
00204                     *domega_in_dy *= 10.0f;
00205 #endif
00206                 }
00207             }
00208         } else {
00209             // CAUTION: the i and o variables are inverted relative to the paper
00210             // eq. 39 - compute actual refractive direction
00211             float3 R, T;
00212 #ifdef __RAY_DIFFERENTIALS__
00213             float3 dRdx, dRdy, dTdx, dTdy;
00214 #endif
00215             bool inside;
00216             fresnel_dielectric(m_eta, m, sd->I, &R, &T,
00217 #ifdef __RAY_DIFFERENTIALS__
00218                 sd->dI.dx, sd->dI.dy, &dRdx, &dRdy, &dTdx, &dTdy,
00219 #endif
00220                 &inside);
00221             
00222             if(!inside) {
00223                 *omega_in = T;
00224 #ifdef __RAY_DIFFERENTIALS__
00225                 *domega_in_dx = dTdx;
00226                 *domega_in_dy = dTdy;
00227 #endif
00228                 // eq. 33
00229                 float cosThetaM2 = cosThetaM * cosThetaM;
00230                 float cosThetaM4 = cosThetaM2 * cosThetaM2;
00231                 float D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
00232                 // eq. 24
00233                 float pm = D * cosThetaM;
00234                 // eval BRDF*cosNI
00235                 float cosNI = dot(m_N, *omega_in);
00236                 // eq. 34: now calculate G1(i,m) and G1(o,m)
00237                 float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
00238                 float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); 
00239                 float G = G1o * G1i;
00240                 // eq. 21
00241                 float cosHI = dot(m, *omega_in);
00242                 float cosHO = dot(m, sd->I);
00243                 float Ht2 = m_eta * cosHI + cosHO;
00244                 Ht2 *= Ht2;
00245                 float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2);
00246                 // eq. 38 and eq. 17
00247                 *pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2;
00248                 *eval = make_float3(out, out, out);
00249 #ifdef __RAY_DIFFERENTIALS__
00250                 // Since there is some blur to this refraction, make the
00251                 // derivatives a bit bigger. In theory this varies with the
00252                 // roughness but the exact relationship is complex and
00253                 // requires more ops than are practical.
00254                 *domega_in_dx *= 10.0f;
00255                 *domega_in_dy *= 10.0f;
00256 #endif
00257             }
00258         }
00259     }
00260     return (m_refractive) ? LABEL_TRANSMIT|LABEL_GLOSSY : LABEL_REFLECT|LABEL_GLOSSY;
00261 }
00262 
00263 /* BECKMANN */
00264 
00265 typedef struct BsdfMicrofacetBeckmannClosure {
00266     //float3 m_N;
00267     float m_ab;
00268     float m_eta;
00269 } BsdfMicrofacetBeckmannClosure;
00270 
00271 __device void bsdf_microfacet_beckmann_setup(ShaderData *sd, ShaderClosure *sc, float ab, float eta, bool refractive)
00272 {
00273     float m_ab = clamp(ab, 1e-4f, 1.0f);
00274     float m_eta = eta;
00275 
00276     sc->data0 = m_ab;
00277     sc->data1 = m_eta;
00278 
00279     if(refractive)
00280         sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
00281     else
00282         sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
00283 
00284     sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
00285 }
00286 
00287 __device void bsdf_microfacet_beckmann_blur(ShaderClosure *sc, float roughness)
00288 {
00289     float m_ab = sc->data0;
00290     m_ab = fmaxf(roughness, m_ab);
00291     sc->data0 = m_ab;
00292 }
00293 
00294 __device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
00295 {
00296     float m_ab = sc->data0;
00297     //float m_eta = sc->data1;
00298     int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
00299     float3 m_N = sd->N;
00300 
00301     if(m_refractive) return make_float3 (0, 0, 0);
00302     float cosNO = dot(m_N, I);
00303     float cosNI = dot(m_N, omega_in);
00304     if(cosNO > 0 && cosNI > 0) {
00305        // get half vector
00306        float3 Hr = normalize(omega_in + I);
00307        // eq. 20: (F*G*D)/(4*in*on)
00308        // eq. 25: first we calculate D(m) with m=Hr:
00309        float alpha2 = m_ab * m_ab;
00310        float cosThetaM = dot(m_N, Hr);
00311        float cosThetaM2 = cosThetaM * cosThetaM;
00312        float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
00313        float cosThetaM4 = cosThetaM2 * cosThetaM2;
00314        float D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 *  cosThetaM4);
00315        // eq. 26, 27: now calculate G1(i,m) and G1(o,m)
00316        float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
00317        float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI)));
00318        float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f;
00319        float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f;
00320        float G = G1o * G1i;
00321        float out = (G * D) * 0.25f / cosNO;
00322        // eq. 24
00323        float pm = D * cosThetaM;
00324        // convert into pdf of the sampled direction
00325        // eq. 38 - but see also:
00326        // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
00327        *pdf = pm * 0.25f / dot(Hr, I);
00328        return make_float3 (out, out, out);
00329     }
00330     return make_float3 (0, 0, 0);
00331 }
00332 
00333 __device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
00334 {
00335     float m_ab = sc->data0;
00336     float m_eta = sc->data1;
00337     int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
00338     float3 m_N = sd->N;
00339 
00340     if(!m_refractive) return make_float3 (0, 0, 0);
00341     float cosNO = dot(m_N, I);
00342     float cosNI = dot(m_N, omega_in);
00343     if(cosNO <= 0 || cosNI >= 0)
00344         return make_float3 (0, 0, 0);
00345     // compute half-vector of the refraction (eq. 16)
00346     float3 ht = -(m_eta * omega_in + I);
00347     float3 Ht = normalize(ht);
00348     float cosHO = dot(Ht, I);
00349 
00350     float cosHI = dot(Ht, omega_in);
00351     // eq. 33: first we calculate D(m) with m=Ht:
00352     float alpha2 = m_ab * m_ab;
00353     float cosThetaM = dot(m_N, Ht);
00354     float cosThetaM2 = cosThetaM * cosThetaM;
00355     float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
00356     float cosThetaM4 = cosThetaM2 * cosThetaM2;
00357     float D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 *  cosThetaM4);
00358     // eq. 26, 27: now calculate G1(i,m) and G1(o,m)
00359     float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
00360     float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI)));
00361     float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f;
00362     float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f;
00363     float G = G1o * G1i;
00364     // probability
00365     float invHt2 = 1 / dot(ht, ht);
00366     *pdf = D * fabsf(cosThetaM) * (fabsf(cosHI) * (m_eta * m_eta)) * invHt2;
00367     float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D) * invHt2) / cosNO;
00368     return make_float3 (out, out, out);
00369 }
00370 
00371 __device float bsdf_microfacet_beckmann_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
00372 {
00373     return 1.0f;
00374 }
00375 
00376 __device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
00377 {
00378     float m_ab = sc->data0;
00379     float m_eta = sc->data1;
00380     int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
00381     float3 m_N = sd->N;
00382 
00383     float cosNO = dot(m_N, sd->I);
00384     if(cosNO > 0) {
00385         float3 X, Y, Z = m_N;
00386         make_orthonormals(Z, &X, &Y);
00387         // generate a random microfacet normal m
00388         // eq. 35,36:
00389         // we take advantage of cos(atan(x)) == 1/sqrt(1+x^2)
00390         //tttt  and sin(atan(x)) == x/sqrt(1+x^2)
00391         float alpha2 = m_ab * m_ab;
00392         float tanThetaM = sqrtf(-alpha2 * logf(1 - randu));
00393         float cosThetaM = 1 / sqrtf(1 + tanThetaM * tanThetaM);
00394         float sinThetaM = cosThetaM * tanThetaM;
00395         float phiM = 2 * M_PI_F * randv;
00396         float3 m = (cosf(phiM) * sinThetaM) * X +
00397                  (sinf(phiM) * sinThetaM) * Y +
00398                                cosThetaM  * Z;
00399 
00400         if(!m_refractive) {
00401             float cosMO = dot(m, sd->I);
00402             if(cosMO > 0) {
00403                 // eq. 39 - compute actual reflected direction
00404                 *omega_in = 2 * cosMO * m - sd->I;
00405                 if(dot(sd->Ng, *omega_in) > 0) {
00406                     // microfacet normal is visible to this ray
00407                     // eq. 25
00408                     float cosThetaM2 = cosThetaM * cosThetaM;
00409                     float tanThetaM2 = tanThetaM * tanThetaM;
00410                     float cosThetaM4 = cosThetaM2 * cosThetaM2;
00411                     float D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 *  cosThetaM4);
00412                     // eq. 24
00413                     float pm = D * cosThetaM;
00414                     // convert into pdf of the sampled direction
00415                     // eq. 38 - but see also:
00416                     // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
00417                     *pdf = pm * 0.25f / cosMO;
00418                     // Eval BRDF*cosNI
00419                     float cosNI = dot(m_N, *omega_in);
00420                     // eq. 26, 27: now calculate G1(i,m) and G1(o,m)
00421                     float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
00422                     float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI)));
00423                     float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f;
00424                     float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f;
00425                     float G = G1o * G1i;
00426                     // eq. 20: (F*G*D)/(4*in*on)
00427                     float out = (G * D) * 0.25f / cosNO;
00428                     *eval = make_float3(out, out, out);
00429 #ifdef __RAY_DIFFERENTIALS__
00430                     *domega_in_dx = (2 * dot(m, sd->dI.dx)) * m - sd->dI.dx;
00431                     *domega_in_dy = (2 * dot(m, sd->dI.dy)) * m - sd->dI.dy;
00432                     // Since there is some blur to this reflection, make the
00433                     // derivatives a bit bigger. In theory this varies with the
00434                     // roughness but the exact relationship is complex and
00435                     // requires more ops than are practical.
00436                     *domega_in_dx *= 10.0f;
00437                     *domega_in_dy *= 10.0f;
00438 #endif
00439                 }
00440             }
00441         } else {
00442             // CAUTION: the i and o variables are inverted relative to the paper
00443             // eq. 39 - compute actual refractive direction
00444             float3 R, T;
00445 #ifdef __RAY_DIFFERENTIALS__
00446             float3 dRdx, dRdy, dTdx, dTdy;
00447 #endif
00448             bool inside;
00449             fresnel_dielectric(m_eta, m, sd->I, &R, &T,
00450 #ifdef __RAY_DIFFERENTIALS__
00451                 sd->dI.dx, sd->dI.dy, &dRdx, &dRdy, &dTdx, &dTdy,
00452 #endif
00453                 &inside);
00454 
00455             if(!inside) {
00456                 *omega_in = T;
00457 #ifdef __RAY_DIFFERENTIALS__
00458                 *domega_in_dx = dTdx;
00459                 *domega_in_dy = dTdy;
00460 #endif
00461 
00462                 // eq. 33
00463                 float cosThetaM2 = cosThetaM * cosThetaM;
00464                 float tanThetaM2 = tanThetaM * tanThetaM;
00465                 float cosThetaM4 = cosThetaM2 * cosThetaM2;
00466                 float D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 *  cosThetaM4);
00467                 // eq. 24
00468                 float pm = D * cosThetaM;
00469                 // eval BRDF*cosNI
00470                 float cosNI = dot(m_N, *omega_in);
00471                 // eq. 26, 27: now calculate G1(i,m) and G1(o,m)
00472                 float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
00473                 float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI)));
00474                 float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f;
00475                 float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f;
00476                 float G = G1o * G1i;
00477                 // eq. 21
00478                 float cosHI = dot(m, *omega_in);
00479                 float cosHO = dot(m, sd->I);
00480                 float Ht2 = m_eta * cosHI + cosHO;
00481                 Ht2 *= Ht2;
00482                 float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2);
00483                 // eq. 38 and eq. 17
00484                 *pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2;
00485                 *eval = make_float3(out, out, out);
00486 #ifdef __RAY_DIFFERENTIALS__
00487                 // Since there is some blur to this refraction, make the
00488                 // derivatives a bit bigger. In theory this varies with the
00489                 // roughness but the exact relationship is complex and
00490                 // requires more ops than are practical.
00491                 *domega_in_dx *= 10.0f;
00492                 *domega_in_dy *= 10.0f;
00493 #endif
00494             }
00495         }
00496     }
00497     return (m_refractive) ? LABEL_TRANSMIT|LABEL_GLOSSY : LABEL_REFLECT|LABEL_GLOSSY;
00498 }
00499 
00500 CCL_NAMESPACE_END
00501 
00502 #endif /* __BSDF_MICROFACET_H__ */
00503