Blender V2.61 - r43446

bsdf_westin.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_WESTIN_H__
00034 #define __BSDF_WESTIN_H__
00035 
00036 CCL_NAMESPACE_BEGIN
00037 
00038 /* WESTIN BACKSCATTER */
00039 
00040 typedef struct BsdfWestinBackscatterClosure {
00041     //float3 m_N;
00042     float m_invroughness;
00043 } BsdfWestinBackscatterClosure;
00044 
00045 __device void bsdf_westin_backscatter_setup(ShaderData *sd, ShaderClosure *sc, float roughness)
00046 {
00047     roughness = clamp(roughness, 1e-5f, 1.0f);
00048     float m_invroughness = 1.0f/roughness;
00049 
00050     sc->type = CLOSURE_BSDF_WESTIN_BACKSCATTER_ID;
00051     sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
00052     sc->data0 = m_invroughness;
00053 }
00054 
00055 __device void bsdf_westin_backscatter_blur(ShaderClosure *sc, float roughness)
00056 {
00057     float m_invroughness = sc->data0;
00058     m_invroughness = min(1.0f/roughness, m_invroughness);
00059     sc->data0 = m_invroughness;
00060 }
00061 
00062 __device float3 bsdf_westin_backscatter_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
00063 {
00064     float m_invroughness = sc->data0;
00065     float3 m_N = sd->N;
00066 
00067     // pdf is implicitly 0 (no indirect sampling)
00068     float cosNO = dot(m_N, I);
00069     float cosNI = dot(m_N, omega_in);
00070     if(cosNO > 0 && cosNI > 0) {
00071         float cosine = dot(I, omega_in);
00072         *pdf = cosine > 0 ? (m_invroughness + 1) * powf(cosine, m_invroughness) : 0;
00073         *pdf *= 0.5f * M_1_PI_F;
00074         return make_float3 (*pdf, *pdf, *pdf);
00075     }
00076     return make_float3 (0, 0, 0);
00077 }
00078 
00079 __device float3 bsdf_westin_backscatter_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
00080 {
00081     return make_float3(0.0f, 0.0f, 0.0f);
00082 }
00083 
00084 __device float bsdf_westin_backscatter_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
00085 {
00086     return 1.0f;
00087 }
00088 
00089 __device int bsdf_westin_backscatter_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)
00090 {
00091     float m_invroughness = sc->data0;
00092     float3 m_N = sd->N;
00093 
00094     float cosNO = dot(m_N, sd->I);
00095     if(cosNO > 0) {
00096 #ifdef __RAY_DIFFERENTIALS__
00097         *domega_in_dx = sd->dI.dx;
00098         *domega_in_dy = sd->dI.dy;
00099 #endif
00100         float3 T, B;
00101         make_orthonormals (sd->I, &T, &B);
00102         float phi = 2 * M_PI_F * randu;
00103         float cosTheta = powf(randv, 1 / (m_invroughness + 1));
00104         float sinTheta2 = 1 - cosTheta * cosTheta;
00105         float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0;
00106         *omega_in = (cosf(phi) * sinTheta) * T +
00107                    (sinf(phi) * sinTheta) * B +
00108                    (cosTheta) * sd->I;
00109         if(dot(sd->Ng, *omega_in) > 0)
00110         {
00111             // common terms for pdf and eval
00112             float cosNI = dot(m_N, *omega_in);
00113             // make sure the direction we chose is still in the right hemisphere
00114             if(cosNI > 0)
00115             {
00116                 *pdf = 0.5f * M_1_PI_F * powf(cosTheta, m_invroughness);
00117                 *pdf = (m_invroughness + 1) * (*pdf);
00118                 *eval = make_float3(*pdf, *pdf, *pdf);
00119 #ifdef __RAY_DIFFERENTIALS__
00120                 // Since there is some blur to this reflection, make the
00121                 // derivatives a bit bigger. In theory this varies with the
00122                 // exponent but the exact relationship is complex and
00123                 // requires more ops than are practical.
00124                 *domega_in_dx *= 10.0f;
00125                 *domega_in_dy *= 10.0f;
00126 #endif
00127             }
00128         }
00129     }
00130     return LABEL_REFLECT|LABEL_GLOSSY;
00131 }
00132 
00133 /* WESTIN SHEEN */
00134 
00135 typedef struct BsdfWestinSheenClosure {
00136     //float3 m_N;
00137     float m_edginess;
00138 } BsdfWestinSheenClosure;
00139 
00140 __device void bsdf_westin_sheen_setup(ShaderData *sd, ShaderClosure *sc, float edginess)
00141 {
00142     sc->type = CLOSURE_BSDF_WESTIN_SHEEN_ID;
00143     sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
00144     sc->data0 = edginess;
00145 }
00146 
00147 __device void bsdf_westin_sheen_blur(ShaderClosure *sc, float roughness)
00148 {
00149 }
00150 
00151 __device float3 bsdf_westin_sheen_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
00152 {
00153     float m_edginess = sc->data0;
00154     float3 m_N = sd->N;
00155 
00156     // pdf is implicitly 0 (no indirect sampling)
00157     float cosNO = dot(m_N, I);
00158     float cosNI = dot(m_N, omega_in);
00159     if(cosNO > 0 && cosNI > 0) {
00160         float sinNO2 = 1 - cosNO * cosNO;
00161         *pdf = cosNI * M_1_PI_F;
00162         float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * (*pdf) : 0;
00163         return make_float3 (westin, westin, westin);
00164     }
00165     return make_float3 (0, 0, 0);
00166 }
00167 
00168 __device float3 bsdf_westin_sheen_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
00169 {
00170     return make_float3(0.0f, 0.0f, 0.0f);
00171 }
00172 
00173 __device float bsdf_westin_sheen_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
00174 {
00175     return 1.0f;
00176 }
00177 
00178 __device int bsdf_westin_sheen_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)
00179 {
00180     float m_edginess = sc->data0;
00181     float3 m_N = sd->N;
00182 
00183     // we are viewing the surface from the right side - send a ray out with cosine
00184     // distribution over the hemisphere
00185     sample_cos_hemisphere(m_N, randu, randv, omega_in, pdf);
00186     if(dot(sd->Ng, *omega_in) > 0) {
00187         // TODO: account for sheen when sampling
00188         float cosNO = dot(m_N, sd->I);
00189         float sinNO2 = 1 - cosNO * cosNO;
00190         float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * (*pdf) : 0;
00191         *eval = make_float3(westin, westin, westin);
00192 #ifdef __RAY_DIFFERENTIALS__
00193         // TODO: find a better approximation for the diffuse bounce
00194         *domega_in_dx = (2 * dot(m_N, sd->dI.dx)) * m_N - sd->dI.dx;
00195         *domega_in_dy = (2 * dot(m_N, sd->dI.dy)) * m_N - sd->dI.dy;
00196         *domega_in_dx *= 125.0f;
00197         *domega_in_dy *= 125.0f;
00198 #endif
00199     } else
00200         pdf = 0;
00201     return LABEL_REFLECT|LABEL_DIFFUSE;
00202 }
00203 
00204 CCL_NAMESPACE_END
00205 
00206 #endif /* __BSDF_WESTIN_H__ */
00207