Cycles:
[blender.git] / intern / cycles / kernel / closure / bsdf_util.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 __BSDF_UTIL_H__
34 #define __BSDF_UTIL_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         }
62         else {
63                 // we are inside the surface, 
64                 cos  = -cos;
65                 neta = eta;
66                 Nn   = -N;
67                 *is_inside = true;
68         }
69         *R = (2 * cos)* Nn - I;
70         float arg = 1 -(neta * neta *(1 -(cos * cos)));
71         if(arg < 0) {
72                 *T = make_float3(0.0f, 0.0f, 0.0f);
73 #ifdef __RAY_DIFFERENTIALS__
74                 *dTdx = make_float3(0.0f, 0.0f, 0.0f);
75                 *dTdy = make_float3(0.0f, 0.0f, 0.0f);
76 #endif
77                 return 1; // total internal reflection
78         }
79         else {
80                 float dnp = sqrtf(arg);
81                 float nK = (neta * cos)- dnp;
82                 *T = -(neta * I)+(nK * Nn);
83 #ifdef __RAY_DIFFERENTIALS__
84                 *dTdx = -(neta * dIdx) + ((neta - neta * neta * cos / dnp) * dot(dIdx, Nn)) * Nn;
85                 *dTdy = -(neta * dIdy) + ((neta - neta * neta * cos / dnp) * dot(dIdy, Nn)) * Nn;
86 #endif
87                 // compute Fresnel terms
88                 float cosTheta1 = cos; // N.R
89                 float cosTheta2 = -dot(Nn, *T);
90                 float pPara = (cosTheta1 - eta * cosTheta2)/(cosTheta1 + eta * cosTheta2);
91                 float pPerp = (eta * cosTheta1 - cosTheta2)/(eta * cosTheta1 + cosTheta2);
92                 return 0.5f * (pPara * pPara + pPerp * pPerp);
93         }
94 }
95
96 __device float fresnel_dielectric_cos(float cosi, float eta)
97 {
98         // compute fresnel reflectance without explicitly computing
99         // the refracted direction
100         float c = fabsf(cosi);
101         float g = eta * eta - 1 + c * c;
102         if(g > 0) {
103                 g = sqrtf(g);
104                 float A = (g - c)/(g + c);
105                 float B = (c *(g + c)- 1)/(c *(g - c)+ 1);
106                 return 0.5f * A * A *(1 + B * B);
107         }
108         return 1.0f; // TIR(no refracted component)
109 }
110
111 __device float fresnel_conductor(float cosi, float eta, float k)
112 {
113         float tmp_f = eta * eta + k * k;
114         float tmp = tmp_f * cosi * cosi;
115         float Rparl2 = (tmp - (2.0f * eta * cosi) + 1)/
116                        (tmp + (2.0f * eta * cosi) + 1);
117         float Rperp2 = (tmp_f - (2.0f * eta * cosi) + cosi * cosi)/
118                        (tmp_f + (2.0f * eta * cosi) + cosi * cosi);
119         return(Rparl2 + Rperp2) * 0.5f;
120 }
121
122 __device float smooth_step(float edge0, float edge1, float x)
123 {
124         float result;
125         if(x < edge0) result = 0.0f;
126         else if(x >= edge1) result = 1.0f;
127         else {
128                 float t = (x - edge0)/(edge1 - edge0);
129                 result = (3.0f-2.0f*t)*(t*t);
130         }
131         return result;
132 }
133
134 CCL_NAMESPACE_END
135
136 #endif /* __BSDF_UTIL_H__ */
137