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 CCL_NAMESPACE_BEGIN 00040 00041 using namespace OSL; 00042 00043 // Computes scattering properties based on Jensen's reparameterization 00044 // described in: 00045 // http://graphics.ucsd.edu/~henrik/papers/fast_bssrdf/ 00046 00047 class SubsurfaceClosure : public VolumeClosure { 00048 public: 00049 float m_g; 00050 float m_eta; 00051 Color3 m_mfp, m_albedo; 00052 static float root_find_Rd(const float Rd0, const float A) { 00053 // quick exit for trivial cases 00054 if (Rd0 <= 0) return 0; 00055 const float A43 = A * 4.0f / 3.0f; 00056 // Find alpha such that f(alpha) = Rd (see eq.15). A simple bisection 00057 // method can be used because this function is monotonicaly increasing. 00058 float lo = 0, hi = 1; 00059 for (int i = 0; i < 20; i++) { // 2^20 divisions should be sufficient 00060 // eval function at midpoint 00061 float alpha = 0.5f * (lo + hi); 00062 float a1 = sqrtf(3 * (1 - alpha)); 00063 float e1 = expf(-a1); 00064 float e2 = expf(-A43 * a1); 00065 float Rd = 0.5f * alpha * (1 + e2) * e1 - Rd0; 00066 if (fabsf(Rd) < 1e-6f) 00067 return alpha; // close enough 00068 else if (Rd > 0) 00069 hi = alpha; // root is on left side 00070 else 00071 lo = alpha; // root is on right side 00072 } 00073 // didn't quite converge, pick result in the middle of remaining interval 00074 return 0.5f * (lo + hi); 00075 } 00076 SubsurfaceClosure() { } 00077 00078 void setup() 00079 { 00080 ior(m_eta); 00081 00082 if (m_g >= 0.99f) m_g = 0.99f; 00083 if (m_g <= -0.99f) m_g = -0.99f; 00084 00085 // eq.10 00086 float inv_eta = 1 / m_eta; 00087 float Fdr = -1.440f * inv_eta * inv_eta + 0.710 * inv_eta + 0.668f + 0.0636 * m_eta; 00088 float A = (1 + Fdr) / (1 - Fdr); 00089 // compute sigma_s, sigma_a (eq.16) 00090 Color3 alpha_prime = Color3 (root_find_Rd(m_albedo[0], A), 00091 root_find_Rd(m_albedo[1], A), 00092 root_find_Rd(m_albedo[2], A)); 00093 Color3 sigma_t_prime = Color3 (m_mfp.x > 0 ? 1.0f / (m_mfp[0] * sqrtf(3 * (1 - alpha_prime[0]))) : 0.0f, 00094 m_mfp.y > 0 ? 1.0f / (m_mfp[1] * sqrtf(3 * (1 - alpha_prime[1]))) : 0.0f, 00095 m_mfp.z > 0 ? 1.0f / (m_mfp[2] * sqrtf(3 * (1 - alpha_prime[2]))) : 0.0f); 00096 Color3 sigma_s_prime = alpha_prime * sigma_t_prime; 00097 00098 sigma_s((1.0f / (1 - m_g)) * sigma_s_prime); 00099 sigma_a(sigma_t_prime - sigma_s_prime); 00100 } 00101 00102 bool mergeable (const ClosurePrimitive *other) const { 00103 const SubsurfaceClosure *comp = (const SubsurfaceClosure *)other; 00104 return m_g == comp->m_g && VolumeClosure::mergeable(other); 00105 } 00106 00107 size_t memsize () const { return sizeof(*this); } 00108 00109 const char *name () const { return "subsurface"; } 00110 00111 void print_on (std::ostream &out) const { 00112 out << name() << " ()"; 00113 } 00114 00115 virtual Color3 eval_phase(const Vec3 &omega_in, const Vec3 &omega_out) const { 00116 float costheta = omega_in.dot(omega_out); 00117 float ph = 0.25f * float(M_1_PI) * ((1 - m_g * m_g) / powf(1 + m_g * m_g - 2.0f * m_g * costheta, 1.5f)); 00118 return Color3 (ph, ph, ph); 00119 } 00120 }; 00121 00122 00123 00124 ClosureParam closure_subsurface_params[] = { 00125 CLOSURE_FLOAT_PARAM (SubsurfaceClosure, m_eta), 00126 CLOSURE_FLOAT_PARAM (SubsurfaceClosure, m_g), 00127 CLOSURE_COLOR_PARAM (SubsurfaceClosure, m_mfp), 00128 CLOSURE_COLOR_PARAM (SubsurfaceClosure, m_albedo), 00129 CLOSURE_STRING_KEYPARAM("label"), 00130 CLOSURE_FINISH_PARAM(SubsurfaceClosure) }; 00131 00132 CLOSURE_PREPARE(closure_subsurface_prepare, SubsurfaceClosure) 00133 00134 CCL_NAMESPACE_END 00135