Cycles / SSS Render Passes:
authorThomas Dinges <blender@dingto.org>
Fri, 2 Aug 2013 19:57:14 +0000 (19:57 +0000)
committerThomas Dinges <blender@dingto.org>
Fri, 2 Aug 2013 19:57:14 +0000 (19:57 +0000)
* Finished the implementation, Direct and Indirect Passes work now.

Patch by Brecht and myself.

intern/cycles/kernel/closure/bsdf.h
intern/cycles/kernel/kernel_accumulate.h
intern/cycles/kernel/kernel_path.h
intern/cycles/kernel/kernel_subsurface.h
intern/cycles/kernel/kernel_types.h
intern/cycles/kernel/svm/svm_types.h

index b2884953a223c63ae65a8cf524954af809b163c6..5e7b845059dc0218ed032e48a7a682ea6f8aa1cd 100644 (file)
@@ -45,6 +45,7 @@ __device int bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const ShaderCl
 
        switch(sc->type) {
                case CLOSURE_BSDF_DIFFUSE_ID:
 
        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;
                        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:
        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__
                                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:
        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__
                                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:
 
        switch(sc->type) {
                case CLOSURE_BSDF_DIFFUSE_ID:
+               case CLOSURE_BSDF_BSSRDF_ID:
                        bsdf_diffuse_blur(sc, roughness);
                        break;
 #ifdef __SVM__
                        bsdf_diffuse_blur(sc, roughness);
                        break;
 #ifdef __SVM__
index 9e26aa6fa2b74e7cefd26049b22dcbeda8863af0..ca420909bc78a426d88bd0b2d3c908bf1eee0267 100644 (file)
@@ -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->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;
 
                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;
                        eval->diffuse = value;
                else if(CLOSURE_IS_BSDF_GLOSSY(type))
                        eval->glossy = value;
-               else
+               else if(CLOSURE_IS_BSDF_TRANSMISSION(type))
                        eval->transmission = value;
                        eval->transmission = value;
+               else if(CLOSURE_IS_BSDF_BSSRDF(type))
+                       eval->subsurface = value;
        }
        else
                eval->diffuse = 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;
                        eval->diffuse += value;
                else if(CLOSURE_IS_BSDF_GLOSSY(type))
                        eval->glossy += value;
-               else
+               else if(CLOSURE_IS_BSDF_TRANSMISSION(type))
                        eval->transmission += value;
                        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 */
        }
 
                /* 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)
                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);
        }
        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->diffuse *= value;
                eval->glossy *= value;
                eval->transmission *= value;
+               eval->subsurface *= value;
 
                /* skipping transparent, this function is used by for eval(), will be zero then */
        }
 
                /* skipping transparent, this function is used by for eval(), will be zero then */
        }
@@ -139,6 +146,7 @@ __device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
                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_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);
 
                L->emission = make_float3(0.0f, 0.0f, 0.0f);
                L->background = make_float3(0.0f, 0.0f, 0.0f);
@@ -167,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_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 */
                        
                        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;
                }
        }
                        *throughput *= sum;
                }
        }
@@ -233,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_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;
 
                        if(is_lamp) {
                                L->shadow.x += shadow.x*shadow_fac;
@@ -242,7 +252,7 @@ __device_inline void path_radiance_accum_light(PathRadiance *L, float3 throughpu
                }
                else {
                        /* indirectly visible lighting after BSDF bounce */
                }
                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;
                }
        }
                        L->indirect += throughput*sum*shadow;
                }
        }
@@ -282,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_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 = 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
 }
        }
 #endif
 }
@@ -298,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_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);
 
                L->direct_emission = make_float3(0.0f, 0.0f, 0.0f);
                L->indirect = make_float3(0.0f, 0.0f, 0.0f);
@@ -312,8 +325,8 @@ __device_inline float3 path_radiance_sum(KernelGlobals *kg, PathRadiance *L)
                path_radiance_sum_indirect(L);
 
                float3 L_sum = L->emission
                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;
 
                if(!kernel_data.background.transparent)
                        L_sum += L->background;
index 40ecb1be91b99bf7feb3f9e9648da5265b6b33de..2806296ba9337520d470ebeba9c91fa74749b3a6 100644 (file)
@@ -892,7 +892,7 @@ __device_noinline void kernel_path_non_progressive_lighting(KernelGlobals *kg, R
 
                int num_samples;
 
 
                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;
                        num_samples = kernel_data.integrator.diffuse_samples;
                else if(CLOSURE_IS_BSDF_GLOSSY(sc->type))
                        num_samples = kernel_data.integrator.glossy_samples;
index f7bccf7197603a3821584a045ba1ed09f7ffd6a1..4fae961512e95d9c4fc4f8a1648eece78c46ae37 100644 (file)
@@ -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;
 
        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); */
 }
        /* todo: evaluate shading to get blurred textures and bump mapping */
        /* shader_eval_surface(kg, sd, 0.0f, state_flag, SHADER_CONTEXT_SSS); */
 }
index 1644f3eeb951a1f30158695615dc85d3de434df2..03ca04ec132203cdca6afff83a8f956c18776695 100644 (file)
@@ -310,6 +310,7 @@ typedef struct PathRadiance {
        float3 path_diffuse;
        float3 path_glossy;
        float3 path_transmission;
        float3 path_diffuse;
        float3 path_glossy;
        float3 path_transmission;
+       float3 path_subsurface;
 
        float4 shadow;
        float mist;
 
        float4 shadow;
        float mist;
@@ -322,6 +323,7 @@ typedef struct BsdfEval {
        float3 glossy;
        float3 transmission;
        float3 transparent;
        float3 glossy;
        float3 transmission;
        float3 transparent;
+       float3 subsurface;
 } BsdfEval;
 
 #else
 } BsdfEval;
 
 #else
index dbfb8d48fbf317b9b4918331a66fea6943f373d5..dd95f19f175fc6a54fb4c52981b6a56657900cc1 100644 (file)
@@ -371,7 +371,8 @@ typedef enum ClosureType {
        CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID,
        CLOSURE_BSDF_SHARP_GLASS_ID,
        
        CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID,
        CLOSURE_BSDF_SHARP_GLASS_ID,
        
-       /* Transparent */
+       /* Special cases */
+       CLOSURE_BSDF_BSSRDF_ID,
        CLOSURE_BSDF_TRANSPARENT_ID,
 
        /* Other */
        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_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)
 #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)