diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 411bd5b8b27..551a0f85623 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -373,7 +373,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") diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 3a46897fcac..fb743acf29a 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -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; diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h index b2884953a22..5e7b845059d 100644 --- a/intern/cycles/kernel/closure/bsdf.h +++ b/intern/cycles/kernel/closure/bsdf.h @@ -45,6 +45,7 @@ __device int bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const ShaderCl switch(sc->type) { case CLOSURE_BSDF_DIFFUSE_ID: + case CLOSURE_BSDF_BSSRDF_ID: label = bsdf_diffuse_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; @@ -134,6 +135,7 @@ __device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const ShaderC if(dot(sd->Ng, omega_in) >= 0.0f) { switch(sc->type) { case CLOSURE_BSDF_DIFFUSE_ID: + case CLOSURE_BSDF_BSSRDF_ID: eval = bsdf_diffuse_eval_reflect(sc, sd->I, omega_in, pdf); break; #ifdef __SVM__ @@ -195,6 +197,7 @@ __device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const ShaderC else { switch(sc->type) { case CLOSURE_BSDF_DIFFUSE_ID: + case CLOSURE_BSDF_BSSRDF_ID: eval = bsdf_diffuse_eval_transmit(sc, sd->I, omega_in, pdf); break; #ifdef __SVM__ @@ -262,6 +265,7 @@ __device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness) switch(sc->type) { case CLOSURE_BSDF_DIFFUSE_ID: + case CLOSURE_BSDF_BSSRDF_ID: bsdf_diffuse_blur(sc, roughness); break; #ifdef __SVM__ diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h index e6307f23b32..ca420909bc7 100644 --- a/intern/cycles/kernel/kernel_accumulate.h +++ b/intern/cycles/kernel/kernel_accumulate.h @@ -33,6 +33,7 @@ __device_inline void bsdf_eval_init(BsdfEval *eval, ClosureType type, float3 val eval->glossy = make_float3(0.0f, 0.0f, 0.0f); eval->transmission = make_float3(0.0f, 0.0f, 0.0f); eval->transparent = make_float3(0.0f, 0.0f, 0.0f); + eval->subsurface = make_float3(0.0f, 0.0f, 0.0f); if(type == CLOSURE_BSDF_TRANSPARENT_ID) eval->transparent = value; @@ -40,8 +41,10 @@ __device_inline void bsdf_eval_init(BsdfEval *eval, ClosureType type, float3 val eval->diffuse = value; else if(CLOSURE_IS_BSDF_GLOSSY(type)) eval->glossy = value; - else + else if(CLOSURE_IS_BSDF_TRANSMISSION(type)) eval->transmission = value; + else if(CLOSURE_IS_BSDF_BSSRDF(type)) + eval->subsurface = value; } else eval->diffuse = value; @@ -58,8 +61,10 @@ __device_inline void bsdf_eval_accum(BsdfEval *eval, ClosureType type, float3 va eval->diffuse += value; else if(CLOSURE_IS_BSDF_GLOSSY(type)) eval->glossy += value; - else + else if(CLOSURE_IS_BSDF_TRANSMISSION(type)) eval->transmission += value; + else if(CLOSURE_IS_BSDF_BSSRDF(type)) + eval->subsurface += value; /* skipping transparent, this function is used by for eval(), will be zero then */ } @@ -77,7 +82,8 @@ __device_inline bool bsdf_eval_is_zero(BsdfEval *eval) return is_zero(eval->diffuse) && is_zero(eval->glossy) && is_zero(eval->transmission) - && is_zero(eval->transparent); + && is_zero(eval->transparent) + && is_zero(eval->subsurface); } else return is_zero(eval->diffuse); @@ -93,6 +99,7 @@ __device_inline void bsdf_eval_mul(BsdfEval *eval, float3 value) eval->diffuse *= value; eval->glossy *= value; eval->transmission *= value; + eval->subsurface *= value; /* skipping transparent, this function is used by for eval(), will be zero then */ } @@ -124,18 +131,22 @@ __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); L->path_transmission = make_float3(0.0f, 0.0f, 0.0f); + L->path_subsurface = make_float3(0.0f, 0.0f, 0.0f); L->emission = make_float3(0.0f, 0.0f, 0.0f); L->background = make_float3(0.0f, 0.0f, 0.0f); @@ -164,14 +175,15 @@ __device_inline void path_radiance_bsdf_bounce(PathRadiance *L, float3 *throughp L->path_diffuse = bsdf_eval->diffuse*value; L->path_glossy = bsdf_eval->glossy*value; L->path_transmission = bsdf_eval->transmission*value; + L->path_subsurface = bsdf_eval->subsurface*value; - *throughput = L->path_diffuse + L->path_glossy + L->path_transmission; + *throughput = L->path_diffuse + L->path_glossy + L->path_transmission + L->path_subsurface; L->direct_throughput = *throughput; } else { /* transparent bounce before first hit, or indirectly visible through BSDF */ - float3 sum = (bsdf_eval->diffuse + bsdf_eval->glossy + bsdf_eval->transmission + bsdf_eval->transparent)*inverse_pdf; + float3 sum = (bsdf_eval->diffuse + bsdf_eval->glossy + bsdf_eval->transmission + bsdf_eval->transparent + bsdf_eval->subsurface)*inverse_pdf; *throughput *= sum; } } @@ -230,6 +242,7 @@ __device_inline void path_radiance_accum_light(PathRadiance *L, float3 throughpu L->direct_diffuse += throughput*bsdf_eval->diffuse*shadow; L->direct_glossy += throughput*bsdf_eval->glossy*shadow; L->direct_transmission += throughput*bsdf_eval->transmission*shadow; + L->direct_subsurface += throughput*bsdf_eval->subsurface*shadow; if(is_lamp) { L->shadow.x += shadow.x*shadow_fac; @@ -239,7 +252,7 @@ __device_inline void path_radiance_accum_light(PathRadiance *L, float3 throughpu } else { /* indirectly visible lighting after BSDF bounce */ - float3 sum = bsdf_eval->diffuse + bsdf_eval->glossy + bsdf_eval->transmission; + float3 sum = bsdf_eval->diffuse + bsdf_eval->glossy + bsdf_eval->transmission + bsdf_eval->subsurface; L->indirect += throughput*sum*shadow; } } @@ -279,11 +292,13 @@ __device_inline void path_radiance_sum_indirect(PathRadiance *L) L->direct_diffuse += L->path_diffuse*L->direct_emission; L->direct_glossy += L->path_glossy*L->direct_emission; L->direct_transmission += L->path_transmission*L->direct_emission; + L->direct_subsurface += L->path_subsurface*L->direct_emission; L->indirect = safe_divide_color(L->indirect, L->direct_throughput); L->indirect_diffuse += L->path_diffuse*L->indirect; L->indirect_glossy += L->path_glossy*L->indirect; L->indirect_transmission += L->path_transmission*L->indirect; + L->indirect_subsurface += L->path_subsurface*L->indirect; } #endif } @@ -295,6 +310,7 @@ __device_inline void path_radiance_reset_indirect(PathRadiance *L) L->path_diffuse = make_float3(0.0f, 0.0f, 0.0f); L->path_glossy = make_float3(0.0f, 0.0f, 0.0f); L->path_transmission = make_float3(0.0f, 0.0f, 0.0f); + L->path_subsurface = make_float3(0.0f, 0.0f, 0.0f); L->direct_emission = make_float3(0.0f, 0.0f, 0.0f); L->indirect = make_float3(0.0f, 0.0f, 0.0f); @@ -309,8 +325,8 @@ __device_inline float3 path_radiance_sum(KernelGlobals *kg, PathRadiance *L) path_radiance_sum_indirect(L); float3 L_sum = L->emission - + L->direct_diffuse + L->direct_glossy + L->direct_transmission - + L->indirect_diffuse + L->indirect_glossy + L->indirect_transmission; + + L->direct_diffuse + L->direct_glossy + L->direct_transmission + L->direct_subsurface + + L->indirect_diffuse + L->indirect_glossy + L->indirect_transmission + L->indirect_subsurface; if(!kernel_data.background.transparent) L_sum += L->background; @@ -337,10 +353,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 +375,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; } diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h index f07e1b1fc64..0b45e243283 100644 --- a/intern/cycles/kernel/kernel_passes.h +++ b/intern/cycles/kernel/kernel_passes.h @@ -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; diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 40ecb1be91b..2806296ba93 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -892,7 +892,7 @@ __device_noinline void kernel_path_non_progressive_lighting(KernelGlobals *kg, R int num_samples; - if(CLOSURE_IS_BSDF_DIFFUSE(sc->type)) + if(CLOSURE_IS_BSDF_DIFFUSE(sc->type) || CLOSURE_IS_BSDF_BSSRDF(sc->type)) num_samples = kernel_data.integrator.diffuse_samples; else if(CLOSURE_IS_BSDF_GLOSSY(sc->type)) num_samples = kernel_data.integrator.glossy_samples; diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index b902230a9b9..111f3cab8ab 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -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__ diff --git a/intern/cycles/kernel/kernel_subsurface.h b/intern/cycles/kernel/kernel_subsurface.h index f7bccf71976..4fae961512e 100644 --- a/intern/cycles/kernel/kernel_subsurface.h +++ b/intern/cycles/kernel/kernel_subsurface.h @@ -163,6 +163,10 @@ __device void subsurface_scatter_setup_diffuse_bsdf(ShaderData *sd, float3 weigh sd->flag |= bsdf_diffuse_setup(sc); sd->randb_closure = 0.0f; + /* replace CLOSURE_BSDF_DIFFUSE_ID with this special ID so render passes + * can recognize it as not being a regular diffuse closure */ + sc->type = CLOSURE_BSDF_BSSRDF_ID; + /* todo: evaluate shading to get blurred textures and bump mapping */ /* shader_eval_surface(kg, sd, 0.0f, state_flag, SHADER_CONTEXT_SSS); */ } diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 1010fdea627..c32ccacff53 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -268,7 +268,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) @@ -291,18 +294,22 @@ 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; float3 path_transmission; + float3 path_subsurface; float4 shadow; float mist; @@ -315,6 +322,7 @@ typedef struct BsdfEval { float3 glossy; float3 transmission; float3 transparent; + float3 subsurface; } BsdfEval; #else @@ -672,22 +680,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; diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index dbfb8d48fbf..dd95f19f175 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -371,7 +371,8 @@ typedef enum ClosureType { CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID, CLOSURE_BSDF_SHARP_GLASS_ID, - /* Transparent */ + /* Special cases */ + CLOSURE_BSDF_BSSRDF_ID, CLOSURE_BSDF_TRANSPARENT_ID, /* Other */ @@ -395,6 +396,7 @@ typedef enum ClosureType { #define CLOSURE_IS_BSDF_DIFFUSE(type) (type >= CLOSURE_BSDF_DIFFUSE_ID && type <= CLOSURE_BSDF_DIFFUSE_TOON_ID) #define CLOSURE_IS_BSDF_GLOSSY(type) (type >= CLOSURE_BSDF_GLOSSY_ID && type <= CLOSURE_BSDF_GLOSSY_TOON_ID) #define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSMISSION_ID && type <= CLOSURE_BSDF_SHARP_GLASS_ID) +#define CLOSURE_IS_BSDF_BSSRDF(type) (type == CLOSURE_BSDF_BSSRDF_ID) #define CLOSURE_IS_BSSRDF(type) (type == CLOSURE_BSSRDF_ID) #define CLOSURE_IS_VOLUME(type) (type >= CLOSURE_VOLUME_ID && type <= CLOSURE_VOLUME_ISOTROPIC_ID) #define CLOSURE_IS_EMISSION(type) (type == CLOSURE_EMISSION_ID) diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp index 2a16b7b6c21..4b48ee1d2c9 100644 --- a/intern/cycles/render/film.cpp +++ b/intern/cycles/render/film.cpp @@ -98,6 +98,9 @@ void Pass::add(PassType type, vector& 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& 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& 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; diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index c151d47334e..4e9e18d43e3 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -778,34 +778,37 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria /* ************** COMPOSITE NODES *************** */ /* output socket defines */ -#define RRES_OUT_IMAGE 0 -#define RRES_OUT_ALPHA 1 -#define RRES_OUT_Z 2 -#define RRES_OUT_NORMAL 3 -#define RRES_OUT_UV 4 -#define RRES_OUT_VEC 5 -#define RRES_OUT_RGBA 6 -#define RRES_OUT_DIFF 7 -#define RRES_OUT_SPEC 8 -#define RRES_OUT_SHADOW 9 -#define RRES_OUT_AO 10 -#define RRES_OUT_REFLECT 11 -#define RRES_OUT_REFRACT 12 -#define RRES_OUT_INDIRECT 13 -#define RRES_OUT_INDEXOB 14 -#define RRES_OUT_INDEXMA 15 -#define RRES_OUT_MIST 16 -#define RRES_OUT_EMIT 17 -#define RRES_OUT_ENV 18 -#define RRES_OUT_DIFF_DIRECT 19 -#define RRES_OUT_DIFF_INDIRECT 20 -#define RRES_OUT_DIFF_COLOR 21 -#define RRES_OUT_GLOSSY_DIRECT 22 -#define RRES_OUT_GLOSSY_INDIRECT 23 -#define RRES_OUT_GLOSSY_COLOR 24 -#define RRES_OUT_TRANSM_DIRECT 25 -#define RRES_OUT_TRANSM_INDIRECT 26 -#define RRES_OUT_TRANSM_COLOR 27 +#define RRES_OUT_IMAGE 0 +#define RRES_OUT_ALPHA 1 +#define RRES_OUT_Z 2 +#define RRES_OUT_NORMAL 3 +#define RRES_OUT_UV 4 +#define RRES_OUT_VEC 5 +#define RRES_OUT_RGBA 6 +#define RRES_OUT_DIFF 7 +#define RRES_OUT_SPEC 8 +#define RRES_OUT_SHADOW 9 +#define RRES_OUT_AO 10 +#define RRES_OUT_REFLECT 11 +#define RRES_OUT_REFRACT 12 +#define RRES_OUT_INDIRECT 13 +#define RRES_OUT_INDEXOB 14 +#define RRES_OUT_INDEXMA 15 +#define RRES_OUT_MIST 16 +#define RRES_OUT_EMIT 17 +#define RRES_OUT_ENV 18 +#define RRES_OUT_DIFF_DIRECT 19 +#define RRES_OUT_DIFF_INDIRECT 20 +#define RRES_OUT_DIFF_COLOR 21 +#define RRES_OUT_GLOSSY_DIRECT 22 +#define RRES_OUT_GLOSSY_INDIRECT 23 +#define RRES_OUT_GLOSSY_COLOR 24 +#define RRES_OUT_TRANSM_DIRECT 25 +#define RRES_OUT_TRANSM_INDIRECT 26 +#define RRES_OUT_TRANSM_COLOR 27 +#define RRES_OUT_SUBSURFACE_DIRECT 28 +#define RRES_OUT_SUBSURFACE_INDIRECT 29 +#define RRES_OUT_SUBSURFACE_COLOR 30 /* note: types are needed to restore callbacks, don't change values */ #define CMP_NODE_VIEWER 201 diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index dd194ed389f..ceb745cf90a 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -209,34 +209,37 @@ typedef struct SceneRenderLayer { #define SCE_LAY_NEG_ZMASK 0x80000 /* srl->passflag */ -#define SCE_PASS_COMBINED (1<<0) -#define SCE_PASS_Z (1<<1) -#define SCE_PASS_RGBA (1<<2) -#define SCE_PASS_DIFFUSE (1<<3) -#define SCE_PASS_SPEC (1<<4) -#define SCE_PASS_SHADOW (1<<5) -#define SCE_PASS_AO (1<<6) -#define SCE_PASS_REFLECT (1<<7) -#define SCE_PASS_NORMAL (1<<8) -#define SCE_PASS_VECTOR (1<<9) -#define SCE_PASS_REFRACT (1<<10) -#define SCE_PASS_INDEXOB (1<<11) -#define SCE_PASS_UV (1<<12) -#define SCE_PASS_INDIRECT (1<<13) -#define SCE_PASS_MIST (1<<14) -#define SCE_PASS_RAYHITS (1<<15) -#define SCE_PASS_EMIT (1<<16) -#define SCE_PASS_ENVIRONMENT (1<<17) -#define SCE_PASS_INDEXMA (1<<18) -#define SCE_PASS_DIFFUSE_DIRECT (1<<19) -#define SCE_PASS_DIFFUSE_INDIRECT (1<<20) -#define SCE_PASS_DIFFUSE_COLOR (1<<21) -#define SCE_PASS_GLOSSY_DIRECT (1<<22) -#define SCE_PASS_GLOSSY_INDIRECT (1<<23) -#define SCE_PASS_GLOSSY_COLOR (1<<24) -#define SCE_PASS_TRANSM_DIRECT (1<<25) -#define SCE_PASS_TRANSM_INDIRECT (1<<26) -#define SCE_PASS_TRANSM_COLOR (1<<27) +#define SCE_PASS_COMBINED (1<<0) +#define SCE_PASS_Z (1<<1) +#define SCE_PASS_RGBA (1<<2) +#define SCE_PASS_DIFFUSE (1<<3) +#define SCE_PASS_SPEC (1<<4) +#define SCE_PASS_SHADOW (1<<5) +#define SCE_PASS_AO (1<<6) +#define SCE_PASS_REFLECT (1<<7) +#define SCE_PASS_NORMAL (1<<8) +#define SCE_PASS_VECTOR (1<<9) +#define SCE_PASS_REFRACT (1<<10) +#define SCE_PASS_INDEXOB (1<<11) +#define SCE_PASS_UV (1<<12) +#define SCE_PASS_INDIRECT (1<<13) +#define SCE_PASS_MIST (1<<14) +#define SCE_PASS_RAYHITS (1<<15) +#define SCE_PASS_EMIT (1<<16) +#define SCE_PASS_ENVIRONMENT (1<<17) +#define SCE_PASS_INDEXMA (1<<18) +#define SCE_PASS_DIFFUSE_DIRECT (1<<19) +#define SCE_PASS_DIFFUSE_INDIRECT (1<<20) +#define SCE_PASS_DIFFUSE_COLOR (1<<21) +#define SCE_PASS_GLOSSY_DIRECT (1<<22) +#define SCE_PASS_GLOSSY_INDIRECT (1<<23) +#define SCE_PASS_GLOSSY_COLOR (1<<24) +#define SCE_PASS_TRANSM_DIRECT (1<<25) +#define SCE_PASS_TRANSM_INDIRECT (1<<26) +#define SCE_PASS_TRANSM_COLOR (1<<27) +#define SCE_PASS_SUBSURFACE_DIRECT (1<<28) +#define SCE_PASS_SUBSURFACE_INDIRECT (1<<29) +#define SCE_PASS_SUBSURFACE_COLOR (1<<30) /* note, srl->passflag is treestore element 'nr' in outliner, short still... */ diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index 64b4e019c27..82cdfcdd631 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -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_SUBSURFACE_DIRECT, "SUBSURFACE_DIRECT", 0, "Subsurface Direct", ""}, + {SCE_PASS_SUBSURFACE_INDIRECT, "SUBSURFACE_INDIRECT", 0, "Subsurface Indirect", ""}, + {SCE_PASS_SUBSURFACE_COLOR, "SUBSURFACE_COLOR", 0, "Subsurface Color", ""}, {0, NULL, 0, NULL, NULL} }; diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index a0e1e29ab55..9e580b1626c 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -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_SUBSURFACE_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_SUBSURFACE_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_SUBSURFACE_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) diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index 0d68b999eb2..d073abf112a 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -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_SUBSURFACE_DIRECT) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBSURFACE_DIRECT, RRES_OUT_SUBSURFACE_DIRECT); + if (passflag & SCE_PASS_SUBSURFACE_INDIRECT) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBSURFACE_INDIRECT, RRES_OUT_SUBSURFACE_INDIRECT); + if (passflag & SCE_PASS_SUBSURFACE_COLOR) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBSURFACE_COLOR, RRES_OUT_SUBSURFACE_COLOR); } static void cmp_node_image_add_multilayer_outputs(bNodeTree *ntree, bNode *node, RenderLayer *rl) @@ -385,35 +395,38 @@ void node_cmp_rlayers_force_hidden_passes(bNode *node) for (sock = node->outputs.first; sock; sock = sock->next) sock->flag &= ~SOCK_UNAVAIL; - set_output_visible(node, passflag, RRES_OUT_IMAGE, SCE_PASS_COMBINED); - set_output_visible(node, passflag, RRES_OUT_ALPHA, SCE_PASS_COMBINED); - - set_output_visible(node, passflag, RRES_OUT_Z, SCE_PASS_Z); - set_output_visible(node, passflag, RRES_OUT_NORMAL, SCE_PASS_NORMAL); - set_output_visible(node, passflag, RRES_OUT_VEC, SCE_PASS_VECTOR); - set_output_visible(node, passflag, RRES_OUT_UV, SCE_PASS_UV); - set_output_visible(node, passflag, RRES_OUT_RGBA, SCE_PASS_RGBA); - set_output_visible(node, passflag, RRES_OUT_DIFF, SCE_PASS_DIFFUSE); - set_output_visible(node, passflag, RRES_OUT_SPEC, SCE_PASS_SPEC); - set_output_visible(node, passflag, RRES_OUT_SHADOW, SCE_PASS_SHADOW); - set_output_visible(node, passflag, RRES_OUT_AO, SCE_PASS_AO); - set_output_visible(node, passflag, RRES_OUT_REFLECT, SCE_PASS_REFLECT); - set_output_visible(node, passflag, RRES_OUT_REFRACT, SCE_PASS_REFRACT); - set_output_visible(node, passflag, RRES_OUT_INDIRECT, SCE_PASS_INDIRECT); - set_output_visible(node, passflag, RRES_OUT_INDEXOB, SCE_PASS_INDEXOB); - set_output_visible(node, passflag, RRES_OUT_INDEXMA, SCE_PASS_INDEXMA); - set_output_visible(node, passflag, RRES_OUT_MIST, SCE_PASS_MIST); - set_output_visible(node, passflag, RRES_OUT_EMIT, SCE_PASS_EMIT); - set_output_visible(node, passflag, RRES_OUT_ENV, SCE_PASS_ENVIRONMENT); - set_output_visible(node, passflag, RRES_OUT_DIFF_DIRECT, SCE_PASS_DIFFUSE_DIRECT); - set_output_visible(node, passflag, RRES_OUT_DIFF_INDIRECT, SCE_PASS_DIFFUSE_INDIRECT); - set_output_visible(node, passflag, RRES_OUT_DIFF_COLOR, SCE_PASS_DIFFUSE_COLOR); - set_output_visible(node, passflag, RRES_OUT_GLOSSY_DIRECT, SCE_PASS_GLOSSY_DIRECT); - set_output_visible(node, passflag, RRES_OUT_GLOSSY_INDIRECT, SCE_PASS_GLOSSY_INDIRECT); - set_output_visible(node, passflag, RRES_OUT_GLOSSY_COLOR, SCE_PASS_GLOSSY_COLOR); - 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_IMAGE, SCE_PASS_COMBINED); + set_output_visible(node, passflag, RRES_OUT_ALPHA, SCE_PASS_COMBINED); + + set_output_visible(node, passflag, RRES_OUT_Z, SCE_PASS_Z); + set_output_visible(node, passflag, RRES_OUT_NORMAL, SCE_PASS_NORMAL); + set_output_visible(node, passflag, RRES_OUT_VEC, SCE_PASS_VECTOR); + set_output_visible(node, passflag, RRES_OUT_UV, SCE_PASS_UV); + set_output_visible(node, passflag, RRES_OUT_RGBA, SCE_PASS_RGBA); + set_output_visible(node, passflag, RRES_OUT_DIFF, SCE_PASS_DIFFUSE); + set_output_visible(node, passflag, RRES_OUT_SPEC, SCE_PASS_SPEC); + set_output_visible(node, passflag, RRES_OUT_SHADOW, SCE_PASS_SHADOW); + set_output_visible(node, passflag, RRES_OUT_AO, SCE_PASS_AO); + set_output_visible(node, passflag, RRES_OUT_REFLECT, SCE_PASS_REFLECT); + set_output_visible(node, passflag, RRES_OUT_REFRACT, SCE_PASS_REFRACT); + set_output_visible(node, passflag, RRES_OUT_INDIRECT, SCE_PASS_INDIRECT); + set_output_visible(node, passflag, RRES_OUT_INDEXOB, SCE_PASS_INDEXOB); + set_output_visible(node, passflag, RRES_OUT_INDEXMA, SCE_PASS_INDEXMA); + set_output_visible(node, passflag, RRES_OUT_MIST, SCE_PASS_MIST); + set_output_visible(node, passflag, RRES_OUT_EMIT, SCE_PASS_EMIT); + set_output_visible(node, passflag, RRES_OUT_ENV, SCE_PASS_ENVIRONMENT); + set_output_visible(node, passflag, RRES_OUT_DIFF_DIRECT, SCE_PASS_DIFFUSE_DIRECT); + set_output_visible(node, passflag, RRES_OUT_DIFF_INDIRECT, SCE_PASS_DIFFUSE_INDIRECT); + set_output_visible(node, passflag, RRES_OUT_DIFF_COLOR, SCE_PASS_DIFFUSE_COLOR); + set_output_visible(node, passflag, RRES_OUT_GLOSSY_DIRECT, SCE_PASS_GLOSSY_DIRECT); + set_output_visible(node, passflag, RRES_OUT_GLOSSY_INDIRECT, SCE_PASS_GLOSSY_INDIRECT); + set_output_visible(node, passflag, RRES_OUT_GLOSSY_COLOR, SCE_PASS_GLOSSY_COLOR); + 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_SUBSURFACE_DIRECT, SCE_PASS_SUBSURFACE_DIRECT); + set_output_visible(node, passflag, RRES_OUT_SUBSURFACE_INDIRECT, SCE_PASS_SUBSURFACE_INDIRECT); + set_output_visible(node, passflag, RRES_OUT_SUBSURFACE_COLOR, SCE_PASS_SUBSURFACE_COLOR); } static void node_composit_init_rlayers(const bContext *C, PointerRNA *ptr) diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index f719e09769d..ce15cc33aac 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -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_SUBSURFACE_DIRECT) { + if (channel == -1) return "SubsurfaceDir"; + if (channel == 0) return "SubsurfaceDir.R"; + if (channel == 1) return "SubsurfaceDir.G"; + return "SubsDir.B"; + } + if (passtype == SCE_PASS_SUBSURFACE_INDIRECT) { + if (channel == -1) return "SubsurfaceInd"; + if (channel == 0) return "SubsurfaceInd.R"; + if (channel == 1) return "SubsurfaceInd.G"; + return "SubsInd.B"; + } + if (passtype == SCE_PASS_SUBSURFACE_COLOR) { + if (channel == -1) return "SubsurfaceCol"; + if (channel == 0) return "SubsurfaceCol.R"; + if (channel == 1) return "SubsurfaceCol.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, "SubsurfaceDir") == 0) + return SCE_PASS_SUBSURFACE_DIRECT; + + if (strcmp(str, "SubsurfaceInd") == 0) + return SCE_PASS_SUBSURFACE_INDIRECT; + + if (strcmp(str, "SubsurfaceCol") == 0) + return SCE_PASS_SUBSURFACE_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_SUBSURFACE_DIRECT) + render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_DIRECT); + if (srl->passflag & SCE_PASS_SUBSURFACE_INDIRECT) + render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_INDIRECT); + if (srl->passflag & SCE_PASS_SUBSURFACE_COLOR) + render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_COLOR); } /* sss, previewrender and envmap don't do layers, so we make a default one */ if (rr->layers.first == NULL && !(layername && layername[0])) {