Cycles: support shader transparency for holdout objects

Now transparent areas of the object will render objects behind.

Fixes T78728.
This commit is contained in:
Brecht Van Lommel 2020-07-08 12:57:59 +02:00
parent 643196cc37
commit 6435acd8f6
Notes: blender-bot 2023-02-14 09:19:09 +01:00
Referenced by issue #101978, cycles, set collection to Holdout does not work with transparent shader
Referenced by issue #88185, Alpha textures do not work with holdout collection in Eevee
Referenced by issue #81875, Cycles: mesh becomes weirdly transparent after some samples CPU only
Referenced by issue #78728, [Cycles] Render Layer only shadow and alpha problem
2 changed files with 28 additions and 15 deletions

View File

@ -284,19 +284,11 @@ ccl_device_forceinline bool kernel_path_shader_apply(KernelGlobals *kg,
#ifdef __HOLDOUT__
if (((sd->flag & SD_HOLDOUT) || (sd->object_flag & SD_OBJECT_HOLDOUT_MASK)) &&
(state->flag & PATH_RAY_TRANSPARENT_BACKGROUND)) {
const float3 holdout_weight = shader_holdout_apply(kg, sd);
if (kernel_data.background.transparent) {
float3 holdout_weight;
if (sd->object_flag & SD_OBJECT_HOLDOUT_MASK) {
holdout_weight = make_float3(1.0f, 1.0f, 1.0f);
}
else {
holdout_weight = shader_holdout_eval(kg, sd);
}
/* any throughput is ok, should all be identical here */
L->transparent += average(holdout_weight * throughput);
}
if (sd->object_flag & SD_OBJECT_HOLDOUT_MASK) {
if (holdout_weight == make_float3(1.0f, 1.0f, 1.0f)) {
return false;
}
}

View File

@ -1017,15 +1017,36 @@ ccl_device float3 shader_emissive_eval(ShaderData *sd)
/* Holdout */
ccl_device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd)
ccl_device float3 shader_holdout_apply(KernelGlobals *kg, ShaderData *sd)
{
float3 weight = make_float3(0.0f, 0.0f, 0.0f);
for (int i = 0; i < sd->num_closure; i++) {
ShaderClosure *sc = &sd->closure[i];
/* For objects marked as holdout, preserve transparency and remove all other
* closures, replacing them with a holdout weight. */
if (sd->object_flag & SD_OBJECT_HOLDOUT_MASK) {
if ((sd->flag & SD_TRANSPARENT) && !(sd->flag & SD_HAS_ONLY_VOLUME)) {
weight = make_float3(1.0f, 1.0f, 1.0f) - sd->closure_transparent_extinction;
if (CLOSURE_IS_HOLDOUT(sc->type))
weight += sc->weight;
for (int i = 0; i < sd->num_closure; i++) {
ShaderClosure *sc = &sd->closure[i];
if (!CLOSURE_IS_BSDF_TRANSPARENT(sc->type)) {
sc->type = NBUILTIN_CLOSURES;
}
}
sd->flag &= ~(SD_CLOSURE_FLAGS - (SD_TRANSPARENT | SD_BSDF));
}
else {
weight = make_float3(1.0f, 1.0f, 1.0f);
}
}
else {
for (int i = 0; i < sd->num_closure; i++) {
ShaderClosure *sc = &sd->closure[i];
if (CLOSURE_IS_HOLDOUT(sc->type)) {
weight += sc->weight;
}
}
}
return weight;