diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 53c92e0bab7..db86fb7538b 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -136,7 +136,6 @@ set(SRC_KERNEL_CLOSURE_HEADERS closure/emissive.h closure/volume.h closure/bsdf_principled_diffuse.h - closure/bsdf_principled_sheen.h closure/bsdf_hair_principled.h ) diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h index 00e238d296e..d6f9734dacb 100644 --- a/intern/cycles/kernel/closure/bsdf.h +++ b/intern/cycles/kernel/closure/bsdf.h @@ -18,7 +18,6 @@ #include "kernel/closure/bsdf_hair.h" #include "kernel/closure/bsdf_hair_principled.h" #include "kernel/closure/bsdf_principled_diffuse.h" -#include "kernel/closure/bsdf_principled_sheen.h" #include "kernel/closure/bssrdf.h" #include "kernel/closure/volume.h" // clang-format on @@ -210,11 +209,6 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg, *sampled_roughness = one_float2(); *eta = 1.0f; break; - case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID: - label = bsdf_principled_sheen_sample(sc, Ng, sd->wi, rand_xy, eval, wo, pdf); - *sampled_roughness = one_float2(); - *eta = 1.0f; - break; case CLOSURE_BSDF_SHEEN_ID: label = bsdf_sheen_sample(sc, Ng, sd->wi, rand_xy, eval, wo, pdf); *sampled_roughness = one_float2(); @@ -351,10 +345,6 @@ ccl_device_inline void bsdf_roughness_eta(const KernelGlobals kg, *roughness = one_float2(); *eta = 1.0f; break; - case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID: - *roughness = one_float2(); - *eta = 1.0f; - break; case CLOSURE_BSDF_SHEEN_ID: alpha = ((ccl_private SheenBsdf *)sc)->roughness; *roughness = make_float2(alpha, alpha); @@ -439,7 +429,6 @@ ccl_device_inline int bsdf_label(const KernelGlobals kg, case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID: label = LABEL_REFLECT | LABEL_DIFFUSE; break; - case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID: case CLOSURE_BSDF_SHEEN_ID: label = LABEL_REFLECT | LABEL_DIFFUSE; break; @@ -534,9 +523,6 @@ ccl_device_inline case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID: eval = bsdf_principled_diffuse_eval(sc, sd->wi, wo, pdf); break; - case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID: - eval = bsdf_principled_sheen_eval(sc, sd->wi, wo, pdf); - break; case CLOSURE_BSDF_SHEEN_ID: eval = bsdf_sheen_eval(sc, sd->wi, wo, pdf); break; @@ -615,10 +601,6 @@ ccl_device_inline Spectrum bsdf_albedo(ccl_private const ShaderData *sd, albedo *= bsdf_microfacet_estimate_fresnel( sd, (ccl_private const MicrofacetBsdf *)sc, reflection, transmission); } - else if (sc->type == CLOSURE_BSDF_PRINCIPLED_SHEEN_ID) { - kernel_assert(reflection); - albedo *= ((ccl_private const PrincipledSheenBsdf *)sc)->avg_value; - } else if (sc->type == CLOSURE_BSDF_HAIR_PRINCIPLED_ID) { /* TODO(lukas): Principled Hair could also be split into a glossy and a transmission component, * similar to Glass BSDFs. */ diff --git a/intern/cycles/kernel/closure/bsdf_principled_sheen.h b/intern/cycles/kernel/closure/bsdf_principled_sheen.h deleted file mode 100644 index ec07aea5d23..00000000000 --- a/intern/cycles/kernel/closure/bsdf_principled_sheen.h +++ /dev/null @@ -1,111 +0,0 @@ -/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation - * - * SPDX-License-Identifier: Apache-2.0 */ - -#pragma once - -/* DISNEY PRINCIPLED SHEEN BRDF - * - * Shading model by Brent Burley (Disney): "Physically Based Shading at Disney" (2012) - */ - -#include "kernel/closure/bsdf_util.h" - -CCL_NAMESPACE_BEGIN - -typedef struct PrincipledSheenBsdf { - SHADER_CLOSURE_BASE; - float avg_value; -} PrincipledSheenBsdf; - -static_assert(sizeof(ShaderClosure) >= sizeof(PrincipledSheenBsdf), - "PrincipledSheenBsdf is too large!"); - -ccl_device_inline float calculate_avg_principled_sheen_brdf(float3 N, float3 I) -{ - /* To compute the average, we set the half-vector to the normal, resulting in - * NdotI = NdotL = NdotV = LdotH */ - float NdotI = dot(N, I); - if (NdotI < 0.0f) { - return 0.0f; - } - - return schlick_fresnel(NdotI) * NdotI; -} - -ccl_device Spectrum -calculate_principled_sheen_brdf(float3 N, float3 V, float3 L, float3 H, ccl_private float *pdf) -{ - float NdotL = dot(N, L); - float NdotV = dot(N, V); - - if (NdotL < 0 || NdotV < 0) { - *pdf = 0.0f; - return zero_spectrum(); - } - - float LdotH = dot(L, H); - - float value = schlick_fresnel(LdotH) * NdotL; - - return make_spectrum(value); -} - -ccl_device int bsdf_principled_sheen_setup(ccl_private const ShaderData *sd, - ccl_private PrincipledSheenBsdf *bsdf) -{ - bsdf->type = CLOSURE_BSDF_PRINCIPLED_SHEEN_ID; - bsdf->avg_value = calculate_avg_principled_sheen_brdf(bsdf->N, sd->wi); - bsdf->sample_weight *= bsdf->avg_value; - return SD_BSDF | SD_BSDF_HAS_EVAL; -} - -ccl_device Spectrum bsdf_principled_sheen_eval(ccl_private const ShaderClosure *sc, - const float3 wi, - const float3 wo, - ccl_private float *pdf) -{ - ccl_private const PrincipledSheenBsdf *bsdf = (ccl_private const PrincipledSheenBsdf *)sc; - const float3 N = bsdf->N; - - if (dot(N, wo) > 0.0f) { - const float3 V = wi; - const float3 L = wo; - const float3 H = normalize(L + V); - - *pdf = fmaxf(dot(N, wo), 0.0f) * M_1_PI_F; - return calculate_principled_sheen_brdf(N, V, L, H, pdf); - } - else { - *pdf = 0.0f; - return zero_spectrum(); - } -} - -ccl_device int bsdf_principled_sheen_sample(ccl_private const ShaderClosure *sc, - float3 Ng, - float3 wi, - float2 rand, - ccl_private Spectrum *eval, - ccl_private float3 *wo, - ccl_private float *pdf) -{ - ccl_private const PrincipledSheenBsdf *bsdf = (ccl_private const PrincipledSheenBsdf *)sc; - - float3 N = bsdf->N; - - sample_cos_hemisphere(N, rand, wo, pdf); - - if (dot(Ng, *wo) > 0) { - float3 H = normalize(wi + *wo); - - *eval = calculate_principled_sheen_brdf(N, wi, *wo, H, pdf); - } - else { - *eval = zero_spectrum(); - *pdf = 0.0f; - } - return LABEL_REFLECT | LABEL_DIFFUSE; -} - -CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/closures_setup.h b/intern/cycles/kernel/osl/closures_setup.h index d929e77d246..52460aa9581 100644 --- a/intern/cycles/kernel/osl/closures_setup.h +++ b/intern/cycles/kernel/osl/closures_setup.h @@ -21,7 +21,6 @@ #include "kernel/closure/bsdf_hair.h" #include "kernel/closure/bsdf_hair_principled.h" #include "kernel/closure/bsdf_principled_diffuse.h" -#include "kernel/closure/bsdf_principled_sheen.h" #include "kernel/closure/volume.h" #include "kernel/closure/bsdf_diffuse_ramp.h" #include "kernel/closure/bsdf_phong_ramp.h" @@ -651,29 +650,6 @@ ccl_device void osl_closure_principled_diffuse_setup( sd->flag |= bsdf_principled_diffuse_setup(bsdf); } -ccl_device void osl_closure_principled_sheen_setup( - KernelGlobals kg, - ccl_private ShaderData *sd, - uint32_t path_flag, - float3 weight, - ccl_private const PrincipledSheenClosure *closure) -{ - if (osl_closure_skip(kg, sd, path_flag, LABEL_DIFFUSE)) { - return; - } - - ccl_private PrincipledSheenBsdf *bsdf = (ccl_private PrincipledSheenBsdf *)bsdf_alloc( - sd, sizeof(PrincipledSheenBsdf), rgb_to_spectrum(weight)); - if (!bsdf) { - return; - } - - bsdf->N = closure->N; - bsdf->avg_value = 0.0f; - - sd->flag |= bsdf_principled_sheen_setup(sd, bsdf); -} - /* Variable cone emissive closure * * This primitive emits in a cone having a configurable penumbra area where the light decays to 0 diff --git a/intern/cycles/kernel/osl/closures_template.h b/intern/cycles/kernel/osl/closures_template.h index c6d6e755542..cb6a5cabd5f 100644 --- a/intern/cycles/kernel/osl/closures_template.h +++ b/intern/cycles/kernel/osl/closures_template.h @@ -137,10 +137,6 @@ OSL_CLOSURE_STRUCT_BEGIN(PrincipledDiffuse, principled_diffuse) OSL_CLOSURE_STRUCT_MEMBER(PrincipledDiffuse, FLOAT, float, roughness, NULL) OSL_CLOSURE_STRUCT_END(PrincipledDiffuse, principled_diffuse) -OSL_CLOSURE_STRUCT_BEGIN(PrincipledSheen, principled_sheen) - OSL_CLOSURE_STRUCT_MEMBER(PrincipledSheen, VECTOR, packed_float3, N, NULL) -OSL_CLOSURE_STRUCT_END(PrincipledSheen, principled_sheen) - OSL_CLOSURE_STRUCT_BEGIN(GenericEmissive, emission) OSL_CLOSURE_STRUCT_END(GenericEmissive, emission) diff --git a/intern/cycles/kernel/osl/shaders/node_principled_bsdf.osl b/intern/cycles/kernel/osl/shaders/node_principled_bsdf.osl index 57e59d32ffe..0145a8752ca 100644 --- a/intern/cycles/kernel/osl/shaders/node_principled_bsdf.osl +++ b/intern/cycles/kernel/osl/shaders/node_principled_bsdf.osl @@ -19,7 +19,8 @@ shader node_principled_bsdf(string distribution = "multi_ggx", float Anisotropic = 0.0, float AnisotropicRotation = 0.0, float Sheen = 0.0, - float SheenTint = 0.5, + float SheenRoughness = 0.5, + color SheenTint = 0.5, float Clearcoat = 0.0, float ClearcoatRoughness = 0.03, float IOR = 1.45, @@ -64,9 +65,7 @@ shader node_principled_bsdf(string distribution = "multi_ggx", } if (Sheen > 1e-5) { - color sheen_color = mix(color(1.0), m_ctint, SheenTint); - - BSDF += sheen_color * Sheen * principled_sheen(Normal); + BSDF += SheenTint * Sheen * sheen(Normal, SheenRoughness); } BSDF *= diffuse_weight; diff --git a/intern/cycles/kernel/osl/shaders/stdcycles.h b/intern/cycles/kernel/osl/shaders/stdcycles.h index 0e9036a286b..b4381706da9 100644 --- a/intern/cycles/kernel/osl/shaders/stdcycles.h +++ b/intern/cycles/kernel/osl/shaders/stdcycles.h @@ -26,7 +26,6 @@ closure color ashikhmin_velvet(normal N, float sigma) BUILTIN; closure color sheen(normal N, float roughness) BUILTIN; closure color ambient_occlusion() BUILTIN; closure color principled_diffuse(normal N, float roughness) BUILTIN; -closure color principled_sheen(normal N) BUILTIN; /* Needed to pass along the color for multi-scattering saturation adjustment, * otherwise could be replaced by microfacet() */ diff --git a/intern/cycles/kernel/svm/closure.h b/intern/cycles/kernel/svm/closure.h index 39844158fce..d3c4e627f49 100644 --- a/intern/cycles/kernel/svm/closure.h +++ b/intern/cycles/kernel/svm/closure.h @@ -94,7 +94,8 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, float specular_tint = stack_load_float(stack, specular_tint_offset); float anisotropic = stack_load_float(stack, anisotropic_offset); float sheen = stack_load_float(stack, sheen_offset); - float sheen_tint = stack_load_float(stack, sheen_tint_offset); + float3 sheen_tint = stack_load_float3(stack, sheen_tint_offset); + float sheen_roughness = stack_load_float(stack, data_node2.w); float clearcoat = stack_load_float(stack, clearcoat_offset); float clearcoat_roughness = stack_load_float(stack, clearcoat_roughness_offset); float transmission = stack_load_float(stack, transmission_offset); @@ -220,23 +221,17 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, /* sheen */ if (diffuse_weight > CLOSURE_WEIGHT_CUTOFF && sheen > CLOSURE_WEIGHT_CUTOFF) { - float m_cdlum = linear_rgb_to_gray(kg, base_color); - float3 m_ctint = m_cdlum > 0.0f ? base_color / m_cdlum : - one_float3(); // normalize lum. to isolate hue+sat + Spectrum sheen_weight = weight * sheen * rgb_to_spectrum(sheen_tint) * diffuse_weight; - /* color of the sheen component */ - float3 sheen_color = make_float3(1.0f - sheen_tint) + m_ctint * sheen_tint; - - Spectrum sheen_weight = weight * sheen * rgb_to_spectrum(sheen_color) * diffuse_weight; - - ccl_private PrincipledSheenBsdf *bsdf = (ccl_private PrincipledSheenBsdf *)bsdf_alloc( - sd, sizeof(PrincipledSheenBsdf), sheen_weight); + ccl_private SheenBsdf *bsdf = (ccl_private SheenBsdf *)bsdf_alloc( + sd, sizeof(SheenBsdf), sheen_weight); if (bsdf) { bsdf->N = N; + bsdf->roughness = sheen_roughness; /* setup bsdf */ - sd->flag |= bsdf_principled_sheen_setup(sd, bsdf); + sd->flag |= bsdf_sheen_setup(kg, sd, bsdf); } } diff --git a/intern/cycles/kernel/svm/types.h b/intern/cycles/kernel/svm/types.h index b22a7737775..418dd589b83 100644 --- a/intern/cycles/kernel/svm/types.h +++ b/intern/cycles/kernel/svm/types.h @@ -415,7 +415,6 @@ typedef enum ClosureType { CLOSURE_BSDF_OREN_NAYAR_ID, CLOSURE_BSDF_DIFFUSE_RAMP_ID, CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID, - CLOSURE_BSDF_PRINCIPLED_SHEEN_ID, CLOSURE_BSDF_SHEEN_ID, CLOSURE_BSDF_DIFFUSE_TOON_ID, CLOSURE_BSDF_TRANSLUCENT_ID, diff --git a/intern/cycles/scene/shader_nodes.cpp b/intern/cycles/scene/shader_nodes.cpp index e463c0a0f81..2664f3dc15e 100644 --- a/intern/cycles/scene/shader_nodes.cpp +++ b/intern/cycles/scene/shader_nodes.cpp @@ -2661,7 +2661,8 @@ NODE_DEFINE(PrincipledBsdfNode) SOCKET_IN_FLOAT(specular_tint, "Specular Tint", 0.0f); SOCKET_IN_FLOAT(anisotropic, "Anisotropic", 0.0f); SOCKET_IN_FLOAT(sheen, "Sheen", 0.0f); - SOCKET_IN_FLOAT(sheen_tint, "Sheen Tint", 0.0f); + SOCKET_IN_FLOAT(sheen_roughness, "Sheen Roughness", 0.5f); + SOCKET_IN_COLOR(sheen_tint, "Sheen Tint", one_float3()); SOCKET_IN_FLOAT(clearcoat, "Clearcoat", 0.0f); SOCKET_IN_FLOAT(clearcoat_roughness, "Clearcoat Roughness", 0.03f); SOCKET_IN_FLOAT(ior, "IOR", 0.0f); @@ -2771,6 +2772,7 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler, ShaderInput *p_specular_tint, ShaderInput *p_anisotropic, ShaderInput *p_sheen, + ShaderInput *p_sheen_roughness, ShaderInput *p_sheen_tint, ShaderInput *p_clearcoat, ShaderInput *p_clearcoat_roughness, @@ -2796,6 +2798,7 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler, int specular_tint_offset = compiler.stack_assign(p_specular_tint); int anisotropic_offset = compiler.stack_assign(p_anisotropic); int sheen_offset = compiler.stack_assign(p_sheen); + int sheen_roughness_offset = compiler.stack_assign(p_sheen_roughness); int sheen_tint_offset = compiler.stack_assign(p_sheen_tint); int clearcoat_offset = compiler.stack_assign(p_clearcoat); int clearcoat_roughness_offset = compiler.stack_assign(p_clearcoat_roughness); @@ -2827,7 +2830,7 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler, ior_offset, transmission_offset, anisotropic_rotation_offset, SVM_STACK_INVALID), distribution, subsurface_method, - SVM_STACK_INVALID); + sheen_roughness_offset); float3 bc_default = get_float3(base_color_in->socket_type); @@ -2864,6 +2867,7 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler) input("Specular Tint"), input("Anisotropic"), input("Sheen"), + input("Sheen Roughness"), input("Sheen Tint"), input("Clearcoat"), input("Clearcoat Roughness"), diff --git a/intern/cycles/scene/shader_nodes.h b/intern/cycles/scene/shader_nodes.h index 82909cbdf30..764e0cc9c52 100644 --- a/intern/cycles/scene/shader_nodes.h +++ b/intern/cycles/scene/shader_nodes.h @@ -526,6 +526,7 @@ class PrincipledBsdfNode : public BsdfBaseNode { ShaderInput *specular_tint, ShaderInput *anisotropic, ShaderInput *sheen, + ShaderInput *sheen_roughness, ShaderInput *sheen_tint, ShaderInput *clearcoat, ShaderInput *clearcoat_roughness, @@ -545,7 +546,8 @@ class PrincipledBsdfNode : public BsdfBaseNode { NODE_SOCKET_API(float, specular_tint) NODE_SOCKET_API(float, anisotropic) NODE_SOCKET_API(float, sheen) - NODE_SOCKET_API(float, sheen_tint) + NODE_SOCKET_API(float, sheen_roughness) + NODE_SOCKET_API(float3, sheen_tint) NODE_SOCKET_API(float, clearcoat) NODE_SOCKET_API(float, clearcoat_roughness) NODE_SOCKET_API(float, ior) diff --git a/source/blender/blenloader/intern/versioning_280.cc b/source/blender/blenloader/intern/versioning_280.cc index de641298145..342040d8973 100644 --- a/source/blender/blenloader/intern/versioning_280.cc +++ b/source/blender/blenloader/intern/versioning_280.cc @@ -1228,43 +1228,23 @@ static void displacement_principled_nodes(bNode *node) } } -static bool node_has_roughness(const bNode *node) -{ - return ELEM(node->type, - SH_NODE_BSDF_GLASS, - SH_NODE_BSDF_GLOSSY_LEGACY, - SH_NODE_BSDF_GLOSSY, - SH_NODE_BSDF_REFRACTION); -} - static void square_roughness_node_insert(bNodeTree *ntree) { - bool need_update = false; - - /* Update default values */ - LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - if (node_has_roughness(node)) { - bNodeSocket *roughness_input = nodeFindSocket(node, SOCK_IN, "Roughness"); - float *roughness_value = version_cycles_node_socket_float_value(roughness_input); - *roughness_value = sqrtf(max_ff(*roughness_value, 0.0f)); - } - } - - /* Iterate backwards from end so we don't encounter newly added links. */ - LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) { - /* Detect link to replace. */ - bNode *fromnode = link->fromnode; - bNodeSocket *fromsock = link->fromsock; - bNode *tonode = link->tonode; - bNodeSocket *tosock = link->tosock; - - if (!(node_has_roughness(tonode) && STREQ(tosock->identifier, "Roughness"))) { - continue; - } - - /* Replace links with sqrt node */ - nodeRemLink(ntree, link); - + auto check_node = [](const bNode *node) { + return ELEM(node->type, + SH_NODE_BSDF_GLASS, + SH_NODE_BSDF_GLOSSY_LEGACY, + SH_NODE_BSDF_GLOSSY, + SH_NODE_BSDF_REFRACTION); + }; + auto update_input = [](const bNode *, bNodeSocket *input) { + float *value = version_cycles_node_socket_float_value(input); + *value = sqrtf(max_ff(*value, 0.0f)); + }; + auto update_input_link = [ntree](bNode *fromnode, + bNodeSocket *fromsock, + bNode *tonode, + bNodeSocket *tosock) { /* Add sqrt node. */ bNode *node = nodeAddStaticNode(nullptr, ntree, SH_NODE_MATH); node->custom1 = NODE_MATH_POWER; @@ -1275,13 +1255,9 @@ static void square_roughness_node_insert(bNodeTree *ntree) *version_cycles_node_socket_float_value(static_cast(node->inputs.last)) = 0.5f; nodeAddLink(ntree, fromnode, fromsock, node, static_cast(node->inputs.first)); nodeAddLink(ntree, node, static_cast(node->outputs.first), tonode, tosock); + }; - need_update = true; - } - - if (need_update) { - version_socket_update_is_used(ntree); - } + version_update_node_input(ntree, check_node, "Roughness", update_input, update_input_link); } static void mapping_node_order_flip(bNode *node) diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index c5245931bf7..5751da5c589 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -25,6 +25,7 @@ #include "BLI_assert.h" #include "BLI_listbase.h" +#include "BLI_math.h" #include "BLI_set.hh" #include "BLI_string_ref.hh" @@ -296,6 +297,49 @@ static void version_replace_velvet_sheen_node(bNodeTree *ntree) } } +/* Convert sheen inputs on the Principled BSDF. */ +static void version_principled_bsdf_sheen(bNodeTree *ntree) +{ + auto check_node = [](const bNode *node) { + return (node->type == SH_NODE_BSDF_PRINCIPLED) && + (nodeFindSocket(node, SOCK_IN, "Sheen Roughness") == nullptr); + }; + auto update_input = [ntree](bNode *node, bNodeSocket *input) { + /* Change socket type to Color. */ + nodeModifySocketTypeStatic(ntree, node, input, SOCK_RGBA, 0); + + /* Account for the change in intensity between the old and new model. + * If the Sheen input is set to a fixed value, adjust it and set the tint to white. + * Otherwise, if it's connected, keep it as-is but set the tint to 0.2 instead. */ + static float default_value_dim[] = {0.2f, 0.2f, 0.2f, 1.0f}; + bNodeSocket *sheen = nodeFindSocket(node, SOCK_IN, "Sheen"); + if (sheen != nullptr && sheen->link == nullptr) { + *version_cycles_node_socket_float_value(sheen) *= 0.2f; + + static float default_value[] = {1.0f, 1.0f, 1.0f, 1.0f}; + copy_v4_v4(version_cycles_node_socket_rgba_value(input), default_value); + } + else { + static float default_value[] = {0.2f, 0.2f, 0.2f, 1.0f}; + copy_v4_v4(version_cycles_node_socket_rgba_value(input), default_value); + } + }; + auto update_input_link = [](bNode *, bNodeSocket *, bNode *, bNodeSocket *) { + /* Don't replace the link here, tint works differently enough now to make conversion + * impractical. */ + }; + + version_update_node_input(ntree, check_node, "Sheen Tint", update_input, update_input_link); + + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (check_node(node)) { + bNodeSocket *input = nodeAddStaticSocket( + ntree, node, SOCK_IN, SOCK_FLOAT, PROP_FACTOR, "Sheen Roughness", "Sheen Roughness"); + *version_cycles_node_socket_float_value(input) = 0.5f; + } + } +} + void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain) { if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 1)) { @@ -450,6 +494,8 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain) version_principled_transmission_roughness(ntree); /* Convert legacy Velvet BSDF nodes into the new Sheen BSDF node. */ version_replace_velvet_sheen_node(ntree); + /* Convert sheen inputs on the Principled BSDF. */ + version_principled_bsdf_sheen(ntree); } } FOREACH_NODETREE_END; diff --git a/source/blender/blenloader/intern/versioning_common.cc b/source/blender/blenloader/intern/versioning_common.cc index b4cf13c51ad..bd121f35763 100644 --- a/source/blender/blenloader/intern/versioning_common.cc +++ b/source/blender/blenloader/intern/versioning_common.cc @@ -403,3 +403,48 @@ IDProperty *version_cycles_visibility_properties_from_ID(ID *id) IDProperty *idprop = IDP_GetProperties(id, false); return (idprop) ? IDP_GetPropertyTypeFromGroup(idprop, "cycles_visibility", IDP_GROUP) : nullptr; } + +void version_update_node_input( + bNodeTree *ntree, + FunctionRef check_node, + const char *socket_identifier, + FunctionRef update_input, + FunctionRef update_input_link) +{ + bool need_update = false; + + /* Iterate backwards from end so we don't encounter newly added links. */ + LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) { + /* Detect link to replace. */ + bNode *fromnode = link->fromnode; + bNodeSocket *fromsock = link->fromsock; + bNode *tonode = link->tonode; + bNodeSocket *tosock = link->tosock; + + if (!(tonode != nullptr && check_node(tonode) && STREQ(tosock->identifier, socket_identifier))) + { + continue; + } + + /* Replace links with updated equivalent */ + nodeRemLink(ntree, link); + update_input_link(fromnode, fromsock, tonode, tosock); + + need_update = true; + } + + /* Update sockets and/or their default values. + * Do this after the link update in case it changes the identifier. */ + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (check_node(node)) { + bNodeSocket *input = nodeFindSocket(node, SOCK_IN, socket_identifier); + if (input != nullptr) { + update_input(node, input); + } + } + } + + if (need_update) { + version_socket_update_is_used(ntree); + } +} diff --git a/source/blender/blenloader/intern/versioning_common.h b/source/blender/blenloader/intern/versioning_common.h index 099b127e02d..3e863de5b5c 100644 --- a/source/blender/blenloader/intern/versioning_common.h +++ b/source/blender/blenloader/intern/versioning_common.h @@ -9,7 +9,9 @@ #pragma once #ifdef __cplusplus +# include "BLI_function_ref.hh" # include "BLI_map.hh" +using blender::FunctionRef; #endif struct ARegion; @@ -149,4 +151,10 @@ void node_tree_relink_with_socket_id_map(bNodeTree &ntree, bNode &old_node, bNode &new_node, const blender::Map &map); +void version_update_node_input( + bNodeTree *ntree, + FunctionRef check_node, + const char *socket_identifier, + FunctionRef update_input, + FunctionRef update_input_link); #endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl index 96c548fd40f..20f41fff18e 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl @@ -5,12 +5,14 @@ vec3 tint_from_color(vec3 color) return (lum > 0.0) ? color / lum : vec3(1.0); /* normalize lum. to isolate hue+sat */ } -float principled_sheen(float NV) +float principled_sheen(float NV, float rough) { - float f = 1.0 - NV; - /* Empirical approximation (manual curve fitting). Can be refined. */ - float sheen = f * f * f * 0.077 + f * 0.01 + 0.00026; - return sheen; + /* Empirical approximation (manual curve fitting) to the sheen albedo. Can be refined. */ + float den = 35.6694f * rough * rough - 24.4269f * rough * NV - 0.1405f * NV * NV + + 6.1211f * rough + 0.28105f * NV - 0.1405f; + float num = 58.5299f * rough * rough - 85.0941f * rough * NV + 9.8955f * NV * NV + + 1.9250f * rough + 74.2268f * NV - 0.2246f; + return saturate(den / num); } void node_bsdf_principled(vec4 base_color, @@ -26,7 +28,8 @@ void node_bsdf_principled(vec4 base_color, float anisotropic, float anisotropic_rotation, float sheen, - float sheen_tint, + float sheen_roughness, + vec4 sheen_tint, float clearcoat, float clearcoat_roughness, float ior, @@ -82,8 +85,7 @@ void node_bsdf_principled(vec4 base_color, diffuse_data.weight = diffuse_weight * weight; diffuse_data.color = mix(base_color.rgb, subsurface_color.rgb, subsurface); /* Sheen Coarse approximation: We reuse the diffuse radiance and just scale it. */ - vec3 sheen_color = mix(vec3(1.0), base_color_tint, sheen_tint); - diffuse_data.color += sheen * sheen_color * principled_sheen(NV); + diffuse_data.color += sheen * sheen_tint.rgb * principled_sheen(NV, sheen_roughness); diffuse_data.N = N; diffuse_data.sss_radius = subsurface_radius * subsurface; diffuse_data.sss_id = uint(do_sss); diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc index b8ee16e8c77..e5345c78414 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc @@ -83,48 +83,50 @@ static void node_declare(NodeDeclarationBuilder &b) #define SOCK_ANISOTROPIC_ROTATION_ID 11 b.add_input("Sheen").default_value(0.0f).min(0.0f).max(1.0f).subtype(PROP_FACTOR); #define SOCK_SHEEN_ID 12 - b.add_input("Sheen Tint") + b.add_input("Sheen Roughness") .default_value(0.5f) .min(0.0f) .max(1.0f) .subtype(PROP_FACTOR); -#define SOCK_SHEEN_TINT_ID 13 +#define SOCK_SHEEN_ROUGHNESS_ID 13 + b.add_input("Sheen Tint").default_value({1.0f, 1.0f, 1.0f, 1.0f}); +#define SOCK_SHEEN_TINT_ID 14 b.add_input("Clearcoat") .default_value(0.0f) .min(0.0f) .max(1.0f) .subtype(PROP_FACTOR); -#define SOCK_CLEARCOAT_ID 14 +#define SOCK_CLEARCOAT_ID 15 b.add_input("Clearcoat Roughness") .default_value(0.03f) .min(0.0f) .max(1.0f) .subtype(PROP_FACTOR); -#define SOCK_CLEARCOAT_ROUGHNESS_ID 15 +#define SOCK_CLEARCOAT_ROUGHNESS_ID 16 b.add_input("IOR").default_value(1.45f).min(0.0f).max(1000.0f); -#define SOCK_IOR_ID 16 +#define SOCK_IOR_ID 17 b.add_input("Transmission") .default_value(0.0f) .min(0.0f) .max(1.0f) .subtype(PROP_FACTOR); -#define SOCK_TRANSMISSION_ID 17 +#define SOCK_TRANSMISSION_ID 18 b.add_input("Emission").default_value({0.0f, 0.0f, 0.0f, 1.0f}); -#define SOCK_EMISSION_ID 18 +#define SOCK_EMISSION_ID 19 b.add_input("Emission Strength").default_value(1.0).min(0.0f).max(1000000.0f); -#define SOCK_EMISSION_STRENGTH_ID 19 +#define SOCK_EMISSION_STRENGTH_ID 20 b.add_input("Alpha").default_value(1.0f).min(0.0f).max(1.0f).subtype(PROP_FACTOR); -#define SOCK_ALPHA_ID 20 +#define SOCK_ALPHA_ID 21 b.add_input("Normal").hide_value(); -#define SOCK_NORMAL_ID 21 +#define SOCK_NORMAL_ID 22 b.add_input("Clearcoat Normal").hide_value(); -#define SOCK_CLEARCOAT_NORMAL_ID 22 +#define SOCK_CLEARCOAT_NORMAL_ID 23 b.add_input("Tangent").hide_value(); -#define SOCK_TANGENT_ID 23 +#define SOCK_TANGENT_ID 24 b.add_input("Weight").unavailable(); -#define SOCK_WEIGHT_ID 24 +#define SOCK_WEIGHT_ID 25 b.add_output("BSDF"); -#define SOCK_BSDF_ID 25 +#define SOCK_BSDF_ID 26 } static void node_shader_buts_principled(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)