Cycles: better path termination for transparency.
[blender.git] / intern / cycles / kernel / closure / bsdf_microfacet_multi_impl.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 /* Evaluate the BSDF from wi to wo.
18  * Evaluation is split into the analytical single-scattering BSDF and the multi-scattering BSDF,
19  * which is evaluated stochastically through a random walk. At each bounce (except for the first one),
20  * the amount of reflection from here towards wo is evaluated before bouncing again.
21  *
22  * Because of the random walk, the evaluation is not deterministic, but its expected value is equal to
23  * the correct BSDF, which is enough for Monte-Carlo rendering. The PDF also can't be determined
24  * analytically, so the single-scattering PDF plus a diffuse term to account for the multi-scattered
25  * energy is used. In combination with MIS, that is enough to produce an unbiased result, although
26  * the balance heuristic isn't necessarily optimal anymore.
27  */
28 ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
29         float3 wi,
30         float3 wo,
31         const bool wo_outside,
32         const float3 color,
33         const float alpha_x,
34         const float alpha_y,
35         ccl_addr_space uint *lcg_state,
36         const float eta,
37         bool use_fresnel,
38         const float3 cspec0)
39 {
40         /* Evaluating for a shallower incoming direction produces less noise, and the properties of the BSDF guarantee reciprocity. */
41         bool swapped = false;
42 #ifdef MF_MULTI_GLASS
43         if(wi.z*wo.z < 0.0f) {
44                 /* Glass transmission is a special case and requires the directions to change hemisphere. */
45                 if(-wo.z < wi.z) {
46                         swapped = true;
47                         float3 tmp = -wo;
48                         wo = -wi;
49                         wi = tmp;
50                 }
51         }
52         else
53 #endif
54         if(wo.z < wi.z) {
55                 swapped = true;
56                 float3 tmp = wo;
57                 wo = wi;
58                 wi = tmp;
59         }
60
61         if(wi.z < 1e-5f || (wo.z < 1e-5f && wo_outside) || (wo.z > -1e-5f && !wo_outside))
62                 return make_float3(0.0f, 0.0f, 0.0f);
63
64         const float2 alpha = make_float2(alpha_x, alpha_y);
65
66         float lambda_r = mf_lambda(-wi, alpha);
67         float shadowing_lambda = mf_lambda(wo_outside? wo: -wo, alpha);
68
69         /* Analytically compute single scattering for lower noise. */
70         float3 eval;
71         float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
72         const float3 wh = normalize(wi+wo);
73 #ifdef MF_MULTI_GLASS
74         eval = mf_eval_phase_glass(-wi, lambda_r, wo, wo_outside, alpha, eta);
75         if(wo_outside)
76                 eval *= -lambda_r / (shadowing_lambda - lambda_r);
77         else
78                 eval *= -lambda_r * beta(-lambda_r, shadowing_lambda+1.0f);
79 #else /* MF_MULTI_GLOSSY */
80         const float G2 = 1.0f / (1.0f - (lambda_r + 1.0f) + shadowing_lambda);
81         float val = G2 * 0.25f / wi.z;
82         if(alpha.x == alpha.y)
83                 val *= D_ggx(wh, alpha.x);
84         else
85                 val *= D_ggx_aniso(wh, alpha);
86         eval = make_float3(val, val, val);
87 #endif
88
89         float F0 = fresnel_dielectric_cos(1.0f, eta);
90         if(use_fresnel) {
91                 throughput = interpolate_fresnel_color(wi, wh, eta, F0, cspec0);
92
93                 eval *= throughput;
94         }
95
96         float3 wr = -wi;
97         float hr = 1.0f;
98         float C1_r = 1.0f;
99         float G1_r = 0.0f;
100         bool outside = true;
101
102         for(int order = 0; order < 10; order++) {
103                 /* Sample microfacet height. */
104                 float height_rand = lcg_step_float_addrspace(lcg_state);
105                 if(!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, height_rand))
106                         break;
107                 /* Sample microfacet normal. */
108                 float vndf_rand_y = lcg_step_float_addrspace(lcg_state);
109                 float vndf_rand_x = lcg_step_float_addrspace(lcg_state);
110                 float3 wm = mf_sample_vndf(-wr, alpha, vndf_rand_x, vndf_rand_y);
111
112 #ifdef MF_MULTI_GLASS
113                 if(order == 0 && use_fresnel) {
114                         /* Evaluate amount of scattering towards wo on this microfacet. */
115                         float3 phase;
116                         if(outside)
117                                 phase = mf_eval_phase_glass(wr, lambda_r, wo, wo_outside, alpha, eta);
118                         else
119                                 phase = mf_eval_phase_glass(wr, lambda_r, -wo, !wo_outside, alpha, 1.0f / eta);
120
121                         eval = throughput * phase * mf_G1(wo_outside ? wo : -wo, mf_C1((outside == wo_outside) ? hr : -hr), shadowing_lambda);
122                 }
123 #endif
124                 if(order > 0) {
125                         /* Evaluate amount of scattering towards wo on this microfacet. */
126                         float3 phase;
127 #ifdef MF_MULTI_GLASS
128                         if(outside)
129                                 phase = mf_eval_phase_glass(wr, lambda_r,  wo,  wo_outside, alpha, eta);
130                         else
131                                 phase = mf_eval_phase_glass(wr, lambda_r, -wo, !wo_outside, alpha, 1.0f/eta);
132 #else /* MF_MULTI_GLOSSY */
133                         phase = mf_eval_phase_glossy(wr, lambda_r, wo, alpha) * throughput;
134 #endif
135                         eval += throughput * phase * mf_G1(wo_outside? wo: -wo, mf_C1((outside == wo_outside)? hr: -hr), shadowing_lambda);
136                 }
137                 if(order+1 < 10) {
138                         /* Bounce from the microfacet. */
139 #ifdef MF_MULTI_GLASS
140                         bool next_outside;
141                         float3 wi_prev = -wr;
142                         float phase_rand = lcg_step_float_addrspace(lcg_state);
143                         wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, phase_rand, &next_outside);
144                         if(!next_outside) {
145                                 outside = !outside;
146                                 wr = -wr;
147                                 hr = -hr;
148                         }
149
150                         if(use_fresnel && !next_outside) {
151                                 throughput *= color;
152                         }
153                         else if(use_fresnel && order > 0) {
154                                 throughput *= interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0);
155                         }
156 #else /* MF_MULTI_GLOSSY */
157                         if(use_fresnel && order > 0) {
158                                 throughput *= interpolate_fresnel_color(-wr, wm, eta, F0, cspec0);
159                         }
160                         wr = mf_sample_phase_glossy(-wr, &throughput, wm);
161 #endif
162
163                         lambda_r = mf_lambda(wr, alpha);
164
165                         if(!use_fresnel)
166                                 throughput *= color;
167
168                         C1_r = mf_C1(hr);
169                         G1_r = mf_G1(wr, C1_r, lambda_r);
170                 }
171         }
172
173         if(swapped)
174                 eval *= fabsf(wi.z / wo.z);
175         return eval;
176 }
177
178 /* Perform a random walk on the microsurface starting from wi, returning the direction in which the walk
179  * escaped the surface in wo. The function returns the throughput between wi and wo.
180  * Without reflection losses due to coloring or fresnel absorption in conductors, the sampling is optimal.
181  */
182 ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(
183         float3 wi,
184         float3 *wo,
185         const float3 color,
186         const float alpha_x,
187         const float alpha_y,
188         ccl_addr_space uint *lcg_state,
189         const float eta,
190         bool use_fresnel,
191         const float3 cspec0)
192 {
193         const float2 alpha = make_float2(alpha_x, alpha_y);
194
195         float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
196         float3 wr = -wi;
197         float lambda_r = mf_lambda(wr, alpha);
198         float hr = 1.0f;
199         float C1_r = 1.0f;
200         float G1_r = 0.0f;
201         bool outside = true;
202
203         float F0 = fresnel_dielectric_cos(1.0f, eta);
204         if(use_fresnel) {
205                 throughput = interpolate_fresnel_color(wi, normalize(wi + wr), eta, F0, cspec0);
206         }
207
208         int order;
209         for(order = 0; order < 10; order++) {
210                 /* Sample microfacet height. */
211                 float height_rand = lcg_step_float_addrspace(lcg_state);
212                 if(!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, height_rand)) {
213                         /* The random walk has left the surface. */
214                         *wo = outside? wr: -wr;
215                         return throughput;
216                 }
217                 /* Sample microfacet normal. */
218                 float vndf_rand_y = lcg_step_float_addrspace(lcg_state);
219                 float vndf_rand_x = lcg_step_float_addrspace(lcg_state);
220                 float3 wm = mf_sample_vndf(-wr, alpha, vndf_rand_x, vndf_rand_y);
221
222                 /* First-bounce color is already accounted for in mix weight. */
223                 if(!use_fresnel && order > 0)
224                         throughput *= color;
225
226                 /* Bounce from the microfacet. */
227 #ifdef MF_MULTI_GLASS
228                 bool next_outside;
229                 float3 wi_prev = -wr;
230                 float phase_rand = lcg_step_float_addrspace(lcg_state);
231                 wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, phase_rand, &next_outside);
232                 if(!next_outside) {
233                         hr = -hr;
234                         wr = -wr;
235                         outside = !outside;
236                 }
237
238                 if(use_fresnel) {
239                         if(!next_outside) {
240                                 throughput *= color;
241                         }
242                         else {
243                                 float3 t_color = interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0);
244
245                                 if(order == 0)
246                                         throughput = t_color;
247                                 else
248                                         throughput *= t_color;
249                         }
250                 }
251 #else /* MF_MULTI_GLOSSY */
252                 if(use_fresnel) {
253                         float3 t_color = interpolate_fresnel_color(-wr, wm, eta, F0, cspec0);
254
255                         if(order == 0)
256                                 throughput = t_color;
257                         else
258                                 throughput *= t_color;
259                 }
260                 wr = mf_sample_phase_glossy(-wr, &throughput, wm);
261 #endif
262
263                 /* Update random walk parameters. */
264                 lambda_r = mf_lambda(wr, alpha);
265                 G1_r = mf_G1(wr, C1_r, lambda_r);
266         }
267         *wo = make_float3(0.0f, 0.0f, 1.0f);
268         return make_float3(0.0f, 0.0f, 0.0f);
269 }
270
271 #undef MF_MULTI_GLASS
272 #undef MF_MULTI_GLOSSY
273 #undef MF_PHASE_FUNCTION