Fix: Cycles: Non-physical layering weights can lead to negative closures

This commit is contained in:
Lukas Stockner 2023-10-19 13:12:43 +02:00
parent 52e6106d28
commit c71e18054c
3 changed files with 13 additions and 4 deletions

@ -223,4 +223,13 @@ ccl_device_inline Spectrum bsdf_principled_hair_sigma_from_concentration(const f
pheomelanin * rgb_to_spectrum(pheomelanin_color);
}
/* Computes the weight for base closure(s) which are layered under another closure.
* layer_albedo is an estimate of the top layer's reflectivity, while weight is the closure weight
* of the entire base+top combination. */
ccl_device_inline Spectrum closure_layering_weight(const Spectrum layer_albedo,
const Spectrum weight)
{
return weight * saturatef(1.0f - reduce_max(safe_divide_color(layer_albedo, weight)));
}
CCL_NAMESPACE_END

@ -151,7 +151,7 @@ ccl_device void flatten_closure_tree(KernelGlobals kg,
if (stack_size == layer_stack_level) {
/* We just finished processing the top layers of a Layer closure, so adjust the weight to
* account for the layering. */
weight *= saturatef(1.0f - reduce_max(safe_divide_color(layer_albedo, weight)));
weight = closure_layering_weight(layer_albedo, weight);
layer_stack_level = -1;
/* If it's fully occluded, skip the base layer we just popped from the stack and grab
* the next entry instead. */

@ -204,7 +204,7 @@ ccl_device
/* Attenuate lower layers */
Spectrum albedo = bsdf_albedo(kg, sd, (ccl_private ShaderClosure *)bsdf, true, false);
weight *= 1.0f - reduce_max(safe_divide_color(albedo, weight));
weight = closure_layering_weight(albedo, weight);
}
}
}
@ -229,7 +229,7 @@ ccl_device
/* Attenuate lower layers */
Spectrum albedo = bsdf_albedo(kg, sd, (ccl_private ShaderClosure *)bsdf, true, false);
weight *= 1.0f - reduce_max(safe_divide_color(albedo, weight));
weight = closure_layering_weight(albedo, weight);
}
}
@ -367,7 +367,7 @@ ccl_device
/* Attenuate lower layers */
Spectrum albedo = bsdf_albedo(kg, sd, (ccl_private ShaderClosure *)bsdf, true, false);
weight *= 1.0f - reduce_max(safe_divide_color(albedo, weight));
weight = closure_layering_weight(albedo, weight);
}
}