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 float3 shader_bsdf_transparency(KernelGlobals *kg, const ShaderData *sd);
25 
bsdf_eval_init(BsdfEval * eval,ClosureType type,float3 value,int use_light_pass)26 ccl_device_inline void bsdf_eval_init(BsdfEval *eval,
27                                       ClosureType type,
28                                       float3 value,
29                                       int use_light_pass)
30 {
31 #ifdef __PASSES__
32   eval->use_light_pass = use_light_pass;
33 
34   if (eval->use_light_pass) {
35     eval->diffuse = make_float3(0.0f, 0.0f, 0.0f);
36     eval->glossy = make_float3(0.0f, 0.0f, 0.0f);
37     eval->transmission = make_float3(0.0f, 0.0f, 0.0f);
38     eval->transparent = make_float3(0.0f, 0.0f, 0.0f);
39     eval->volume = make_float3(0.0f, 0.0f, 0.0f);
40 
41     if (type == CLOSURE_BSDF_TRANSPARENT_ID)
42       eval->transparent = value;
43     else if (CLOSURE_IS_BSDF_DIFFUSE(type) || CLOSURE_IS_BSDF_BSSRDF(type))
44       eval->diffuse = value;
45     else if (CLOSURE_IS_BSDF_GLOSSY(type))
46       eval->glossy = value;
47     else if (CLOSURE_IS_BSDF_TRANSMISSION(type))
48       eval->transmission = value;
49     else if (CLOSURE_IS_PHASE(type))
50       eval->volume = value;
51   }
52   else
53 #endif
54   {
55     eval->diffuse = value;
56   }
57 #ifdef __SHADOW_TRICKS__
58   eval->sum_no_mis = make_float3(0.0f, 0.0f, 0.0f);
59 #endif
60 }
61 
bsdf_eval_accum(BsdfEval * eval,ClosureType type,float3 value,float mis_weight)62 ccl_device_inline void bsdf_eval_accum(BsdfEval *eval,
63                                        ClosureType type,
64                                        float3 value,
65                                        float mis_weight)
66 {
67 #ifdef __SHADOW_TRICKS__
68   eval->sum_no_mis += value;
69 #endif
70   value *= mis_weight;
71 #ifdef __PASSES__
72   if (eval->use_light_pass) {
73     if (CLOSURE_IS_BSDF_DIFFUSE(type) || CLOSURE_IS_BSDF_BSSRDF(type))
74       eval->diffuse += value;
75     else if (CLOSURE_IS_BSDF_GLOSSY(type))
76       eval->glossy += value;
77     else if (CLOSURE_IS_BSDF_TRANSMISSION(type))
78       eval->transmission += value;
79     else if (CLOSURE_IS_PHASE(type))
80       eval->volume += value;
81 
82     /* skipping transparent, this function is used by for eval(), will be zero then */
83   }
84   else
85 #endif
86   {
87     eval->diffuse += value;
88   }
89 }
90 
bsdf_eval_is_zero(BsdfEval * eval)91 ccl_device_inline bool bsdf_eval_is_zero(BsdfEval *eval)
92 {
93 #ifdef __PASSES__
94   if (eval->use_light_pass) {
95     return is_zero(eval->diffuse) && is_zero(eval->glossy) && is_zero(eval->transmission) &&
96            is_zero(eval->transparent) && is_zero(eval->volume);
97   }
98   else
99 #endif
100   {
101     return is_zero(eval->diffuse);
102   }
103 }
104 
bsdf_eval_mis(BsdfEval * eval,float value)105 ccl_device_inline void bsdf_eval_mis(BsdfEval *eval, float value)
106 {
107 #ifdef __PASSES__
108   if (eval->use_light_pass) {
109     eval->diffuse *= value;
110     eval->glossy *= value;
111     eval->transmission *= value;
112     eval->volume *= value;
113 
114     /* skipping transparent, this function is used by for eval(), will be zero then */
115   }
116   else
117 #endif
118   {
119     eval->diffuse *= value;
120   }
121 }
122 
bsdf_eval_mul(BsdfEval * eval,float value)123 ccl_device_inline void bsdf_eval_mul(BsdfEval *eval, float value)
124 {
125 #ifdef __SHADOW_TRICKS__
126   eval->sum_no_mis *= value;
127 #endif
128   bsdf_eval_mis(eval, value);
129 }
130 
bsdf_eval_mul3(BsdfEval * eval,float3 value)131 ccl_device_inline void bsdf_eval_mul3(BsdfEval *eval, float3 value)
132 {
133 #ifdef __SHADOW_TRICKS__
134   eval->sum_no_mis *= value;
135 #endif
136 #ifdef __PASSES__
137   if (eval->use_light_pass) {
138     eval->diffuse *= value;
139     eval->glossy *= value;
140     eval->transmission *= value;
141     eval->volume *= value;
142 
143     /* skipping transparent, this function is used by for eval(), will be zero then */
144   }
145   else
146     eval->diffuse *= value;
147 #else
148   eval->diffuse *= value;
149 #endif
150 }
151 
bsdf_eval_sum(const BsdfEval * eval)152 ccl_device_inline float3 bsdf_eval_sum(const BsdfEval *eval)
153 {
154 #ifdef __PASSES__
155   if (eval->use_light_pass) {
156     return eval->diffuse + eval->glossy + eval->transmission + eval->volume;
157   }
158   else
159 #endif
160     return eval->diffuse;
161 }
162 
163 /* Path Radiance
164  *
165  * We accumulate different render passes separately. After summing at the end
166  * to get the combined result, it should be identical. We definite directly
167  * visible as the first non-transparent hit, while indirectly visible are the
168  * bounces after that. */
169 
path_radiance_init(KernelGlobals * kg,PathRadiance * L)170 ccl_device_inline void path_radiance_init(KernelGlobals *kg, PathRadiance *L)
171 {
172   /* clear all */
173 #ifdef __PASSES__
174   L->use_light_pass = kernel_data.film.use_light_pass;
175 
176   if (kernel_data.film.use_light_pass) {
177     L->indirect = make_float3(0.0f, 0.0f, 0.0f);
178     L->direct_emission = make_float3(0.0f, 0.0f, 0.0f);
179 
180     L->color_diffuse = make_float3(0.0f, 0.0f, 0.0f);
181     L->color_glossy = make_float3(0.0f, 0.0f, 0.0f);
182     L->color_transmission = make_float3(0.0f, 0.0f, 0.0f);
183 
184     L->direct_diffuse = make_float3(0.0f, 0.0f, 0.0f);
185     L->direct_glossy = make_float3(0.0f, 0.0f, 0.0f);
186     L->direct_transmission = make_float3(0.0f, 0.0f, 0.0f);
187     L->direct_volume = make_float3(0.0f, 0.0f, 0.0f);
188 
189     L->indirect_diffuse = make_float3(0.0f, 0.0f, 0.0f);
190     L->indirect_glossy = make_float3(0.0f, 0.0f, 0.0f);
191     L->indirect_transmission = make_float3(0.0f, 0.0f, 0.0f);
192     L->indirect_volume = make_float3(0.0f, 0.0f, 0.0f);
193 
194     L->transparent = 0.0f;
195     L->emission = make_float3(0.0f, 0.0f, 0.0f);
196     L->background = make_float3(0.0f, 0.0f, 0.0f);
197     L->ao = make_float3(0.0f, 0.0f, 0.0f);
198     L->shadow = make_float3(0.0f, 0.0f, 0.0f);
199     L->mist = 0.0f;
200 
201     L->state.diffuse = make_float3(0.0f, 0.0f, 0.0f);
202     L->state.glossy = make_float3(0.0f, 0.0f, 0.0f);
203     L->state.transmission = make_float3(0.0f, 0.0f, 0.0f);
204     L->state.volume = make_float3(0.0f, 0.0f, 0.0f);
205     L->state.direct = make_float3(0.0f, 0.0f, 0.0f);
206   }
207   else
208 #endif
209   {
210     L->transparent = 0.0f;
211     L->emission = make_float3(0.0f, 0.0f, 0.0f);
212   }
213 
214 #ifdef __SHADOW_TRICKS__
215   L->path_total = make_float3(0.0f, 0.0f, 0.0f);
216   L->path_total_shaded = make_float3(0.0f, 0.0f, 0.0f);
217   L->shadow_background_color = make_float3(0.0f, 0.0f, 0.0f);
218   L->shadow_throughput = 0.0f;
219   L->shadow_transparency = 1.0f;
220   L->has_shadow_catcher = 0;
221 #endif
222 
223 #ifdef __DENOISING_FEATURES__
224   L->denoising_normal = make_float3(0.0f, 0.0f, 0.0f);
225   L->denoising_albedo = make_float3(0.0f, 0.0f, 0.0f);
226   L->denoising_depth = 0.0f;
227 #endif
228 
229 #ifdef __KERNEL_DEBUG__
230   L->debug_data.num_bvh_traversed_nodes = 0;
231   L->debug_data.num_bvh_traversed_instances = 0;
232   L->debug_data.num_bvh_intersections = 0;
233   L->debug_data.num_ray_bounces = 0;
234 #endif
235 }
236 
path_radiance_bsdf_bounce(KernelGlobals * kg,PathRadianceState * L_state,ccl_addr_space float3 * throughput,BsdfEval * bsdf_eval,float bsdf_pdf,int bounce,int bsdf_label)237 ccl_device_inline void path_radiance_bsdf_bounce(KernelGlobals *kg,
238                                                  PathRadianceState *L_state,
239                                                  ccl_addr_space float3 *throughput,
240                                                  BsdfEval *bsdf_eval,
241                                                  float bsdf_pdf,
242                                                  int bounce,
243                                                  int bsdf_label)
244 {
245   float inverse_pdf = 1.0f / bsdf_pdf;
246 
247 #ifdef __PASSES__
248   if (kernel_data.film.use_light_pass) {
249     if (bounce == 0 && !(bsdf_label & LABEL_TRANSPARENT)) {
250       /* first on directly visible surface */
251       float3 value = *throughput * inverse_pdf;
252 
253       L_state->diffuse = bsdf_eval->diffuse * value;
254       L_state->glossy = bsdf_eval->glossy * value;
255       L_state->transmission = bsdf_eval->transmission * value;
256       L_state->volume = bsdf_eval->volume * value;
257 
258       *throughput = L_state->diffuse + L_state->glossy + L_state->transmission + L_state->volume;
259 
260       L_state->direct = *throughput;
261     }
262     else {
263       /* transparent bounce before first hit, or indirectly visible through BSDF */
264       float3 sum = (bsdf_eval_sum(bsdf_eval) + bsdf_eval->transparent) * inverse_pdf;
265       *throughput *= sum;
266     }
267   }
268   else
269 #endif
270   {
271     *throughput *= bsdf_eval->diffuse * inverse_pdf;
272   }
273 }
274 
275 #ifdef __CLAMP_SAMPLE__
path_radiance_clamp(KernelGlobals * kg,float3 * L,int bounce)276 ccl_device_forceinline void path_radiance_clamp(KernelGlobals *kg, float3 *L, int bounce)
277 {
278   float limit = (bounce > 0) ? kernel_data.integrator.sample_clamp_indirect :
279                                kernel_data.integrator.sample_clamp_direct;
280   float sum = reduce_add(fabs(*L));
281   if (sum > limit) {
282     *L *= limit / sum;
283   }
284 }
285 
path_radiance_clamp_throughput(KernelGlobals * kg,float3 * L,float3 * throughput,int bounce)286 ccl_device_forceinline void path_radiance_clamp_throughput(KernelGlobals *kg,
287                                                            float3 *L,
288                                                            float3 *throughput,
289                                                            int bounce)
290 {
291   float limit = (bounce > 0) ? kernel_data.integrator.sample_clamp_indirect :
292                                kernel_data.integrator.sample_clamp_direct;
293 
294   float sum = reduce_add(fabs(*L));
295   if (sum > limit) {
296     float clamp_factor = limit / sum;
297     *L *= clamp_factor;
298     *throughput *= clamp_factor;
299   }
300 }
301 
302 #endif
303 
path_radiance_accum_emission(KernelGlobals * kg,PathRadiance * L,ccl_addr_space PathState * state,float3 throughput,float3 value)304 ccl_device_inline void path_radiance_accum_emission(KernelGlobals *kg,
305                                                     PathRadiance *L,
306                                                     ccl_addr_space PathState *state,
307                                                     float3 throughput,
308                                                     float3 value)
309 {
310 #ifdef __SHADOW_TRICKS__
311   if (state->flag & PATH_RAY_SHADOW_CATCHER) {
312     return;
313   }
314 #endif
315 
316   float3 contribution = throughput * value;
317 #ifdef __CLAMP_SAMPLE__
318   path_radiance_clamp(kg, &contribution, state->bounce - 1);
319 #endif
320 
321 #ifdef __PASSES__
322   if (L->use_light_pass) {
323     if (state->bounce == 0)
324       L->emission += contribution;
325     else if (state->bounce == 1)
326       L->direct_emission += contribution;
327     else
328       L->indirect += contribution;
329   }
330   else
331 #endif
332   {
333     L->emission += contribution;
334   }
335 }
336 
path_radiance_accum_ao(KernelGlobals * kg,PathRadiance * L,ccl_addr_space PathState * state,float3 throughput,float3 alpha,float3 bsdf,float3 ao)337 ccl_device_inline void path_radiance_accum_ao(KernelGlobals *kg,
338                                               PathRadiance *L,
339                                               ccl_addr_space PathState *state,
340                                               float3 throughput,
341                                               float3 alpha,
342                                               float3 bsdf,
343                                               float3 ao)
344 {
345 #ifdef __PASSES__
346   /* Store AO pass. */
347   if (L->use_light_pass && state->bounce == 0) {
348     L->ao += alpha * throughput * ao;
349   }
350 #endif
351 
352 #ifdef __SHADOW_TRICKS__
353   /* For shadow catcher, accumulate ratio. */
354   if (state->flag & PATH_RAY_STORE_SHADOW_INFO) {
355     float3 light = throughput * bsdf;
356     L->path_total += light;
357     L->path_total_shaded += ao * light;
358 
359     if (state->flag & PATH_RAY_SHADOW_CATCHER) {
360       return;
361     }
362   }
363 #endif
364 
365   float3 contribution = throughput * bsdf * ao;
366 
367 #ifdef __PASSES__
368   if (L->use_light_pass) {
369     if (state->bounce == 0) {
370       /* Directly visible lighting. */
371       L->direct_diffuse += contribution;
372     }
373     else {
374       /* Indirectly visible lighting after BSDF bounce. */
375       L->indirect += contribution;
376     }
377   }
378   else
379 #endif
380   {
381     L->emission += contribution;
382   }
383 }
384 
path_radiance_accum_total_ao(PathRadiance * L,ccl_addr_space PathState * state,float3 throughput,float3 bsdf)385 ccl_device_inline void path_radiance_accum_total_ao(PathRadiance *L,
386                                                     ccl_addr_space PathState *state,
387                                                     float3 throughput,
388                                                     float3 bsdf)
389 {
390 #ifdef __SHADOW_TRICKS__
391   if (state->flag & PATH_RAY_STORE_SHADOW_INFO) {
392     L->path_total += throughput * bsdf;
393   }
394 #else
395   (void)L;
396   (void)state;
397   (void)throughput;
398   (void)bsdf;
399 #endif
400 }
401 
path_radiance_accum_light(KernelGlobals * kg,PathRadiance * L,ccl_addr_space PathState * state,float3 throughput,BsdfEval * bsdf_eval,float3 shadow,float shadow_fac,bool is_lamp)402 ccl_device_inline void path_radiance_accum_light(KernelGlobals *kg,
403                                                  PathRadiance *L,
404                                                  ccl_addr_space PathState *state,
405                                                  float3 throughput,
406                                                  BsdfEval *bsdf_eval,
407                                                  float3 shadow,
408                                                  float shadow_fac,
409                                                  bool is_lamp)
410 {
411 #ifdef __SHADOW_TRICKS__
412   if (state->flag & PATH_RAY_STORE_SHADOW_INFO) {
413     float3 light = throughput * bsdf_eval->sum_no_mis;
414     L->path_total += light;
415     L->path_total_shaded += shadow * light;
416 
417     if (state->flag & PATH_RAY_SHADOW_CATCHER) {
418       return;
419     }
420   }
421 #endif
422 
423   float3 shaded_throughput = throughput * shadow;
424 
425 #ifdef __PASSES__
426   if (L->use_light_pass) {
427     /* Compute the clamping based on the total contribution.
428      * The resulting scale is then be applied to all individual components. */
429     float3 full_contribution = shaded_throughput * bsdf_eval_sum(bsdf_eval);
430 #  ifdef __CLAMP_SAMPLE__
431     path_radiance_clamp_throughput(kg, &full_contribution, &shaded_throughput, state->bounce);
432 #  endif
433 
434     if (state->bounce == 0) {
435       /* directly visible lighting */
436       L->direct_diffuse += shaded_throughput * bsdf_eval->diffuse;
437       L->direct_glossy += shaded_throughput * bsdf_eval->glossy;
438       L->direct_transmission += shaded_throughput * bsdf_eval->transmission;
439       L->direct_volume += shaded_throughput * bsdf_eval->volume;
440 
441       if (is_lamp) {
442         L->shadow += shadow * shadow_fac;
443       }
444     }
445     else {
446       /* indirectly visible lighting after BSDF bounce */
447       L->indirect += full_contribution;
448     }
449   }
450   else
451 #endif
452   {
453     float3 contribution = shaded_throughput * bsdf_eval->diffuse;
454     path_radiance_clamp(kg, &contribution, state->bounce);
455     L->emission += contribution;
456   }
457 }
458 
path_radiance_accum_total_light(PathRadiance * L,ccl_addr_space PathState * state,float3 throughput,const BsdfEval * bsdf_eval)459 ccl_device_inline void path_radiance_accum_total_light(PathRadiance *L,
460                                                        ccl_addr_space PathState *state,
461                                                        float3 throughput,
462                                                        const BsdfEval *bsdf_eval)
463 {
464 #ifdef __SHADOW_TRICKS__
465   if (state->flag & PATH_RAY_STORE_SHADOW_INFO) {
466     L->path_total += throughput * bsdf_eval->sum_no_mis;
467   }
468 #else
469   (void)L;
470   (void)state;
471   (void)throughput;
472   (void)bsdf_eval;
473 #endif
474 }
475 
path_radiance_accum_background(KernelGlobals * kg,PathRadiance * L,ccl_addr_space PathState * state,float3 throughput,float3 value)476 ccl_device_inline void path_radiance_accum_background(KernelGlobals *kg,
477                                                       PathRadiance *L,
478                                                       ccl_addr_space PathState *state,
479                                                       float3 throughput,
480                                                       float3 value)
481 {
482 
483 #ifdef __SHADOW_TRICKS__
484   if (state->flag & PATH_RAY_STORE_SHADOW_INFO) {
485     L->path_total += throughput * value;
486     L->path_total_shaded += throughput * value * L->shadow_transparency;
487 
488     if (state->flag & PATH_RAY_SHADOW_CATCHER) {
489       return;
490     }
491   }
492 #endif
493 
494   float3 contribution = throughput * value;
495 #ifdef __CLAMP_SAMPLE__
496   path_radiance_clamp(kg, &contribution, state->bounce - 1);
497 #endif
498 
499 #ifdef __PASSES__
500   if (L->use_light_pass) {
501     if (state->flag & PATH_RAY_TRANSPARENT_BACKGROUND)
502       L->background += contribution;
503     else if (state->bounce == 1)
504       L->direct_emission += contribution;
505     else
506       L->indirect += contribution;
507   }
508   else
509 #endif
510   {
511     L->emission += contribution;
512   }
513 
514 #ifdef __DENOISING_FEATURES__
515   L->denoising_albedo += state->denoising_feature_weight * state->denoising_feature_throughput *
516                          value;
517 #endif /* __DENOISING_FEATURES__ */
518 }
519 
path_radiance_accum_transparent(PathRadiance * L,ccl_addr_space PathState * state,float3 throughput)520 ccl_device_inline void path_radiance_accum_transparent(PathRadiance *L,
521                                                        ccl_addr_space PathState *state,
522                                                        float3 throughput)
523 {
524   L->transparent += average(throughput);
525 }
526 
527 #ifdef __SHADOW_TRICKS__
path_radiance_accum_shadowcatcher(PathRadiance * L,float3 throughput,float3 background)528 ccl_device_inline void path_radiance_accum_shadowcatcher(PathRadiance *L,
529                                                          float3 throughput,
530                                                          float3 background)
531 {
532   L->shadow_throughput += average(throughput);
533   L->shadow_background_color += throughput * background;
534   L->has_shadow_catcher = 1;
535 }
536 #endif
537 
path_radiance_sum_indirect(PathRadiance * L)538 ccl_device_inline void path_radiance_sum_indirect(PathRadiance *L)
539 {
540 #ifdef __PASSES__
541   /* this division is a bit ugly, but means we only have to keep track of
542    * only a single throughput further along the path, here we recover just
543    * the indirect path that is not influenced by any particular BSDF type */
544   if (L->use_light_pass) {
545     L->direct_emission = safe_divide_color(L->direct_emission, L->state.direct);
546     L->direct_diffuse += L->state.diffuse * L->direct_emission;
547     L->direct_glossy += L->state.glossy * L->direct_emission;
548     L->direct_transmission += L->state.transmission * L->direct_emission;
549     L->direct_volume += L->state.volume * L->direct_emission;
550 
551     L->indirect = safe_divide_color(L->indirect, L->state.direct);
552     L->indirect_diffuse += L->state.diffuse * L->indirect;
553     L->indirect_glossy += L->state.glossy * L->indirect;
554     L->indirect_transmission += L->state.transmission * L->indirect;
555     L->indirect_volume += L->state.volume * L->indirect;
556   }
557 #endif
558 }
559 
path_radiance_reset_indirect(PathRadiance * L)560 ccl_device_inline void path_radiance_reset_indirect(PathRadiance *L)
561 {
562 #ifdef __PASSES__
563   if (L->use_light_pass) {
564     L->state.diffuse = make_float3(0.0f, 0.0f, 0.0f);
565     L->state.glossy = make_float3(0.0f, 0.0f, 0.0f);
566     L->state.transmission = make_float3(0.0f, 0.0f, 0.0f);
567     L->state.volume = make_float3(0.0f, 0.0f, 0.0f);
568 
569     L->direct_emission = make_float3(0.0f, 0.0f, 0.0f);
570     L->indirect = make_float3(0.0f, 0.0f, 0.0f);
571   }
572 #endif
573 }
574 
path_radiance_copy_indirect(PathRadiance * L,const PathRadiance * L_src)575 ccl_device_inline void path_radiance_copy_indirect(PathRadiance *L, const PathRadiance *L_src)
576 {
577 #ifdef __PASSES__
578   if (L->use_light_pass) {
579     L->state = L_src->state;
580 
581     L->direct_emission = L_src->direct_emission;
582     L->indirect = L_src->indirect;
583   }
584 #endif
585 }
586 
587 #ifdef __SHADOW_TRICKS__
path_radiance_sum_shadowcatcher(KernelGlobals * kg,PathRadiance * L,float3 * L_sum,float * alpha)588 ccl_device_inline void path_radiance_sum_shadowcatcher(KernelGlobals *kg,
589                                                        PathRadiance *L,
590                                                        float3 *L_sum,
591                                                        float *alpha)
592 {
593   /* Calculate current shadow of the path. */
594   float path_total = average(L->path_total);
595   float shadow;
596 
597   if (UNLIKELY(!isfinite_safe(path_total))) {
598     kernel_assert(!"Non-finite total radiance along the path");
599     shadow = 0.0f;
600   }
601   else if (path_total == 0.0f) {
602     shadow = L->shadow_transparency;
603   }
604   else {
605     float path_total_shaded = average(L->path_total_shaded);
606     shadow = path_total_shaded / path_total;
607   }
608 
609   /* Calculate final light sum and transparency for shadow catcher object. */
610   if (kernel_data.background.transparent) {
611     *alpha -= L->shadow_throughput * shadow;
612   }
613   else {
614     L->shadow_background_color *= shadow;
615     *L_sum += L->shadow_background_color;
616   }
617 }
618 #endif
619 
path_radiance_clamp_and_sum(KernelGlobals * kg,PathRadiance * L,float * alpha)620 ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg,
621                                                      PathRadiance *L,
622                                                      float *alpha)
623 {
624   float3 L_sum;
625   /* Light Passes are used */
626 #ifdef __PASSES__
627   float3 L_direct, L_indirect;
628   if (L->use_light_pass) {
629     path_radiance_sum_indirect(L);
630 
631     L_direct = L->direct_diffuse + L->direct_glossy + L->direct_transmission + L->direct_volume +
632                L->emission;
633     L_indirect = L->indirect_diffuse + L->indirect_glossy + L->indirect_transmission +
634                  L->indirect_volume;
635 
636     if (!kernel_data.background.transparent)
637       L_direct += L->background;
638 
639     L_sum = L_direct + L_indirect;
640     float sum = fabsf((L_sum).x) + fabsf((L_sum).y) + fabsf((L_sum).z);
641 
642     /* Reject invalid value */
643     if (!isfinite_safe(sum)) {
644       kernel_assert(!"Non-finite sum in path_radiance_clamp_and_sum!");
645       L_sum = make_float3(0.0f, 0.0f, 0.0f);
646 
647       L->direct_diffuse = make_float3(0.0f, 0.0f, 0.0f);
648       L->direct_glossy = make_float3(0.0f, 0.0f, 0.0f);
649       L->direct_transmission = make_float3(0.0f, 0.0f, 0.0f);
650       L->direct_volume = make_float3(0.0f, 0.0f, 0.0f);
651 
652       L->indirect_diffuse = make_float3(0.0f, 0.0f, 0.0f);
653       L->indirect_glossy = make_float3(0.0f, 0.0f, 0.0f);
654       L->indirect_transmission = make_float3(0.0f, 0.0f, 0.0f);
655       L->indirect_volume = make_float3(0.0f, 0.0f, 0.0f);
656 
657       L->emission = make_float3(0.0f, 0.0f, 0.0f);
658     }
659   }
660 
661   /* No Light Passes */
662   else
663 #endif
664   {
665     L_sum = L->emission;
666 
667     /* Reject invalid value */
668     float sum = fabsf((L_sum).x) + fabsf((L_sum).y) + fabsf((L_sum).z);
669     if (!isfinite_safe(sum)) {
670       kernel_assert(!"Non-finite final sum in path_radiance_clamp_and_sum!");
671       L_sum = make_float3(0.0f, 0.0f, 0.0f);
672     }
673   }
674 
675   /* Compute alpha. */
676   *alpha = 1.0f - L->transparent;
677 
678   /* Add shadow catcher contributions. */
679 #ifdef __SHADOW_TRICKS__
680   if (L->has_shadow_catcher) {
681     path_radiance_sum_shadowcatcher(kg, L, &L_sum, alpha);
682   }
683 #endif /* __SHADOW_TRICKS__ */
684 
685   return L_sum;
686 }
687 
path_radiance_split_denoising(KernelGlobals * kg,PathRadiance * L,float3 * noisy,float3 * clean)688 ccl_device_inline void path_radiance_split_denoising(KernelGlobals *kg,
689                                                      PathRadiance *L,
690                                                      float3 *noisy,
691                                                      float3 *clean)
692 {
693 #ifdef __PASSES__
694   kernel_assert(L->use_light_pass);
695 
696   *clean = L->emission + L->background;
697   *noisy = L->direct_volume + L->indirect_volume;
698 
699 #  define ADD_COMPONENT(flag, component) \
700     if (kernel_data.film.denoising_flags & flag) \
701       *clean += component; \
702     else \
703       *noisy += component;
704 
705   ADD_COMPONENT(DENOISING_CLEAN_DIFFUSE_DIR, L->direct_diffuse);
706   ADD_COMPONENT(DENOISING_CLEAN_DIFFUSE_IND, L->indirect_diffuse);
707   ADD_COMPONENT(DENOISING_CLEAN_GLOSSY_DIR, L->direct_glossy);
708   ADD_COMPONENT(DENOISING_CLEAN_GLOSSY_IND, L->indirect_glossy);
709   ADD_COMPONENT(DENOISING_CLEAN_TRANSMISSION_DIR, L->direct_transmission);
710   ADD_COMPONENT(DENOISING_CLEAN_TRANSMISSION_IND, L->indirect_transmission);
711 #  undef ADD_COMPONENT
712 #else
713   *noisy = L->emission;
714   *clean = make_float3(0.0f, 0.0f, 0.0f);
715 #endif
716 
717 #ifdef __SHADOW_TRICKS__
718   if (L->has_shadow_catcher) {
719     *noisy += L->shadow_background_color;
720   }
721 #endif
722 
723   *noisy = ensure_finite3(*noisy);
724   *clean = ensure_finite3(*clean);
725 }
726 
path_radiance_accum_sample(PathRadiance * L,PathRadiance * L_sample)727 ccl_device_inline void path_radiance_accum_sample(PathRadiance *L, PathRadiance *L_sample)
728 {
729 #ifdef __SPLIT_KERNEL__
730 #  define safe_float3_add(f, v) \
731     do { \
732       ccl_global float *p = (ccl_global float *)(&(f)); \
733       atomic_add_and_fetch_float(p + 0, (v).x); \
734       atomic_add_and_fetch_float(p + 1, (v).y); \
735       atomic_add_and_fetch_float(p + 2, (v).z); \
736     } while (0)
737 #  define safe_float_add(f, v) atomic_add_and_fetch_float(&(f), (v))
738 #else
739 #  define safe_float3_add(f, v) (f) += (v)
740 #  define safe_float_add(f, v) (f) += (v)
741 #endif /* __SPLIT_KERNEL__ */
742 
743 #ifdef __PASSES__
744   safe_float3_add(L->direct_diffuse, L_sample->direct_diffuse);
745   safe_float3_add(L->direct_glossy, L_sample->direct_glossy);
746   safe_float3_add(L->direct_transmission, L_sample->direct_transmission);
747   safe_float3_add(L->direct_volume, L_sample->direct_volume);
748 
749   safe_float3_add(L->indirect_diffuse, L_sample->indirect_diffuse);
750   safe_float3_add(L->indirect_glossy, L_sample->indirect_glossy);
751   safe_float3_add(L->indirect_transmission, L_sample->indirect_transmission);
752   safe_float3_add(L->indirect_volume, L_sample->indirect_volume);
753 
754   safe_float3_add(L->background, L_sample->background);
755   safe_float3_add(L->ao, L_sample->ao);
756   safe_float3_add(L->shadow, L_sample->shadow);
757   safe_float_add(L->mist, L_sample->mist);
758 #endif /* __PASSES__ */
759   safe_float3_add(L->emission, L_sample->emission);
760 
761 #undef safe_float_add
762 #undef safe_float3_add
763 }
764 
765 CCL_NAMESPACE_END
766