Cycles / SSS Render Passes:
authorThomas Dinges <blender@dingto.org>
Wed, 24 Jul 2013 23:47:02 +0000 (23:47 +0000)
committerThomas Dinges <blender@dingto.org>
Wed, 24 Jul 2013 23:47:02 +0000 (23:47 +0000)
* First step toward Subsurface Scattering render passes (Color, Direct and Indirect).
* Added UI, DNA and RNA for the new Passes on the Blender side.
* Basic Cycles integration.
* Only the SSS Color Pass works so far.

ToDo: Direct and Indirect Pass.
Should "subsurface" be a part of BsdfEval and "path_subsurface" of PathRadiance or is that the wrong way? Should it be integrated more like the AO render pass? Some input from Brecht or Stuart would be nice. :)

13 files changed:
intern/cycles/blender/addon/ui.py
intern/cycles/blender/blender_session.cpp
intern/cycles/kernel/kernel_accumulate.h
intern/cycles/kernel/kernel_passes.h
intern/cycles/kernel/kernel_shader.h
intern/cycles/kernel/kernel_types.h
intern/cycles/render/film.cpp
source/blender/blenkernel/BKE_node.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesrna/intern/rna_render.c
source/blender/makesrna/intern/rna_scene.c
source/blender/nodes/composite/nodes/node_composite_image.c
source/blender/render/intern/source/render_result.c

index 54e31ea4b649bd4bcedef97d3475ef178f5f7c30..b32b9ef48a4bf0145a8e76bb79627be29a99b0f5 100644 (file)
@@ -369,7 +369,13 @@ class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel):
         row.prop(rl, "use_pass_transmission_direct", text="Direct", toggle=True)
         row.prop(rl, "use_pass_transmission_indirect", text="Indirect", toggle=True)
         row.prop(rl, "use_pass_transmission_color", text="Color", toggle=True)
-
+        col.label(text="Subsurface:")
+        row = col.row(align=True)
+        row.prop(rl, "use_pass_subsurface_direct", text="Direct", toggle=True)
+        row.prop(rl, "use_pass_subsurface_indirect", text="Indirect", toggle=True)
+        row.prop(rl, "use_pass_subsurface_color", text="Color", toggle=True)
+        
+        col.separator()
         col.prop(rl, "use_pass_emit", text="Emission")
         col.prop(rl, "use_pass_environment")
         col.prop(rl, "use_pass_ambient_occlusion")
index 86bdbc0749f572ca3667eb4772ec3945ac36ab2b..6e535e82886be7a9bed9e749731c157c926da779 100644 (file)
@@ -216,6 +216,8 @@ static PassType get_pass_type(BL::RenderPass b_pass)
                        return PASS_GLOSSY_DIRECT;
                case BL::RenderPass::type_TRANSMISSION_DIRECT:
                        return PASS_TRANSMISSION_DIRECT;
+               case BL::RenderPass::type_SUBSURFACE_DIRECT:
+                       return PASS_SUBSURFACE_DIRECT;
 
                case BL::RenderPass::type_DIFFUSE_INDIRECT:
                        return PASS_DIFFUSE_INDIRECT;
@@ -223,6 +225,8 @@ static PassType get_pass_type(BL::RenderPass b_pass)
                        return PASS_GLOSSY_INDIRECT;
                case BL::RenderPass::type_TRANSMISSION_INDIRECT:
                        return PASS_TRANSMISSION_INDIRECT;
+               case BL::RenderPass::type_SUBSURFACE_INDIRECT:
+                       return PASS_SUBSURFACE_INDIRECT;
 
                case BL::RenderPass::type_DIFFUSE_COLOR:
                        return PASS_DIFFUSE_COLOR;
@@ -230,6 +234,8 @@ static PassType get_pass_type(BL::RenderPass b_pass)
                        return PASS_GLOSSY_COLOR;
                case BL::RenderPass::type_TRANSMISSION_COLOR:
                        return PASS_TRANSMISSION_COLOR;
+               case BL::RenderPass::type_SUBSURFACE_COLOR:
+                       return PASS_SUBSURFACE_COLOR;
 
                case BL::RenderPass::type_EMIT:
                        return PASS_EMISSION;
index e6307f23b32f2e5f0cb828dd921246ba86809f93..9e26aa6fa2b74e7cefd26049b22dcbeda8863af0 100644 (file)
@@ -124,14 +124,17 @@ __device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
                L->color_diffuse = make_float3(0.0f, 0.0f, 0.0f);
                L->color_glossy = make_float3(0.0f, 0.0f, 0.0f);
                L->color_transmission = make_float3(0.0f, 0.0f, 0.0f);
+               L->color_subsurface = make_float3(0.0f, 0.0f, 0.0f);
 
                L->direct_diffuse = make_float3(0.0f, 0.0f, 0.0f);
                L->direct_glossy = make_float3(0.0f, 0.0f, 0.0f);
                L->direct_transmission = make_float3(0.0f, 0.0f, 0.0f);
+               L->direct_subsurface = make_float3(0.0f, 0.0f, 0.0f);
 
                L->indirect_diffuse = make_float3(0.0f, 0.0f, 0.0f);
                L->indirect_glossy = make_float3(0.0f, 0.0f, 0.0f);
                L->indirect_transmission = make_float3(0.0f, 0.0f, 0.0f);
+               L->indirect_subsurface = make_float3(0.0f, 0.0f, 0.0f);
 
                L->path_diffuse = make_float3(0.0f, 0.0f, 0.0f);
                L->path_glossy = make_float3(0.0f, 0.0f, 0.0f);
@@ -337,10 +340,12 @@ __device_inline void path_radiance_clamp(PathRadiance *L, float3 *L_sum, float c
                        L->direct_diffuse = make_float3(0.0f, 0.0f, 0.0f);
                        L->direct_glossy = make_float3(0.0f, 0.0f, 0.0f);
                        L->direct_transmission = make_float3(0.0f, 0.0f, 0.0f);
+                       L->direct_subsurface = make_float3(0.0f, 0.0f, 0.0f);
 
                        L->indirect_diffuse = make_float3(0.0f, 0.0f, 0.0f);
                        L->indirect_glossy = make_float3(0.0f, 0.0f, 0.0f);
                        L->indirect_transmission = make_float3(0.0f, 0.0f, 0.0f);
+                       L->indirect_subsurface = make_float3(0.0f, 0.0f, 0.0f);
 
                        L->emission = make_float3(0.0f, 0.0f, 0.0f);
                }
@@ -357,10 +362,12 @@ __device_inline void path_radiance_clamp(PathRadiance *L, float3 *L_sum, float c
                        L->direct_diffuse *= scale;
                        L->direct_glossy *= scale;
                        L->direct_transmission *= scale;
+                       L->direct_subsurface *= scale;
 
                        L->indirect_diffuse *= scale;
                        L->indirect_glossy *= scale;
                        L->indirect_transmission *= scale;
+                       L->indirect_subsurface *= scale;
 
                        L->emission *= scale;
                }
index f07e1b1fc649261dba7e7f7ac5bbabba65843817..0b45e2432831ea52a8921f4af6d45852cba1a3d1 100644 (file)
@@ -86,6 +86,8 @@ __device_inline void kernel_write_data_passes(KernelGlobals *kg, __global float
                L->color_glossy += shader_bsdf_glossy(kg, sd)*throughput;
        if(flag & (PASS_TRANSMISSION_INDIRECT|PASS_TRANSMISSION_COLOR|PASS_TRANSMISSION_DIRECT))
                L->color_transmission += shader_bsdf_transmission(kg, sd)*throughput;
+       if(flag & (PASS_SUBSURFACE_INDIRECT|PASS_SUBSURFACE_COLOR|PASS_SUBSURFACE_DIRECT))
+               L->color_subsurface += shader_bsdf_subsurface(kg, sd)*throughput;
 
        if(flag & PASS_MIST) {
                /* bring depth into 0..1 range */
@@ -128,12 +130,16 @@ __device_inline void kernel_write_light_passes(KernelGlobals *kg, __global float
                kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_indirect, sample, L->indirect_glossy);
        if(flag & PASS_TRANSMISSION_INDIRECT)
                kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_indirect, sample, L->indirect_transmission);
+       if(flag & PASS_SUBSURFACE_INDIRECT)
+               kernel_write_pass_float3(buffer + kernel_data.film.pass_subsurface_indirect, sample, L->indirect_subsurface);
        if(flag & PASS_DIFFUSE_DIRECT)
                kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_direct, sample, L->direct_diffuse);
        if(flag & PASS_GLOSSY_DIRECT)
                kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_direct, sample, L->direct_glossy);
        if(flag & PASS_TRANSMISSION_DIRECT)
                kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_direct, sample, L->direct_transmission);
+       if(flag & PASS_SUBSURFACE_DIRECT)
+               kernel_write_pass_float3(buffer + kernel_data.film.pass_subsurface_direct, sample, L->direct_subsurface);
 
        if(flag & PASS_EMISSION)
                kernel_write_pass_float3(buffer + kernel_data.film.pass_emission, sample, L->emission);
@@ -148,6 +154,8 @@ __device_inline void kernel_write_light_passes(KernelGlobals *kg, __global float
                kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_color, sample, L->color_glossy);
        if(flag & PASS_TRANSMISSION_COLOR)
                kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_color, sample, L->color_transmission);
+       if(flag & PASS_SUBSURFACE_COLOR)
+               kernel_write_pass_float3(buffer + kernel_data.film.pass_subsurface_color, sample, L->color_subsurface);
        if(flag & PASS_SHADOW) {
                float4 shadow = L->shadow;
                shadow.w = kernel_data.film.pass_shadow_scale;
index cbaebe306211522e2fdee9212e2575594040ba55..333c116070d40e7e02b8846c638e986bc24e6915 100644 (file)
@@ -685,6 +685,27 @@ __device float3 shader_bsdf_transmission(KernelGlobals *kg, ShaderData *sd)
 #endif
 }
 
+__device float3 shader_bsdf_subsurface(KernelGlobals *kg, ShaderData *sd)
+{
+#ifdef __MULTI_CLOSURE__
+       float3 eval = make_float3(0.0f, 0.0f, 0.0f);
+
+       for(int i = 0; i< sd->num_closure; i++) {
+               ShaderClosure *sc = &sd->closure[i];
+
+               if(CLOSURE_IS_BSSRDF(sc->type))
+                       eval += sc->weight;
+       }
+
+       return eval;
+#else
+       if(CLOSURE_IS_BSSRDF(sd->closure.type))
+               return sd->closure.weight;
+       else
+               return make_float3(0.0f, 0.0f, 0.0f);
+#endif
+}
+
 __device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_factor, float3 *N)
 {
 #ifdef __MULTI_CLOSURE__
index 13404abd87e107d6ce21000aa36da835600ea486..12a4506af13c178b2498379b5b8c050a8e5f3860 100644 (file)
@@ -269,7 +269,10 @@ typedef enum PassType {
        PASS_SHADOW = 262144,
        PASS_MOTION = 524288,
        PASS_MOTION_WEIGHT = 1048576,
-       PASS_MIST = 2097152
+       PASS_MIST = 2097152,
+       PASS_SUBSURFACE_DIRECT = 4194304,
+       PASS_SUBSURFACE_INDIRECT = 8388608,
+       PASS_SUBSURFACE_COLOR = 16777216
 } PassType;
 
 #define PASS_ALL (~0)
@@ -292,14 +295,17 @@ typedef struct PathRadiance {
        float3 color_diffuse;
        float3 color_glossy;
        float3 color_transmission;
+       float3 color_subsurface;
 
        float3 direct_diffuse;
        float3 direct_glossy;
        float3 direct_transmission;
+       float3 direct_subsurface;
 
        float3 indirect_diffuse;
        float3 indirect_glossy;
        float3 indirect_transmission;
+       float3 indirect_subsurface;
 
        float3 path_diffuse;
        float3 path_glossy;
@@ -673,22 +679,27 @@ typedef struct KernelFilm {
        int pass_diffuse_color;
        int pass_glossy_color;
        int pass_transmission_color;
+       int pass_subsurface_color;
+       
        int pass_diffuse_indirect;
-
        int pass_glossy_indirect;
        int pass_transmission_indirect;
+       int pass_subsurface_indirect;
+       
        int pass_diffuse_direct;
        int pass_glossy_direct;
-
        int pass_transmission_direct;
+       int pass_subsurface_direct;
+       
        int pass_emission;
        int pass_background;
        int pass_ao;
+       int pass_pad1;
 
        int pass_shadow;
        float pass_shadow_scale;
        int filter_table_offset;
-       int pass_pad1;
+       int pass_pad2;
 
        int pass_mist;
        float mist_start;
index 2a16b7b6c217b9948f16f99a6cb8adef0f01871d..4b48ee1d2c9fa988bd8228b076d230d24c0ee753 100644 (file)
@@ -98,6 +98,9 @@ void Pass::add(PassType type, vector<Pass>& passes)
                case PASS_TRANSMISSION_COLOR:
                        pass.components = 4;
                        break;
+               case PASS_SUBSURFACE_COLOR:
+                       pass.components = 4;
+                       break;
                case PASS_DIFFUSE_INDIRECT:
                        pass.components = 4;
                        pass.exposure = true;
@@ -113,6 +116,11 @@ void Pass::add(PassType type, vector<Pass>& passes)
                        pass.exposure = true;
                        pass.divide_type = PASS_TRANSMISSION_COLOR;
                        break;
+               case PASS_SUBSURFACE_INDIRECT:
+                       pass.components = 4;
+                       pass.exposure = true;
+                       pass.divide_type = PASS_SUBSURFACE_COLOR;
+                       break;
                case PASS_DIFFUSE_DIRECT:
                        pass.components = 4;
                        pass.exposure = true;
@@ -128,6 +136,11 @@ void Pass::add(PassType type, vector<Pass>& passes)
                        pass.exposure = true;
                        pass.divide_type = PASS_TRANSMISSION_COLOR;
                        break;
+               case PASS_SUBSURFACE_DIRECT:
+                       pass.components = 4;
+                       pass.exposure = true;
+                       pass.divide_type = PASS_SUBSURFACE_COLOR;
+                       break;
 
                case PASS_EMISSION:
                        pass.components = 4;
@@ -327,6 +340,10 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
                                kfilm->pass_transmission_color = kfilm->pass_stride;
                                kfilm->use_light_pass = 1;
                                break;
+                       case PASS_SUBSURFACE_COLOR:
+                               kfilm->pass_subsurface_color = kfilm->pass_stride;
+                               kfilm->use_light_pass = 1;
+                               break;
                        case PASS_DIFFUSE_INDIRECT:
                                kfilm->pass_diffuse_indirect = kfilm->pass_stride;
                                kfilm->use_light_pass = 1;
@@ -339,6 +356,10 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
                                kfilm->pass_transmission_indirect = kfilm->pass_stride;
                                kfilm->use_light_pass = 1;
                                break;
+                       case PASS_SUBSURFACE_INDIRECT:
+                               kfilm->pass_subsurface_indirect = kfilm->pass_stride;
+                               kfilm->use_light_pass = 1;
+                               break;
                        case PASS_DIFFUSE_DIRECT:
                                kfilm->pass_diffuse_direct = kfilm->pass_stride;
                                kfilm->use_light_pass = 1;
@@ -351,6 +372,10 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
                                kfilm->pass_transmission_direct = kfilm->pass_stride;
                                kfilm->use_light_pass = 1;
                                break;
+                       case PASS_SUBSURFACE_DIRECT:
+                               kfilm->pass_subsurface_direct = kfilm->pass_stride;
+                               kfilm->use_light_pass = 1;
+                               break;
 
                        case PASS_EMISSION:
                                kfilm->pass_emission = kfilm->pass_stride;
index c151d47334e83bdc034d2c3885ceacdb155f0b25..71f859cd766c78e448662e78b9534951b4a1daf1 100644 (file)
@@ -806,6 +806,9 @@ void            ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria
 #define RRES_OUT_TRANSM_DIRECT         25
 #define RRES_OUT_TRANSM_INDIRECT       26
 #define RRES_OUT_TRANSM_COLOR          27
+#define RRES_OUT_SUBS_DIRECT           28
+#define RRES_OUT_SUBS_INDIRECT         29
+#define RRES_OUT_SUBS_COLOR                    30
 
 /* note: types are needed to restore callbacks, don't change values */
 #define CMP_NODE_VIEWER                201
index 5e877ed697b35a43cb0dee974d7c1847a61b867c..c9aa19ccc67531b4f05c1c64be6db884c964ec15 100644 (file)
@@ -237,6 +237,9 @@ typedef struct SceneRenderLayer {
 #define SCE_PASS_TRANSM_DIRECT         (1<<25)
 #define SCE_PASS_TRANSM_INDIRECT       (1<<26)
 #define SCE_PASS_TRANSM_COLOR          (1<<27)
+#define SCE_PASS_SUBS_DIRECT           (1<<28)
+#define SCE_PASS_SUBS_INDIRECT         (1<<29)
+#define SCE_PASS_SUBS_COLOR                    (1<<30)
 
 /* note, srl->passflag is treestore element 'nr' in outliner, short still... */
 
index 64b4e019c27a1a28b211d71079b6951939659472..fe3219ce599b620c51a01b37e50b4bafd5fc310e 100644 (file)
@@ -570,6 +570,9 @@ static void rna_def_render_pass(BlenderRNA *brna)
                {SCE_PASS_TRANSM_DIRECT, "TRANSMISSION_DIRECT", 0, "Transmission Direct", ""},
                {SCE_PASS_TRANSM_INDIRECT, "TRANSMISSION_INDIRECT", 0, "Transmission Indirect", ""},
                {SCE_PASS_TRANSM_COLOR, "TRANSMISSION_COLOR", 0, "Transmission Color", ""},
+               {SCE_PASS_SUBS_DIRECT, "SUBSURFACE_DIRECT", 0, "Subsurface Direct", ""},
+               {SCE_PASS_SUBS_INDIRECT, "SUBSURFACE_INDIRECT", 0, "Subsurface Indirect", ""},
+               {SCE_PASS_SUBS_COLOR, "SUBSURFACE_COLOR", 0, "Subsurface Color", ""},
                {0, NULL, 0, NULL, NULL}
        };
        
index d6dc216272058e1def5b5aba798420cfbca10bc2..549fffcada7d7afebb815ffc58f6cc0702307738 100644 (file)
@@ -2555,6 +2555,24 @@ void rna_def_render_layer_common(StructRNA *srna, int scene)
        RNA_def_property_ui_text(prop, "Transmission Color", "Deliver transmission color pass");
        if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
        else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+       
+       prop = RNA_def_property(srna, "use_pass_subsurface_direct", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_SUBS_DIRECT);
+       RNA_def_property_ui_text(prop, "Subsurface Direct", "Deliver subsurface direct pass");
+       if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+       else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+       prop = RNA_def_property(srna, "use_pass_subsurface_indirect", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_SUBS_INDIRECT);
+       RNA_def_property_ui_text(prop, "Subsurface Indirect", "Deliver subsurface indirect pass");
+       if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+       else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+       prop = RNA_def_property(srna, "use_pass_subsurface_color", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_SUBS_COLOR);
+       RNA_def_property_ui_text(prop, "Subsurface Color", "Deliver subsurface color pass");
+       if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+       else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
 }
 
 static void rna_def_freestyle_linesets(BlenderRNA *brna, PropertyRNA *cprop)
index 0d68b999eb2a2c0c28af87ad618a250cab74d8e3..5c656352a3c61ad9779d51f0ef8296486da2e46b 100644 (file)
@@ -72,6 +72,9 @@ static bNodeSocketTemplate cmp_node_rlayers_out[] = {
        {       SOCK_RGBA, 0, N_("Transmission Direct"),        0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
        {       SOCK_RGBA, 0, N_("Transmission Indirect"),      0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
        {       SOCK_RGBA, 0, N_("Transmission Color"),         0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_RGBA, 0, N_("Subsurface Direct"),          0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_RGBA, 0, N_("Subsurface Indirect"),        0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_RGBA, 0, N_("Subsurface Color"),           0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
        {       -1, 0, ""       }
 };
 
@@ -152,6 +155,13 @@ static void cmp_node_image_add_render_pass_outputs(bNodeTree *ntree, bNode *node
                cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_INDIRECT, RRES_OUT_TRANSM_INDIRECT);
        if (passflag & SCE_PASS_TRANSM_COLOR)
                cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_COLOR, RRES_OUT_TRANSM_COLOR);
+               
+       if (passflag & SCE_PASS_SUBS_DIRECT)
+               cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBS_DIRECT, RRES_OUT_SUBS_DIRECT);
+       if (passflag & SCE_PASS_SUBS_INDIRECT)
+               cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBS_INDIRECT, RRES_OUT_SUBS_INDIRECT);
+       if (passflag & SCE_PASS_SUBS_COLOR)
+               cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBS_COLOR, RRES_OUT_SUBS_COLOR);
 }
 
 static void cmp_node_image_add_multilayer_outputs(bNodeTree *ntree, bNode *node, RenderLayer *rl)
@@ -414,6 +424,9 @@ void node_cmp_rlayers_force_hidden_passes(bNode *node)
        set_output_visible(node, passflag, RRES_OUT_TRANSM_DIRECT,    SCE_PASS_TRANSM_DIRECT);
        set_output_visible(node, passflag, RRES_OUT_TRANSM_INDIRECT,  SCE_PASS_TRANSM_INDIRECT);
        set_output_visible(node, passflag, RRES_OUT_TRANSM_COLOR,     SCE_PASS_TRANSM_COLOR);
+       set_output_visible(node, passflag, RRES_OUT_SUBS_DIRECT,      SCE_PASS_SUBS_DIRECT);
+       set_output_visible(node, passflag, RRES_OUT_SUBS_INDIRECT,    SCE_PASS_SUBS_INDIRECT);
+       set_output_visible(node, passflag, RRES_OUT_SUBS_COLOR,       SCE_PASS_SUBS_COLOR);
 }
 
 static void node_composit_init_rlayers(const bContext *C, PointerRNA *ptr)
index f719e09769d32cd3f4fdef985ddef46b290b0ced..c5c85f665f0fb6f9b2c557d608f516b7190fbd80 100644 (file)
@@ -279,6 +279,24 @@ static const char *get_pass_name(int passtype, int channel)
                if (channel == 1) return "TransCol.G";
                return "TransCol.B";
        }
+       if (passtype == SCE_PASS_SUBS_DIRECT) {
+               if (channel == -1) return "SubsDir";
+               if (channel == 0) return "SubsDir.R";
+               if (channel == 1) return "SubsDir.G";
+               return "SubsDir.B";
+       }
+       if (passtype == SCE_PASS_SUBS_INDIRECT) {
+               if (channel == -1) return "SubsInd";
+               if (channel == 0) return "SubsInd.R";
+               if (channel == 1) return "SubsInd.G";
+               return "SubsInd.B";
+       }
+       if (passtype == SCE_PASS_SUBS_COLOR) {
+               if (channel == -1) return "SubsCol";
+               if (channel == 0) return "SubsCol.R";
+               if (channel == 1) return "SubsCol.G";
+               return "SubsCol.B";
+       }
        return "Unknown";
 }
 
@@ -368,6 +386,15 @@ static int passtype_from_name(const char *str)
 
        if (strcmp(str, "TransCol") == 0)
                return SCE_PASS_TRANSM_COLOR;
+               
+       if (strcmp(str, "SubsDir") == 0)
+               return SCE_PASS_SUBS_DIRECT;
+
+       if (strcmp(str, "SubsInd") == 0)
+               return SCE_PASS_SUBS_INDIRECT;
+
+       if (strcmp(str, "SubsCol") == 0)
+               return SCE_PASS_SUBS_COLOR;
 
        return 0;
 }
@@ -538,6 +565,12 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
                        render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_INDIRECT);
                if (srl->passflag  & SCE_PASS_TRANSM_COLOR)
                        render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_COLOR);
+               if (srl->passflag  & SCE_PASS_SUBS_DIRECT)
+                       render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBS_DIRECT);
+               if (srl->passflag  & SCE_PASS_SUBS_INDIRECT)
+                       render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBS_INDIRECT);
+               if (srl->passflag  & SCE_PASS_SUBS_COLOR)
+                       render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBS_COLOR);
        }
        /* sss, previewrender and envmap don't do layers, so we make a default one */
        if (rr->layers.first == NULL && !(layername && layername[0])) {