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.
This commit is contained in:
parent
095a01a73a
commit
90d4b823d7
Notes:
blender-bot
2023-02-14 06:00:46 +01:00
Referenced by issue #62692, Cycles transparency shader
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue