Merge remote-tracking branch 'origin/master' into blender2.8
[blender.git] / intern / cycles / kernel / kernel_accumulate.h
1 /*
2  * Copyright 2011-2013 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 /* BSDF Eval
20  *
21  * BSDF evaluation result, split per BSDF type. This is used to accumulate
22  * render passes separately. */
23
24 ccl_device_inline void bsdf_eval_init(BsdfEval *eval, ClosureType type, float3 value, int use_light_pass)
25 {
26 #ifdef __PASSES__
27         eval->use_light_pass = use_light_pass;
28
29         if(eval->use_light_pass) {
30                 eval->diffuse = make_float3(0.0f, 0.0f, 0.0f);
31                 eval->glossy = make_float3(0.0f, 0.0f, 0.0f);
32                 eval->transmission = make_float3(0.0f, 0.0f, 0.0f);
33                 eval->transparent = make_float3(0.0f, 0.0f, 0.0f);
34                 eval->subsurface = make_float3(0.0f, 0.0f, 0.0f);
35                 eval->scatter = 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 if(CLOSURE_IS_BSDF_TRANSMISSION(type))
44                         eval->transmission = value;
45                 else if(CLOSURE_IS_BSDF_BSSRDF(type))
46                         eval->subsurface = value;
47                 else if(CLOSURE_IS_PHASE(type))
48                         eval->scatter = value;
49         }
50         else
51 #endif
52         {
53                 eval->diffuse = value;
54         }
55 }
56
57 ccl_device_inline void bsdf_eval_accum(BsdfEval *eval, ClosureType type, float3 value)
58 {
59 #ifdef __PASSES__
60         if(eval->use_light_pass) {
61                 if(CLOSURE_IS_BSDF_DIFFUSE(type))
62                         eval->diffuse += value;
63                 else if(CLOSURE_IS_BSDF_GLOSSY(type))
64                         eval->glossy += value;
65                 else if(CLOSURE_IS_BSDF_TRANSMISSION(type))
66                         eval->transmission += value;
67                 else if(CLOSURE_IS_BSDF_BSSRDF(type))
68                         eval->subsurface += value;
69                 else if(CLOSURE_IS_PHASE(type))
70                         eval->scatter += value;
71
72                 /* skipping transparent, this function is used by for eval(), will be zero then */
73         }
74         else
75 #endif
76         {
77                 eval->diffuse += value;
78         }
79 }
80
81 ccl_device_inline bool bsdf_eval_is_zero(BsdfEval *eval)
82 {
83 #ifdef __PASSES__
84         if(eval->use_light_pass) {
85                 return is_zero(eval->diffuse)
86                         && is_zero(eval->glossy)
87                         && is_zero(eval->transmission)
88                         && is_zero(eval->transparent)
89                         && is_zero(eval->subsurface)
90                         && is_zero(eval->scatter);
91         }
92         else
93 #endif
94         {
95                 return is_zero(eval->diffuse);
96         }
97 }
98
99 ccl_device_inline void bsdf_eval_mul(BsdfEval *eval, float value)
100 {
101 #ifdef __PASSES__
102         if(eval->use_light_pass) {
103                 eval->diffuse *= value;
104                 eval->glossy *= value;
105                 eval->transmission *= value;
106                 eval->subsurface *= value;
107                 eval->scatter *= value;
108
109                 /* skipping transparent, this function is used by for eval(), will be zero then */
110         }
111         else
112 #endif
113         {
114                 eval->diffuse *= value;
115         }
116 }
117
118 ccl_device_inline void bsdf_eval_mul3(BsdfEval *eval, float3 value)
119 {
120 #ifdef __PASSES__
121         if(eval->use_light_pass) {
122                 eval->diffuse *= value;
123                 eval->glossy *= value;
124                 eval->transmission *= value;
125                 eval->subsurface *= value;
126                 eval->scatter *= value;
127
128                 /* skipping transparent, this function is used by for eval(), will be zero then */
129         }
130         else
131                 eval->diffuse *= value;
132 #else
133         eval->diffuse *= value;
134 #endif
135 }
136
137 ccl_device_inline float3 bsdf_eval_sum(BsdfEval *eval)
138 {
139 #ifdef __PASSES__
140         if(eval->use_light_pass) {
141                 return eval->diffuse + eval->glossy + eval->transmission + eval->subsurface + eval->scatter;
142         }
143         else
144 #endif
145         return eval->diffuse;
146 }
147
148 /* Path Radiance
149  *
150  * We accumulate different render passes separately. After summing at the end
151  * to get the combined result, it should be identical. We definite directly
152  * visible as the first non-transparent hit, while indirectly visible are the
153  * bounces after that. */
154
155 ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
156 {
157         /* clear all */
158 #ifdef __PASSES__
159         L->use_light_pass = use_light_pass;
160
161         if(use_light_pass) {
162                 L->indirect = make_float3(0.0f, 0.0f, 0.0f);
163                 L->direct_throughput = make_float3(0.0f, 0.0f, 0.0f);
164                 L->direct_emission = make_float3(0.0f, 0.0f, 0.0f);
165
166                 L->color_diffuse = make_float3(0.0f, 0.0f, 0.0f);
167                 L->color_glossy = make_float3(0.0f, 0.0f, 0.0f);
168                 L->color_transmission = make_float3(0.0f, 0.0f, 0.0f);
169                 L->color_subsurface = make_float3(0.0f, 0.0f, 0.0f);
170                 L->color_scatter = make_float3(0.0f, 0.0f, 0.0f);
171
172                 L->direct_diffuse = make_float3(0.0f, 0.0f, 0.0f);
173                 L->direct_glossy = make_float3(0.0f, 0.0f, 0.0f);
174                 L->direct_transmission = make_float3(0.0f, 0.0f, 0.0f);
175                 L->direct_subsurface = make_float3(0.0f, 0.0f, 0.0f);
176                 L->direct_scatter = make_float3(0.0f, 0.0f, 0.0f);
177
178                 L->indirect_diffuse = make_float3(0.0f, 0.0f, 0.0f);
179                 L->indirect_glossy = make_float3(0.0f, 0.0f, 0.0f);
180                 L->indirect_transmission = make_float3(0.0f, 0.0f, 0.0f);
181                 L->indirect_subsurface = make_float3(0.0f, 0.0f, 0.0f);
182                 L->indirect_scatter = make_float3(0.0f, 0.0f, 0.0f);
183
184                 L->path_diffuse = make_float3(0.0f, 0.0f, 0.0f);
185                 L->path_glossy = make_float3(0.0f, 0.0f, 0.0f);
186                 L->path_transmission = make_float3(0.0f, 0.0f, 0.0f);
187                 L->path_subsurface = make_float3(0.0f, 0.0f, 0.0f);
188                 L->path_scatter = make_float3(0.0f, 0.0f, 0.0f);
189
190                 L->emission = make_float3(0.0f, 0.0f, 0.0f);
191                 L->background = make_float3(0.0f, 0.0f, 0.0f);
192                 L->ao = make_float3(0.0f, 0.0f, 0.0f);
193                 L->shadow = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
194                 L->mist = 0.0f;
195         }
196         else
197 #endif
198         {
199                 L->emission = make_float3(0.0f, 0.0f, 0.0f);
200         }
201 }
202
203 ccl_device_inline void path_radiance_bsdf_bounce(PathRadiance *L, ccl_addr_space float3 *throughput,
204         BsdfEval *bsdf_eval, float bsdf_pdf, int bounce, int bsdf_label)
205 {
206         float inverse_pdf = 1.0f/bsdf_pdf;
207
208 #ifdef __PASSES__
209         if(L->use_light_pass) {
210                 if(bounce == 0 && !(bsdf_label & LABEL_TRANSPARENT)) {
211                         /* first on directly visible surface */
212                         float3 value = *throughput*inverse_pdf;
213
214                         L->path_diffuse = bsdf_eval->diffuse*value;
215                         L->path_glossy = bsdf_eval->glossy*value;
216                         L->path_transmission = bsdf_eval->transmission*value;
217                         L->path_subsurface = bsdf_eval->subsurface*value;
218                         L->path_scatter = bsdf_eval->scatter*value;
219
220                         *throughput = L->path_diffuse + L->path_glossy + L->path_transmission + L->path_subsurface + L->path_scatter;
221                         
222                         L->direct_throughput = *throughput;
223                 }
224                 else {
225                         /* transparent bounce before first hit, or indirectly visible through BSDF */
226                         float3 sum = (bsdf_eval_sum(bsdf_eval) + bsdf_eval->transparent) * inverse_pdf;
227                         *throughput *= sum;
228                 }
229         }
230         else
231 #endif
232         {
233                 *throughput *= bsdf_eval->diffuse*inverse_pdf;
234         }
235 }
236
237 ccl_device_inline void path_radiance_accum_emission(PathRadiance *L, float3 throughput, float3 value, int bounce)
238 {
239 #ifdef __PASSES__
240         if(L->use_light_pass) {
241                 if(bounce == 0)
242                         L->emission += throughput*value;
243                 else if(bounce == 1)
244                         L->direct_emission += throughput*value;
245                 else
246                         L->indirect += throughput*value;
247         }
248         else
249 #endif
250         {
251                 L->emission += throughput*value;
252         }
253 }
254
255 ccl_device_inline void path_radiance_accum_ao(PathRadiance *L, float3 throughput, float3 alpha, float3 bsdf, float3 ao, int bounce)
256 {
257 #ifdef __PASSES__
258         if(L->use_light_pass) {
259                 if(bounce == 0) {
260                         /* directly visible lighting */
261                         L->direct_diffuse += throughput*bsdf*ao;
262                         L->ao += alpha*throughput*ao;
263                 }
264                 else {
265                         /* indirectly visible lighting after BSDF bounce */
266                         L->indirect += throughput*bsdf*ao;
267                 }
268         }
269         else
270 #endif
271         {
272                 L->emission += throughput*bsdf*ao;
273         }
274 }
275
276 ccl_device_inline void path_radiance_accum_light(PathRadiance *L, float3 throughput, BsdfEval *bsdf_eval, float3 shadow, float shadow_fac, int bounce, bool is_lamp)
277 {
278 #ifdef __PASSES__
279         if(L->use_light_pass) {
280                 if(bounce == 0) {
281                         /* directly visible lighting */
282                         L->direct_diffuse += throughput*bsdf_eval->diffuse*shadow;
283                         L->direct_glossy += throughput*bsdf_eval->glossy*shadow;
284                         L->direct_transmission += throughput*bsdf_eval->transmission*shadow;
285                         L->direct_subsurface += throughput*bsdf_eval->subsurface*shadow;
286                         L->direct_scatter += throughput*bsdf_eval->scatter*shadow;
287
288                         if(is_lamp) {
289                                 L->shadow.x += shadow.x*shadow_fac;
290                                 L->shadow.y += shadow.y*shadow_fac;
291                                 L->shadow.z += shadow.z*shadow_fac;
292                         }
293                 }
294                 else {
295                         /* indirectly visible lighting after BSDF bounce */
296                         L->indirect += throughput*bsdf_eval_sum(bsdf_eval)*shadow;
297                 }
298         }
299         else
300 #endif
301         {
302                 L->emission += throughput*bsdf_eval->diffuse*shadow;
303         }
304 }
305
306 ccl_device_inline void path_radiance_accum_background(PathRadiance *L, float3 throughput, float3 value, int bounce)
307 {
308 #ifdef __PASSES__
309         if(L->use_light_pass) {
310                 if(bounce == 0)
311                         L->background += throughput*value;
312                 else if(bounce == 1)
313                         L->direct_emission += throughput*value;
314                 else
315                         L->indirect += throughput*value;
316         }
317         else
318 #endif
319         {
320                 L->emission += throughput*value;
321         }
322 }
323
324 ccl_device_inline void path_radiance_sum_indirect(PathRadiance *L)
325 {
326 #ifdef __PASSES__
327         /* this division is a bit ugly, but means we only have to keep track of
328          * only a single throughput further along the path, here we recover just
329          * the indirect path that is not influenced by any particular BSDF type */
330         if(L->use_light_pass) {
331                 L->direct_emission = safe_divide_color(L->direct_emission, L->direct_throughput);
332                 L->direct_diffuse += L->path_diffuse*L->direct_emission;
333                 L->direct_glossy += L->path_glossy*L->direct_emission;
334                 L->direct_transmission += L->path_transmission*L->direct_emission;
335                 L->direct_subsurface += L->path_subsurface*L->direct_emission;
336                 L->direct_scatter += L->path_scatter*L->direct_emission;
337
338                 L->indirect = safe_divide_color(L->indirect, L->direct_throughput);
339                 L->indirect_diffuse += L->path_diffuse*L->indirect;
340                 L->indirect_glossy += L->path_glossy*L->indirect;
341                 L->indirect_transmission += L->path_transmission*L->indirect;
342                 L->indirect_subsurface += L->path_subsurface*L->indirect;
343                 L->indirect_scatter += L->path_scatter*L->indirect;
344         }
345 #endif
346 }
347
348 ccl_device_inline void path_radiance_reset_indirect(PathRadiance *L)
349 {
350 #ifdef __PASSES__
351         if(L->use_light_pass) {
352                 L->path_diffuse = make_float3(0.0f, 0.0f, 0.0f);
353                 L->path_glossy = make_float3(0.0f, 0.0f, 0.0f);
354                 L->path_transmission = make_float3(0.0f, 0.0f, 0.0f);
355                 L->path_subsurface = make_float3(0.0f, 0.0f, 0.0f);
356                 L->path_scatter = make_float3(0.0f, 0.0f, 0.0f);
357
358                 L->direct_emission = make_float3(0.0f, 0.0f, 0.0f);
359                 L->indirect = make_float3(0.0f, 0.0f, 0.0f);
360         }
361 #endif
362 }
363
364 ccl_device_inline void path_radiance_copy_indirect(PathRadiance *L,
365                                                    const PathRadiance *L_src)
366 {
367 #ifdef __PASSES__
368         if(L->use_light_pass) {
369                 L->path_diffuse = L_src->path_diffuse;
370                 L->path_glossy = L_src->path_glossy;
371                 L->path_transmission = L_src->path_transmission;
372                 L->path_subsurface = L_src->path_subsurface;
373                 L->path_scatter = L_src->path_scatter;
374
375                 L->direct_emission = L_src->direct_emission;
376                 L->indirect = L_src->indirect;
377         }
378 #endif
379 }
380
381 ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadiance *L)
382 {
383         float3 L_sum;
384         /* Light Passes are used */
385 #ifdef __PASSES__
386         float3 L_direct, L_indirect;
387         float clamp_direct = kernel_data.integrator.sample_clamp_direct;
388         float clamp_indirect = kernel_data.integrator.sample_clamp_indirect;
389         if(L->use_light_pass) {
390                 path_radiance_sum_indirect(L);
391
392                 L_direct = L->direct_diffuse + L->direct_glossy + L->direct_transmission + L->direct_subsurface + L->direct_scatter + L->emission;
393                 L_indirect = L->indirect_diffuse + L->indirect_glossy + L->indirect_transmission + L->indirect_subsurface + L->indirect_scatter;
394
395                 if(!kernel_data.background.transparent)
396                         L_direct += L->background;
397
398                 L_sum = L_direct + L_indirect;
399                 float sum = fabsf((L_sum).x) + fabsf((L_sum).y) + fabsf((L_sum).z);
400
401                 /* Reject invalid value */
402                 if(!isfinite(sum)) {
403                         kernel_assert(!"Non-finite sum in path_radiance_clamp_and_sum!");
404                         L_sum = make_float3(0.0f, 0.0f, 0.0f);
405
406                         L->direct_diffuse = make_float3(0.0f, 0.0f, 0.0f);
407                         L->direct_glossy = make_float3(0.0f, 0.0f, 0.0f);
408                         L->direct_transmission = make_float3(0.0f, 0.0f, 0.0f);
409                         L->direct_subsurface = make_float3(0.0f, 0.0f, 0.0f);
410                         L->direct_scatter = make_float3(0.0f, 0.0f, 0.0f);
411
412                         L->indirect_diffuse = make_float3(0.0f, 0.0f, 0.0f);
413                         L->indirect_glossy = make_float3(0.0f, 0.0f, 0.0f);
414                         L->indirect_transmission = make_float3(0.0f, 0.0f, 0.0f);
415                         L->indirect_subsurface = make_float3(0.0f, 0.0f, 0.0f);
416                         L->indirect_scatter = make_float3(0.0f, 0.0f, 0.0f);
417
418                         L->emission = make_float3(0.0f, 0.0f, 0.0f);
419                 }
420
421                 /* Clamp direct and indirect samples */
422 #ifdef __CLAMP_SAMPLE__
423                 else if(sum > clamp_direct || sum > clamp_indirect) {
424                         float scale;
425
426                         /* Direct */
427                         float sum_direct = fabsf(L_direct.x) + fabsf(L_direct.y) + fabsf(L_direct.z);
428                         if(sum_direct > clamp_direct) {
429                                 scale = clamp_direct/sum_direct;
430                                 L_direct *= scale;
431
432                                 L->direct_diffuse *= scale;
433                                 L->direct_glossy *= scale;
434                                 L->direct_transmission *= scale;
435                                 L->direct_subsurface *= scale;
436                                 L->direct_scatter *= scale;
437                                 L->emission *= scale;
438                                 L->background *= scale;
439                         }
440
441                         /* Indirect */
442                         float sum_indirect = fabsf(L_indirect.x) + fabsf(L_indirect.y) + fabsf(L_indirect.z);
443                         if(sum_indirect > clamp_indirect) {
444                                 scale = clamp_indirect/sum_indirect;
445                                 L_indirect *= scale;
446
447                                 L->indirect_diffuse *= scale;
448                                 L->indirect_glossy *= scale;
449                                 L->indirect_transmission *= scale;
450                                 L->indirect_subsurface *= scale;
451                                 L->indirect_scatter *= scale;
452                         }
453
454                         /* Sum again, after clamping */
455                         L_sum = L_direct + L_indirect;
456                 }
457 #endif
458
459                 return L_sum;
460         }
461
462         /* No Light Passes */
463         else
464 #endif
465         {
466                 L_sum = L->emission;
467         }
468
469         /* Reject invalid value */
470         float sum = fabsf((L_sum).x) + fabsf((L_sum).y) + fabsf((L_sum).z);
471         if(!isfinite(sum)) {
472                 kernel_assert(!"Non-finite final sum in path_radiance_clamp_and_sum!");
473                 L_sum = make_float3(0.0f, 0.0f, 0.0f);
474         }
475
476         return L_sum;
477 }
478
479 ccl_device_inline void path_radiance_accum_sample(PathRadiance *L, PathRadiance *L_sample, int num_samples)
480 {
481         float fac = 1.0f/num_samples;
482
483 #ifdef __PASSES__
484         L->direct_diffuse += L_sample->direct_diffuse*fac;
485         L->direct_glossy += L_sample->direct_glossy*fac;
486         L->direct_transmission += L_sample->direct_transmission*fac;
487         L->direct_subsurface += L_sample->direct_subsurface*fac;
488         L->direct_scatter += L_sample->direct_scatter*fac;
489
490         L->indirect_diffuse += L_sample->indirect_diffuse*fac;
491         L->indirect_glossy += L_sample->indirect_glossy*fac;
492         L->indirect_transmission += L_sample->indirect_transmission*fac;
493         L->indirect_subsurface += L_sample->indirect_subsurface*fac;
494         L->indirect_scatter += L_sample->indirect_scatter*fac;
495
496         L->background += L_sample->background*fac;
497         L->ao += L_sample->ao*fac;
498         L->shadow += L_sample->shadow*fac;
499         L->mist += L_sample->mist*fac;
500 #endif
501         L->emission += L_sample->emission * fac;
502 }
503
504 CCL_NAMESPACE_END
505