8f8e19dd059e82b693569643deb29303758a77db
[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 float3 MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi, float3 wo, const bool wo_outside, const float3 color, const float alpha_x, const float alpha_y, ccl_addr_space uint* lcg_state
29 #ifdef MF_MULTI_GLASS
30         , const float eta
31 #elif defined(MF_MULTI_GLOSSY)
32         , float3 *n, float3 *k
33 #endif
34 )
35 {
36         /* Evaluating for a shallower incoming direction produces less noise, and the properties of the BSDF guarantee reciprocity. */
37         bool swapped = false;
38 #ifdef MF_MULTI_GLASS
39         if(wi.z*wo.z < 0.0f) {
40                 /* Glass transmission is a special case and requires the directions to change hemisphere. */
41                 if(-wo.z < wi.z) {
42                         swapped = true;
43                         float3 tmp = -wo;
44                         wo = -wi;
45                         wi = tmp;
46                 }
47         }
48         else
49 #endif
50         if(wo.z < wi.z) {
51                 swapped = true;
52                 float3 tmp = wo;
53                 wo = wi;
54                 wi = tmp;
55         }
56
57         if(wi.z < 1e-5f || (wo.z < 1e-5f && wo_outside) || (wo.z > -1e-5f && !wo_outside))
58                 return make_float3(0.0f, 0.0f, 0.0f);
59
60         const float2 alpha = make_float2(alpha_x, alpha_y);
61
62         float lambda_r = mf_lambda(-wi, alpha);
63         float shadowing_lambda = mf_lambda(wo_outside? wo: -wo, alpha);
64
65         /* Analytically compute single scattering for lower noise. */
66         float3 eval;
67 #ifdef MF_MULTI_GLASS
68         eval = mf_eval_phase_glass(-wi, lambda_r, wo, wo_outside, alpha, eta);
69         if(wo_outside)
70                 eval *= -lambda_r / (shadowing_lambda - lambda_r);
71         else
72                 eval *= -lambda_r * beta(-lambda_r, shadowing_lambda+1.0f);
73 #elif defined(MF_MULTI_DIFFUSE)
74         /* Diffuse has no special closed form for the single scattering bounce */
75         eval = make_float3(0.0f, 0.0f, 0.0f);
76 #else /* MF_MULTI_GLOSSY */
77         const float3 wh = normalize(wi+wo);
78         const float G2 = 1.0f / (1.0f - (lambda_r + 1.0f) + shadowing_lambda);
79         float val = G2 * 0.25f / wi.z;
80         if(alpha.x == alpha.y)
81                 val *= D_ggx(wh, alpha.x);
82         else
83                 val *= D_ggx_aniso(wh, alpha);
84         if(n && k) {
85                 eval = fresnel_conductor(dot(wh, wi), *n, *k) * val;
86         }
87         else {
88                 eval = make_float3(val, val, val);
89         }
90 #endif
91
92         float3 wr = -wi;
93         float hr = 1.0f;
94         float C1_r = 1.0f;
95         float G1_r = 0.0f;
96         bool outside = true;
97         float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
98
99         for(int order = 0; order < 10; order++) {
100                 /* Sample microfacet height and normal */
101                 if(!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, lcg_step_float(lcg_state)))
102                         break;
103                 float3 wm = mf_sample_vndf(-wr, alpha, make_float2(lcg_step_float(lcg_state), lcg_step_float(lcg_state)));
104
105 #ifdef MF_MULTI_DIFFUSE
106                 if(order == 0) {
107                         /* Compute single-scattering for diffuse. */
108                         const float G2_G1 = -lambda_r / (shadowing_lambda - lambda_r);
109                         eval += throughput * G2_G1 * mf_eval_phase_diffuse(wo, wm);
110                 }
111 #endif
112                 if(order > 0) {
113                         /* Evaluate amount of scattering towards wo on this microfacet. */
114                         float3 phase;
115 #ifdef MF_MULTI_GLASS
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 #elif defined(MF_MULTI_DIFFUSE)
121                         phase = mf_eval_phase_diffuse(wo, wm);
122 #else /* MF_MULTI_GLOSSY */
123                         phase = mf_eval_phase_glossy(wr, lambda_r, wo, alpha, n, k) * throughput;
124 #endif
125                         eval += throughput * phase * mf_G1(wo_outside? wo: -wo, mf_C1((outside == wo_outside)? hr: -hr), shadowing_lambda);
126                 }
127                 if(order+1 < 10) {
128                         /* Bounce from the microfacet. */
129 #ifdef MF_MULTI_GLASS
130                         bool next_outside;
131                         wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, lcg_step_float(lcg_state), &next_outside);
132                         if(!next_outside) {
133                                 outside = !outside;
134                                 wr = -wr;
135                                 hr = -hr;
136                         }
137 #elif defined(MF_MULTI_DIFFUSE)
138                         wr = mf_sample_phase_diffuse(wm, lcg_step_float(lcg_state), lcg_step_float(lcg_state));
139 #else /* MF_MULTI_GLOSSY */
140                         wr = mf_sample_phase_glossy(-wr, n, k, &throughput, wm);
141 #endif
142
143                         lambda_r = mf_lambda(wr, alpha);
144
145                         throughput *= color;
146
147                         C1_r = mf_C1(hr);
148                         G1_r = mf_G1(wr, C1_r, lambda_r);
149                 }
150         }
151
152         if(swapped)
153                 eval *= fabsf(wi.z / wo.z);
154         return eval;
155 }
156
157 /* Perform a random walk on the microsurface starting from wi, returning the direction in which the walk
158  * escaped the surface in wo. The function returns the throughput between wi and wo.
159  * Without reflection losses due to coloring or fresnel absorption in conductors, the sampling is optimal.
160  */
161 ccl_device float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi, float3 *wo, const float3 color, const float alpha_x, const float alpha_y, ccl_addr_space uint *lcg_state
162 #ifdef MF_MULTI_GLASS
163         , const float eta
164 #elif defined(MF_MULTI_GLOSSY)
165         , float3 *n, float3 *k
166 #endif
167 )
168 {
169         const float2 alpha = make_float2(alpha_x, alpha_y);
170
171         float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
172         float3 wr = -wi;
173         float lambda_r = mf_lambda(wr, alpha);
174         float hr = 1.0f;
175         float C1_r = 1.0f;
176         float G1_r = 0.0f;
177         bool outside = true;
178
179         int order;
180         for(order = 0; order < 10; order++) {
181                 /* Sample microfacet height. */
182                 if(!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, lcg_step_float(lcg_state))) {
183                         /* The random walk has left the surface. */
184                         *wo = outside? wr: -wr;
185                         return throughput;
186                 }
187                 /* Sample microfacet normal. */
188                 float3 wm = mf_sample_vndf(-wr, alpha, make_float2(lcg_step_float(lcg_state), lcg_step_float(lcg_state)));
189
190                 /* First-bounce color is already accounted for in mix weight. */
191                 if(order > 0)
192                         throughput *= color;
193
194                 /* Bounce from the microfacet. */
195 #ifdef MF_MULTI_GLASS
196                 bool next_outside;
197                 wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, lcg_step_float(lcg_state), &next_outside);
198                 if(!next_outside) {
199                         hr = -hr;
200                         wr = -wr;
201                         outside = !outside;
202                 }
203 #elif defined(MF_MULTI_DIFFUSE)
204                 wr = mf_sample_phase_diffuse(wm, lcg_step_float(lcg_state), lcg_step_float(lcg_state));
205 #else /* MF_MULTI_GLOSSY */
206                 wr = mf_sample_phase_glossy(-wr, n, k, &throughput, wm);
207 #endif
208
209                 /* Update random walk parameters. */
210                 lambda_r = mf_lambda(wr, alpha);
211                 G1_r = mf_G1(wr, C1_r, lambda_r);
212         }
213         *wo = make_float3(0.0f, 0.0f, 1.0f);
214         return make_float3(0.0f, 0.0f, 0.0f);
215 }
216
217 #undef MF_MULTI_GLASS
218 #undef MF_MULTI_DIFFUSE
219 #undef MF_MULTI_GLOSSY
220 #undef MF_PHASE_FUNCTION