From 8f71a84496a95528303fbe0bb7c1406060353425 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sun, 12 May 2019 14:39:30 +0200 Subject: Cycles/Eevee: add Emission and Alpha inputs to Principled BSDF This makes it easier to set up materials with emission and transparency. Importers/exporters and add-ons are recommended to now use these rather than creating separate transparent BSDF and emission nodes. --- intern/cycles/render/graph.cpp | 37 +++++++++++++++++++++++++++++++++ intern/cycles/render/graph.h | 9 +++++++++ intern/cycles/render/nodes.cpp | 46 +++++++++++++++++++++++++++++++++++++++++- intern/cycles/render/nodes.h | 3 +++ 4 files changed, 94 insertions(+), 1 deletion(-) (limited to 'intern/cycles') diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index e5fd39f08b7..9203c4468d2 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -127,6 +127,12 @@ ShaderOutput *ShaderNode::output(ustring name) return NULL; } +void ShaderNode::remove_input(ShaderInput *input) +{ + assert(input->link == NULL); + inputs.erase(remove(inputs.begin(), inputs.end(), input), inputs.end()); +} + void ShaderNode::attributes(Shader *shader, AttributeRequestSet *attributes) { foreach (ShaderInput *input, inputs) { @@ -297,6 +303,28 @@ void ShaderGraph::disconnect(ShaderInput *to) from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end()); } +void ShaderGraph::relink(ShaderInput *from, ShaderInput *to) +{ + ShaderOutput *out = from->link; + if (out) { + disconnect(from); + connect(out, to); + } + to->parent->copy_value(to->socket_type, *(from->parent), from->socket_type); +} + +void ShaderGraph::relink(ShaderOutput *from, ShaderOutput *to) +{ + /* Copy because disconnect modifies this list. */ + vector outputs = from->links; + + foreach (ShaderInput *sock, outputs) { + disconnect(sock); + if (to) + connect(to, sock); + } +} + void ShaderGraph::relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to) { simplified = false; @@ -320,6 +348,7 @@ void ShaderGraph::relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to) void ShaderGraph::simplify(Scene *scene) { if (!simplified) { + expand(); default_inputs(scene->shader_manager->use_osl()); clean(scene); refine_bump_nodes(); @@ -780,6 +809,14 @@ void ShaderGraph::clean(Scene *scene) nodes = newnodes; } +void ShaderGraph::expand() +{ + /* Call expand on all nodes, to generate additional nodes. */ + foreach (ShaderNode *node, nodes) { + node->expand(this); + } +} + void ShaderGraph::default_inputs(bool do_osl) { /* nodes can specify default texture coordinates, for now we give diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h index b1aa5cf3168..cade04de374 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -147,6 +147,7 @@ class ShaderNode : public Node { virtual ~ShaderNode(); void create_inputs_outputs(const NodeType *type); + void remove_input(ShaderInput *input); ShaderInput *input(const char *name); ShaderOutput *output(const char *name); @@ -158,6 +159,11 @@ class ShaderNode : public Node { virtual void compile(SVMCompiler &compiler) = 0; virtual void compile(OSLCompiler &compiler) = 0; + /* Expand node into additional nodes. */ + virtual void expand(ShaderGraph * /* graph */) + { + } + /* ** Node optimization ** */ /* Check whether the node can be replaced with single constant. */ virtual void constant_fold(const ConstantFolder & /*folder*/) @@ -322,6 +328,8 @@ class ShaderGraph { void connect(ShaderOutput *from, ShaderInput *to); void disconnect(ShaderOutput *from); void disconnect(ShaderInput *to); + void relink(ShaderInput *from, ShaderInput *to); + void relink(ShaderOutput *from, ShaderOutput *to); void relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to); void remove_proxy_nodes(); @@ -346,6 +354,7 @@ class ShaderGraph { void break_cycles(ShaderNode *node, vector &visited, vector &on_stack); void bump_from_displacement(bool use_object_space); void refine_bump_nodes(); + void expand(); void default_inputs(bool do_osl); void transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume); diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 6e86643cc2b..86cc2030d1b 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -2427,6 +2427,8 @@ NODE_DEFINE(PrincipledBsdfNode) SOCKET_IN_FLOAT(transmission, "Transmission", 0.0f); SOCKET_IN_FLOAT(transmission_roughness, "Transmission Roughness", 0.0f); SOCKET_IN_FLOAT(anisotropic_rotation, "Anisotropic Rotation", 0.0f); + SOCKET_IN_COLOR(emission, "Emission", make_float3(0.0f, 0.0f, 0.0f)); + SOCKET_IN_FLOAT(alpha, "Alpha", 1.0f); SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL); SOCKET_IN_NORMAL(clearcoat_normal, "Clearcoat Normal", @@ -2447,6 +2449,48 @@ PrincipledBsdfNode::PrincipledBsdfNode() : BsdfBaseNode(node_type) distribution_orig = NBUILTIN_CLOSURES; } +void PrincipledBsdfNode::expand(ShaderGraph *graph) +{ + ShaderOutput *principled_out = output("BSDF"); + + ShaderInput *emission_in = input("Emission"); + if (emission_in->link || emission != make_float3(0.0f, 0.0f, 0.0f)) { + /* Create add closure and emission. */ + AddClosureNode *add = new AddClosureNode(); + EmissionNode *emission_node = new EmissionNode(); + ShaderOutput *new_out = add->output("Closure"); + + graph->add(add); + graph->add(emission_node); + + emission_node->strength = 1.0f; + 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; + } + + ShaderInput *alpha_in = input("Alpha"); + if (alpha_in->link || alpha != 1.0f) { + /* Create mix and transparent BSDF for alpha transparency. */ + MixClosureNode *mix = new MixClosureNode(); + TransparentBsdfNode *transparent = new TransparentBsdfNode(); + + 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(alpha_in); +} + bool PrincipledBsdfNode::has_surface_bssrdf() { ShaderInput *subsurface_in = input("Subsurface"); @@ -2627,7 +2671,7 @@ NODE_DEFINE(TransparentBsdfNode) { NodeType *type = NodeType::add("transparent_bsdf", create, NodeType::SHADER); - SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f)); + SOCKET_IN_COLOR(color, "Color", make_float3(1.0f, 1.0f, 1.0f)); SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL); SOCKET_OUT_CLOSURE(BSDF, "BSDF"); diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 88fa728ecd1..3dd84ad8dca 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -487,6 +487,7 @@ class PrincipledBsdfNode : public BsdfBaseNode { public: SHADER_NODE_CLASS(PrincipledBsdfNode) + void expand(ShaderGraph *graph); bool has_surface_bssrdf(); bool has_bssrdf_bump(); void compile(SVMCompiler &compiler, @@ -515,6 +516,8 @@ class PrincipledBsdfNode : public BsdfBaseNode { float surface_mix_weight; ClosureType distribution, distribution_orig; ClosureType subsurface_method; + float3 emission; + float alpha; bool has_integrator_dependency(); void attributes(Shader *shader, AttributeRequestSet *attributes); -- cgit v1.2.3