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