Cycles: better path termination for transparency.
[blender.git] / intern / cycles / kernel / closure / bsdf_microfacet_multi.h
1 /*
2  * Copyright 2011-2016 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 CCL_NAMESPACE_BEGIN
18
19 /* Most of the code is based on the supplemental implementations from https://eheitzresearch.wordpress.com/240-2/. */
20
21 /* === GGX Microfacet distribution functions === */
22
23 /* Isotropic GGX microfacet distribution */
24 ccl_device_forceinline float D_ggx(float3 wm, float alpha)
25 {
26         wm.z *= wm.z;
27         alpha *= alpha;
28         float tmp = (1.0f - wm.z) + alpha * wm.z;
29         return alpha / max(M_PI_F * tmp*tmp, 1e-7f);
30 }
31
32 /* Anisotropic GGX microfacet distribution */
33 ccl_device_forceinline float D_ggx_aniso(const float3 wm, const float2 alpha)
34 {
35         float slope_x = -wm.x/alpha.x;
36         float slope_y = -wm.y/alpha.y;
37         float tmp = wm.z*wm.z + slope_x*slope_x + slope_y*slope_y;
38
39         return 1.0f / max(M_PI_F * tmp*tmp * alpha.x*alpha.y, 1e-7f);
40 }
41
42 /* Sample slope distribution (based on page 14 of the supplemental implementation). */
43 ccl_device_forceinline float2 mf_sampleP22_11(const float cosI, const float randx, const float randy)
44 {
45         if(cosI > 0.9999f || fabsf(cosI) < 1e-6f) {
46                 const float r = sqrtf(randx / max(1.0f - randx, 1e-7f));
47                 const float phi = M_2PI_F * randy;
48                 return make_float2(r*cosf(phi), r*sinf(phi));
49         }
50
51         const float sinI = safe_sqrtf(1.0f - cosI*cosI);
52         const float tanI = sinI/cosI;
53         const float projA = 0.5f * (cosI + 1.0f);
54         if(projA < 0.0001f)
55                 return make_float2(0.0f, 0.0f);
56         const float A = 2.0f*randx*projA / cosI - 1.0f;
57         float tmp = A*A-1.0f;
58         if(fabsf(tmp) < 1e-7f)
59                 return make_float2(0.0f, 0.0f);
60         tmp = 1.0f / tmp;
61         const float D = safe_sqrtf(tanI*tanI*tmp*tmp - (A*A-tanI*tanI)*tmp);
62
63         const float slopeX2 = tanI*tmp + D;
64         const float slopeX = (A < 0.0f || slopeX2 > 1.0f/tanI)? (tanI*tmp - D) : slopeX2;
65
66         float U2;
67         if(randy >= 0.5f)
68                 U2 = 2.0f*(randy - 0.5f);
69         else
70                 U2 = 2.0f*(0.5f - randy);
71         const float z = (U2*(U2*(U2*0.27385f-0.73369f)+0.46341f)) / (U2*(U2*(U2*0.093073f+0.309420f)-1.0f)+0.597999f);
72         const float slopeY = z * sqrtf(1.0f + slopeX*slopeX);
73
74         if(randy >= 0.5f)
75                 return make_float2(slopeX, slopeY);
76         else
77                 return make_float2(slopeX, -slopeY);
78 }
79
80 /* Visible normal sampling for the GGX distribution (based on page 7 of the supplemental implementation). */
81 ccl_device_forceinline float3 mf_sample_vndf(const float3 wi, const float2 alpha, const float randx, const float randy)
82 {
83         const float3 wi_11 = normalize(make_float3(alpha.x*wi.x, alpha.y*wi.y, wi.z));
84         const float2 slope_11 = mf_sampleP22_11(wi_11.z, randx, randy);
85
86         const float3 cossin_phi = safe_normalize(make_float3(wi_11.x, wi_11.y, 0.0f));
87         const float slope_x = alpha.x*(cossin_phi.x * slope_11.x - cossin_phi.y * slope_11.y);
88         const float slope_y = alpha.y*(cossin_phi.y * slope_11.x + cossin_phi.x * slope_11.y);
89
90         kernel_assert(isfinite(slope_x));
91         return normalize(make_float3(-slope_x, -slope_y, 1.0f));
92 }
93
94 /* === Phase functions: Glossy and Glass === */
95
96 /* Phase function for reflective materials. */
97 ccl_device_forceinline float3 mf_sample_phase_glossy(const float3 wi, float3 *weight, const float3 wm)
98 {
99         return -wi + 2.0f * wm * dot(wi, wm);
100 }
101
102 ccl_device_forceinline float3 mf_eval_phase_glossy(const float3 w, const float lambda, const float3 wo, const float2 alpha)
103 {
104         if(w.z > 0.9999f)
105                 return make_float3(0.0f, 0.0f, 0.0f);
106
107         const float3 wh = normalize(wo - w);
108         if(wh.z < 0.0f)
109                 return make_float3(0.0f, 0.0f, 0.0f);
110
111         float pArea = (w.z < -0.9999f)? 1.0f: lambda*w.z;
112
113         const float dotW_WH = dot(-w, wh);
114         if(dotW_WH < 0.0f)
115                 return make_float3(0.0f, 0.0f, 0.0f);
116
117         float phase = max(0.0f, dotW_WH) * 0.25f / max(pArea * dotW_WH, 1e-7f);
118         if(alpha.x == alpha.y)
119                 phase *= D_ggx(wh, alpha.x);
120         else
121                 phase *= D_ggx_aniso(wh, alpha);
122
123         return make_float3(phase, phase, phase);
124 }
125
126 /* Phase function for dielectric transmissive materials, including both reflection and refraction according to the dielectric fresnel term. */
127 ccl_device_forceinline float3 mf_sample_phase_glass(const float3 wi, const float eta, const float3 wm, const float randV, bool *outside)
128 {
129         float cosI = dot(wi, wm);
130         float f = fresnel_dielectric_cos(cosI, eta);
131         if(randV < f) {
132                 *outside = true;
133                 return -wi + 2.0f * wm * cosI;
134         }
135         *outside = false;
136         float inv_eta = 1.0f/eta;
137         float cosT = -safe_sqrtf(1.0f - (1.0f - cosI*cosI) * inv_eta*inv_eta);
138         return normalize(wm*(cosI*inv_eta + cosT) - wi*inv_eta);
139 }
140
141 ccl_device_forceinline float3 mf_eval_phase_glass(const float3 w, const float lambda, const float3 wo, const bool wo_outside, const float2 alpha, const float eta)
142 {
143         if(w.z > 0.9999f)
144                 return make_float3(0.0f, 0.0f, 0.0f);
145
146         float pArea = (w.z < -0.9999f)? 1.0f: lambda*w.z;
147         float v;
148         if(wo_outside) {
149                 const float3 wh = normalize(wo - w);
150                 if(wh.z < 0.0f)
151                         return make_float3(0.0f, 0.0f, 0.0f);
152
153                 const float dotW_WH = dot(-w, wh);
154                 v = fresnel_dielectric_cos(dotW_WH, eta) * max(0.0f, dotW_WH) * D_ggx(wh, alpha.x) * 0.25f / (pArea * dotW_WH);
155         }
156         else {
157                 float3 wh = normalize(wo*eta - w);
158                 if(wh.z < 0.0f)
159                         wh = -wh;
160                 const float dotW_WH = dot(-w, wh), dotWO_WH = dot(wo, wh);
161                 if(dotW_WH < 0.0f)
162                         return make_float3(0.0f, 0.0f, 0.0f);
163
164                 float temp = dotW_WH + eta*dotWO_WH;
165                 v = (1.0f - fresnel_dielectric_cos(dotW_WH, eta)) * max(0.0f, dotW_WH) * max(0.0f, -dotWO_WH) * D_ggx(wh, alpha.x) / (pArea * temp * temp);
166         }
167
168         return make_float3(v, v, v);
169 }
170
171 /* === Utility functions for the random walks === */
172
173 /* Smith Lambda function for GGX (based on page 12 of the supplemental implementation). */
174 ccl_device_forceinline float mf_lambda(const float3 w, const float2 alpha)
175 {
176         if(w.z > 0.9999f)
177                 return 0.0f;
178         else if(w.z < -0.9999f)
179                 return -0.9999f;
180
181         const float inv_wz2 = 1.0f / max(w.z*w.z, 1e-7f);
182         const float2 wa = make_float2(w.x, w.y)*alpha;
183         float v = sqrtf(1.0f + dot(wa, wa) * inv_wz2);
184         if(w.z <= 0.0f)
185                 v = -v;
186
187         return 0.5f*(v - 1.0f);
188 }
189
190 /* Height distribution CDF (based on page 4 of the supplemental implementation). */
191 ccl_device_forceinline float mf_invC1(const float h)
192 {
193         return 2.0f * saturate(h) - 1.0f;
194 }
195
196 ccl_device_forceinline float mf_C1(const float h)
197 {
198         return saturate(0.5f * (h + 1.0f));
199 }
200
201 /* Masking function (based on page 16 of the supplemental implementation). */
202 ccl_device_forceinline float mf_G1(const float3 w, const float C1, const float lambda)
203 {
204         if(w.z > 0.9999f)
205                 return 1.0f;
206         if(w.z < 1e-5f)
207                 return 0.0f;
208         return powf(C1, lambda);
209 }
210
211 /* Sampling from the visible height distribution (based on page 17 of the supplemental implementation). */
212 ccl_device_forceinline bool mf_sample_height(const float3 w, float *h, float *C1, float *G1, float *lambda, const float U)
213 {
214         if(w.z > 0.9999f)
215                 return false;
216         if(w.z < -0.9999f) {
217                 *C1 *= U;
218                 *h = mf_invC1(*C1);
219                 *G1 = mf_G1(w, *C1, *lambda);
220         }
221         else if(fabsf(w.z) >= 0.0001f) {
222                 if(U > 1.0f - *G1)
223                         return false;
224                 if(*lambda >= 0.0f) {
225                         *C1 = 1.0f;
226                 }
227                 else {
228                         *C1 *= powf(1.0f-U, -1.0f / *lambda);
229                 }
230                 *h = mf_invC1(*C1);
231                 *G1 = mf_G1(w, *C1, *lambda);
232         }
233         return true;
234 }
235
236 /* === PDF approximations for the different phase functions. ===
237  * As explained in bsdf_microfacet_multi_impl.h, using approximations with MIS still produces an unbiased result. */
238
239 /* Approximation for the albedo of the single-scattering GGX distribution,
240  * the missing energy is then approximated as a diffuse reflection for the PDF. */
241 ccl_device_forceinline float mf_ggx_albedo(float r)
242 {
243         float albedo = 0.806495f*expf(-1.98712f*r*r) + 0.199531f;
244         albedo -= ((((((1.76741f*r - 8.43891f)*r + 15.784f)*r - 14.398f)*r + 6.45221f)*r - 1.19722f)*r + 0.027803f)*r + 0.00568739f;
245         return saturate(albedo);
246 }
247
248 ccl_device_inline float mf_ggx_transmission_albedo(float a, float ior)
249 {
250         if(ior < 1.0f) {
251                 ior = 1.0f/ior;
252         }
253         a = saturate(a);
254         ior = clamp(ior, 1.0f, 3.0f);
255         float I_1 = 0.0476898f*expf(-0.978352f*(ior-0.65657f)*(ior-0.65657f)) - 0.033756f*ior + 0.993261f;
256         float R_1 = (((0.116991f*a - 0.270369f)*a + 0.0501366f)*a - 0.00411511f)*a + 1.00008f;
257         float I_2 = (((-2.08704f*ior + 26.3298f)*ior - 127.906f)*ior + 292.958f)*ior - 287.946f + 199.803f/(ior*ior) - 101.668f/(ior*ior*ior);
258         float R_2 = ((((5.3725f*a -24.9307f)*a + 22.7437f)*a - 3.40751f)*a + 0.0986325f)*a + 0.00493504f;
259
260         return saturate(1.0f + I_2*R_2*0.0019127f - (1.0f - I_1)*(1.0f - R_1)*9.3205f);
261 }
262
263 ccl_device_forceinline float mf_ggx_pdf(const float3 wi, const float3 wo, const float alpha)
264 {
265         float D = D_ggx(normalize(wi+wo), alpha);
266         float lambda = mf_lambda(wi, make_float2(alpha, alpha));
267         float singlescatter = 0.25f * D / max((1.0f + lambda) * wi.z, 1e-7f);
268
269         float multiscatter = wo.z * M_1_PI_F;
270
271         float albedo = mf_ggx_albedo(alpha);
272         return albedo*singlescatter + (1.0f - albedo)*multiscatter;
273 }
274
275 ccl_device_forceinline float mf_ggx_aniso_pdf(const float3 wi, const float3 wo, const float2 alpha)
276 {
277         float D = D_ggx_aniso(normalize(wi+wo), alpha);
278         float lambda = mf_lambda(wi, alpha);
279         float singlescatter = 0.25f * D / max((1.0f + lambda) * wi.z, 1e-7f);
280
281         float multiscatter = wo.z * M_1_PI_F;
282
283         float albedo = mf_ggx_albedo(sqrtf(alpha.x*alpha.y));
284         return albedo*singlescatter + (1.0f - albedo)*multiscatter;
285 }
286
287 ccl_device_forceinline float mf_glass_pdf(const float3 wi, const float3 wo, const float alpha, const float eta)
288 {
289         bool reflective = (wi.z*wo.z > 0.0f);
290
291         float wh_len;
292         float3 wh = normalize_len(wi + (reflective? wo : (wo*eta)), &wh_len);
293         if(wh.z < 0.0f)
294                 wh = -wh;
295         float3 r_wi = (wi.z < 0.0f)? -wi: wi;
296         float lambda = mf_lambda(r_wi, make_float2(alpha, alpha));
297         float D = D_ggx(wh, alpha);
298         float fresnel = fresnel_dielectric_cos(dot(r_wi, wh), eta);
299
300         float multiscatter = fabsf(wo.z * M_1_PI_F);
301         if(reflective) {
302                 float singlescatter = 0.25f * D / max((1.0f + lambda) * r_wi.z, 1e-7f);
303                 float albedo = mf_ggx_albedo(alpha);
304                 return fresnel * (albedo*singlescatter + (1.0f - albedo)*multiscatter);
305         }
306         else {
307                 float singlescatter = fabsf(dot(r_wi, wh)*dot(wo, wh) * D * eta*eta / max((1.0f + lambda) * r_wi.z * wh_len*wh_len, 1e-7f));
308                 float albedo = mf_ggx_transmission_albedo(alpha, eta);
309                 return (1.0f - fresnel) * (albedo*singlescatter + (1.0f - albedo)*multiscatter);
310         }
311 }
312
313 /* === Actual random walk implementations, one version of mf_eval and mf_sample per phase function. === */
314
315 #define MF_NAME_JOIN(x,y) x ## _ ## y
316 #define MF_NAME_EVAL(x,y) MF_NAME_JOIN(x,y)
317 #define MF_FUNCTION_FULL_NAME(prefix) MF_NAME_EVAL(prefix, MF_PHASE_FUNCTION)
318
319 #define MF_PHASE_FUNCTION glass
320 #define MF_MULTI_GLASS
321 #include "kernel/closure/bsdf_microfacet_multi_impl.h"
322
323 #define MF_PHASE_FUNCTION glossy
324 #define MF_MULTI_GLOSSY
325 #include "kernel/closure/bsdf_microfacet_multi_impl.h"
326
327 ccl_device void bsdf_microfacet_multi_ggx_blur(ShaderClosure *sc, float roughness)
328 {
329         MicrofacetBsdf *bsdf = (MicrofacetBsdf*)sc;
330
331         bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
332         bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
333 }
334
335 /* === Closure implementations === */
336
337 /* Multiscattering GGX Glossy closure */
338
339 ccl_device int bsdf_microfacet_multi_ggx_common_setup(MicrofacetBsdf *bsdf)
340 {
341         bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
342         bsdf->alpha_y = clamp(bsdf->alpha_y, 1e-4f, 1.0f);
343         bsdf->extra->color.x = saturate(bsdf->extra->color.x);
344         bsdf->extra->color.y = saturate(bsdf->extra->color.y);
345         bsdf->extra->color.z = saturate(bsdf->extra->color.z);
346         bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
347         bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
348         bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
349
350         return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
351 }
352
353 ccl_device int bsdf_microfacet_multi_ggx_aniso_setup(MicrofacetBsdf *bsdf)
354 {
355         if(is_zero(bsdf->T))
356                 bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
357
358         bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
359
360         return bsdf_microfacet_multi_ggx_common_setup(bsdf);
361 }
362
363 ccl_device int bsdf_microfacet_multi_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
364 {
365         if(is_zero(bsdf->T))
366                 bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
367
368         bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID;
369
370         float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
371         float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
372         bsdf->sample_weight *= F;
373
374         return bsdf_microfacet_multi_ggx_common_setup(bsdf);
375 }
376
377 ccl_device int bsdf_microfacet_multi_ggx_setup(MicrofacetBsdf *bsdf)
378 {
379         bsdf->alpha_y = bsdf->alpha_x;
380
381         bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
382
383         return bsdf_microfacet_multi_ggx_common_setup(bsdf);
384 }
385
386 ccl_device int bsdf_microfacet_multi_ggx_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
387 {
388         bsdf->alpha_y = bsdf->alpha_x;
389
390         bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID;
391
392         float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
393         float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
394         bsdf->sample_weight *= F;
395
396         return bsdf_microfacet_multi_ggx_common_setup(bsdf);
397 }
398
399 ccl_device int bsdf_microfacet_multi_ggx_refraction_setup(MicrofacetBsdf *bsdf)
400 {
401         bsdf->alpha_y = bsdf->alpha_x;
402
403         bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
404
405         return bsdf_microfacet_multi_ggx_common_setup(bsdf);
406 }
407
408 ccl_device float3 bsdf_microfacet_multi_ggx_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) {
409         *pdf = 0.0f;
410         return make_float3(0.0f, 0.0f, 0.0f);
411 }
412
413 ccl_device float3 bsdf_microfacet_multi_ggx_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) {
414         const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
415
416         if(bsdf->alpha_x*bsdf->alpha_y < 1e-7f) {
417                 return make_float3(0.0f, 0.0f, 0.0f);
418         }
419
420         bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID);
421
422         bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y);
423         float3 X, Y, Z;
424         Z = bsdf->N;
425         if(is_aniso)
426                 make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
427         else
428                 make_orthonormals(Z, &X, &Y);
429
430         float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
431         float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
432
433         if(is_aniso)
434                 *pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
435         else
436                 *pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x);
437         return mf_eval_glossy(localI, localO, true, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, use_fresnel, bsdf->extra->cspec0);
438 }
439
440 ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals *kg, 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, ccl_addr_space uint *lcg_state)
441 {
442         const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
443
444         float3 X, Y, Z;
445         Z = bsdf->N;
446
447         if(bsdf->alpha_x*bsdf->alpha_y < 1e-7f) {
448                 *omega_in = 2*dot(Z, I)*Z - I;
449                 *pdf = 1e6f;
450                 *eval = make_float3(1e6f, 1e6f, 1e6f);
451 #ifdef __RAY_DIFFERENTIALS__
452                 *domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
453                 *domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
454 #endif
455                 return LABEL_REFLECT|LABEL_SINGULAR;
456         }
457
458         bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID);
459
460         bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y);
461         if(is_aniso)
462                 make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
463         else
464                 make_orthonormals(Z, &X, &Y);
465
466         float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
467         float3 localO;
468
469         *eval = mf_sample_glossy(localI, &localO, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, use_fresnel, bsdf->extra->cspec0);
470         if(is_aniso)
471                 *pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
472         else
473                 *pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x);
474         *eval *= *pdf;
475
476         *omega_in = X*localO.x + Y*localO.y + Z*localO.z;
477
478 #ifdef __RAY_DIFFERENTIALS__
479         *domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
480         *domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
481 #endif
482         return LABEL_REFLECT|LABEL_GLOSSY;
483 }
484
485 /* Multiscattering GGX Glass closure */
486
487 ccl_device int bsdf_microfacet_multi_ggx_glass_setup(MicrofacetBsdf *bsdf)
488 {
489         bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
490         bsdf->alpha_y = bsdf->alpha_x;
491         bsdf->ior = max(0.0f, bsdf->ior);
492         bsdf->extra->color.x = saturate(bsdf->extra->color.x);
493         bsdf->extra->color.y = saturate(bsdf->extra->color.y);
494         bsdf->extra->color.z = saturate(bsdf->extra->color.z);
495
496         bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
497
498         return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
499 }
500
501 ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
502 {
503         bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
504         bsdf->alpha_y = bsdf->alpha_x;
505         bsdf->ior = max(0.0f, bsdf->ior);
506         bsdf->extra->color.x = saturate(bsdf->extra->color.x);
507         bsdf->extra->color.y = saturate(bsdf->extra->color.y);
508         bsdf->extra->color.z = saturate(bsdf->extra->color.z);
509         bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
510         bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
511         bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
512
513         bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID;
514
515         float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
516         float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
517         bsdf->sample_weight *= F;
518
519         return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
520 }
521
522 ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) {
523         const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
524
525         if(bsdf->alpha_x*bsdf->alpha_y < 1e-7f) {
526                 return make_float3(0.0f, 0.0f, 0.0f);
527         }
528
529         float3 X, Y, Z;
530         Z = bsdf->N;
531         make_orthonormals(Z, &X, &Y);
532
533         float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
534         float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
535
536         *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
537         return mf_eval_glass(localI, localO, false, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, false, bsdf->extra->color);
538 }
539
540 ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) {
541         const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
542
543         if(bsdf->alpha_x*bsdf->alpha_y < 1e-7f) {
544                 return make_float3(0.0f, 0.0f, 0.0f);
545         }
546
547         bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
548
549         float3 X, Y, Z;
550         Z = bsdf->N;
551         make_orthonormals(Z, &X, &Y);
552
553         float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
554         float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
555
556         *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
557         return mf_eval_glass(localI, localO, true, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, use_fresnel, bsdf->extra->cspec0);
558 }
559
560 ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals *kg, 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, ccl_addr_space uint *lcg_state)
561 {
562         const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
563
564         float3 X, Y, Z;
565         Z = bsdf->N;
566
567         if(bsdf->alpha_x*bsdf->alpha_y < 1e-7f) {
568                 float3 R, T;
569 #ifdef __RAY_DIFFERENTIALS__
570                 float3 dRdx, dRdy, dTdx, dTdy;
571 #endif
572                 bool inside;
573                 float fresnel = fresnel_dielectric(bsdf->ior, Z, I, &R, &T,
574 #ifdef __RAY_DIFFERENTIALS__
575                                 dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy,
576 #endif
577                                 &inside);
578
579                 *pdf = 1e6f;
580                 *eval = make_float3(1e6f, 1e6f, 1e6f);
581                 if(randu < fresnel) {
582                         *omega_in = R;
583 #ifdef __RAY_DIFFERENTIALS__
584                         *domega_in_dx = dRdx;
585                         *domega_in_dy = dRdy;
586 #endif
587                         return LABEL_REFLECT|LABEL_SINGULAR;
588                 }
589                 else {
590                         *omega_in = T;
591 #ifdef __RAY_DIFFERENTIALS__
592                         *domega_in_dx = dTdx;
593                         *domega_in_dy = dTdy;
594 #endif
595                         return LABEL_TRANSMIT|LABEL_SINGULAR;
596                 }
597         }
598
599         bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
600
601         make_orthonormals(Z, &X, &Y);
602
603         float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
604         float3 localO;
605
606         *eval = mf_sample_glass(localI, &localO, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, use_fresnel, bsdf->extra->cspec0);
607         *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
608         *eval *= *pdf;
609
610         *omega_in = X*localO.x + Y*localO.y + Z*localO.z;
611         if(localO.z*localI.z > 0.0f) {
612 #ifdef __RAY_DIFFERENTIALS__
613                 *domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
614                 *domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
615 #endif
616                 return LABEL_REFLECT|LABEL_GLOSSY;
617         }
618         else {
619 #ifdef __RAY_DIFFERENTIALS__
620                 float cosI = dot(Z, I);
621                 float dnp = max(sqrtf(1.0f - (bsdf->ior * bsdf->ior * (1.0f - cosI*cosI))), 1e-7f);
622                 *domega_in_dx = -(bsdf->ior * dIdx) + ((bsdf->ior - bsdf->ior * bsdf->ior * cosI / dnp) * dot(dIdx, Z)) * Z;
623                 *domega_in_dy = -(bsdf->ior * dIdy) + ((bsdf->ior - bsdf->ior * bsdf->ior * cosI / dnp) * dot(dIdy, Z)) * Z;
624 #endif
625
626                 return LABEL_TRANSMIT|LABEL_GLOSSY;
627         }
628 }
629
630 CCL_NAMESPACE_END