// ======================================================================== // // Copyright 2009-2013 Intel Corporation // // // // Licensed under the Apache License, Version 2.0 (the "License"); // // you may not use this file except in compliance with the License. // // You may obtain a copy of the License at // // // // http://www.apache.org/licenses/LICENSE-2.0 // // // // Unless required by applicable law or agreed to in writing, software // // distributed under the License is distributed on an "AS IS" BASIS, // // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // // See the License for the specific language governing permissions and // // limitations under the License. // // ======================================================================== // #pragma once /*! \addtogroup rivl_render_embree_ivl */ /*! @{ */ /*! Reflects a viewing vector V at a normal N. */ inline Sample3f reflect_(const Vec3f &V, const Vec3f &N) { float cosi = dot(V,N); return make_Sample3f(2.0f*cosi*N-V, 1.0f); } /*! Reflects a viewing vector V at a normal N. Cosine between V * and N is given as input. */ inline Sample3f reflect_(const Vec3f &V, const Vec3f &N, const float cosi) { return make_Sample3f(2.0f*cosi*N-V, 1.0f); } // ======================================================= /*!Refracts a viewing vector V at a normal N using the relative * refraction index eta. Eta is refraction index of outside medium * (where N points into) divided by refraction index of the inside * medium. The vectors V and N have to point towards the same side * of the surface. The cosine between V and N is given as input and * the cosine of -N and transmission ray is computed as output. */ inline Sample3f refract(const Vec3f& V, const Vec3f& N, const float eta, const float cosi, float &cost) { const float k = 1.0f-eta*eta*(1.0f-cosi*cosi); if (k < 0.0f) { cost = 0.0f; return make_Sample3f(make_Vec3f(0.f),0.0f); } cost = sqrt(k); return make_Sample3f(eta*(cosi*N-V)-cost*N, sqr(eta)); } /*! Computes fresnel coefficient for media interface with relative * refraction index eta. Eta is the outside refraction index * divided by the inside refraction index. Both cosines have to be * positive. */ inline float fresnelDielectric(const float cosi, const float cost, const float eta) { const float Rper = (eta*cosi - cost) * rcp(eta*cosi + cost); const float Rpar = ( cosi - eta*cost) * rcp( cosi + eta*cost); return 0.5f*(Rpar*Rpar + Rper*Rper); } /*! Computes fresnel coefficient for media interface with relative * refraction index eta. Eta is the outside refraction index * divided by the inside refraction index. The cosine has to be * positive. */ inline float fresnelDielectric(const float cosi, const float eta) { const float k = 1.0f-eta*eta*(1.0f-cosi*cosi); if (k < 0.0f) return 1.0f; const float cost = sqrt(k); return fresnelDielectric(cosi, cost, eta); } /*! Computes fresnel coefficient for conductor medium with complex * refraction index (eta,k). The cosine has to be positive. */ inline Vec3f fresnelConductor(const float cosi, const Vec3f& eta, const Vec3f& k) { const Vec3f tmp = eta*eta + k*k; const Vec3f Rpar = (tmp * (cosi*cosi) - 2.0f*eta*cosi + make_Vec3f(1.0f)) * rcp(tmp * (cosi*cosi) + 2.0f*eta*cosi + make_Vec3f(1.0f)); const Vec3f Rper = (tmp - 2.0f*eta*cosi + make_Vec3f(cosi*cosi)) * rcp(tmp + 2.0f*eta*cosi + make_Vec3f(cosi*cosi)); return 0.5f * (Rpar + Rper); } // ======================================================= struct FresnelConductor { Vec3f eta; //!< Real part of refraction index Vec3f k; //!< Imaginary part of refraction index }; inline Vec3f eval(varying const FresnelConductor& THIS, const float cosTheta) { return fresnelConductor(cosTheta,THIS.eta,THIS.k); } inline uniform FresnelConductor make_FresnelConductor(const uniform Vec3f& eta, const uniform Vec3f& k) { uniform FresnelConductor m; m.eta = eta; m.k = k; return m; } #if defined(ISPC) inline varying FresnelConductor make_FresnelConductor(const varying Vec3f& eta, const varying Vec3f& k) { varying FresnelConductor m; m.eta = eta; m.k = k; return m; } #endif // ======================================================= struct FresnelDielectric { /*! refraction index of the medium the incident ray travels in */ float etai; /*! refraction index of the medium the outgoing transmission rays * travels in */ float etat; }; inline Vec3f eval(const uniform FresnelDielectric& THIS, const float cosTheta) { return make_Vec3f(fresnelDielectric(cosTheta,THIS.etai/THIS.etat)); } inline uniform FresnelDielectric make_FresnelDielectric(const uniform float etai, const uniform float etat) { uniform FresnelDielectric m; m.etai = etai; m.etat = etat; return m; } #if defined(ISPC) inline varying FresnelDielectric make_FresnelDielectric(const varying float etai, const varying float etat) { varying FresnelDielectric m; m.etai = etai; m.etat = etat; return m; } #endif // ======================================================= struct PowerCosineDistribution { float exp; }; inline float eval(const uniform PowerCosineDistribution &THIS, const float cosThetaH) { return (THIS.exp+2) * (1.0f/(2.0f*(M_PI))) * pow(abs(cosThetaH), THIS.exp); } #if defined(ISPC) inline float eval(const varying PowerCosineDistribution &THIS, const float cosThetaH) { return (THIS.exp+2) * (1.0f/(2.0f*(M_PI))) * pow(abs(cosThetaH), THIS.exp); } #endif /*! Samples the power cosine distribution. */ inline void sample(const uniform PowerCosineDistribution& THIS, const Vec3f& wo, const Vec3f& N, Sample3f &wi, const Vec2f s) { Sample3f wh = powerCosineSampleHemisphere(s.x,s.y,N,THIS.exp); Sample3f r = reflect_(wo,wh.v); wi = make_Sample3f(r.v,wh.pdf/(4.0f*abs(dot(wo,wh.v)))); } /*! Samples the power cosine distribution. */ #if defined(ISPC) inline void sample(const varying PowerCosineDistribution& THIS, const Vec3f& wo, const Vec3f& N, Sample3f &wi, const Vec2f s) { Sample3f wh = powerCosineSampleHemisphere(s.x,s.y,N,THIS.exp); Sample3f r = reflect_(wo,wh.v); wi = make_Sample3f(r.v,wh.pdf/(4.0f*abs(dot(wo,wh.v)))); } #endif inline uniform PowerCosineDistribution make_PowerCosineDistribution(const uniform float _exp) { uniform PowerCosineDistribution m; m.exp = _exp; return m; } #if defined(ISPC) inline varying PowerCosineDistribution make_PowerCosineDistribution(const varying float _exp) { varying PowerCosineDistribution m; m.exp = _exp; return m; } #endif /*! @} */