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
12 changed files with 74 additions and 45 deletions

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

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

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

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

@ -652,7 +652,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
#endif #endif
/* holdout mask objects do not write data passes */ /* 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 /* blurring of bsdf after bounces, for rays that have a small likelihood
* of following this particular path (diffuse, rough glossy) */ * 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 #endif
/* holdout mask objects do not write data passes */ /* 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__ #ifdef __EMISSION__
/* emission */ /* emission */

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

@ -261,6 +261,7 @@ Film::Film()
{ {
exposure = 0.8f; exposure = 0.8f;
Pass::add(PASS_COMBINED, passes); Pass::add(PASS_COMBINED, passes);
pass_alpha_threshold = 0.5f;
filter_type = FILTER_BOX; filter_type = FILTER_BOX;
filter_width = 1.0f; 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_stride = align_up(kfilm->pass_stride, 4);
kfilm->pass_alpha_threshold = pass_alpha_threshold;
/* update filter table */ /* update filter table */
vector<float> table = filter_table(filter_type, filter_width); vector<float> table = filter_table(filter_type, filter_width);
@ -425,8 +427,12 @@ bool Film::modified(const Film& film)
{ {
return !(exposure == film.exposure return !(exposure == film.exposure
&& Pass::equals(passes, film.passes) && Pass::equals(passes, film.passes)
&& pass_alpha_threshold == film.pass_alpha_threshold
&& filter_type == film.filter_type && 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_) void Film::tag_passes_update(Scene *scene, const vector<Pass>& passes_)

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

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

@ -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.planes = R_IMF_PLANES_RGBA;
scene->r.im_format.compress = 15; 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->freestyleConfig.sphere_radius = 0.1f;
srl->pass_alpha_threshold = 0.5f;
}
} }
for (linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next) for (linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next)

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

@ -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, " RNA_def_property_ui_text(prop, "Samples", "Override number of render samples for this render layer, "
"0 will use the scene setting"); "0 will use the scene setting");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); 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 */ /* layer options */