Cycles: switch to squared roughness convention for all nodes.

This was already done for the Principled BSDF to be compatible with typical
baked roughness maps in PBR workflows.
This commit is contained in:
Brecht Van Lommel 2018-03-10 16:09:22 +01:00
parent 8a76f8dac3
commit 7613ffc944
11 changed files with 99 additions and 34 deletions

@ -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()

@ -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);
}

@ -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));
}

@ -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);
}

@ -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);
}

@ -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) {

@ -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");

@ -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

@ -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;
}

@ -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},

@ -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, "" }
};