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 #include <OpenImageIO/fmath.h> 00034 00035 #include <OSL/genclosure.h> 00036 00037 #include "osl_closures.h" 00038 00039 #include "util_math.h" 00040 00041 CCL_NAMESPACE_BEGIN 00042 00043 using namespace OSL; 00044 00045 class WestinBackscatterClosure : public BSDFClosure { 00046 public: 00047 Vec3 m_N; 00048 float m_roughness; 00049 float m_invroughness; 00050 WestinBackscatterClosure() : BSDFClosure(Labels::GLOSSY) { } 00051 00052 void setup() 00053 { 00054 m_roughness = clamp(m_roughness, 1e-5f, 1.0f); 00055 m_invroughness = m_roughness > 0 ? 1 / m_roughness : 0; 00056 } 00057 00058 bool mergeable (const ClosurePrimitive *other) const { 00059 const WestinBackscatterClosure *comp = (const WestinBackscatterClosure *)other; 00060 return m_N == comp->m_N && m_roughness == comp->m_roughness && 00061 BSDFClosure::mergeable(other); 00062 } 00063 00064 size_t memsize () const { return sizeof(*this); } 00065 00066 const char *name () const { return "westin_backscatter"; } 00067 00068 void print_on (std::ostream &out) const 00069 { 00070 out << name() << " ("; 00071 out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; 00072 out << m_roughness; 00073 out << ")"; 00074 } 00075 00076 float albedo (const Vec3 &omega_out) const 00077 { 00078 return 1.0f; 00079 } 00080 00081 Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const 00082 { 00083 // pdf is implicitly 0 (no indirect sampling) 00084 float cosNO = m_N.dot(omega_out); 00085 float cosNI = m_N.dot(omega_in); 00086 if (cosNO > 0 && cosNI > 0) { 00087 float cosine = omega_out.dot(omega_in); 00088 pdf = cosine > 0 ? (m_invroughness + 1) * powf(cosine, m_invroughness) : 0; 00089 pdf *= 0.5f * float(M_1_PI); 00090 return Color3 (pdf, pdf, pdf); 00091 } 00092 return Color3 (0, 0, 0); 00093 } 00094 00095 Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const 00096 { 00097 return Color3 (0, 0, 0); 00098 } 00099 00100 ustring sample (const Vec3 &Ng, 00101 const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, 00102 float randu, float randv, 00103 Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, 00104 float &pdf, Color3 &eval) const 00105 { 00106 float cosNO = m_N.dot(omega_out); 00107 if (cosNO > 0) { 00108 domega_in_dx = domega_out_dx; 00109 domega_in_dy = domega_out_dy; 00110 Vec3 T, B; 00111 make_orthonormals (omega_out, T, B); 00112 float phi = 2 * (float) M_PI * randu; 00113 float cosTheta = powf(randv, 1 / (m_invroughness + 1)); 00114 float sinTheta2 = 1 - cosTheta * cosTheta; 00115 float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0; 00116 omega_in = (cosf(phi) * sinTheta) * T + 00117 (sinf(phi) * sinTheta) * B + 00118 ( cosTheta) * omega_out; 00119 if (Ng.dot(omega_in) > 0) 00120 { 00121 // common terms for pdf and eval 00122 float cosNI = m_N.dot(omega_in); 00123 // make sure the direction we chose is still in the right hemisphere 00124 if (cosNI > 0) 00125 { 00126 pdf = 0.5f * (float) M_1_PI * powf(cosTheta, m_invroughness); 00127 pdf = (m_invroughness + 1) * pdf; 00128 eval.setValue(pdf, pdf, pdf); 00129 // Since there is some blur to this reflection, make the 00130 // derivatives a bit bigger. In theory this varies with the 00131 // exponent but the exact relationship is complex and 00132 // requires more ops than are practical. 00133 domega_in_dx *= 10; 00134 domega_in_dy *= 10; 00135 } 00136 } 00137 } 00138 return Labels::REFLECT; 00139 } 00140 00141 }; 00142 00143 00144 class WestinSheenClosure : public BSDFClosure { 00145 public: 00146 Vec3 m_N; 00147 float m_edginess; 00148 // float m_normalization; 00149 WestinSheenClosure() : BSDFClosure(Labels::DIFFUSE) { } 00150 00151 void setup() {}; 00152 00153 bool mergeable (const ClosurePrimitive *other) const { 00154 const WestinSheenClosure *comp = (const WestinSheenClosure *)other; 00155 return m_N == comp->m_N && m_edginess == comp->m_edginess && 00156 BSDFClosure::mergeable(other); 00157 } 00158 00159 size_t memsize () const { return sizeof(*this); } 00160 00161 const char *name () const { return "westin_sheen"; } 00162 00163 void print_on (std::ostream &out) const 00164 { 00165 out << name() << " ("; 00166 out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; 00167 out << m_edginess; 00168 out << ")"; 00169 } 00170 00171 float albedo (const Vec3 &omega_out) const 00172 { 00173 return 1.0f; 00174 } 00175 00176 Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const 00177 { 00178 // pdf is implicitly 0 (no indirect sampling) 00179 float cosNO = m_N.dot(omega_out); 00180 float cosNI = m_N.dot(omega_in); 00181 if (cosNO > 0 && cosNI > 0) { 00182 float sinNO2 = 1 - cosNO * cosNO; 00183 pdf = cosNI * float(M_1_PI); 00184 float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * pdf : 0; 00185 return Color3 (westin, westin, westin); 00186 } 00187 return Color3 (0, 0, 0); 00188 } 00189 00190 Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const 00191 { 00192 return Color3 (0, 0, 0); 00193 } 00194 00195 ustring sample (const Vec3 &Ng, 00196 const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, 00197 float randu, float randv, 00198 Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, 00199 float &pdf, Color3 &eval) const 00200 { 00201 // we are viewing the surface from the right side - send a ray out with cosine 00202 // distribution over the hemisphere 00203 sample_cos_hemisphere (m_N, omega_out, randu, randv, omega_in, pdf); 00204 if (Ng.dot(omega_in) > 0) { 00205 // TODO: account for sheen when sampling 00206 float cosNO = m_N.dot(omega_out); 00207 float sinNO2 = 1 - cosNO * cosNO; 00208 float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * pdf : 0; 00209 eval.setValue(westin, westin, westin); 00210 // TODO: find a better approximation for the diffuse bounce 00211 domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; 00212 domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; 00213 domega_in_dx *= 125; 00214 domega_in_dy *= 125; 00215 } else 00216 pdf = 0; 00217 return Labels::REFLECT; 00218 } 00219 }; 00220 00221 00222 00223 ClosureParam bsdf_westin_backscatter_params[] = { 00224 CLOSURE_VECTOR_PARAM(WestinBackscatterClosure, m_N), 00225 CLOSURE_FLOAT_PARAM (WestinBackscatterClosure, m_roughness), 00226 CLOSURE_STRING_KEYPARAM("label"), 00227 CLOSURE_FINISH_PARAM(WestinBackscatterClosure) }; 00228 00229 ClosureParam bsdf_westin_sheen_params[] = { 00230 CLOSURE_VECTOR_PARAM(WestinSheenClosure, m_N), 00231 CLOSURE_FLOAT_PARAM (WestinSheenClosure, m_edginess), 00232 CLOSURE_STRING_KEYPARAM("label"), 00233 CLOSURE_FINISH_PARAM(WestinSheenClosure) }; 00234 00235 CLOSURE_PREPARE(bsdf_westin_backscatter_prepare, WestinBackscatterClosure) 00236 CLOSURE_PREPARE(bsdf_westin_sheen_prepare, WestinSheenClosure) 00237 00238 CCL_NAMESPACE_END 00239