Cycles: switch to squared roughness convention for all nodes.
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Sat, 10 Mar 2018 15:09:22 +0000 (16:09 +0100)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Sat, 10 Mar 2018 17:05:01 +0000 (18:05 +0100)
This was already done for the Principled BSDF to be compatible with typical
baked roughness maps in PBR workflows.

intern/cycles/blender/addon/version_update.py
intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl
intern/cycles/kernel/shaders/node_glass_bsdf.osl
intern/cycles/kernel/shaders/node_glossy_bsdf.osl
intern/cycles/kernel/shaders/node_refraction_bsdf.osl
intern/cycles/kernel/svm/svm_closure.h
intern/cycles/render/nodes.cpp
source/blender/blenkernel/BKE_blender_version.h
source/blender/gpu/shaders/gpu_shader_material.glsl
source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c
source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c

index 90cecec..292f0a1 100644 (file)
@@ -17,6 +17,7 @@
 # <pep8 compliant>
 
 import bpy
+import math
 
 from bpy.app.handlers import persistent
 
@@ -138,6 +139,56 @@ def displacement_principled_nodes(node):
         if node.subsurface_method != 'RANDOM_WALK':
             node.subsurface_method = 'BURLEY'
 
+def square_roughness_node_insert(material, nodetree, traversed):
+    if nodetree in traversed:
+        return
+    traversed.add(nodetree)
+
+    roughness_node_types = {
+        'ShaderNodeBsdfAnisotropic',
+        'ShaderNodeBsdfGlass',
+        'ShaderNodeBsdfGlossy',
+        'ShaderNodeBsdfRefraction'}
+
+    # Update default values
+    for node in nodetree.nodes:
+        if node.bl_idname == 'ShaderNodeGroup':
+            square_roughness_node_insert(material, node.node_tree, traversed)
+        elif node.bl_idname in roughness_node_types:
+            roughness_input = node.inputs['Roughness']
+            roughness_input.default_value = math.sqrt(max(roughness_input.default_value, 0.0))
+
+    # Gather roughness links to replace
+    roughness_links = []
+    for link in nodetree.links:
+        if link.to_node.bl_idname in roughness_node_types and \
+           link.to_socket.identifier == 'Roughness':
+           roughness_links.append(link)
+
+    # Replace links with sqrt node
+    for link in roughness_links:
+        from_node = link.from_node
+        from_socket = link.from_socket
+        to_node = link.to_node
+        to_socket = link.to_socket
+
+        nodetree.links.remove(link)
+
+        node = nodetree.nodes.new(type='ShaderNodeMath')
+        node.operation = 'POWER'
+        node.location[0] = 0.5 * (from_node.location[0] + to_node.location[0]);
+        node.location[1] = 0.5 * (from_node.location[1] + to_node.location[1]);
+
+        nodetree.links.new(from_socket, node.inputs[0])
+        node.inputs[1].default_value = 0.5
+        nodetree.links.new(node.outputs['Value'], to_socket)
+
+def square_roughness_nodes_insert():
+    traversed = set()
+    for material in bpy.data.materials:
+        if check_is_new_shading_material(material):
+            square_roughness_node_insert(material, material.node_tree, traversed)
+
 
 def mapping_node_order_flip(node):
     """
@@ -376,3 +427,7 @@ def do_versions(self):
                 cmat.displacement_method = 'BUMP'
 
         foreach_cycles_node(displacement_principled_nodes)
+
+    if bpy.data.version <= (2, 79, 3):
+        # Switch to squared roughness convention
+        square_roughness_nodes_insert()
index bef6d7e..21e28ec 100644 (file)
@@ -33,27 +33,28 @@ shader node_anisotropic_bsdf(
                T = rotate(T, Rotation * M_2PI, point(0.0, 0.0, 0.0), Normal);
 
        /* compute roughness */
-       float RoughnessU, RoughnessV;
+       float roughness = Roughness * Roughness;
+       float roughness_u, roughness_v;
        float aniso = clamp(Anisotropy, -0.99, 0.99);
 
        if (aniso < 0.0) {
-               RoughnessU = Roughness / (1.0 + aniso);
-               RoughnessV = Roughness * (1.0 + aniso);
+               roughness_u = roughness / (1.0 + aniso);
+               roughness_v = roughness * (1.0 + aniso);
        }
        else {
-               RoughnessU = Roughness * (1.0 - aniso);
-               RoughnessV = Roughness / (1.0 - aniso);
+               roughness_u = roughness * (1.0 - aniso);
+               roughness_v = roughness / (1.0 - aniso);
        }
 
        if (distribution == "sharp")
                BSDF = Color * reflection(Normal);
        else if (distribution == "beckmann")
-               BSDF = Color * microfacet_beckmann_aniso(Normal, T, RoughnessU, RoughnessV);
+               BSDF = Color * microfacet_beckmann_aniso(Normal, T, roughness_u, roughness_v);
        else if (distribution == "GGX")
-               BSDF = Color * microfacet_ggx_aniso(Normal, T, RoughnessU, RoughnessV);
+               BSDF = Color * microfacet_ggx_aniso(Normal, T, roughness_u, roughness_v);
        else if (distribution == "Multiscatter GGX")
-               BSDF = Color * microfacet_multi_ggx_aniso(Normal, T, RoughnessU, RoughnessV, Color);
+               BSDF = Color * microfacet_multi_ggx_aniso(Normal, T, roughness_u, roughness_v, Color);
        else
-               BSDF = Color * ashikhmin_shirley(Normal, T, RoughnessU, RoughnessV);
+               BSDF = Color * ashikhmin_shirley(Normal, T, roughness_u, roughness_v);
 }
 
index a9723a8..2e71386 100644 (file)
@@ -29,16 +29,17 @@ shader node_glass_bsdf(
        float eta = backfacing() ? 1.0 / f : f;
        float cosi = dot(I, Normal);
        float Fr = fresnel_dielectric_cos(cosi, eta);
+       float roughness = Roughness * Roughness;
 
        if (distribution == "sharp")
                BSDF = Color * (Fr * reflection(Normal) + (1.0 - Fr) * refraction(Normal, eta));
        else if (distribution == "beckmann")
-               BSDF = Color * (Fr * microfacet_beckmann(Normal, Roughness) +
-                               (1.0 - Fr) * microfacet_beckmann_refraction(Normal, Roughness, eta));
+               BSDF = Color * (Fr * microfacet_beckmann(Normal, roughness) +
+                               (1.0 - Fr) * microfacet_beckmann_refraction(Normal, roughness, eta));
        else if (distribution == "Multiscatter GGX")
-               BSDF = Color * microfacet_multi_ggx_glass(Normal, Roughness, eta, Color);
+               BSDF = Color * microfacet_multi_ggx_glass(Normal, roughness, eta, Color);
        else if (distribution == "GGX")
-               BSDF = Color * (Fr * microfacet_ggx(Normal, Roughness) +
-                               (1.0 - Fr) * microfacet_ggx_refraction(Normal, Roughness, eta));
+               BSDF = Color * (Fr * microfacet_ggx(Normal, roughness) +
+                               (1.0 - Fr) * microfacet_ggx_refraction(Normal, roughness, eta));
 }
 
index f4ea7e7..7415211 100644 (file)
@@ -24,16 +24,18 @@ shader node_glossy_bsdf(
        normal Normal = N,
        output closure color BSDF = 0)
 {
+       float roughness = Roughness * Roughness;
+
        if (distribution == "sharp")
                BSDF = Color * reflection(Normal);
        else if (distribution == "beckmann")
-               BSDF = Color * microfacet_beckmann(Normal, Roughness);
+               BSDF = Color * microfacet_beckmann(Normal, roughness);
        else if (distribution == "GGX")
-               BSDF = Color * microfacet_ggx(Normal, Roughness);
+               BSDF = Color * microfacet_ggx(Normal, roughness);
        else if (distribution == "Multiscatter GGX")
-               BSDF = Color * microfacet_multi_ggx(Normal, Roughness, Color);
+               BSDF = Color * microfacet_multi_ggx(Normal, roughness, Color);
        else
-               BSDF = Color * ashikhmin_shirley(Normal, vector(0, 0, 0), Roughness, Roughness);
+               BSDF = Color * ashikhmin_shirley(Normal, vector(0, 0, 0), roughness, roughness);
 
 }
 
index 828becf..eaab728 100644 (file)
@@ -26,12 +26,13 @@ shader node_refraction_bsdf(
 {
        float f = max(IOR, 1e-5);
        float eta = backfacing() ? 1.0 / f : f;
+       float roughness = Roughness * Roughness;
 
        if (distribution == "sharp")
                BSDF = Color * refraction(Normal, eta);
        else if (distribution == "beckmann")
-               BSDF = Color * microfacet_beckmann_refraction(Normal, Roughness, eta);
+               BSDF = Color * microfacet_beckmann_refraction(Normal, roughness, eta);
        else if (distribution == "GGX")
-               BSDF = Color * microfacet_ggx_refraction(Normal, Roughness, eta);
+               BSDF = Color * microfacet_ggx_refraction(Normal, roughness, eta);
 }
 
index a54095e..886a133 100644 (file)
@@ -468,10 +468,12 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
                                break;
                        }
 
+                       float roughness = sqr(param1);
+
                        bsdf->N = N;
                        bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
-                       bsdf->alpha_x = param1;
-                       bsdf->alpha_y = param1;
+                       bsdf->alpha_x = roughness;
+                       bsdf->alpha_y = roughness;
                        bsdf->ior = 0.0f;
                        bsdf->extra = NULL;
 
@@ -525,8 +527,9 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
                                        sd->flag |= bsdf_refraction_setup(bsdf);
                                }
                                else {
-                                       bsdf->alpha_x = param1;
-                                       bsdf->alpha_y = param1;
+                                       float roughness = sqr(param1);
+                                       bsdf->alpha_x = roughness;
+                                       bsdf->alpha_y = roughness;
                                        bsdf->ior = eta;
 
                                        if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID)
@@ -557,7 +560,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
                        /* fresnel */
                        float cosNO = dot(N, sd->I);
                        float fresnel = fresnel_dielectric_cos(cosNO, eta);
-                       float roughness = param1;
+                       float roughness = sqr(param1);
 
                        /* reflection */
 #ifdef __CAUSTICS_TRICKS__
@@ -611,8 +614,9 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
                        bsdf->extra = extra;
                        bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
 
-                       bsdf->alpha_x = param1;
-                       bsdf->alpha_y = param1;
+                       float roughness = sqr(param1);
+                       bsdf->alpha_x = roughness;
+                       bsdf->alpha_y = roughness;
                        float eta = fmaxf(param2, 1e-5f);
                        bsdf->ior = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
 
@@ -648,7 +652,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
                                        bsdf->T = rotate_around_axis(bsdf->T, bsdf->N, rotation * M_2PI_F);
 
                                /* compute roughness */
-                               float roughness = param1;
+                               float roughness = sqr(param1);
                                float anisotropy = clamp(param2, -0.99f, 0.99f);
 
                                if(anisotropy < 0.0f) {
index f117962..e36a75f 100644 (file)
@@ -1858,7 +1858,7 @@ NODE_DEFINE(AnisotropicBsdfNode)
 
        SOCKET_IN_VECTOR(tangent, "Tangent", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TANGENT);
 
-       SOCKET_IN_FLOAT(roughness, "Roughness", 0.2f);
+       SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
        SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.5f);
        SOCKET_IN_FLOAT(rotation, "Rotation", 0.0f);
 
@@ -1918,7 +1918,7 @@ NODE_DEFINE(GlossyBsdfNode)
        distribution_enum.insert("ashikhmin_shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID);
        distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID);
        SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_ID);
-       SOCKET_IN_FLOAT(roughness, "Roughness", 0.2f);
+       SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
 
        SOCKET_OUT_CLOSURE(BSDF, "BSDF");
 
index 6cd93e1..b5d906b 100644 (file)
@@ -28,7 +28,7 @@
  * and keep comment above the defines.
  * Use STRINGIFY() rather than defining with quotes */
 #define BLENDER_VERSION         279
-#define BLENDER_SUBVERSION      3
+#define BLENDER_SUBVERSION      4
 /* Several breakages with 270, e.g. constraint deg vs rad */
 #define BLENDER_MINVERSION      270
 #define BLENDER_MINSUBVERSION   6
index 1f5ffbd..a0ca719 100644 (file)
@@ -2599,7 +2599,8 @@ void node_bsdf_glossy(vec4 color, float roughness, vec3 N, out vec4 result)
                vec3 light_specular = gl_LightSource[i].specular.rgb;
 
                /* we mix in some diffuse so low roughness still shows up */
-               float bsdf = 0.5 * pow(max(dot(N, H), 0.0), 1.0 / roughness);
+               float r2 = roughness * roughness;
+               float bsdf = 0.5 * pow(max(dot(N, H), 0.0), 1.0 / r2);
                bsdf += 0.5 * max(dot(N, light_position), 0.0);
                L += light_specular * bsdf;
        }
index 01ca0bd..6410441 100644 (file)
@@ -31,7 +31,7 @@
 
 static bNodeSocketTemplate sh_node_bsdf_anisotropic_in[] = {
        {       SOCK_RGBA, 1, N_("Color"),                      0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
-       {       SOCK_FLOAT, 1, N_("Roughness"),     0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+       {       SOCK_FLOAT, 1, N_("Roughness"),     0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
        {       SOCK_FLOAT, 1, N_("Anisotropy"),        0.5f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f},
        {       SOCK_FLOAT, 1, N_("Rotation"),          0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
        {       SOCK_VECTOR, 1, N_("Normal"),           0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
index 7e1bc97..c13fd89 100644 (file)
@@ -31,7 +31,7 @@
 
 static bNodeSocketTemplate sh_node_bsdf_glossy_in[] = {
        {       SOCK_RGBA,  1, N_("Color"),             0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
-       {       SOCK_FLOAT, 1, N_("Roughness"), 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+       {       SOCK_FLOAT, 1, N_("Roughness"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
        {       SOCK_VECTOR, 1, N_("Normal"),   0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
        {       -1, 0, ""       }
 };