Cycles: add pass alpha threshold value to render layers.

Z, Index, normal, UV and vector passes are only affected by surfaces with alpha
transparency equal to or higher than this threshold. With value 0.0 the first
surface hit will always write to these passes, regardless of transparency. With
higher values surfaces that are mostly transparent can be skipped until an opaque
surface is encountered.
This commit is contained in:
Brecht Van Lommel 2014-02-06 15:18:34 +01:00
parent 5cbddd4ca4
commit a41648c1dc
Notes: blender-bot 2023-10-18 15:23:11 +02:00
Referenced by issue #38600, Material/Object Index does not account for transparent Materials.
12 changed files with 74 additions and 45 deletions

View File

@ -391,6 +391,8 @@ class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel):
col.separator()
col.prop(rl, "use_pass_shadow")
col.prop(rl, "use_pass_ambient_occlusion")
col.separator()
col.prop(rl, "pass_alpha_threshold")
col = split.column()
col.label(text="Diffuse:")

View File

@ -382,6 +382,7 @@ void BlenderSession::render()
end_render_result(b_engine, b_rr, true, false);
buffer_params.passes = passes;
scene->film->pass_alpha_threshold = b_iter->pass_alpha_threshold();
scene->film->tag_passes_update(scene, passes);
scene->film->tag_update(scene);
scene->integrator->tag_update(scene);

View File

@ -38,7 +38,7 @@ CCL_NAMESPACE_BEGIN
ccl_device int bsdf_transparent_setup(ShaderClosure *sc)
{
sc->type = CLOSURE_BSDF_TRANSPARENT_ID;
return SD_BSDF;
return SD_BSDF|SD_TRANSPARENT;
}
ccl_device void bsdf_transparent_blur(ShaderClosure *sc, float roughness)

View File

@ -35,9 +35,11 @@ ccl_device_inline void kernel_write_pass_float4(ccl_global float *buffer, int sa
}
ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global float *buffer, PathRadiance *L,
ShaderData *sd, int sample, int path_flag, float3 throughput)
ShaderData *sd, int sample, PathState *state, float3 throughput)
{
#ifdef __PASSES__
int path_flag = state->flag;
if(!(path_flag & PATH_RAY_CAMERA))
return;
@ -46,35 +48,41 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global fl
if(!(flag & PASS_ALL))
return;
/* todo: add alpha threshold */
if(!(path_flag & PATH_RAY_TRANSPARENT)) {
if(sample == 0) {
if(flag & PASS_DEPTH) {
float depth = camera_distance(kg, sd->P);
kernel_write_pass_float(buffer + kernel_data.film.pass_depth, sample, depth);
}
if(flag & PASS_OBJECT_ID) {
float id = object_pass_id(kg, sd->object);
kernel_write_pass_float(buffer + kernel_data.film.pass_object_id, sample, id);
}
if(flag & PASS_MATERIAL_ID) {
float id = shader_pass_id(kg, sd);
kernel_write_pass_float(buffer + kernel_data.film.pass_material_id, sample, id);
}
}
if(!(path_flag & PATH_RAY_SINGLE_PASS_DONE)) {
if(!(sd->flag & SD_TRANSPARENT) ||
kernel_data.film.pass_alpha_threshold == 0.0f ||
average(shader_bsdf_alpha(kg, sd)) >= kernel_data.film.pass_alpha_threshold) {
if(flag & PASS_NORMAL) {
float3 normal = sd->N;
kernel_write_pass_float3(buffer + kernel_data.film.pass_normal, sample, normal);
}
if(flag & PASS_UV) {
float3 uv = primitive_uv(kg, sd);
kernel_write_pass_float3(buffer + kernel_data.film.pass_uv, sample, uv);
}
if(flag & PASS_MOTION) {
float4 speed = primitive_motion_vector(kg, sd);
kernel_write_pass_float4(buffer + kernel_data.film.pass_motion, sample, speed);
kernel_write_pass_float(buffer + kernel_data.film.pass_motion_weight, sample, 1.0f);
if(sample == 0) {
if(flag & PASS_DEPTH) {
float depth = camera_distance(kg, sd->P);
kernel_write_pass_float(buffer + kernel_data.film.pass_depth, sample, depth);
}
if(flag & PASS_OBJECT_ID) {
float id = object_pass_id(kg, sd->object);
kernel_write_pass_float(buffer + kernel_data.film.pass_object_id, sample, id);
}
if(flag & PASS_MATERIAL_ID) {
float id = shader_pass_id(kg, sd);
kernel_write_pass_float(buffer + kernel_data.film.pass_material_id, sample, id);
}
}
if(flag & PASS_NORMAL) {
float3 normal = sd->N;
kernel_write_pass_float3(buffer + kernel_data.film.pass_normal, sample, normal);
}
if(flag & PASS_UV) {
float3 uv = primitive_uv(kg, sd);
kernel_write_pass_float3(buffer + kernel_data.film.pass_uv, sample, uv);
}
if(flag & PASS_MOTION) {
float4 speed = primitive_motion_vector(kg, sd);
kernel_write_pass_float4(buffer + kernel_data.film.pass_motion, sample, speed);
kernel_write_pass_float(buffer + kernel_data.film.pass_motion_weight, sample, 1.0f);
}
state->flag |= PATH_RAY_SINGLE_PASS_DONE;
}
}

View File

@ -652,7 +652,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
#endif
/* holdout mask objects do not write data passes */
kernel_write_data_passes(kg, buffer, &L, &sd, sample, state.flag, throughput);
kernel_write_data_passes(kg, buffer, &L, &sd, sample, &state, throughput);
/* blurring of bsdf after bounces, for rays that have a small likelihood
* of following this particular path (diffuse, rough glossy) */
@ -1185,7 +1185,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
#endif
/* holdout mask objects do not write data passes */
kernel_write_data_passes(kg, buffer, &L, &sd, sample, state.flag, throughput);
kernel_write_data_passes(kg, buffer, &L, &sd, sample, &state, throughput);
#ifdef __EMISSION__
/* emission */

View File

@ -234,6 +234,7 @@ enum PathRayFlag {
PATH_RAY_DIFFUSE_ANCESTOR = 2048,
PATH_RAY_GLOSSY_ANCESTOR = 4096,
PATH_RAY_BSSRDF_ANCESTOR = 8192,
PATH_RAY_SINGLE_PASS_DONE = 8192,
/* this gives collisions with localview bits
* see: blender_util.h, grr - Campbell */
@ -519,23 +520,24 @@ enum ShaderDataFlag {
SD_ABSORPTION = 128, /* have volume absorption closure? */
SD_SCATTER = 256, /* have volume phase closure? */
SD_AO = 512, /* have ao closure? */
SD_TRANSPARENT = 1024, /* have transparent closure? */
SD_CLOSURE_FLAGS = (SD_EMISSION|SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY|SD_BSSRDF|SD_HOLDOUT|SD_ABSORPTION|SD_SCATTER|SD_AO),
/* shader flags */
SD_USE_MIS = 1024, /* direct light sample */
SD_HAS_TRANSPARENT_SHADOW = 2048, /* has transparent shadow */
SD_HAS_VOLUME = 4096, /* has volume shader */
SD_HAS_ONLY_VOLUME = 8192, /* has only volume shader, no surface */
SD_HETEROGENEOUS_VOLUME = 16384, /* has heterogeneous volume */
SD_HAS_BSSRDF_BUMP = 32768, /* bssrdf normal uses bump */
SD_USE_MIS = 2048, /* direct light sample */
SD_HAS_TRANSPARENT_SHADOW = 4096, /* has transparent shadow */
SD_HAS_VOLUME = 8192, /* has volume shader */
SD_HAS_ONLY_VOLUME = 16384, /* has only volume shader, no surface */
SD_HETEROGENEOUS_VOLUME = 32768, /* has heterogeneous volume */
SD_HAS_BSSRDF_BUMP = 65536, /* bssrdf normal uses bump */
SD_SHADER_FLAGS = (SD_USE_MIS|SD_HAS_TRANSPARENT_SHADOW|SD_HAS_VOLUME|SD_HAS_ONLY_VOLUME|SD_HETEROGENEOUS_VOLUME|SD_HAS_BSSRDF_BUMP),
/* object flags */
SD_HOLDOUT_MASK = 65536, /* holdout for camera rays */
SD_OBJECT_MOTION = 131072, /* has object motion blur */
SD_TRANSFORM_APPLIED = 262144, /* vertices have transform applied */
SD_HOLDOUT_MASK = 131072, /* holdout for camera rays */
SD_OBJECT_MOTION = 262144, /* has object motion blur */
SD_TRANSFORM_APPLIED = 524288, /* vertices have transform applied */
SD_OBJECT_FLAGS = (SD_HOLDOUT_MASK|SD_OBJECT_MOTION|SD_TRANSFORM_APPLIED)
};
@ -758,7 +760,7 @@ typedef struct KernelFilm {
int pass_emission;
int pass_background;
int pass_ao;
int pass_pad1;
float pass_alpha_threshold;
int pass_shadow;
float pass_shadow_scale;

View File

@ -261,6 +261,7 @@ Film::Film()
{
exposure = 0.8f;
Pass::add(PASS_COMBINED, passes);
pass_alpha_threshold = 0.5f;
filter_type = FILTER_BOX;
filter_width = 1.0f;
@ -399,6 +400,7 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
}
kfilm->pass_stride = align_up(kfilm->pass_stride, 4);
kfilm->pass_alpha_threshold = pass_alpha_threshold;
/* update filter table */
vector<float> table = filter_table(filter_type, filter_width);
@ -425,8 +427,12 @@ bool Film::modified(const Film& film)
{
return !(exposure == film.exposure
&& Pass::equals(passes, film.passes)
&& pass_alpha_threshold == film.pass_alpha_threshold
&& filter_type == film.filter_type
&& filter_width == film.filter_width);
&& filter_width == film.filter_width
&& mist_start == film.mist_start
&& mist_depth == film.mist_depth
&& mist_falloff == film.mist_falloff);
}
void Film::tag_passes_update(Scene *scene, const vector<Pass>& passes_)

View File

@ -50,6 +50,7 @@ class Film {
public:
float exposure;
vector<Pass> passes;
float pass_alpha_threshold;
FilterType filter_type;
float filter_width;

View File

@ -1707,6 +1707,7 @@ SceneRenderLayer *BKE_scene_add_render_layer(Scene *sce, const char *name)
srl->lay = (1 << 20) - 1;
srl->layflag = 0x7FFF; /* solid ztra halo edge strand */
srl->passflag = SCE_PASS_COMBINED | SCE_PASS_Z;
slr->pass_alpha_threshold = 0.5f;
BKE_freestyle_config_init(&srl->freestyleConfig);
return srl;

View File

@ -48,8 +48,10 @@ void BLO_update_defaults_startup_blend(Main *main)
scene->r.im_format.planes = R_IMF_PLANES_RGBA;
scene->r.im_format.compress = 15;
for (srl = scene->r.layers.first; srl; srl = srl->next)
for (srl = scene->r.layers.first; srl; srl = srl->next) {
srl->freestyleConfig.sphere_radius = 0.1f;
srl->pass_alpha_threshold = 0.5f;
}
}
for (linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next)

View File

@ -187,7 +187,7 @@ typedef struct SceneRenderLayer {
int pass_xor;
int samples;
int pad;
float pass_alpha_threshold;
struct FreestyleConfig freestyleConfig;
} SceneRenderLayer;

View File

@ -2271,6 +2271,12 @@ void rna_def_render_layer_common(StructRNA *srna, int scene)
RNA_def_property_ui_text(prop, "Samples", "Override number of render samples for this render layer, "
"0 will use the scene setting");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "pass_alpha_threshold", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_ui_text(prop, "Alpha Treshold", "Z, Index, normal, UV and vector passes are"
"only affected by surfaces with alpha transparency equal to"
"or higher than this threshold");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
}
/* layer options */