Cycles: add pass alpha threshold value to render layers.
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Thu, 6 Feb 2014 14:18:34 +0000 (15:18 +0100)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Thu, 6 Feb 2014 14:24:15 +0000 (15:24 +0100)
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.

12 files changed:
intern/cycles/blender/addon/ui.py
intern/cycles/blender/blender_session.cpp
intern/cycles/kernel/closure/bsdf_transparent.h
intern/cycles/kernel/kernel_passes.h
intern/cycles/kernel/kernel_path.h
intern/cycles/kernel/kernel_types.h
intern/cycles/render/film.cpp
intern/cycles/render/film.h
source/blender/blenkernel/intern/scene.c
source/blender/blenloader/intern/versioning_defaults.c
source/blender/makesdna/DNA_scene_types.h
source/blender/makesrna/intern/rna_scene.c

index 0b107de58a98566990dc14d05fe7fa4436c38690..55322fed8b8168f802b99f1c86a4dd33094a50ee 100644 (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:")
index f81de7d529ad332302eb9b748ac6a1ed4e90b70e..94d390cc330731b70559c1ed16d51cffce399781 100644 (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);
index e62aecf3da68ba4ea14e4bebba1b9bf3c50d7155..73601d20c3a45b57cb705cd470199f8d9d2c1954 100644 (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)
index 512db9ec3927f842dd8746271b71bb0a1bddb0c6..9cdcb8c52295e9f95a899411134d49bddce69a44 100644 (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(!(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(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_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_NORMAL) {
+                               float3 normal = sd->N;
+                               kernel_write_pass_float3(buffer + kernel_data.film.pass_normal, sample, normal);
                        }
-                       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_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(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;
                }
        }
 
index 8460af85d4ce8ec2cd5d941e6f20c26410ad8168..aabac2e8e5eef6a0ff5850a99f89425eea2107f1 100644 (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 */
index cdde0fe02919cde97bc1bf4cf704fed8435538a7..06bf6b7c5ddd452943122617e38f332713b53780 100644 (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;
index f97417b5251eb49f9db7de7de0ba96412c60f3ed..23a70303557102d337c380b83ebd2e340d6b7e5a 100644 (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_)
index a991d36182f19f47b8aab26e85d3a500c5eae3e4..1e1c775aac3f6941beae5f582ff693176caf1c85 100644 (file)
@@ -50,6 +50,7 @@ class Film {
 public:
        float exposure;
        vector<Pass> passes;
+       float pass_alpha_threshold;
 
        FilterType filter_type;
        float filter_width;
index 1088b3a2523f7b28b2c2f8ae95b576b18c7cf3c3..580f7ab2e5435382a2e3ae4790707101ecb539ab 100644 (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;
index 82fa58b57e18faf5e7ad4394a64d274dbcfc6402..d6117224bb4f54edb4c44f8e52b31ca1ef03403c 100644 (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)
index 177b687802d0df7c1cf238c732a92c103f9beb7c..8c4026e8b670099f03422a5240ccdfb813348e72 100644 (file)
@@ -187,7 +187,7 @@ typedef struct SceneRenderLayer {
        int pass_xor;
 
        int samples;
-       int pad;
+       float pass_alpha_threshold;
        
        struct FreestyleConfig freestyleConfig;
 } SceneRenderLayer;
index e901737c670b7f3b57eafed2cbbbb206f70db475..a3b8c9ff8592ef94ff133b5d1baa1ca1765ff74f 100644 (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 */