* This is embarrassing...
[blender.git] / intern / cycles / kernel / closure / bsdf_toon.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_TOON_H__
34 #define __BSDF_TOON_H__
35
36 CCL_NAMESPACE_BEGIN
37
38 /* DIFFUSE TOON */
39
40 __device int bsdf_diffuse_toon_setup(ShaderClosure *sc)
41 {
42         sc->type = CLOSURE_BSDF_DIFFUSE_TOON_ID;
43         sc->data0 = clamp(sc->data0, 0.0f, 1.0f);
44         sc->data1 = clamp(sc->data1, 0.0f, 1.0f);
45
46         return SD_BSDF|SD_BSDF_HAS_EVAL;
47 }
48
49 __device void bsdf_diffuse_toon_blur(ShaderClosure *sc, float roughness)
50 {
51 }
52
53 __device float3 bsdf_toon_get_intensity(float max_angle, float smooth, float angle)
54 {
55         float is;
56
57         if(angle < max_angle)
58                 is = 1.0f;
59         else if(angle < (max_angle + smooth) && smooth != 0.0f)
60                 is = (1.0f - (angle - max_angle)/smooth);
61         else
62                 is = 0.0f;
63         
64         return make_float3(is, is, is);
65 }
66
67 __device float bsdf_toon_get_sample_angle(float max_angle, float smooth)
68 {
69         return fminf(max_angle + smooth, M_PI_2_F);
70 }
71
72 __device float3 bsdf_diffuse_toon_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
73 {
74         float max_angle = sc->data0*M_PI_2_F;
75         float smooth = sc->data1*M_PI_2_F;
76         float angle = safe_acosf(fmaxf(dot(sc->N, omega_in), 0.0f));
77
78         float3 eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
79         
80         if(eval.x > 0.0f) {
81                 float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
82
83                 *pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
84                 return *pdf * eval;
85         }
86
87         return make_float3(0.0f, 0.0f, 0.0f);
88 }
89
90 __device float3 bsdf_diffuse_toon_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 __device int bsdf_diffuse_toon_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 max_angle = sc->data0*M_PI_2_F;
98         float smooth = sc->data1*M_PI_2_F;
99         float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
100         float angle = sample_angle*randu;
101
102         if(sample_angle > 0.0f) {
103                 sample_uniform_cone(sc->N, sample_angle, randu, randv, omega_in, pdf);
104
105                 if(dot(Ng, *omega_in) > 0.0f) {
106                         *eval = *pdf * bsdf_toon_get_intensity(max_angle, smooth, angle);
107
108 #ifdef __RAY_DIFFERENTIALS__
109                         // TODO: find a better approximation for the bounce
110                         *domega_in_dx = (2.0f * dot(sc->N, dIdx)) * sc->N - dIdx;
111                         *domega_in_dy = (2.0f * dot(sc->N, dIdy)) * sc->N - dIdy;
112 #endif
113                 }
114                 else
115                         *pdf = 0.0f;
116         }
117
118         return LABEL_REFLECT | LABEL_DIFFUSE;
119
120 }
121
122 /* SPECULAR TOON */
123
124 __device int bsdf_specular_toon_setup(ShaderClosure *sc)
125 {
126         sc->type = CLOSURE_BSDF_SPECULAR_TOON_ID;
127         sc->data0 = clamp(sc->data0, 0.0f, 1.0f);
128         sc->data1 = clamp(sc->data1, 0.0f, 1.0f);
129
130         return SD_BSDF|SD_BSDF_HAS_EVAL;
131 }
132
133 __device void bsdf_specular_toon_blur(ShaderClosure *sc, float roughness)
134 {
135 }
136
137 __device float3 bsdf_specular_toon_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
138 {
139         float max_angle = sc->data0*M_PI_2_F;
140         float smooth = sc->data1*M_PI_2_F;
141         float cosNI = dot(sc->N, omega_in);
142         float cosNO = dot(sc->N, I);
143         
144         if(cosNI > 0 && cosNO > 0) {
145                 /* reflect the view vector */
146                 float3 R = (2 * cosNO) * sc->N - I;
147                 float cosRI = dot(R, omega_in);
148
149                 float angle = safe_acosf(fmaxf(cosRI, 0.0f));
150
151                 float3 eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
152                 float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
153
154                 *pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
155                 return *pdf * eval;
156         }
157         
158         return make_float3(0.0f, 0.0f, 0.0f);
159 }
160
161 __device float3 bsdf_specular_toon_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
162 {
163         return make_float3(0.0f, 0.0f, 0.0f);
164 }
165
166 __device int bsdf_specular_toon_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)
167 {
168         float max_angle = sc->data0*M_PI_2_F;
169         float smooth = sc->data1*M_PI_2_F;
170         float cosNO = dot(sc->N, I);
171         
172         if(cosNO > 0) {
173                 /* reflect the view vector */
174                 float3 R = (2 * cosNO) * sc->N - I;
175
176                 float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
177                 float angle = sample_angle*randu;
178
179                 sample_uniform_cone(R, sample_angle, randu, randv, omega_in, pdf);
180
181                 if(dot(Ng, *omega_in) > 0.0f) {
182                         float cosNI = dot(sc->N, *omega_in);
183
184                         /* make sure the direction we chose is still in the right hemisphere */
185                         if(cosNI > 0) {
186                                 *eval = *pdf * bsdf_toon_get_intensity(max_angle, smooth, angle);
187
188 #ifdef __RAY_DIFFERENTIALS__
189                                 *domega_in_dx = (2 * dot(sc->N, dIdx)) * sc->N - dIdx;
190                                 *domega_in_dy = (2 * dot(sc->N, dIdy)) * sc->N - dIdy;
191 #endif
192                         }
193                         else
194                                 *pdf = 0.0f;
195                 }
196                 else
197                         *pdf = 0.0f;
198         }
199
200         return LABEL_GLOSSY | LABEL_REFLECT;
201 }
202
203 CCL_NAMESPACE_END
204
205 #endif /* __BSDF_TOON_H__ */
206