From b3ca6d8a2f4f866b323fc2df0a3beff577218c27 Mon Sep 17 00:00:00 2001 From: Pascal Schoen Date: Tue, 26 Jul 2016 12:30:25 +0200 Subject: [PATCH] Improvement of the SSS in the Disney shader * Now the bump normal is correctly used for the SSS. * SSS in Disney uses the Disney diffuse shader --- intern/cycles/kernel/closure/bsdf.h | 3 +++ intern/cycles/kernel/closure/bssrdf.h | 24 ++++++++++++++------ intern/cycles/kernel/kernel_subsurface.h | 22 +++++++++++++----- intern/cycles/kernel/osl/osl_bssrdf.cpp | 2 ++ intern/cycles/kernel/osl/osl_shader.cpp | 4 +++- intern/cycles/kernel/svm/svm_closure.h | 29 ++++++++++++++---------- intern/cycles/kernel/svm/svm_types.h | 4 +++- intern/cycles/render/nodes.cpp | 7 ++++++ intern/cycles/render/nodes.h | 2 ++ 9 files changed, 70 insertions(+), 27 deletions(-) diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h index 8ede88f4b4a..1f225e1e96c 100644 --- a/intern/cycles/kernel/closure/bsdf.h +++ b/intern/cycles/kernel/closure/bsdf.h @@ -121,6 +121,7 @@ ccl_device int bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const Shader eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_DISNEY_DIFFUSE_ID: + case CLOSURE_BSDF_BSSRDF_DISNEY_ID: label = bsdf_disney_diffuse_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; @@ -217,6 +218,7 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade eval = bsdf_hair_transmission_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_DISNEY_DIFFUSE_ID: + case CLOSURE_BSDF_BSSRDF_DISNEY_ID: eval = bsdf_disney_diffuse_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_DISNEY_SHEEN_ID: @@ -291,6 +293,7 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade eval = bsdf_hair_transmission_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_DISNEY_DIFFUSE_ID: + case CLOSURE_BSDF_BSSRDF_DISNEY_ID: eval = bsdf_disney_diffuse_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_DISNEY_SHEEN_ID: diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h index c24720cefbe..a1920841e6e 100644 --- a/intern/cycles/kernel/closure/bssrdf.h +++ b/intern/cycles/kernel/closure/bssrdf.h @@ -329,10 +329,20 @@ ccl_device int bssrdf_setup(ShaderClosure *sc, ClosureType type) { if(sc->data0 < BSSRDF_MIN_RADIUS) { /* revert to diffuse BSDF if radius too small */ - sc->data0 = 0.0f; - sc->data1 = 0.0f; - int flag = bsdf_diffuse_setup(sc); - sc->type = CLOSURE_BSDF_BSSRDF_ID; + int flag; + if (type == CLOSURE_BSSRDF_DISNEY_ID) { + sc->data0 = sc->data3; + sc->data1 = 0.0f; + flag = bsdf_disney_diffuse_setup(sc); + sc->type = CLOSURE_BSDF_BSSRDF_DISNEY_ID; + } + else { + sc->data0 = 0.0f; + sc->data1 = 0.0f; + flag = bsdf_diffuse_setup(sc); + sc->type = CLOSURE_BSDF_BSSRDF_ID; + } + return flag; } else { @@ -340,7 +350,7 @@ ccl_device int bssrdf_setup(ShaderClosure *sc, ClosureType type) sc->T.x = saturate(sc->T.x); /* sharpness */ sc->type = type; - if(type == CLOSURE_BSSRDF_BURLEY_ID) { + if (type == CLOSURE_BSSRDF_BURLEY_ID || type == CLOSURE_BSSRDF_DISNEY_ID) { bssrdf_burley_setup(sc); } @@ -354,7 +364,7 @@ ccl_device void bssrdf_sample(ShaderClosure *sc, float xi, float *r, float *h) bssrdf_cubic_sample(sc, xi, r, h); else if(sc->type == CLOSURE_BSSRDF_GAUSSIAN_ID) bssrdf_gaussian_sample(sc, xi, r, h); - else /*if(sc->type == CLOSURE_BSSRDF_BURLEY_ID)*/ + else /*if(sc->type == CLOSURE_BSSRDF_BURLEY_ID || sc->type == CLOSURE_BSSRDF_DISNEY_ID)*/ bssrdf_burley_sample(sc, xi, r, h); } @@ -364,7 +374,7 @@ ccl_device float bssrdf_pdf(ShaderClosure *sc, float r) return bssrdf_cubic_pdf(sc, r); else if(sc->type == CLOSURE_BSSRDF_GAUSSIAN_ID) return bssrdf_gaussian_pdf(sc, r); - else /*if(sc->type == CLOSURE_BSSRDF_BURLEY_ID)*/ + else /*if(sc->type == CLOSURE_BSSRDF_BURLEY_ID || sc->type == CLOSURE_BSSRDF_DISNEY_ID)*/ return bssrdf_burley_pdf(sc, r); } diff --git a/intern/cycles/kernel/kernel_subsurface.h b/intern/cycles/kernel/kernel_subsurface.h index 705b57ba6ff..f64b3472739 100644 --- a/intern/cycles/kernel/kernel_subsurface.h +++ b/intern/cycles/kernel/kernel_subsurface.h @@ -147,14 +147,24 @@ ccl_device void subsurface_scatter_setup_diffuse_bsdf(ShaderData *sd, float3 wei sc->weight = weight; sc->sample_weight = 1.0f; - sc->data0 = 0.0f; - sc->data1 = 0.0f; sc->N = N; - sd->flag |= bsdf_diffuse_setup(sc); + if (sc->type == CLOSURE_BSSRDF_DISNEY_ID) { + sc->data0 = sc->data3; + sd->flag |= bsdf_disney_diffuse_setup(sc); - /* 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; + /* replace CLOSURE_BSDF_DISNEY_DIFFUSE_ID with this special ID so render passes + * can recognize it as not being a regular Disney diffuse closure */ + sc->type = CLOSURE_BSDF_BSSRDF_DISNEY_ID; + } + else { + sc->data0 = 0.0f; + sc->data1 = 0.0f; + sd->flag |= bsdf_diffuse_setup(sc); + + /* 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; + } } else sd->num_closure = 0; diff --git a/intern/cycles/kernel/osl/osl_bssrdf.cpp b/intern/cycles/kernel/osl/osl_bssrdf.cpp index da4afb138f6..f5284653c49 100644 --- a/intern/cycles/kernel/osl/osl_bssrdf.cpp +++ b/intern/cycles/kernel/osl/osl_bssrdf.cpp @@ -41,7 +41,9 @@ #include "kernel_types.h" #include "kernel_montecarlo.h" +#include "closure/bsdf_util.h" #include "closure/bsdf_diffuse.h" +#include "closure/bsdf_disney_diffuse.h" #include "closure/bssrdf.h" CCL_NAMESPACE_BEGIN diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index f58368e6789..a2f1c31a7c5 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -23,7 +23,9 @@ #include "geom/geom_object.h" +#include "closure/bsdf_util.h" #include "closure/bsdf_diffuse.h" +#include "closure/bsdf_disney_diffuse.h" #include "closure/bssrdf.h" #include "osl_bssrdf.h" @@ -278,7 +280,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag, bssrdf->radius = make_float3(0.0f, 0.0f, 0.0f); float3 albedo = - (bssrdf->sc.type == CLOSURE_BSSRDF_BURLEY_ID) + (bssrdf->sc.type == CLOSURE_BSSRDF_BURLEY_ID || bssrdf->sc.type == CLOSURE_BSSRDF_DISNEY_ID) ? bssrdf->albedo : make_float3(0.0f, 0.0f, 0.0f); diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h index 26bde574246..939080658be 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -193,19 +193,18 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * #ifdef __SUBSURFACE__ float3 albedo = baseColor; - float3 subsurf_weight = baseColor * weight * saturate(subsurface) * diffuse_weight; + float3 subsurf_weight = weight * diffuse_weight; float subsurf_sample_weight = fabsf(average(subsurf_weight)); /* disable in case of diffuse ancestor, can't see it well then and * adds considerably noise due to probabilities of continuing path * getting lower and lower */ - float radius_weight = 1.0f; - if(path_flag & PATH_RAY_DIFFUSE_ANCESTOR) - radius_weight = 0.0f; + if (path_flag & PATH_RAY_DIFFUSE_ANCESTOR) + subsurface = 0.0f; if (subsurf_sample_weight > CLOSURE_WEIGHT_CUTOFF && ccl_fetch(sd, num_closure) + 2 < MAX_CLOSURE) { /* radius * scale */ - float3 radius = make_float3(1.0f, 1.0f, 1.0f) * radius_weight; + float3 radius = make_float3(1.0f, 1.0f, 1.0f) * subsurface; /* sharpness */ float sharpness = 0.0f; /* texture color blur */ @@ -218,12 +217,14 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * sc->data0 = radius.x; sc->data1 = texture_blur; sc->data2 = albedo.x; + sc->data3 = roughness; sc->T.x = sharpness; + sc->color0 = baseColor; # ifdef __OSL__ sc->prim = NULL; # endif sc->N = N; - ccl_fetch(sd, flag) |= bssrdf_setup(sc, (ClosureType)CLOSURE_BSSRDF_BURLEY_ID); + ccl_fetch(sd, flag) |= bssrdf_setup(sc, (ClosureType)CLOSURE_BSSRDF_DISNEY_ID); ccl_fetch(sd, num_closure)++; sc_next(sc); @@ -235,12 +236,14 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * sc->data0 = radius.y; sc->data1 = texture_blur; sc->data2 = albedo.y; + sc->data3 = roughness; sc->T.x = sharpness; + sc->color0 = baseColor; # ifdef __OSL__ sc->prim = NULL; # endif sc->N = N; - ccl_fetch(sd, flag) |= bssrdf_setup(sc, (ClosureType)CLOSURE_BSSRDF_BURLEY_ID); + ccl_fetch(sd, flag) |= bssrdf_setup(sc, (ClosureType)CLOSURE_BSSRDF_DISNEY_ID); ccl_fetch(sd, num_closure)++; sc_next(sc); @@ -252,23 +255,24 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * sc->data0 = radius.z; sc->data1 = texture_blur; sc->data2 = albedo.z; + sc->data3 = roughness; sc->T.x = sharpness; + sc->color0 = baseColor; # ifdef __OSL__ sc->prim = NULL; # endif sc->N = N; - ccl_fetch(sd, flag) |= bssrdf_setup(sc, (ClosureType)CLOSURE_BSSRDF_BURLEY_ID); + ccl_fetch(sd, flag) |= bssrdf_setup(sc, (ClosureType)CLOSURE_BSSRDF_DISNEY_ID); ccl_fetch(sd, num_closure)++; sc_next(sc); } } -#endif - +#else /* diffuse */ - if ((1.0f - saturate(subsurface)) * diffuse_weight > 0.0f) { + if (diffuse_weight > 0.0f) { if (ccl_fetch(sd, num_closure) < MAX_CLOSURE) { - float3 diff_weight = weight * (1.0f - saturate(subsurface)) * diffuse_weight; + float3 diff_weight = weight * diffuse_weight; float diff_sample_weight = fabsf(average(diff_weight)); if (diff_sample_weight > CLOSURE_WEIGHT_CUTOFF) { @@ -289,6 +293,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * } } } +#endif /* sheen */ if (diffuse_weight > 0.0f && sheen != 0.0f) { diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 3814093cc0b..f69b4cc5c8e 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -412,11 +412,13 @@ typedef enum ClosureType { /* Special cases */ CLOSURE_BSDF_BSSRDF_ID, + CLOSURE_BSDF_BSSRDF_DISNEY_ID, CLOSURE_BSDF_TRANSPARENT_ID, /* BSSRDF */ CLOSURE_BSSRDF_CUBIC_ID, CLOSURE_BSSRDF_GAUSSIAN_ID, + CLOSURE_BSSRDF_DISNEY_ID, CLOSURE_BSSRDF_BURLEY_ID, /* Other */ @@ -440,7 +442,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_HAIR_REFLECTION_ID) #define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSMISSION_ID && type <= CLOSURE_BSDF_HAIR_TRANSMISSION_ID) -#define CLOSURE_IS_BSDF_BSSRDF(type) (type == CLOSURE_BSDF_BSSRDF_ID) +#define CLOSURE_IS_BSDF_BSSRDF(type) (type == CLOSURE_BSDF_BSSRDF_ID || type == CLOSURE_BSDF_BSSRDF_DISNEY_ID) #define CLOSURE_IS_BSDF_ANISOTROPIC(type) (type >= CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID) #define CLOSURE_IS_BSDF_OR_BSSRDF(type) (type <= CLOSURE_BSSRDF_BURLEY_ID) #define CLOSURE_IS_BSSRDF(type) (type >= CLOSURE_BSSRDF_CUBIC_ID && type <= CLOSURE_BSSRDF_BURLEY_ID) diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 00f6d168c97..a5ea3d48a34 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -2202,6 +2202,13 @@ void DisneyBsdfNode::compile(OSLCompiler& compiler) compiler.add(this, "node_disney_bsdf"); } +bool DisneyBsdfNode::has_bssrdf_bump() +{ + /* detect if anything is plugged into the normal input besides the default */ + ShaderInput *normal_in = input("Normal"); + return (normal_in->link && normal_in->link->parent->special_type != SHADER_SPECIAL_TYPE_GEOMETRY); +} + /* Translucent BSDF Closure */ TranslucentBsdfNode::TranslucentBsdfNode() diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index a509f30e67e..c0f0dc29099 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -420,6 +420,8 @@ public: SHADER_NODE_CLASS(DisneyBsdfNode) bool has_spatial_varying() { return true; } + bool has_surface_bssrdf() { return true; } + bool has_bssrdf_bump(); void compile(SVMCompiler& compiler, ShaderInput *metallic, ShaderInput *subsurface, ShaderInput *specular, ShaderInput *roughness, ShaderInput *specularTint, ShaderInput *anisotropic, ShaderInput *sheen, ShaderInput *sheenTint, ShaderInput *clearcoat, ShaderInput *clearcoatGloss,