diff --git a/intern/cycles/kernel/osl/shaders/node_principled_bsdf.osl b/intern/cycles/kernel/osl/shaders/node_principled_bsdf.osl index f871142b310..a8e9de9c463 100644 --- a/intern/cycles/kernel/osl/shaders/node_principled_bsdf.osl +++ b/intern/cycles/kernel/osl/shaders/node_principled_bsdf.osl @@ -28,6 +28,9 @@ shader node_principled_bsdf(string distribution = "multi_ggx", color CoatTint = color(1.0, 1.0, 1.0), float IOR = 1.45, float Transmission = 0.0, + color Emission = 1.0, + float EmissionStrength = 0.0, + float Alpha = 1.0, normal Normal = N, normal CoatNormal = N, normal Tangent = normalize(dPdu), @@ -99,6 +102,10 @@ shader node_principled_bsdf(string distribution = "multi_ggx", BSDF = mix(BSDF, MetallicBSDF, clamp(Metallic, 0.0, 1.0)); } + if (EmissionStrength > 0.0 && Emission != color(0.0)) { + BSDF += EmissionStrength * Emission * emission(); + } + if (Coat > 1e-5) { float coat_ior = max(CoatIOR, 1.0); if (CoatTint != color(1.0)) { @@ -117,4 +124,6 @@ shader node_principled_bsdf(string distribution = "multi_ggx", closure color SheenBSDF = sheen(Normal, SheenRoughness); BSDF = layer(SheenTint * Sheen * SheenBSDF, BSDF); } + + BSDF = mix(transparent(), BSDF, Alpha); } diff --git a/intern/cycles/kernel/svm/closure.h b/intern/cycles/kernel/svm/closure.h index 40205c72a1d..e28780996b6 100644 --- a/intern/cycles/kernel/svm/closure.h +++ b/intern/cycles/kernel/svm/closure.h @@ -22,6 +22,7 @@ ccl_device_inline int svm_node_closure_bsdf_skip(KernelGlobals kg, int offset, u read_node(kg, &offset); read_node(kg, &offset); read_node(kg, &offset); + read_node(kg, &offset); } return offset; @@ -53,6 +54,12 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, return svm_node_closure_bsdf_skip(kg, offset, type); } } + else IF_KERNEL_NODES_FEATURE(EMISSION) { + if (type != CLOSURE_BSDF_PRINCIPLED_ID) { + /* Only principled BSDF can have emission. */ + return svm_node_closure_bsdf_skip(kg, offset, type); + } + } else { return svm_node_closure_bsdf_skip(kg, offset, type); } @@ -70,7 +77,8 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, uint specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset, sheen_offset, sheen_tint_offset, sheen_roughness_offset, coat_offset, coat_roughness_offset, coat_ior_offset, eta_offset, transmission_offset, - anisotropic_rotation_offset, coat_tint_offset, coat_normal_offset, dummy; + anisotropic_rotation_offset, coat_tint_offset, coat_normal_offset, dummy, + alpha_offset, emission_strength_offset, emission_offset; uint4 data_node2 = read_node(kg, &offset); float3 T = stack_load_float3(stack, data_node.y); @@ -129,6 +137,20 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, sd->N; coat_normal = maybe_ensure_valid_specular_reflection(sd, coat_normal); + uint4 data_alpha_emission = read_node(kg, &offset); + svm_unpack_node_uchar4(data_alpha_emission.x, + &alpha_offset, + &emission_strength_offset, + &emission_offset, + &dummy); + float alpha = stack_valid(alpha_offset) ? stack_load_float(stack, alpha_offset) : + __uint_as_float(data_alpha_emission.y); + float3 emission = stack_load_float3(stack, emission_offset); + /* Emission strength */ + emission *= stack_valid(emission_strength_offset) ? + stack_load_float(stack, emission_strength_offset) : + __uint_as_float(data_alpha_emission.z); + Spectrum weight = closure_weight * mix_weight; float alpha_x = sqr(roughness), alpha_y = sqr(roughness); @@ -151,6 +173,12 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, const bool glass_caustics = true; #endif + /* Before any actual shader components, apply transparency. */ + if (alpha < 1.0f) { + bsdf_transparent_setup(sd, weight * (1.0f - alpha), path_flag); + weight *= alpha; + } + /* First layer: Sheen */ if (sheen > CLOSURE_WEIGHT_CUTOFF) { ccl_private SheenBsdf *bsdf = (ccl_private SheenBsdf *)bsdf_alloc( @@ -217,6 +245,11 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, weight *= power(rgb_to_spectrum(coat_tint), coat * optical_depth); } + /* Emission (attenuated by sheen and coat) */ + if (!is_zero(emission)) { + emission_setup(sd, rgb_to_spectrum(emission) * weight); + } + /* Metallic component */ if (reflective_caustics && metallic > CLOSURE_WEIGHT_CUTOFF) { ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( diff --git a/intern/cycles/scene/shader.cpp b/intern/cycles/scene/shader.cpp index 9d4f32e4f9f..e7fe755cd1b 100644 --- a/intern/cycles/scene/shader.cpp +++ b/intern/cycles/scene/shader.cpp @@ -133,11 +133,18 @@ static float3 output_estimate_emission(ShaderOutput *output, bool &is_constant) return zero_float3(); } else if (node->type == EmissionNode::get_node_type() || - node->type == BackgroundNode::get_node_type()) + node->type == BackgroundNode::get_node_type() || + node->type == PrincipledBsdfNode::get_node_type()) { + const bool is_principled = (node->type == PrincipledBsdfNode::get_node_type()); /* Emission and Background node. */ - ShaderInput *color_in = node->input("Color"); - ShaderInput *strength_in = node->input("Strength"); + ShaderInput *color_in = node->input(is_principled ? "Emission" : "Color"); + ShaderInput *strength_in = node->input(is_principled ? "Emission Strength" : "Strength"); + + if (is_principled) { + /* Too many parameters (coat, sheen, alpha) influence Emission for the Principled BSDF. */ + is_constant = false; + } float3 estimate = one_float3(); diff --git a/intern/cycles/scene/shader_nodes.cpp b/intern/cycles/scene/shader_nodes.cpp index 05bb1c47a7a..c52c4258202 100644 --- a/intern/cycles/scene/shader_nodes.cpp +++ b/intern/cycles/scene/shader_nodes.cpp @@ -2681,8 +2681,8 @@ NODE_DEFINE(PrincipledBsdfNode) SOCKET_IN_FLOAT(ior, "IOR", 0.0f); SOCKET_IN_FLOAT(transmission, "Transmission", 0.0f); SOCKET_IN_FLOAT(anisotropic_rotation, "Anisotropic Rotation", 0.0f); - SOCKET_IN_COLOR(emission, "Emission", zero_float3()); - SOCKET_IN_FLOAT(emission_strength, "Emission Strength", 1.0f); + SOCKET_IN_COLOR(emission, "Emission", one_float3()); + SOCKET_IN_FLOAT(emission_strength, "Emission Strength", 0.0f); SOCKET_IN_FLOAT(alpha, "Alpha", 1.0f); SOCKET_IN_NORMAL(normal, "Normal", zero_float3(), SocketType::LINK_NORMAL); SOCKET_IN_NORMAL(coat_normal, "Coat Normal", zero_float3(), SocketType::LINK_NORMAL); @@ -2700,60 +2700,33 @@ PrincipledBsdfNode::PrincipledBsdfNode() : BsdfBaseNode(get_node_type()) distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID; } -void PrincipledBsdfNode::expand(ShaderGraph *graph) +void PrincipledBsdfNode::simplify_settings(Scene * /* scene */) { - ShaderOutput *principled_out = output("BSDF"); - - ShaderInput *emission_in = input("Emission"); - ShaderInput *emission_strength_in = input("Emission Strength"); - if ((emission_in->link || emission != zero_float3()) && - (emission_strength_in->link || emission_strength != 0.0f)) - { - /* Create add closure and emission, and relink inputs. */ - AddClosureNode *add = graph->create_node(); - EmissionNode *emission_node = graph->create_node(); - ShaderOutput *new_out = add->output("Closure"); - - graph->add(add); - graph->add(emission_node); - - graph->relink(emission_strength_in, emission_node->input("Strength")); - graph->relink(emission_in, emission_node->input("Color")); - graph->relink(principled_out, new_out); - graph->connect(emission_node->output("Emission"), add->input("Closure1")); - graph->connect(principled_out, add->input("Closure2")); - - principled_out = new_out; - } - else { - /* Disconnect unused links if the other value is zero, required before - * we remove the input from the node entirely. */ + if (!has_surface_emission()) { + /* Emission will be zero, so optimize away any connected emission input. */ + ShaderInput *emission_in = input("Emission"); + ShaderInput *strength_in = input("Emission Strength"); if (emission_in->link) { emission_in->disconnect(); } - if (emission_strength_in->link) { - emission_strength_in->disconnect(); + if (strength_in->link) { + strength_in->disconnect(); } } +} +bool PrincipledBsdfNode::has_surface_transparent() +{ ShaderInput *alpha_in = input("Alpha"); - if (alpha_in->link || alpha != 1.0f) { - /* Create mix and transparent BSDF for alpha transparency. */ - MixClosureNode *mix = graph->create_node(); - TransparentBsdfNode *transparent = graph->create_node(); + return (alpha_in->link != NULL || alpha < (1.0f - CLOSURE_WEIGHT_CUTOFF)); +} - graph->add(mix); - graph->add(transparent); - - graph->relink(alpha_in, mix->input("Fac")); - graph->relink(principled_out, mix->output("Closure")); - graph->connect(transparent->output("BSDF"), mix->input("Closure1")); - graph->connect(principled_out, mix->input("Closure2")); - } - - remove_input(emission_in); - remove_input(emission_strength_in); - remove_input(alpha_in); +bool PrincipledBsdfNode::has_surface_emission() +{ + ShaderInput *emission_in = input("Emission"); + ShaderInput *emission_strength_in = input("Emission Strength"); + return (emission_in->link != NULL || reduce_max(emission) > CLOSURE_WEIGHT_CUTOFF) && + (emission_strength_in->link != NULL || emission_strength > CLOSURE_WEIGHT_CUTOFF); } bool PrincipledBsdfNode::has_surface_bssrdf() @@ -2781,6 +2754,9 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler) ShaderInput *p_metallic = input("Metallic"); ShaderInput *p_subsurface = input("Subsurface"); + ShaderInput *emission_strength_in = input("Emission Strength"); + ShaderInput *alpha_in = input("Alpha"); + float3 weight = one_float3(); compiler.add_node(NODE_CLOSURE_SET_WEIGHT, weight); @@ -2806,6 +2782,9 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler) int subsurface_scale_offset = compiler.stack_assign(input("Subsurface Scale")); int subsurface_ior_offset = compiler.stack_assign(input("Subsurface IOR")); int subsurface_anisotropy_offset = compiler.stack_assign(input("Subsurface Anisotropy")); + int alpha_offset = compiler.stack_assign_if_linked(alpha_in); + int emission_strength_offset = compiler.stack_assign_if_linked(emission_strength_in); + int emission_offset = compiler.stack_assign(input("Emission")); compiler.add_node(NODE_CLOSURE_BSDF, compiler.encode_uchar4(closure, @@ -2843,6 +2822,13 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler) subsurface_radius_offset, subsurface_scale_offset, subsurface_anisotropy_offset); + + compiler.add_node( + compiler.encode_uchar4( + alpha_offset, emission_strength_offset, emission_offset, SVM_STACK_INVALID), + __float_as_int(get_float(alpha_in->socket_type)), + __float_as_int(get_float(emission_strength_in->socket_type)), + SVM_STACK_INVALID); } void PrincipledBsdfNode::compile(OSLCompiler &compiler) diff --git a/intern/cycles/scene/shader_nodes.h b/intern/cycles/scene/shader_nodes.h index 3bf71bb14a7..3cb4fe4ab41 100644 --- a/intern/cycles/scene/shader_nodes.h +++ b/intern/cycles/scene/shader_nodes.h @@ -514,9 +514,9 @@ class PrincipledBsdfNode : public BsdfBaseNode { public: SHADER_NODE_CLASS(PrincipledBsdfNode) - void expand(ShaderGraph *graph); bool has_surface_bssrdf(); bool has_bssrdf_bump(); + void simplify_settings(Scene *scene); NODE_SOCKET_API(float3, base_color) NODE_SOCKET_API(float3, subsurface_radius) @@ -555,6 +555,8 @@ class PrincipledBsdfNode : public BsdfBaseNode { { return true; } + bool has_surface_transparent(); + bool has_surface_emission(); }; class TranslucentBsdfNode : public BsdfNode { diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index 758c1adef9f..e93fe2ab2b0 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -660,6 +660,33 @@ static void version_principled_bsdf_subsurface(bNodeTree *ntree) } } +/* Convert emission inputs on the Principled BSDF. */ +static void version_principled_bsdf_emission(bNodeTree *ntree) +{ + /* Blender 3.x and before would default to Emission = 0.0, Emission Strength = 1.0. + * Now we default the other way around (1.0 and 0.0), but because the Strength input was added + * a bit later, a file that only has the Emission socket would now end up as (1.0, 0.0) instead + * of (1.0, 1.0). + * Therefore, set strength to 1.0 for those files. + */ + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (node->type != SH_NODE_BSDF_PRINCIPLED) { + continue; + } + if (!nodeFindSocket(node, SOCK_IN, "Emission")) { + /* Old enough to have neither, new defaults are fine. */ + continue; + } + if (nodeFindSocket(node, SOCK_IN, "Emission Strength")) { + /* New enough to have both, no need to do anything. */ + continue; + } + bNodeSocket *sock = nodeAddStaticSocket( + ntree, node, SOCK_IN, SOCK_FLOAT, PROP_NONE, "Emission Strength", "Emission Strength"); + *version_cycles_node_socket_float_value(sock) = 1.0f; + } +} + /* Replace old Principled Hair BSDF as a variant in the new Principled Hair BSDF. */ static void version_replace_principled_hair_model(bNodeTree *ntree) { @@ -1178,6 +1205,8 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain) version_principled_bsdf_coat(ntree); /* Convert subsurface inputs on the Principled BSDF. */ version_principled_bsdf_subsurface(ntree); + /* Convert emission on the Principled BSDF. */ + version_principled_bsdf_emission(ntree); } } FOREACH_NODETREE_END; diff --git a/source/blender/blenloader/intern/versioning_defaults.cc b/source/blender/blenloader/intern/versioning_defaults.cc index 8bf2fbe14e1..8a3040f579f 100644 --- a/source/blender/blenloader/intern/versioning_defaults.cc +++ b/source/blender/blenloader/intern/versioning_defaults.cc @@ -608,9 +608,12 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) for (bNode *node : ma->nodetree->all_nodes()) { if (node->type == SH_NODE_BSDF_PRINCIPLED) { bNodeSocket *roughness_socket = nodeFindSocket(node, SOCK_IN, "Roughness"); - bNodeSocketValueFloat *roughness_data = static_cast( - roughness_socket->default_value); - roughness_data->value = 0.5f; + *version_cycles_node_socket_float_value(roughness_socket) = 0.5f; + bNodeSocket *emission = nodeFindSocket(node, SOCK_IN, "Emission"); + copy_v4_fl(version_cycles_node_socket_rgba_value(emission), 1.0f); + bNodeSocket *emission_strength = nodeFindSocket(node, SOCK_IN, "Emission Strength"); + *version_cycles_node_socket_float_value(emission_strength) = 0.0f; + node->custom1 = SHD_GLOSSY_MULTI_GGX; node->custom2 = SHD_SUBSURFACE_RANDOM_WALK; BKE_ntree_update_tag_node_property(ma->nodetree, node); 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 56a91706f47..1179fa869c2 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc @@ -143,9 +143,9 @@ static void node_declare(NodeDeclarationBuilder &b) .max(1.0f) .subtype(PROP_FACTOR); #define SOCK_TRANSMISSION_ID 20 - b.add_input("Emission").default_value({0.0f, 0.0f, 0.0f, 1.0f}); + b.add_input("Emission").default_value({1.0f, 1.0f, 1.0f, 1.0f}); #define SOCK_EMISSION_ID 21 - b.add_input("Emission Strength").default_value(1.0).min(0.0f).max(1000000.0f); + b.add_input("Emission Strength").default_value(0.0).min(0.0f).max(1000000.0f); #define SOCK_EMISSION_STRENGTH_ID 22 b.add_input("Alpha").default_value(1.0f).min(0.0f).max(1.0f).subtype(PROP_FACTOR); #define SOCK_ALPHA_ID 23