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