Cycles: change __device and similar qualifiers to ccl_device in kernel code.
[blender.git] / intern / cycles / kernel / closure / bsdf_ward.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_WARD_H__
34 #define __BSDF_WARD_H__
35
36 CCL_NAMESPACE_BEGIN
37
38 /* WARD */
39
40 ccl_device int bsdf_ward_setup(ShaderClosure *sc)
41 {
42         sc->data0 = clamp(sc->data0, 1e-4f, 1.0f); /* m_ax */
43         sc->data1 = clamp(sc->data1, 1e-4f, 1.0f); /* m_ay */
44
45         sc->type = CLOSURE_BSDF_WARD_ID;
46         return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
47 }
48
49 ccl_device void bsdf_ward_blur(ShaderClosure *sc, float roughness)
50 {
51         sc->data0 = fmaxf(roughness, sc->data0); /* m_ax */
52         sc->data1 = fmaxf(roughness, sc->data1); /* m_ay */
53 }
54
55 ccl_device float3 bsdf_ward_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
56 {
57         float m_ax = sc->data0;
58         float m_ay = sc->data1;
59         float3 N = sc->N;
60         float3 T = sc->T;
61
62         float cosNO = dot(N, I);
63         float cosNI = dot(N, omega_in);
64
65         if(cosNI > 0.0f && cosNO > 0.0f) {
66                 cosNO = max(cosNO, 1e-4f);
67                 cosNI = max(cosNI, 1e-4f);
68
69                 // get half vector and get x,y basis on the surface for anisotropy
70                 float3 H = normalize(omega_in + I); // normalize needed for pdf
71                 float3 X, Y;
72                 make_orthonormals_tangent(N, T, &X, &Y);
73                 // eq. 4
74                 float dotx = dot(H, X) / m_ax;
75                 float doty = dot(H, Y) / m_ay;
76                 float dotn = dot(H, N);
77                 float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn);
78                 float denom = (M_4PI_F * m_ax * m_ay * sqrtf(cosNO * cosNI));
79                 float exp_val = expf(-exp_arg);
80                 float out = cosNI * exp_val / denom;
81                 float oh = dot(H, I);
82                 denom = M_4PI_F * m_ax * m_ay * oh * dotn * dotn * dotn;
83                 *pdf = exp_val / denom;
84                 return make_float3 (out, out, out);
85         }
86
87         return make_float3 (0, 0, 0);
88 }
89
90 ccl_device float3 bsdf_ward_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
91 {
92         return make_float3(0.0f, 0.0f, 0.0f);
93 }
94
95 ccl_device int bsdf_ward_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
96 {
97         float m_ax = sc->data0;
98         float m_ay = sc->data1;
99         float3 N = sc->N;
100         float3 T = sc->T;
101
102         float cosNO = dot(N, I);
103         if(cosNO > 0.0f) {
104                 // get x,y basis on the surface for anisotropy
105                 float3 X, Y;
106                 make_orthonormals_tangent(N, T, &X, &Y);
107                 // generate random angles for the half vector
108                 // eq. 7 (taking care around discontinuities to keep
109                 //ttoutput angle in the right quadrant)
110                 // we take advantage of cos(atan(x)) == 1/sqrt(1+x^2)
111                 //tttt  and sin(atan(x)) == x/sqrt(1+x^2)
112                 float alphaRatio = m_ay / m_ax;
113                 float cosPhi, sinPhi;
114                 if(randu < 0.25f) {
115                         float val = 4 * randu;
116                         float tanPhi = alphaRatio * tanf(M_PI_2_F * val);
117                         cosPhi = 1 / sqrtf(1 + tanPhi * tanPhi);
118                         sinPhi = tanPhi * cosPhi;
119                 }
120                 else if(randu < 0.5f) {
121                         float val = 1 - 4 * (0.5f - randu);
122                         float tanPhi = alphaRatio * tanf(M_PI_2_F * val);
123                         // phi = M_PI_F - phi;
124                         cosPhi = -1 / sqrtf(1 + tanPhi * tanPhi);
125                         sinPhi = -tanPhi * cosPhi;
126                 }
127                 else if(randu < 0.75f) {
128                         float val = 4 * (randu - 0.5f);
129                         float tanPhi = alphaRatio * tanf(M_PI_2_F * val);
130                         //phi = M_PI_F + phi;
131                         cosPhi = -1 / sqrtf(1 + tanPhi * tanPhi);
132                         sinPhi = tanPhi * cosPhi;
133                 }
134                 else {
135                         float val = 1 - 4 * (1 - randu);
136                         float tanPhi = alphaRatio * tanf(M_PI_2_F * val);
137                         // phi = M_2PI_F - phi;
138                         cosPhi = 1 / sqrtf(1 + tanPhi * tanPhi);
139                         sinPhi = -tanPhi * cosPhi;
140                 }
141                 // eq. 6
142                 // we take advantage of cos(atan(x)) == 1/sqrt(1+x^2)
143                 //tttt  and sin(atan(x)) == x/sqrt(1+x^2)
144                 float thetaDenom = (cosPhi * cosPhi) / (m_ax * m_ax) + (sinPhi * sinPhi) / (m_ay * m_ay);
145                 float tanTheta2 = -logf(1 - randv) / thetaDenom;
146                 float cosTheta  = 1 / sqrtf(1 + tanTheta2);
147                 float sinTheta  = cosTheta * sqrtf(tanTheta2);
148
149                 float3 h; // already normalized becaused expressed from spherical coordinates
150                 h.x = sinTheta * cosPhi;
151                 h.y = sinTheta * sinPhi;
152                 h.z = cosTheta;
153                 // compute terms that are easier in local space
154                 float dotx = h.x / m_ax;
155                 float doty = h.y / m_ay;
156                 float dotn = h.z;
157                 // transform to world space
158                 h = h.x * X + h.y * Y + h.z * N;
159                 // generate the final sample
160                 float oh = dot(h, I);
161                 *omega_in = 2.0f * oh * h - I;
162                 if(dot(Ng, *omega_in) > 0) {
163                         float cosNI = dot(N, *omega_in);
164                         if(cosNI > 0) {
165                                 cosNO = max(cosNO, 1e-4f);
166                                 cosNI = max(cosNI, 1e-4f);
167
168                                 // eq. 9
169                                 float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn);
170                                 float denom = M_4PI_F * m_ax * m_ay * oh * dotn * dotn * dotn;
171                                 *pdf = expf(-exp_arg) / denom;
172                                 // compiler will reuse expressions already computed
173                                 denom = (M_4PI_F * m_ax * m_ay * sqrtf(cosNO * cosNI));
174                                 float power = cosNI * expf(-exp_arg) / denom;
175                                 *eval = make_float3(power, power, power);
176 #ifdef __RAY_DIFFERENTIALS__
177                                 *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
178                                 *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy;
179 #endif
180                         }
181                 }
182         }
183         return LABEL_REFLECT|LABEL_GLOSSY;
184 }
185
186 CCL_NAMESPACE_END
187
188 #endif /* __BSDF_WARD_H__ */
189