diff options
Diffstat (limited to 'intern/cycles/kernel/kernel_accumulate.h')
-rw-r--r-- | intern/cycles/kernel/kernel_accumulate.h | 146 |
1 files changed, 81 insertions, 65 deletions
diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h index 46a51f5a560..606c288649a 100644 --- a/intern/cycles/kernel/kernel_accumulate.h +++ b/intern/cycles/kernel/kernel_accumulate.h @@ -174,13 +174,13 @@ ccl_device_inline float3 bsdf_eval_sum(const BsdfEval *eval) * visible as the first non-transparent hit, while indirectly visible are the * bounces after that. */ -ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass) +ccl_device_inline void path_radiance_init(KernelGlobals *kg, PathRadiance *L) { /* clear all */ #ifdef __PASSES__ - L->use_light_pass = use_light_pass; + L->use_light_pass = kernel_data.film.use_light_pass; - if (use_light_pass) { + if (kernel_data.film.use_light_pass) { L->indirect = make_float3(0.0f, 0.0f, 0.0f); L->direct_emission = make_float3(0.0f, 0.0f, 0.0f); @@ -285,7 +285,37 @@ ccl_device_inline void path_radiance_bsdf_bounce(KernelGlobals *kg, } } -ccl_device_inline void path_radiance_accum_emission(PathRadiance *L, +#ifdef __CLAMP_SAMPLE__ +ccl_device_forceinline void path_radiance_clamp(KernelGlobals *kg, float3 *L, int bounce) +{ + float limit = (bounce > 0) ? kernel_data.integrator.sample_clamp_indirect : + kernel_data.integrator.sample_clamp_direct; + float sum = reduce_add(fabs(*L)); + if (sum > limit) { + *L *= limit / sum; + } +} + +ccl_device_forceinline void path_radiance_clamp_throughput(KernelGlobals *kg, + float3 *L, + float3 *throughput, + int bounce) +{ + float limit = (bounce > 0) ? kernel_data.integrator.sample_clamp_indirect : + kernel_data.integrator.sample_clamp_direct; + + float sum = reduce_add(fabs(*L)); + if (sum > limit) { + float clamp_factor = limit / sum; + *L *= clamp_factor; + *throughput *= clamp_factor; + } +} + +#endif + +ccl_device_inline void path_radiance_accum_emission(KernelGlobals *kg, + PathRadiance *L, ccl_addr_space PathState *state, float3 throughput, float3 value) @@ -296,23 +326,29 @@ ccl_device_inline void path_radiance_accum_emission(PathRadiance *L, } #endif + float3 contribution = throughput * value; +#ifdef __CLAMP_SAMPLE__ + path_radiance_clamp(kg, &contribution, state->bounce - 1); +#endif + #ifdef __PASSES__ if (L->use_light_pass) { if (state->bounce == 0) - L->emission += throughput * value; + L->emission += contribution; else if (state->bounce == 1) - L->direct_emission += throughput * value; + L->direct_emission += contribution; else - L->indirect += throughput * value; + L->indirect += contribution; } else #endif { - L->emission += throughput * value; + L->emission += contribution; } } -ccl_device_inline void path_radiance_accum_ao(PathRadiance *L, +ccl_device_inline void path_radiance_accum_ao(KernelGlobals *kg, + PathRadiance *L, ccl_addr_space PathState *state, float3 throughput, float3 alpha, @@ -339,21 +375,23 @@ ccl_device_inline void path_radiance_accum_ao(PathRadiance *L, } #endif + float3 contribution = throughput * bsdf * ao; + #ifdef __PASSES__ if (L->use_light_pass) { if (state->bounce == 0) { /* Directly visible lighting. */ - L->direct_diffuse += throughput * bsdf * ao; + L->direct_diffuse += contribution; } else { /* Indirectly visible lighting after BSDF bounce. */ - L->indirect += throughput * bsdf * ao; + L->indirect += contribution; } } else #endif { - L->emission += throughput * bsdf * ao; + L->emission += contribution; } } @@ -374,7 +412,8 @@ ccl_device_inline void path_radiance_accum_total_ao(PathRadiance *L, #endif } -ccl_device_inline void path_radiance_accum_light(PathRadiance *L, +ccl_device_inline void path_radiance_accum_light(KernelGlobals *kg, + PathRadiance *L, ccl_addr_space PathState *state, float3 throughput, BsdfEval *bsdf_eval, @@ -394,15 +433,24 @@ ccl_device_inline void path_radiance_accum_light(PathRadiance *L, } #endif + float3 shaded_throughput = throughput * shadow; + #ifdef __PASSES__ if (L->use_light_pass) { + /* Compute the clamping based on the total contribution. + * The resulting scale is then be applied to all individual components. */ + float3 full_contribution = shaded_throughput * bsdf_eval_sum(bsdf_eval); +# ifdef __CLAMP_SAMPLE__ + path_radiance_clamp_throughput(kg, &full_contribution, &shaded_throughput, state->bounce); +# endif + if (state->bounce == 0) { /* directly visible lighting */ - L->direct_diffuse += throughput * bsdf_eval->diffuse * shadow; - L->direct_glossy += throughput * bsdf_eval->glossy * shadow; - L->direct_transmission += throughput * bsdf_eval->transmission * shadow; - L->direct_subsurface += throughput * bsdf_eval->subsurface * shadow; - L->direct_scatter += throughput * bsdf_eval->scatter * shadow; + L->direct_diffuse += shaded_throughput * bsdf_eval->diffuse; + L->direct_glossy += shaded_throughput * bsdf_eval->glossy; + L->direct_transmission += shaded_throughput * bsdf_eval->transmission; + L->direct_subsurface += shaded_throughput * bsdf_eval->subsurface; + L->direct_scatter += shaded_throughput * bsdf_eval->scatter; if (is_lamp) { L->shadow.x += shadow.x * shadow_fac; @@ -412,13 +460,15 @@ ccl_device_inline void path_radiance_accum_light(PathRadiance *L, } else { /* indirectly visible lighting after BSDF bounce */ - L->indirect += throughput * bsdf_eval_sum(bsdf_eval) * shadow; + L->indirect += full_contribution; } } else #endif { - L->emission += throughput * bsdf_eval->diffuse * shadow; + float3 contribution = shaded_throughput * bsdf_eval->diffuse; + path_radiance_clamp(kg, &contribution, state->bounce); + L->emission += contribution; } } @@ -439,7 +489,8 @@ ccl_device_inline void path_radiance_accum_total_light(PathRadiance *L, #endif } -ccl_device_inline void path_radiance_accum_background(PathRadiance *L, +ccl_device_inline void path_radiance_accum_background(KernelGlobals *kg, + PathRadiance *L, ccl_addr_space PathState *state, float3 throughput, float3 value) @@ -456,19 +507,24 @@ ccl_device_inline void path_radiance_accum_background(PathRadiance *L, } #endif + float3 contribution = throughput * value; +#ifdef __CLAMP_SAMPLE__ + path_radiance_clamp(kg, &contribution, state->bounce - 1); +#endif + #ifdef __PASSES__ if (L->use_light_pass) { if (state->flag & PATH_RAY_TRANSPARENT_BACKGROUND) - L->background += throughput * value; + L->background += contribution; else if (state->bounce == 1) - L->direct_emission += throughput * value; + L->direct_emission += contribution; else - L->indirect += throughput * value; + L->indirect += contribution; } else #endif { - L->emission += throughput * value; + L->emission += contribution; } #ifdef __DENOISING_FEATURES__ @@ -587,8 +643,6 @@ ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, /* Light Passes are used */ #ifdef __PASSES__ float3 L_direct, L_indirect; - float clamp_direct = kernel_data.integrator.sample_clamp_direct; - float clamp_indirect = kernel_data.integrator.sample_clamp_indirect; if (L->use_light_pass) { path_radiance_sum_indirect(L); @@ -622,44 +676,6 @@ ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, L->emission = make_float3(0.0f, 0.0f, 0.0f); } - - /* Clamp direct and indirect samples */ -# ifdef __CLAMP_SAMPLE__ - else if (sum > clamp_direct || sum > clamp_indirect) { - float scale; - - /* Direct */ - float sum_direct = fabsf(L_direct.x) + fabsf(L_direct.y) + fabsf(L_direct.z); - if (sum_direct > clamp_direct) { - scale = clamp_direct / sum_direct; - L_direct *= scale; - - L->direct_diffuse *= scale; - L->direct_glossy *= scale; - L->direct_transmission *= scale; - L->direct_subsurface *= scale; - L->direct_scatter *= scale; - L->emission *= scale; - L->background *= scale; - } - - /* Indirect */ - float sum_indirect = fabsf(L_indirect.x) + fabsf(L_indirect.y) + fabsf(L_indirect.z); - if (sum_indirect > clamp_indirect) { - scale = clamp_indirect / sum_indirect; - L_indirect *= scale; - - L->indirect_diffuse *= scale; - L->indirect_glossy *= scale; - L->indirect_transmission *= scale; - L->indirect_subsurface *= scale; - L->indirect_scatter *= scale; - } - - /* Sum again, after clamping */ - L_sum = L_direct + L_indirect; - } -# endif } /* No Light Passes */ |