added clearcoat implementation
[blender.git] / intern / cycles / kernel / closure / bsdf_disney_diffuse.h
1
2 /*
3  * Adapted from Open Shading Language with this license:
4  *
5  * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
6  * All Rights Reserved.
7  *
8  * Modifications Copyright 2011, Blender Foundation.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are
12  * met:
13  * * Redistributions of source code must retain the above copyright
14  *   notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above copyright
16  *   notice, this list of conditions and the following disclaimer in the
17  *   documentation and/or other materials provided with the distribution.
18  * * Neither the name of Sony Pictures Imageworks nor the names of its
19  *   contributors may be used to endorse or promote products derived from
20  *   this software without specific prior written permission.
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #ifndef __BSDF_DISNEY_DIFFUSE_H__
35 #define __BSDF_DISNEY_DIFFUSE_H__
36
37 #include <cmath>
38
39 CCL_NAMESPACE_BEGIN
40
41 /* DISNEY DIFFUSE */
42
43 ccl_device float diff_sqr(float a) {
44         return a * a;
45 }
46
47 ccl_device float3 diff_mon2lin(float3 x, float gamma) {
48         return make_float3(pow(x[0], gamma), pow(x[1], gamma), pow(x[2], gamma));
49 }
50
51 ccl_device float diff_GTR1(float NdotH, float a) {
52         if (a >= 1.0f) return 1.0f / M_PI_F;
53         float a2 = a*a;
54         float t = 1.0f + (a2 - 1.0f) * NdotH * NdotH;
55         return (a2 - 1.0f) / (M_PI_F * log(a2) * t);
56 }
57
58 ccl_device float diff_GTR2(float NdotH, float a) {
59         float a2 = a * a;
60         float t = 1.0f + (a2 - 1.0f) * NdotH * NdotH;
61         return a2 / (M_PI_F * t * t);
62 }
63
64 ccl_device float diff_GTR2_aniso(
65         float NdotH,
66         float HdotX,
67         float HdotY,
68         float ax,
69         float ay)
70 {
71         return 1.0f / (M_PI_F * ax * ay * diff_sqr(diff_sqr(HdotX / ax) + diff_sqr(HdotY / ay)
72                 + NdotH * NdotH));
73 }
74
75 ccl_device float diff_smithG_GGX(float Ndotv, float alphaG) {
76         float a = alphaG * alphaG;
77         float b = Ndotv * Ndotv;
78         return 1.0f / (Ndotv + sqrtf(a + b - a * b));
79 }
80
81 ccl_device float diff_SchlickFresnel(float u) {
82         float m = clamp(1.0f - u, 0.0f, 1.0f);
83         float m2 = m * m;
84         return m2 * m2 * m; // pow(m, 5)
85 }
86
87 ccl_device float3 diff_transform_to_local(const float3& v, const float3& n,
88         const float3& x, const float3& y)
89 {
90         return make_float3(dot(v, x), dot(v, n), dot(v, y));
91 }
92
93 ccl_device float3 diff_mix(float3 x, float3 y, float a) {
94         return x * (1.0f - a) + y * a;
95 }
96
97 ccl_device float diff_mix(float x, float y, float a) {
98         return x * (1.0f - a) + y * a;
99 }
100
101 /* structures */
102 struct DisneyDiffuseBRDFParams {
103         // brdf parameters
104         float3 m_base_color;
105         float m_subsurface;
106         float m_roughness;
107         float m_sheen;
108         float m_sheen_tint;
109
110         // precomputed values
111         float3 m_cdlin, m_ctint, m_csheen;
112         float m_cdlum;
113         float m_weights[4];
114
115         void precompute_values() {
116                 m_cdlin = m_base_color;
117                 m_cdlum = 0.3f * m_cdlin[0] + 0.6f * m_cdlin[1] + 0.1f * m_cdlin[2]; // luminance approx.
118
119                 m_ctint = m_cdlum > 0.0f ? m_cdlin / m_cdlum : make_float3(1.0f, 1.0f, 1.0f); // normalize lum. to isolate hue+sat
120                 m_csheen = diff_mix(make_float3(1.0f, 1.0f, 1.0f), m_ctint, m_sheen_tint);
121         }
122 };
123
124 typedef struct DisneyDiffuseBRDFParams DisneyDiffuseBRDFParams;
125
126 /* brdf */
127 ccl_device float3 calculate_disney_diffuse_brdf(const ShaderClosure *sc,
128         const DisneyDiffuseBRDFParams *params, float3 N, float3 V, float3 L,
129         float3 H, float *pdf, bool withNdotL = true)
130 {
131         float NdotL = dot(N, L);
132         float NdotV = dot(N, V);
133
134     if (NdotL < 0 || NdotV < 0) {
135         *pdf = 0.0f;
136         return make_float3(0.0f, 0.0f, 0.0f);
137     }
138
139         float LdotH = dot(L, H);
140
141     float Fd = 0.0f;
142         float FL = diff_SchlickFresnel(NdotL), FV = diff_SchlickFresnel(NdotV);
143
144     if (params->m_subsurface != 1.0f) {
145             const float Fd90 = 0.5f + 2.0f * LdotH*LdotH * params->m_roughness;
146             Fd = diff_mix(1.0f, Fd90, FL) * diff_mix(1.0f, Fd90, FV);
147     }
148
149     if (params->m_subsurface > 0.0f) {
150             float Fss90 = LdotH*LdotH * params->m_roughness;
151             float Fss = diff_mix(1.0f, Fss90, FL) * diff_mix(1.0f, Fss90, FV);
152             float ss = 1.25f * (Fss * (1.0f / (NdotL + NdotV) - 0.5f) + 0.5f);
153         Fd = diff_mix(Fd, ss, params->m_subsurface);
154     }
155
156         float3 value = M_1_PI_F * Fd * params->m_cdlin;
157
158         //if (params->m_gamma > 0.5f)
159                 *pdf = M_1_PI_F;
160
161         /*if (params->m_exposure > 0.95f)
162                 *pdf *= params->m_cdlum;
163         else if (params->m_exposure > 0.85f)
164                 *pdf *= params->m_cdlum * NdotL;
165         else if (params->m_exposure > 0.75f)
166                 *pdf *= params->m_cdlum * 0.5f;
167         else if (params->m_exposure > 0.65f)
168                 *pdf *= params->m_cdlum * NdotL * 0.5f;
169         else if (params->m_exposure > 0.55f)
170                 *pdf *= NdotL;
171         else if (params->m_exposure > 0.45f)
172                 *pdf *= NdotL * 0.5f;
173         else if (params->m_exposure > 0.35f)*/
174                 *pdf *= 0.5f;
175
176         // sheen component
177         if (params->m_sheen != 0.0f) {
178             float FH = diff_SchlickFresnel(LdotH);
179
180                 value += FH * params->m_sheen * params->m_csheen;
181                 //*pdf += 0.5f * M_1_PI_F * params->m_sheen;
182         }
183
184         if (withNdotL)
185                 value *= NdotL;
186
187         // brightness
188         //value *= params->m_brightness;
189
190         // exposure
191         //value *= pow(2.0f, params->m_exposure);
192
193         // gamma
194         /*value[0] = pow(value[0], 1.0f / params->m_gamma);
195         value[1] = pow(value[1], 1.0f / params->m_gamma);
196         value[2] = pow(value[2], 1.0f / params->m_gamma);*/
197
198         return value;
199 }
200
201 ccl_device int bsdf_disney_diffuse_setup(ShaderClosure *sc)
202 {
203         sc->type = CLOSURE_BSDF_DISNEY_DIFFUSE_ID;
204         return SD_BSDF|SD_BSDF_HAS_EVAL;
205 }
206
207 ccl_device float3 bsdf_disney_diffuse_eval_reflect(const ShaderClosure *sc,
208         const DisneyDiffuseBRDFParams *params, const float3 I,
209         const float3 omega_in, float *pdf)
210 {
211         float3 N = normalize(sc->N);
212         float3 V = I; // outgoing
213         float3 L = omega_in; // incoming
214         float3 H = normalize(L + V);
215
216     if (dot(sc->N, omega_in) > 0.0f) {
217         float3 value = calculate_disney_diffuse_brdf(sc, params, N, V, L, H, pdf);
218
219                 return value;
220     }
221     else {
222         *pdf = 0.0f;
223         return make_float3(0.0f, 0.0f, 0.0f);
224     }
225 }
226
227 ccl_device float3 bsdf_disney_diffuse_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
228 {
229         return make_float3(0.0f, 0.0f, 0.0f);
230 }
231
232 ccl_device int bsdf_disney_diffuse_sample(const ShaderClosure *sc, const DisneyDiffuseBRDFParams *params,
233         float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv,
234         float3 *eval, float3 *omega_in, float3 *domega_in_dx,
235         float3 *domega_in_dy, float *pdf)
236 {
237         float3 N = normalize(sc->N);
238
239         /*if (params->m_brightness > 0.5f)
240                 sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
241         else*/
242                 sample_uniform_hemisphere(N, randu, randv, omega_in, pdf);
243
244         if (dot(Ng, *omega_in) > 0) {
245                 float3 V = I; // outgoing
246                 float3 L = *omega_in; // incoming
247                 float3 H = normalize(L + V);
248
249                 *eval = calculate_disney_diffuse_brdf(sc, params, N, V, L, H, pdf, true);
250
251 #ifdef __RAY_DIFFERENTIALS__
252                 // TODO: find a better approximation for the diffuse bounce
253                 *domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx);
254                 *domega_in_dy = -((2 * dot(N, dIdy)) * N - dIdy);
255 #endif
256         }
257         else {
258                 *pdf = 0;
259         }
260         return LABEL_REFLECT|LABEL_DIFFUSE;
261 }
262
263 CCL_NAMESPACE_END
264
265 #endif /* __BSDF_DISNEY_DIFFUSE_H__ */
266
267