Blender V2.61 - r43446
|
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