From 90d4b823d72922922bb3d0af48ec2f592d210cdd Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 13 Sep 2017 18:28:31 +0200 Subject: Cycles: use defensive sampling for picking BSDFs and BSSRDFs. For the first bounce we now give each BSDF or BSSRDF a minimum sample weight, which helps reduce noise for a typical case where you have a glossy BSDF with a small weight due to Fresnel, but not necessarily small contribution relative to a diffuse or transmission BSDF below. We can probably find a better heuristic that also enables this on further bounces, for example when looking through a perfect mirror, but I wasn't able to find a robust one so far. --- intern/cycles/kernel/kernel_path.h | 5 ++--- intern/cycles/kernel/kernel_shader.h | 28 +++++++++++++++++++++++++ intern/cycles/kernel/split/kernel_shader_eval.h | 10 +++++++-- 3 files changed, 38 insertions(+), 5 deletions(-) (limited to 'intern/cycles/kernel') diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 2df21f1cda3..d43d6374c13 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -435,9 +435,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, &isect, ray); shader_eval_surface(kg, sd, state, state->flag); -#ifdef __BRANCHED_PATH__ - shader_merge_closures(sd); -#endif /* __BRANCHED_PATH__ */ + shader_prepare_closures(sd, state); /* Apply shadow catcher, holdout, emission. */ if(!kernel_path_shader_apply(kg, @@ -588,6 +586,7 @@ ccl_device_forceinline void kernel_path_integrate( /* Setup and evaluate shader. */ shader_setup_from_ray(kg, &sd, &isect, ray); shader_eval_surface(kg, &sd, state, state->flag); + shader_prepare_closures(&sd, state); /* Apply shadow catcher, holdout, emission. */ if(!kernel_path_shader_apply(kg, diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 5ef4475e259..bb3add5d7ca 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -494,6 +494,34 @@ ccl_device_inline void shader_merge_closures(ShaderData *sd) } #endif +/* Defensive sampling. */ + +ccl_device_inline void shader_prepare_closures(ShaderData *sd, + ccl_addr_space PathState *state) +{ + /* We can likely also do defensive sampling at deeper bounces, particularly + * for cases like a perfect mirror but possibly also others. This will need + * a good heuristic. */ + if(state->bounce + state->transparent_bounce == 0 && sd->num_closure > 1) { + float sum = 0.0f; + + for(int i = 0; i < sd->num_closure; i++) { + ShaderClosure *sc = &sd->closure[i]; + if(CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) { + sum += sc->sample_weight; + } + } + + for(int i = 0; i < sd->num_closure; i++) { + ShaderClosure *sc = &sd->closure[i]; + if(CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) { + sc->sample_weight = max(sc->sample_weight, 0.125f * sum); + } + } + } +} + + /* BSDF */ ccl_device_inline void _shader_bsdf_multi_eval(KernelGlobals *kg, ShaderData *sd, const float3 omega_in, float *pdf, diff --git a/intern/cycles/kernel/split/kernel_shader_eval.h b/intern/cycles/kernel/split/kernel_shader_eval.h index c792c4adb0e..7032461b04a 100644 --- a/intern/cycles/kernel/split/kernel_shader_eval.h +++ b/intern/cycles/kernel/split/kernel_shader_eval.h @@ -52,8 +52,14 @@ ccl_device void kernel_shader_eval(KernelGlobals *kg) shader_eval_surface(kg, &kernel_split_state.sd[ray_index], state, state->flag); #ifdef __BRANCHED_PATH__ - shader_merge_closures(&kernel_split_state.sd[ray_index]); -#endif /* __BRANCHED_PATH__ */ + if(kernel_data.integrator.branched) { + shader_merge_closures(&kernel_split_state.sd[ray_index]); + } + else +#endif + { + shader_prepare_closures(&kernel_split_state.sd[ray_index], state); + } } } -- cgit v1.2.3