Improved the clearcoat part by using GTR1 instead of GTR2
authorPascal Schoen <pascal_schoen@gmx.net>
Mon, 7 Nov 2016 07:13:41 +0000 (08:13 +0100)
committerPascal Schoen <pascal_schoen@gmx.net>
Mon, 7 Nov 2016 07:13:41 +0000 (08:13 +0100)
intern/cycles/kernel/closure/bsdf_microfacet.h
intern/cycles/kernel/osl/osl_closures.cpp
intern/cycles/kernel/shaders/node_disney_bsdf.osl
intern/cycles/kernel/svm/svm_closure.h

index 227150a48babeffa6bff9f204993c3292ae00426..213135b576d6a5391882e1762f21ac9f8226081a 100644 (file)
@@ -38,6 +38,7 @@ CCL_NAMESPACE_BEGIN
 typedef ccl_addr_space struct MicrofacetExtra {
        float3 color, cspec0;
        bool use_fresnel, is_disney_clearcoat;
+       float clearcoat;
 } MicrofacetExtra;
 
 typedef ccl_addr_space struct MicrofacetBsdf {
@@ -253,6 +254,14 @@ ccl_device_forceinline float3 reflection_color(const MicrofacetBsdf *bsdf, float
     return F;
 }
 
+ccl_device_forceinline float D_GTR1(float NdotH, float alpha)
+{
+    if (alpha >= 1.0f) return M_1_PI_F;
+       float alpha2 = alpha*alpha;
+    float t = 1.0f + (alpha2 - 1.0f) * NdotH*NdotH;
+    return (alpha2 - 1.0f) / (M_1_PI_F * logf(alpha2) * t);
+}
+
 /* GGX microfacet with Smith shadow-masking from:
  *
  * Microfacet Models for Refraction through Rough Surfaces
@@ -404,14 +413,18 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
                        float cosThetaM2 = cosThetaM * cosThetaM;
                        float cosThetaM4 = cosThetaM2 * cosThetaM2;
                        float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
-                       D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
 
-                       if(bsdf->extra) {
-                               if(bsdf->extra->is_disney_clearcoat) {
-                    /* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */
-                                       alpha2 = 0.0625f;
-                }
+                       if(bsdf->extra && bsdf->extra->is_disney_clearcoat) {
+                               /* use GTR1 for clearcoat */
+                               D = D_GTR1(cosThetaM, bsdf->alpha_x);
+
+                               /* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */
+                               alpha2 = 0.0625f;
             }
+                       else {
+                               /* use GTR2 otherwise */
+                               D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
+                       }
 
                        /* eq. 34: now calculate G1(i,m) and G1(o,m) */
                        G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
@@ -460,6 +473,9 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
                float common = D * 0.25f / cosNO;
 
         float3 F = reflection_color(bsdf, omega_in, m);
+               if(bsdf->extra && bsdf->extra->is_disney_clearcoat) {
+                       F *= 0.25f * bsdf->extra->clearcoat;
+               }
 
                float3 out = F * G * common;
 
@@ -592,20 +608,26 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
                                                        float cosThetaM2 = cosThetaM * cosThetaM;
                                                        float cosThetaM4 = cosThetaM2 * cosThetaM2;
                                                        float tanThetaM2 = 1/(cosThetaM2) - 1;
-                                                       D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
 
                                                        /* eval BRDF*cosNI */
                                                        float cosNI = dot(N, *omega_in);
 
-                                                       /* eq. 34: now calculate G1(i,m) */
                                                        if(bsdf->extra && bsdf->extra->is_disney_clearcoat) {
+                                                               /* use GTR1 for clearcoat */
+                                                               D = D_GTR1(cosThetaM, bsdf->alpha_x);
+
                                                                /* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */
                                                                alpha2 = 0.0625f;
 
                                                                /* recalculate G1o */
                                                                G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
                             }
+                                                       else {
+                                                               /* use GTR2 otherwise */
+                                                               D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
+                                                       }
 
+                                                       /* eq. 34: now calculate G1(i,m) */
                                                        G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); 
                                                }
                                                else {
@@ -639,6 +661,9 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
                                                *pdf = common;
 
                         float3 F = reflection_color(bsdf, *omega_in, m);
+                                               if(bsdf->extra && bsdf->extra->is_disney_clearcoat) {
+                                                       F *= 0.25f * bsdf->extra->clearcoat;
+                                               }
 
                                                *eval = G1i * common * F;
                                        }
index 1dac0910a362a363b452d51f016f27e1fb0a0529..4d51dda7197345706515de41b2a8b22ad8f4d148 100644 (file)
@@ -205,6 +205,7 @@ public:
                        bsdf->alpha_y = 0.1f * (1.0f - clearcoat_gloss) + 0.001f * clearcoat_gloss;
 
                        bsdf->extra->cspec0 = make_float3(0.04f, 0.04f, 0.04f);
+                       bsdf->extra->clearcoat = clearcoat;
 
                        return bsdf;
                }
index 7e78c4cfed410b8009a8e9d4a1dcd3dc77504388..48aad1d90c9bdf7412c477e945c0d1adae3828ec 100644 (file)
@@ -113,7 +113,7 @@ shader node_disney_bsdf(
     }
     
     if (Clearcoat > 1e-5) {
-        BSDF = BSDF + 0.25 * Clearcoat * disney_clearcoat(ClearcoatNormal, Clearcoat, ClearcoatGloss);
+        BSDF = BSDF + disney_clearcoat(ClearcoatNormal, Clearcoat, ClearcoatGloss);
     }
 }
 
index db6c1ec4159fb7af1c02d53b221a13bca2d53102..213265b2d37e50903b34e489a54e56609cc9ba06 100644 (file)
@@ -432,9 +432,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
                        if(kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0) {
 #endif
                                if(clearcoat > CLOSURE_WEIGHT_CUTOFF) {
-                                       float3 clearcoat_weight = 0.25f * clearcoat * weight;
-
-                                       MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), clearcoat_weight);
+                                       MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
                                        MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
 
                                        if(bsdf && extra) {
@@ -446,6 +444,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
                                                bsdf->alpha_y = 0.1f * (1.0f - clearcoat_gloss) + 0.001f * clearcoat_gloss;
 
                                                bsdf->extra->cspec0 = make_float3(0.04f, 0.04f, 0.04f);
+                                               bsdf->extra->clearcoat = clearcoat;
 
                                                /* setup bsdf */
                                                ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_clearcoat_setup(bsdf);