Cycles: svn merge -r41225:41232 ^/trunk/blender
[blender.git] / intern / cycles / kernel / svm / bsdf.h
1 /* 
2  * Adapted from Open Shading Language with this license: 
3  * 
4  * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. 
5  * All Rights Reserved. 
6  * 
7  * Modifications Copyright 2011, Blender Foundation. 
8  *  
9  * Redistribution and use in source and binary forms, with or without 
10  * modification, are permitted provided that the following conditions are 
11  * met: 
12  * * Redistributions of source code must retain the above copyright 
13  *   notice, this list of conditions and the following disclaimer. 
14  * * Redistributions in binary form must reproduce the above copyright 
15  *   notice, this list of conditions and the following disclaimer in the 
16  *   documentation and/or other materials provided with the distribution. 
17  * * Neither the name of Sony Pictures Imageworks nor the names of its 
18  *   contributors may be used to endorse or promote products derived from 
19  *   this software without specific prior written permission. 
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
31 */
32
33 #ifndef __OSL_BSDF_H__
34 #define __OSL_BSDF_H__
35
36 CCL_NAMESPACE_BEGIN
37
38 __device float fresnel_dielectric(float eta, const float3 N,
39                 const float3 I, float3 *R, float3 *T,
40 #ifdef __RAY_DIFFERENTIALS__
41                 const float3 dIdx, const float3 dIdy,
42                 float3 *dRdx, float3 *dRdy,
43                 float3 *dTdx, float3 *dTdy, 
44 #endif
45                 bool *is_inside)
46 {
47         float cos = dot(N, I), neta;
48         float3 Nn;
49         // compute reflection
50         *R =(2 * cos)* N - I;
51 #ifdef __RAY_DIFFERENTIALS__
52         *dRdx = (2 * dot(N, dIdx)) * N - dIdx;
53         *dRdy = (2 * dot(N, dIdy)) * N - dIdy;
54 #endif
55         // check which side of the surface we are on
56         if(cos > 0) {
57                 // we are on the outside of the surface, going in
58                 neta = 1 / eta;
59                 Nn   = N;
60                 *is_inside = false;
61         } else {
62                 // we are inside the surface, 
63                 cos  = -cos;
64                 neta = eta;
65                 Nn   = -N;
66                 *is_inside = true;
67         }
68         *R =(2 * cos)* Nn - I;
69         float arg = 1 -(neta * neta *(1 -(cos * cos)));
70         if(arg < 0) {
71                 *T= make_float3(0.0f, 0.0f, 0.0f);
72 #ifdef __RAY_DIFFERENTIALS__
73                 *dTdx= make_float3(0.0f, 0.0f, 0.0f);
74                 *dTdy= make_float3(0.0f, 0.0f, 0.0f);
75 #endif
76                 return 1; // total internal reflection
77         } else {
78                 float dnp = sqrtf(arg);
79                 float nK =(neta * cos)- dnp;
80                 *T = -(neta * I)+(nK * Nn);
81 #ifdef __RAY_DIFFERENTIALS__
82                 *dTdx = -(neta * dIdx) + ((neta - neta * neta * cos / dnp) * dot(dIdx, Nn)) * Nn;
83                 *dTdy = -(neta * dIdy) + ((neta - neta * neta * cos / dnp) * dot(dIdy, Nn)) * Nn;
84 #endif
85                 // compute Fresnel terms
86                 float cosTheta1 = cos; // N.R
87                 float cosTheta2 = -dot(Nn, *T);
88                 float pPara =(cosTheta1 - eta * cosTheta2)/(cosTheta1 + eta * cosTheta2);
89                 float pPerp =(eta * cosTheta1 - cosTheta2)/(eta * cosTheta1 + cosTheta2);
90                 return 0.5f * (pPara * pPara + pPerp * pPerp);
91         }
92 }
93
94 __device float fresnel_dielectric_cos(float cosi, float eta)
95 {
96         // compute fresnel reflectance without explicitly computing
97         // the refracted direction
98         float c = fabsf(cosi);
99         float g = eta * eta - 1 + c * c;
100         if(g > 0) {
101                 g = sqrtf(g);
102                 float A =(g - c)/(g + c);
103                 float B =(c *(g + c)- 1)/(c *(g - c)+ 1);
104                 return 0.5f * A * A *(1 + B * B);
105         }
106         return 1.0f; // TIR(no refracted component)
107 }
108
109 __device float fresnel_conductor(float cosi, float eta, float k)
110 {
111         float tmp_f = eta * eta + k * k;
112         float tmp = tmp_f * cosi * cosi;
113         float Rparl2 =(tmp -(2.0f * eta * cosi)+ 1)/
114                                  (tmp +(2.0f * eta * cosi)+ 1);
115         float Rperp2 =(tmp_f -(2.0f * eta * cosi)+ cosi * cosi)/
116                                  (tmp_f +(2.0f * eta * cosi)+ cosi * cosi);
117         return(Rparl2 + Rperp2) * 0.5f;
118 }
119
120 __device float smooth_step(float edge0, float edge1, float x)
121 {
122         float result;
123         if(x < edge0) result = 0.0f;
124         else if(x >= edge1) result = 1.0f;
125         else {
126                 float t = (x - edge0)/(edge1 - edge0);
127                 result = (3.0f-2.0f*t)*(t*t);
128         }
129         return result;
130 }
131
132 CCL_NAMESPACE_END
133
134 #endif /* __OSL_BSDF_H__ */
135