Cycles OSL minor optimizations: recycle shading context, don't do memory
[blender.git] / intern / cycles / kernel / closure / bsdf.h
index cfb6321a91841cbebad59399bf936da89730ad45..f26aefe7fd34559c34925693b827981ca54fd401 100644 (file)
 /*
- * Adapted from Open Shading Language with this license:
+ * Copyright 2011, Blender Foundation.
  *
- * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
- * All Rights Reserved.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
  *
- * Modifications Copyright 2011, Blender Foundation.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * * Neither the name of Sony Pictures Imageworks nor the names of its
- *   contributors may be used to endorse or promote products derived from
- *   this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
-#ifndef __OSL_BSDF_H__
-#define __OSL_BSDF_H__
+#include "../closure/bsdf_ashikhmin_velvet.h"
+#include "../closure/bsdf_diffuse.h"
+#include "../closure/bsdf_oren_nayar.h"
+#include "../closure/bsdf_phong_ramp.h"
+#include "../closure/bsdf_diffuse_ramp.h"
+#include "../closure/bsdf_microfacet.h"
+#include "../closure/bsdf_reflection.h"
+#include "../closure/bsdf_refraction.h"
+#include "../closure/bsdf_transparent.h"
+#ifdef __ANISOTROPIC__
+#include "../closure/bsdf_ward.h"
+#endif
+#include "../closure/bsdf_westin.h"
 
 CCL_NAMESPACE_BEGIN
 
-__device float fresnel_dielectric(float eta, const float3 N,
-               const float3 I, float3 *R, float3 *T,
-#ifdef __RAY_DIFFERENTIALS__
-               const float3 dIdx, const float3 dIdy,
-               float3 *dRdx, float3 *dRdy,
-               float3 *dTdx, float3 *dTdy, 
-#endif
-               bool *is_inside)
+__device int bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, differential3 *domega_in, float *pdf)
 {
-       float cos = dot(N, I), neta;
-       float3 Nn;
-       // compute reflection
-       *R = (2 * cos)* N - I;
-#ifdef __RAY_DIFFERENTIALS__
-       *dRdx = (2 * dot(N, dIdx)) * N - dIdx;
-       *dRdy = (2 * dot(N, dIdy)) * N - dIdy;
+       int label;
+
+#ifdef __OSL__
+       if(kg->osl && sc->prim)
+               return OSLShader::bsdf_sample(sd, sc, randu, randv, *eval, *omega_in, *domega_in, *pdf);
 #endif
-       // check which side of the surface we are on
-       if(cos > 0) {
-               // we are on the outside of the surface, going in
-               neta = 1 / eta;
-               Nn   = N;
-               *is_inside = false;
-       }
-       else {
-               // we are inside the surface, 
-               cos  = -cos;
-               neta = eta;
-               Nn   = -N;
-               *is_inside = true;
-       }
-       *R = (2 * cos)* Nn - I;
-       float arg = 1 -(neta * neta *(1 -(cos * cos)));
-       if(arg < 0) {
-               *T = make_float3(0.0f, 0.0f, 0.0f);
-#ifdef __RAY_DIFFERENTIALS__
-               *dTdx = make_float3(0.0f, 0.0f, 0.0f);
-               *dTdy = make_float3(0.0f, 0.0f, 0.0f);
+
+       switch(sc->type) {
+               case CLOSURE_BSDF_DIFFUSE_ID:
+                       label = bsdf_diffuse_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+                               eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       break;
+#ifdef __SVM__
+               case CLOSURE_BSDF_OREN_NAYAR_ID:
+                       label = bsdf_oren_nayar_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+                               eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       break;
+               /*case CLOSURE_BSDF_PHONG_RAMP_ID:
+                       label = bsdf_phong_ramp_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+                               eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       break;
+               case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
+                       label = bsdf_diffuse_ramp_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+                               eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       break;*/
+               case CLOSURE_BSDF_TRANSLUCENT_ID:
+                       label = bsdf_translucent_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+                               eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       break;
+               case CLOSURE_BSDF_REFLECTION_ID:
+                       label = bsdf_reflection_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+                               eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       break;
+               case CLOSURE_BSDF_REFRACTION_ID:
+                       label = bsdf_refraction_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+                               eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       break;
+               case CLOSURE_BSDF_TRANSPARENT_ID:
+                       label = bsdf_transparent_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+                               eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       break;
+               case CLOSURE_BSDF_MICROFACET_GGX_ID:
+               case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
+                       label = bsdf_microfacet_ggx_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+                               eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       break;
+               case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
+               case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
+                       label = bsdf_microfacet_beckmann_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+                               eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       break;
+#ifdef __ANISOTROPIC__
+               case CLOSURE_BSDF_WARD_ID:
+                       label = bsdf_ward_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+                               eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       break;
 #endif
-               return 1; // total internal reflection
-       }
-       else {
-               float dnp = sqrtf(arg);
-               float nK = (neta * cos)- dnp;
-               *T = -(neta * I)+(nK * Nn);
-#ifdef __RAY_DIFFERENTIALS__
-               *dTdx = -(neta * dIdx) + ((neta - neta * neta * cos / dnp) * dot(dIdx, Nn)) * Nn;
-               *dTdy = -(neta * dIdy) + ((neta - neta * neta * cos / dnp) * dot(dIdy, Nn)) * Nn;
+               case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
+                       label = bsdf_ashikhmin_velvet_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+                               eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       break;
+               case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID:
+                       label = bsdf_westin_backscatter_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+                               eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       break;
+               case CLOSURE_BSDF_WESTIN_SHEEN_ID:
+                       label = bsdf_westin_sheen_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+                               eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       break;
 #endif
-               // compute Fresnel terms
-               float cosTheta1 = cos; // N.R
-               float cosTheta2 = -dot(Nn, *T);
-               float pPara = (cosTheta1 - eta * cosTheta2)/(cosTheta1 + eta * cosTheta2);
-               float pPerp = (eta * cosTheta1 - cosTheta2)/(eta * cosTheta1 + cosTheta2);
-               return 0.5f * (pPara * pPara + pPerp * pPerp);
+               default:
+                       label = LABEL_NONE;
+                       break;
        }
+
+       return label;
 }
 
-__device float fresnel_dielectric_cos(float cosi, float eta)
+__device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, float *pdf)
 {
-       // compute fresnel reflectance without explicitly computing
-       // the refracted direction
-       float c = fabsf(cosi);
-       float g = eta * eta - 1 + c * c;
-       if(g > 0) {
-               g = sqrtf(g);
-               float A = (g - c)/(g + c);
-               float B = (c *(g + c)- 1)/(c *(g - c)+ 1);
-               return 0.5f * A * A *(1 + B * B);
+       float3 eval;
+
+#ifdef __OSL__
+       if(kg->osl && sc->prim)
+               return OSLShader::bsdf_eval(sd, sc, omega_in, *pdf);
+#endif
+
+       if(dot(sd->Ng, omega_in) >= 0.0f) {
+               switch(sc->type) {
+                       case CLOSURE_BSDF_DIFFUSE_ID:
+                               eval = bsdf_diffuse_eval_reflect(sc, sd->I, omega_in, pdf);
+                               break;
+#ifdef __SVM__
+                       case CLOSURE_BSDF_OREN_NAYAR_ID:
+                               eval = bsdf_oren_nayar_eval_reflect(sc, sd->I, omega_in, pdf);
+                               break;
+                       /*case CLOSURE_BSDF_PHONG_RAMP_ID:
+                               eval = bsdf_phong_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
+                               break;
+                       case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
+                               eval = bsdf_diffuse_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
+                               break;*/
+                       case CLOSURE_BSDF_TRANSLUCENT_ID:
+                               eval = bsdf_translucent_eval_reflect(sc, sd->I, omega_in, pdf);
+                               break;
+                       case CLOSURE_BSDF_REFLECTION_ID:
+                               eval = bsdf_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
+                               break;
+                       case CLOSURE_BSDF_REFRACTION_ID:
+                               eval = bsdf_refraction_eval_reflect(sc, sd->I, omega_in, pdf);
+                               break;
+                       case CLOSURE_BSDF_TRANSPARENT_ID:
+                               eval = bsdf_transparent_eval_reflect(sc, sd->I, omega_in, pdf);
+                               break;
+                       case CLOSURE_BSDF_MICROFACET_GGX_ID:
+                       case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
+                               eval = bsdf_microfacet_ggx_eval_reflect(sc, sd->I, omega_in, pdf);
+                               break;
+                       case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
+                       case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
+                               eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf);
+                               break;
+#ifdef __ANISOTROPIC__
+                       case CLOSURE_BSDF_WARD_ID:
+                               eval = bsdf_ward_eval_reflect(sc, sd->I, omega_in, pdf);
+                               break;
+#endif
+                       case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
+                               eval = bsdf_ashikhmin_velvet_eval_reflect(sc, sd->I, omega_in, pdf);
+                               break;
+                       case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID:
+                               eval = bsdf_westin_backscatter_eval_reflect(sc, sd->I, omega_in, pdf);
+                               break;
+                       case CLOSURE_BSDF_WESTIN_SHEEN_ID:
+                               eval = bsdf_westin_sheen_eval_reflect(sc, sd->I, omega_in, pdf);
+                               break;
+#endif
+                       default:
+                               eval = make_float3(0.0f, 0.0f, 0.0f);
+                               break;
+               }
+       }
+       else {
+               switch(sc->type) {
+                       case CLOSURE_BSDF_DIFFUSE_ID:
+                               eval = bsdf_diffuse_eval_transmit(sc, sd->I, omega_in, pdf);
+                               break;
+#ifdef __SVM__
+                       case CLOSURE_BSDF_OREN_NAYAR_ID:
+                               eval = bsdf_oren_nayar_eval_transmit(sc, sd->I, omega_in, pdf);
+                               break;
+                       case CLOSURE_BSDF_TRANSLUCENT_ID:
+                               eval = bsdf_translucent_eval_transmit(sc, sd->I, omega_in, pdf);
+                               break;
+                       case CLOSURE_BSDF_REFLECTION_ID:
+                               eval = bsdf_reflection_eval_transmit(sc, sd->I, omega_in, pdf);
+                               break;
+                       case CLOSURE_BSDF_REFRACTION_ID:
+                               eval = bsdf_refraction_eval_transmit(sc, sd->I, omega_in, pdf);
+                               break;
+                       case CLOSURE_BSDF_TRANSPARENT_ID:
+                               eval = bsdf_transparent_eval_transmit(sc, sd->I, omega_in, pdf);
+                               break;
+                       case CLOSURE_BSDF_MICROFACET_GGX_ID:
+                       case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
+                               eval = bsdf_microfacet_ggx_eval_transmit(sc, sd->I, omega_in, pdf);
+                               break;
+                       case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
+                       case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
+                               eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf);
+                               break;
+#ifdef __ANISOTROPIC__
+                       case CLOSURE_BSDF_WARD_ID:
+                               eval = bsdf_ward_eval_transmit(sc, sd->I, omega_in, pdf);
+                               break;
+#endif
+                       case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
+                               eval = bsdf_ashikhmin_velvet_eval_transmit(sc, sd->I, omega_in, pdf);
+                               break;
+                       case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID:
+                               eval = bsdf_westin_backscatter_eval_transmit(sc, sd->I, omega_in, pdf);
+                               break;
+                       case CLOSURE_BSDF_WESTIN_SHEEN_ID:
+                               eval = bsdf_westin_sheen_eval_transmit(sc, sd->I, omega_in, pdf);
+                               break;
+#endif
+                       default:
+                               eval = make_float3(0.0f, 0.0f, 0.0f);
+                               break;
+               }
        }
-       return 1.0f; // TIR(no refracted component)
-}
 
-__device float fresnel_conductor(float cosi, float eta, float k)
-{
-       float tmp_f = eta * eta + k * k;
-       float tmp = tmp_f * cosi * cosi;
-       float Rparl2 = (tmp - (2.0f * eta * cosi) + 1)/
-                      (tmp + (2.0f * eta * cosi) + 1);
-       float Rperp2 = (tmp_f - (2.0f * eta * cosi) + cosi * cosi)/
-                      (tmp_f + (2.0f * eta * cosi) + cosi * cosi);
-       return(Rparl2 + Rperp2) * 0.5f;
+       return eval;
 }
 
-__device float smooth_step(float edge0, float edge1, float x)
+__device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness)
 {
-       float result;
-       if(x < edge0) result = 0.0f;
-       else if(x >= edge1) result = 1.0f;
-       else {
-               float t = (x - edge0)/(edge1 - edge0);
-               result = (3.0f-2.0f*t)*(t*t);
+#ifdef __OSL__
+       if(kg->osl && sc->prim) {
+               OSLShader::bsdf_blur(sc, roughness);
+               return;
+       }
+#endif
+
+       switch(sc->type) {
+               case CLOSURE_BSDF_DIFFUSE_ID:
+                       bsdf_diffuse_blur(sc, roughness);
+                       break;
+#ifdef __SVM__
+               case CLOSURE_BSDF_OREN_NAYAR_ID:
+                       bsdf_oren_nayar_blur(sc, roughness);
+                       break;
+               /*case CLOSURE_BSDF_PHONG_RAMP_ID:
+                       bsdf_phong_ramp_blur(sc, roughness);
+                       break;
+               case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
+                       bsdf_diffuse_ramp_blur(sc, roughness);
+                       break;*/
+               case CLOSURE_BSDF_TRANSLUCENT_ID:
+                       bsdf_translucent_blur(sc, roughness);
+                       break;
+               case CLOSURE_BSDF_REFLECTION_ID:
+                       bsdf_reflection_blur(sc, roughness);
+                       break;
+               case CLOSURE_BSDF_REFRACTION_ID:
+                       bsdf_refraction_blur(sc, roughness);
+                       break;
+               case CLOSURE_BSDF_TRANSPARENT_ID:
+                       bsdf_transparent_blur(sc, roughness);
+                       break;
+               case CLOSURE_BSDF_MICROFACET_GGX_ID:
+               case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
+                       bsdf_microfacet_ggx_blur(sc, roughness);
+                       break;
+               case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
+               case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
+                       bsdf_microfacet_beckmann_blur(sc, roughness);
+                       break;
+#ifdef __ANISOTROPIC__
+               case CLOSURE_BSDF_WARD_ID:
+                       bsdf_ward_blur(sc, roughness);
+                       break;
+#endif
+               case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
+                       bsdf_ashikhmin_velvet_blur(sc, roughness);
+                       break;
+               case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID:
+                       bsdf_westin_backscatter_blur(sc, roughness);
+                       break;
+               case CLOSURE_BSDF_WESTIN_SHEEN_ID:
+                       bsdf_westin_sheen_blur(sc, roughness);
+                       break;
+#endif
+               default:
+                       break;
        }
-       return result;
 }
 
 CCL_NAMESPACE_END
 
-#endif /* __OSL_BSDF_H__ */
-