9e26aa6fa2b74e7cefd26049b22dcbeda8863af0
[blender.git] / intern / cycles / kernel / kernel_accumulate.h
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 CCL_NAMESPACE_BEGIN
20
21 /* BSDF Eval
22  *
23  * BSDF evaluation result, split per BSDF type. This is used to accumulate
24  * render passes separately. */
25
26 __device_inline void bsdf_eval_init(BsdfEval *eval, ClosureType type, float3 value, int use_light_pass)
27 {
28 #ifdef __PASSES__
29         eval->use_light_pass = use_light_pass;
30
31         if(eval->use_light_pass) {
32                 eval->diffuse = make_float3(0.0f, 0.0f, 0.0f);
33                 eval->glossy = make_float3(0.0f, 0.0f, 0.0f);
34                 eval->transmission = make_float3(0.0f, 0.0f, 0.0f);
35                 eval->transparent = make_float3(0.0f, 0.0f, 0.0f);
36
37                 if(type == CLOSURE_BSDF_TRANSPARENT_ID)
38                         eval->transparent = value;
39                 else if(CLOSURE_IS_BSDF_DIFFUSE(type))
40                         eval->diffuse = value;
41                 else if(CLOSURE_IS_BSDF_GLOSSY(type))
42                         eval->glossy = value;
43                 else
44                         eval->transmission = value;
45         }
46         else
47                 eval->diffuse = value;
48 #else
49         *eval = value;
50 #endif
51 }
52
53 __device_inline void bsdf_eval_accum(BsdfEval *eval, ClosureType type, float3 value)
54 {
55 #ifdef __PASSES__
56         if(eval->use_light_pass) {
57                 if(CLOSURE_IS_BSDF_DIFFUSE(type))
58                         eval->diffuse += value;
59                 else if(CLOSURE_IS_BSDF_GLOSSY(type))
60                         eval->glossy += value;
61                 else
62                         eval->transmission += value;
63
64                 /* skipping transparent, this function is used by for eval(), will be zero then */
65         }
66         else
67                 eval->diffuse += value;
68 #else
69         *eval += value;
70 #endif
71 }
72
73 __device_inline bool bsdf_eval_is_zero(BsdfEval *eval)
74 {
75 #ifdef __PASSES__
76         if(eval->use_light_pass) {
77                 return is_zero(eval->diffuse)
78                         && is_zero(eval->glossy)
79                         && is_zero(eval->transmission)
80                         && is_zero(eval->transparent);
81         }
82         else
83                 return is_zero(eval->diffuse);
84 #else
85         return is_zero(*eval);
86 #endif
87 }
88
89 __device_inline void bsdf_eval_mul(BsdfEval *eval, float3 value)
90 {
91 #ifdef __PASSES__
92         if(eval->use_light_pass) {
93                 eval->diffuse *= value;
94                 eval->glossy *= value;
95                 eval->transmission *= value;
96
97                 /* skipping transparent, this function is used by for eval(), will be zero then */
98         }
99         else
100                 eval->diffuse *= value;
101 #else
102         *eval *= value;
103 #endif
104 }
105
106 /* Path Radiance
107  *
108  * We accumulate different render passes separately. After summing at the end
109  * to get the combined result, it should be identical. We definte directly
110  * visible as the first non-transparent hit, while indirectly visible are the
111  * bounces after that. */
112
113 __device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
114 {
115         /* clear all */
116 #ifdef __PASSES__
117         L->use_light_pass = use_light_pass;
118
119         if(use_light_pass) {
120                 L->indirect = make_float3(0.0f, 0.0f, 0.0f);
121                 L->direct_throughput = make_float3(0.0f, 0.0f, 0.0f);
122                 L->direct_emission = make_float3(0.0f, 0.0f, 0.0f);
123
124                 L->color_diffuse = make_float3(0.0f, 0.0f, 0.0f);
125                 L->color_glossy = make_float3(0.0f, 0.0f, 0.0f);
126                 L->color_transmission = make_float3(0.0f, 0.0f, 0.0f);
127                 L->color_subsurface = make_float3(0.0f, 0.0f, 0.0f);
128
129                 L->direct_diffuse = make_float3(0.0f, 0.0f, 0.0f);
130                 L->direct_glossy = make_float3(0.0f, 0.0f, 0.0f);
131                 L->direct_transmission = make_float3(0.0f, 0.0f, 0.0f);
132                 L->direct_subsurface = make_float3(0.0f, 0.0f, 0.0f);
133
134                 L->indirect_diffuse = make_float3(0.0f, 0.0f, 0.0f);
135                 L->indirect_glossy = make_float3(0.0f, 0.0f, 0.0f);
136                 L->indirect_transmission = make_float3(0.0f, 0.0f, 0.0f);
137                 L->indirect_subsurface = make_float3(0.0f, 0.0f, 0.0f);
138
139                 L->path_diffuse = make_float3(0.0f, 0.0f, 0.0f);
140                 L->path_glossy = make_float3(0.0f, 0.0f, 0.0f);
141                 L->path_transmission = make_float3(0.0f, 0.0f, 0.0f);
142
143                 L->emission = make_float3(0.0f, 0.0f, 0.0f);
144                 L->background = make_float3(0.0f, 0.0f, 0.0f);
145                 L->ao = make_float3(0.0f, 0.0f, 0.0f);
146                 L->shadow = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
147                 L->mist = 0.0f;
148         }
149         else
150                 L->emission = make_float3(0.0f, 0.0f, 0.0f);
151 #else
152         *L = make_float3(0.0f, 0.0f, 0.0f);
153 #endif
154 }
155
156 __device_inline void path_radiance_bsdf_bounce(PathRadiance *L, float3 *throughput,
157         BsdfEval *bsdf_eval, float bsdf_pdf, int bounce, int bsdf_label)
158 {
159         float inverse_pdf = 1.0f/bsdf_pdf;
160
161 #ifdef __PASSES__
162         if(L->use_light_pass) {
163                 if(bounce == 0 && !(bsdf_label & LABEL_TRANSPARENT)) {
164                         /* first on directly visible surface */
165                         float3 value = *throughput*inverse_pdf;
166
167                         L->path_diffuse = bsdf_eval->diffuse*value;
168                         L->path_glossy = bsdf_eval->glossy*value;
169                         L->path_transmission = bsdf_eval->transmission*value;
170
171                         *throughput = L->path_diffuse + L->path_glossy + L->path_transmission;
172                         
173                         L->direct_throughput = *throughput;
174                 }
175                 else {
176                         /* transparent bounce before first hit, or indirectly visible through BSDF */
177                         float3 sum = (bsdf_eval->diffuse + bsdf_eval->glossy + bsdf_eval->transmission + bsdf_eval->transparent)*inverse_pdf;
178                         *throughput *= sum;
179                 }
180         }
181         else
182                 *throughput *= bsdf_eval->diffuse*inverse_pdf;
183 #else
184         *throughput *= *bsdf_eval*inverse_pdf;
185 #endif
186 }
187
188 __device_inline void path_radiance_accum_emission(PathRadiance *L, float3 throughput, float3 value, int bounce)
189 {
190 #ifdef __PASSES__
191         if(L->use_light_pass) {
192                 if(bounce == 0)
193                         L->emission += throughput*value;
194                 else if(bounce == 1)
195                         L->direct_emission += throughput*value;
196                 else
197                         L->indirect += throughput*value;
198         }
199         else
200                 L->emission += throughput*value;
201 #else
202         *L += throughput*value;
203 #endif
204 }
205
206 __device_inline void path_radiance_accum_ao(PathRadiance *L, float3 throughput, float3 bsdf, float3 ao, int bounce)
207 {
208 #ifdef __PASSES__
209         if(L->use_light_pass) {
210                 if(bounce == 0) {
211                         /* directly visible lighting */
212                         L->direct_diffuse += throughput*bsdf*ao;
213                         L->ao += throughput*ao;
214                 }
215                 else {
216                         /* indirectly visible lighting after BSDF bounce */
217                         L->indirect += throughput*bsdf*ao;
218                 }
219         }
220         else
221                 L->emission += throughput*bsdf*ao;
222 #else
223         *L += throughput*bsdf*ao;
224 #endif
225 }
226
227 __device_inline void path_radiance_accum_light(PathRadiance *L, float3 throughput, BsdfEval *bsdf_eval, float3 shadow, float shadow_fac, int bounce, bool is_lamp)
228 {
229 #ifdef __PASSES__
230         if(L->use_light_pass) {
231                 if(bounce == 0) {
232                         /* directly visible lighting */
233                         L->direct_diffuse += throughput*bsdf_eval->diffuse*shadow;
234                         L->direct_glossy += throughput*bsdf_eval->glossy*shadow;
235                         L->direct_transmission += throughput*bsdf_eval->transmission*shadow;
236
237                         if(is_lamp) {
238                                 L->shadow.x += shadow.x*shadow_fac;
239                                 L->shadow.y += shadow.y*shadow_fac;
240                                 L->shadow.z += shadow.z*shadow_fac;
241                         }
242                 }
243                 else {
244                         /* indirectly visible lighting after BSDF bounce */
245                         float3 sum = bsdf_eval->diffuse + bsdf_eval->glossy + bsdf_eval->transmission;
246                         L->indirect += throughput*sum*shadow;
247                 }
248         }
249         else
250                 L->emission += throughput*bsdf_eval->diffuse*shadow;
251 #else
252         *L += throughput*(*bsdf_eval)*shadow;
253 #endif
254 }
255
256 __device_inline void path_radiance_accum_background(PathRadiance *L, float3 throughput, float3 value, int bounce)
257 {
258 #ifdef __PASSES__
259         if(L->use_light_pass) {
260                 if(bounce == 0)
261                         L->background += throughput*value;
262                 else if(bounce == 1)
263                         L->direct_emission += throughput*value;
264                 else
265                         L->indirect += throughput*value;
266         }
267         else
268                 L->emission += throughput*value;
269 #else
270         *L += throughput*value;
271 #endif
272 }
273
274 __device_inline void path_radiance_sum_indirect(PathRadiance *L)
275 {
276 #ifdef __PASSES__
277         /* this division is a bit ugly, but means we only have to keep track of
278          * only a single throughput further along the path, here we recover just
279          * the indirect parth that is not influenced by any particular BSDF type */
280         if(L->use_light_pass) {
281                 L->direct_emission = safe_divide_color(L->direct_emission, L->direct_throughput);
282                 L->direct_diffuse += L->path_diffuse*L->direct_emission;
283                 L->direct_glossy += L->path_glossy*L->direct_emission;
284                 L->direct_transmission += L->path_transmission*L->direct_emission;
285
286                 L->indirect = safe_divide_color(L->indirect, L->direct_throughput);
287                 L->indirect_diffuse += L->path_diffuse*L->indirect;
288                 L->indirect_glossy += L->path_glossy*L->indirect;
289                 L->indirect_transmission += L->path_transmission*L->indirect;
290         }
291 #endif
292 }
293
294 __device_inline void path_radiance_reset_indirect(PathRadiance *L)
295 {
296 #ifdef __PASSES__
297         if(L->use_light_pass) {
298                 L->path_diffuse = make_float3(0.0f, 0.0f, 0.0f);
299                 L->path_glossy = make_float3(0.0f, 0.0f, 0.0f);
300                 L->path_transmission = make_float3(0.0f, 0.0f, 0.0f);
301
302                 L->direct_emission = make_float3(0.0f, 0.0f, 0.0f);
303                 L->indirect = make_float3(0.0f, 0.0f, 0.0f);
304         }
305 #endif
306 }
307
308 __device_inline float3 path_radiance_sum(KernelGlobals *kg, PathRadiance *L)
309 {
310 #ifdef __PASSES__
311         if(L->use_light_pass) {
312                 path_radiance_sum_indirect(L);
313
314                 float3 L_sum = L->emission
315                         + L->direct_diffuse + L->direct_glossy + L->direct_transmission
316                         + L->indirect_diffuse + L->indirect_glossy + L->indirect_transmission;
317
318                 if(!kernel_data.background.transparent)
319                         L_sum += L->background;
320
321                 return L_sum;
322         }
323         else
324                 return L->emission;
325 #else
326         return *L;
327 #endif
328 }
329
330 __device_inline void path_radiance_clamp(PathRadiance *L, float3 *L_sum, float clamp)
331 {
332         float sum = fabsf((*L_sum).x) + fabsf((*L_sum).y) + fabsf((*L_sum).z);
333
334         if(!isfinite(sum)) {
335                 /* invalid value, reject */
336                 *L_sum = make_float3(0.0f, 0.0f, 0.0f);
337
338 #ifdef __PASSES__
339                 if(L->use_light_pass) {
340                         L->direct_diffuse = make_float3(0.0f, 0.0f, 0.0f);
341                         L->direct_glossy = make_float3(0.0f, 0.0f, 0.0f);
342                         L->direct_transmission = make_float3(0.0f, 0.0f, 0.0f);
343                         L->direct_subsurface = make_float3(0.0f, 0.0f, 0.0f);
344
345                         L->indirect_diffuse = make_float3(0.0f, 0.0f, 0.0f);
346                         L->indirect_glossy = make_float3(0.0f, 0.0f, 0.0f);
347                         L->indirect_transmission = make_float3(0.0f, 0.0f, 0.0f);
348                         L->indirect_subsurface = make_float3(0.0f, 0.0f, 0.0f);
349
350                         L->emission = make_float3(0.0f, 0.0f, 0.0f);
351                 }
352 #endif
353         }
354         else if(sum > clamp) {
355                 /* value to high, scale down */
356                 float scale = clamp/sum;
357
358                 *L_sum *= scale;
359
360 #ifdef __PASSES__
361                 if(L->use_light_pass) {
362                         L->direct_diffuse *= scale;
363                         L->direct_glossy *= scale;
364                         L->direct_transmission *= scale;
365                         L->direct_subsurface *= scale;
366
367                         L->indirect_diffuse *= scale;
368                         L->indirect_glossy *= scale;
369                         L->indirect_transmission *= scale;
370                         L->indirect_subsurface *= scale;
371
372                         L->emission *= scale;
373                 }
374 #endif
375         }
376 }
377
378 CCL_NAMESPACE_END
379