From dd8bfa0929f9f1ae940e7da0468fbdd6744e50bb Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 2 May 2016 00:05:16 +0200 Subject: Code refactor: reduce special node types, use generic constant folding. --- intern/cycles/blender/blender_shader.cpp | 19 ++-- intern/cycles/render/graph.cpp | 187 +++++-------------------------- intern/cycles/render/graph.h | 10 +- intern/cycles/render/mesh.cpp | 2 +- intern/cycles/render/nodes.cpp | 186 ++++++++++++++++++++++-------- intern/cycles/render/nodes.h | 57 +++------- intern/cycles/render/osl.cpp | 4 +- intern/cycles/render/shader.cpp | 2 +- intern/cycles/render/svm.cpp | 2 +- 9 files changed, 200 insertions(+), 269 deletions(-) (limited to 'intern') diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 3f919bcad88..6e4ca6627a1 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -32,7 +32,7 @@ CCL_NAMESPACE_BEGIN typedef map PtrInputMap; typedef map PtrOutputMap; -typedef map ProxyMap; +typedef map ProxyMap; /* Find */ @@ -321,10 +321,6 @@ static ShaderNode *add_node(Scene *scene, BL::ShaderNodeMixRGB b_mix_node(b_node); MixNode *mix = new MixNode(); mix->type = MixNode::type_enum[b_mix_node.blend_type()]; - /* Tag if it's Mix */ - if(b_mix_node.blend_type() == 0) - mix->special_type = SHADER_SPECIAL_TYPE_MIX_RGB; - mix->use_clamp = b_mix_node.use_clamp(); node = mix; } @@ -1029,7 +1025,8 @@ static void add_nodes(Scene *scene, BL::Node::internal_links_iterator b_link; for(b_node->internal_links.begin(b_link); b_link != b_node->internal_links.end(); ++b_link) { BL::NodeSocket to_socket(b_link->to_socket()); - ProxyNode *proxy = new ProxyNode(convert_socket_type(to_socket)); + ShaderSocketType to_socket_type = convert_socket_type(to_socket); + ConvertNode *proxy = new ConvertNode(to_socket_type, to_socket_type, true); input_map[b_link->from_socket().ptr.data] = proxy->inputs[0]; output_map[b_link->to_socket().ptr.data] = proxy->outputs[0]; @@ -1051,7 +1048,8 @@ static void add_nodes(Scene *scene, * so that links have something to connect to and assert won't fail. */ for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) { - ProxyNode *proxy = new ProxyNode(convert_socket_type(*b_input)); + ShaderSocketType input_type = convert_socket_type(*b_input); + ConvertNode *proxy = new ConvertNode(input_type, input_type, true); graph->add(proxy); /* register the proxy node for internal binding */ @@ -1062,7 +1060,8 @@ static void add_nodes(Scene *scene, set_default_value(proxy->inputs[0], *b_input, b_data, b_ntree); } for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { - ProxyNode *proxy = new ProxyNode(convert_socket_type(*b_output)); + ShaderSocketType output_type = convert_socket_type(*b_output); + ConvertNode *proxy = new ConvertNode(output_type, output_type, true); graph->add(proxy); /* register the proxy node for internal binding */ @@ -1088,7 +1087,7 @@ static void add_nodes(Scene *scene, for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { ProxyMap::const_iterator proxy_it = proxy_input_map.find(b_output->identifier()); if(proxy_it != proxy_input_map.end()) { - ProxyNode *proxy = proxy_it->second; + ConvertNode *proxy = proxy_it->second; output_map[b_output->ptr.data] = proxy->outputs[0]; } @@ -1102,7 +1101,7 @@ static void add_nodes(Scene *scene, for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) { ProxyMap::const_iterator proxy_it = proxy_output_map.find(b_input->identifier()); if(proxy_it != proxy_output_map.end()) { - ProxyNode *proxy = proxy_it->second; + ConvertNode *proxy = proxy_it->second; input_map[b_input->ptr.data] = proxy->inputs[0]; diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index 4a9b2f1103c..b23fd2a7a8b 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -290,18 +290,21 @@ void ShaderGraph::disconnect(ShaderInput *to) from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end()); } -void ShaderGraph::relink(vector inputs, vector outputs, ShaderOutput *output) +void ShaderGraph::relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to) { - /* Remove nodes and re-link if output isn't NULL. */ - foreach(ShaderInput *sock, inputs) { + /* Copy because disconnect modifies this list */ + vector outputs = from->links; + + /* Bypass node by moving all links from "from" to "to" */ + foreach(ShaderInput *sock, node->inputs) { if(sock->link) disconnect(sock); } foreach(ShaderInput *sock, outputs) { disconnect(sock); - if(output) - connect(output, sock); + if(to) + connect(to, sock); } } @@ -411,39 +414,29 @@ void ShaderGraph::copy_nodes(ShaderNodeSet& nodes, ShaderNodeMap& nnodemap) /* Graph simplification */ /* ******************** */ -/* Step 1: Remove unused nodes. - * Remove nodes which are not needed in the graph, such as proxies, - * mix nodes with a factor of 0 or 1, emission shaders without contribution... +/* Step 1: Remove proxy nodes. + * These only exists temporarily when exporting groups, and we must remove them + * early so that node->attributes() and default links do not see them. */ -void ShaderGraph::remove_unneeded_nodes() +void ShaderGraph::remove_proxy_nodes() { vector removed(num_node_ids, false); bool any_node_removed = false; - ShaderNode *geom = NULL; - - /* find and unlink proxy nodes */ foreach(ShaderNode *node, nodes) { if(node->special_type == SHADER_SPECIAL_TYPE_PROXY) { - ProxyNode *proxy = static_cast(node); + ConvertNode *proxy = static_cast(node); ShaderInput *input = proxy->inputs[0]; ShaderOutput *output = proxy->outputs[0]; - /* temp. copy of the output links list. - * output->links is modified when we disconnect! - */ - vector links(output->links); - ShaderOutput *from = input->link; - /* bypass the proxy node */ - if(from) { - disconnect(input); - foreach(ShaderInput *to, links) { - disconnect(to); - connect(from, to); - } + if(input->link) { + relink(proxy, output, input->link); } else { + /* Copy because disconnect modifies this list */ + vector links(output->links); + foreach(ShaderInput *to, links) { /* remove any autoconvert nodes too if they lead to * sockets with an automatically set default value */ @@ -465,132 +458,16 @@ void ShaderGraph::remove_unneeded_nodes() } disconnect(to); - + /* transfer the default input value to the target socket */ to->set(input->value); to->set(input->value_string); } } - + removed[proxy->id] = true; any_node_removed = true; } - else if(node->special_type == SHADER_SPECIAL_TYPE_BACKGROUND) { - BackgroundNode *bg = static_cast(node); - - if(bg->outputs[0]->links.size()) { - /* Black color or zero strength, remove node */ - if((!bg->inputs[0]->link && bg->inputs[0]->value == make_float3(0.0f, 0.0f, 0.0f)) || - (!bg->inputs[1]->link && bg->inputs[1]->value.x == 0.0f)) - { - vector inputs = bg->outputs[0]->links; - - relink(bg->inputs, inputs, NULL); - removed[bg->id] = true; - any_node_removed = true; - } - } - } - else if(node->special_type == SHADER_SPECIAL_TYPE_EMISSION) { - EmissionNode *em = static_cast(node); - - if(em->outputs[0]->links.size()) { - /* Black color or zero strength, remove node */ - if((!em->inputs[0]->link && em->inputs[0]->value == make_float3(0.0f, 0.0f, 0.0f)) || - (!em->inputs[1]->link && em->inputs[1]->value.x == 0.0f)) - { - vector inputs = em->outputs[0]->links; - - relink(em->inputs, inputs, NULL); - removed[em->id] = true; - any_node_removed = true; - } - } - } - else if(node->special_type == SHADER_SPECIAL_TYPE_BUMP) { - BumpNode *bump = static_cast(node); - - if(bump->outputs[0]->links.size()) { - /* Height inputs is not connected. */ - /* TODO(sergey): Ignore bump with zero strength. */ - if(bump->inputs[0]->link == NULL) { - vector inputs = bump->outputs[0]->links; - if(bump->inputs[4]->link == NULL) { - if(geom == NULL) { - geom = new GeometryNode(); - } - relink(bump->inputs, inputs, geom->output("Normal")); - } - else { - relink(bump->inputs, inputs, bump->input("Normal")->link); - } - removed[bump->id] = true; - any_node_removed = true; - } - } - } - else if(node->special_type == SHADER_SPECIAL_TYPE_MIX_CLOSURE) { - MixClosureNode *mix = static_cast(node); - - /* remove useless mix closures nodes */ - if(mix->outputs[0]->links.size() && mix->inputs[1]->link == mix->inputs[2]->link) { - ShaderOutput *output = mix->inputs[1]->link; - vector inputs = mix->outputs[0]->links; - - relink(mix->inputs, inputs, output); - removed[mix->id] = true; - any_node_removed = true; - } - - /* remove unused mix closure input when factor is 0.0 or 1.0 */ - /* check for closure links and make sure factor link is disconnected */ - if(mix->outputs[0]->links.size() && mix->inputs[1]->link && mix->inputs[2]->link && !mix->inputs[0]->link) { - /* factor 0.0 */ - if(mix->inputs[0]->value.x == 0.0f) { - ShaderOutput *output = mix->inputs[1]->link; - vector inputs = mix->outputs[0]->links; - - relink(mix->inputs, inputs, output); - removed[mix->id] = true; - any_node_removed = true; - } - /* factor 1.0 */ - else if(mix->inputs[0]->value.x == 1.0f) { - ShaderOutput *output = mix->inputs[2]->link; - vector inputs = mix->outputs[0]->links; - - relink(mix->inputs, inputs, output); - removed[mix->id] = true; - any_node_removed = true; - } - } - } - else if(node->special_type == SHADER_SPECIAL_TYPE_MIX_RGB) { - MixNode *mix = static_cast(node); - - /* remove unused Mix RGB inputs when factor is 0.0 or 1.0 */ - /* check for color links and make sure factor link is disconnected */ - if(mix->outputs[0]->links.size() && mix->inputs[1]->link && mix->inputs[2]->link && !mix->inputs[0]->link) { - /* factor 0.0 */ - if(mix->inputs[0]->value.x == 0.0f) { - ShaderOutput *output = mix->inputs[1]->link; - vector inputs = mix->outputs[0]->links; - - relink(mix->inputs, inputs, output); - removed[mix->id] = true; - any_node_removed = true; - } - /* factor 1.0 */ - else if(mix->inputs[0]->value.x == 1.0f) { - ShaderOutput *output = mix->inputs[2]->link; - vector inputs = mix->outputs[0]->links; - - relink(mix->inputs, inputs, output); - removed[mix->id] = true; - any_node_removed = true; - } - } - } } /* remove nodes */ @@ -606,10 +483,6 @@ void ShaderGraph::remove_unneeded_nodes() nodes = newnodes; } - - if(geom != NULL) { - add(geom); - } } /* Step 2: Constant folding. @@ -634,6 +507,9 @@ void ShaderGraph::constant_fold() traverse_queue.pop(); done.insert(node); foreach(ShaderOutput *output, node->outputs) { + if (output->links.size() == 0) { + continue; + } /* Schedule node which was depending on the value, * when possible. Do it before disconnect. */ @@ -652,7 +528,7 @@ void ShaderGraph::constant_fold() } /* Optimize current node. */ float3 optimized_value = make_float3(0.0f, 0.0f, 0.0f); - if(node->constant_fold(output, &optimized_value)) { + if(node->constant_fold(this, output, &optimized_value)) { /* Apply optimized value to connected sockets. */ vector links(output->links); foreach(ShaderInput *input, links) { @@ -737,8 +613,7 @@ void ShaderGraph::deduplicate_nodes() } /* TODO(sergey): Consider making it an utility function. */ for(int i = 0; i < node->outputs.size(); ++i) { - vector inputs = node->outputs[i]->links; - relink(node->inputs, inputs, other_node->outputs[i]); + relink(node, node->outputs[i], other_node->outputs[i]); } break; } @@ -771,15 +646,9 @@ void ShaderGraph::break_cycles(ShaderNode *node, vector& visited, vectorname == ustring("bump") && node->input("Height")->link) { + if(node->special_type == SHADER_SPECIAL_TYPE_BUMP && node->input("Height")->link) { ShaderInput *bump_input = node->input("Height"); ShaderNodeSet nodes_bump; diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h index 214199a1c52..2236f51957c 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -76,15 +76,11 @@ enum ShaderBump { enum ShaderNodeSpecialType { SHADER_SPECIAL_TYPE_NONE, SHADER_SPECIAL_TYPE_PROXY, - SHADER_SPECIAL_TYPE_MIX_CLOSURE, - SHADER_SPECIAL_TYPE_MIX_RGB, /* Only Mix subtype */ SHADER_SPECIAL_TYPE_AUTOCONVERT, SHADER_SPECIAL_TYPE_GEOMETRY, SHADER_SPECIAL_TYPE_SCRIPT, - SHADER_SPECIAL_TYPE_BACKGROUND, SHADER_SPECIAL_TYPE_IMAGE_SLOT, SHADER_SPECIAL_TYPE_CLOSURE, - SHADER_SPECIAL_TYPE_EMISSION, SHADER_SPECIAL_TYPE_BUMP, }; @@ -197,7 +193,7 @@ public: /* ** Node optimization ** */ /* Check whether the node can be replaced with single constant. */ - virtual bool constant_fold(ShaderOutput * /*socket*/, float3 * /*optimized_value*/) { return false; } + virtual bool constant_fold(ShaderGraph * /*graph*/, ShaderOutput * /*socket*/, float3 * /*optimized_value*/) { return false; } /* Simplify settings used by artists to the ones which are simpler to * evaluate in the kernel but keep the final result unchanged. @@ -307,9 +303,9 @@ public: void connect(ShaderOutput *from, ShaderInput *to); void disconnect(ShaderInput *to); - void relink(vector inputs, vector outputs, ShaderOutput *output); + void relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to); - void remove_unneeded_nodes(); + void remove_proxy_nodes(); void finalize(Scene *scene, bool do_bump = false, bool do_osl = false, diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index cc8519219ed..f8273107e1b 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -1210,7 +1210,7 @@ void MeshManager::device_update_displacement_images(Device *device, progress); return; } - ImageSlotNode *image_node = static_cast(node); + ImageSlotTextureNode *image_node = static_cast(node); int slot = image_node->slot; if(slot != -1) { bump_images.insert(slot); diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 57fb1a78f5b..8e8b99ec5e7 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1595,10 +1595,12 @@ ConvertNode::ConvertNode(ShaderSocketType from_, ShaderSocketType to_, bool auto from = from_; to = to_; - if(autoconvert) - special_type = SHADER_SPECIAL_TYPE_AUTOCONVERT; - - assert(from != to); + if(autoconvert) { + if(from == to) + special_type = SHADER_SPECIAL_TYPE_PROXY; + else + special_type = SHADER_SPECIAL_TYPE_AUTOCONVERT; + } if(from == SHADER_SOCKET_FLOAT) add_input("Val", SHADER_SOCKET_FLOAT); @@ -1614,6 +1616,8 @@ ConvertNode::ConvertNode(ShaderSocketType from_, ShaderSocketType to_, bool auto add_input("Normal", SHADER_SOCKET_NORMAL); else if(from == SHADER_SOCKET_STRING) add_input("String", SHADER_SOCKET_STRING); + else if(from == SHADER_SOCKET_CLOSURE) + add_input("Closure", SHADER_SOCKET_CLOSURE); else assert(0); @@ -1631,48 +1635,50 @@ ConvertNode::ConvertNode(ShaderSocketType from_, ShaderSocketType to_, bool auto add_output("Normal", SHADER_SOCKET_NORMAL); else if(to == SHADER_SOCKET_STRING) add_output("String", SHADER_SOCKET_STRING); + else if(to == SHADER_SOCKET_CLOSURE) + add_output("Closure", SHADER_SOCKET_CLOSURE); else assert(0); } -bool ConvertNode::constant_fold(ShaderOutput *socket, float3 *optimized_value) +bool ConvertNode::constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value) { ShaderInput *in = inputs[0]; float3 value = in->value; /* TODO(DingTo): conversion from/to int is not supported yet, don't fold in that case */ - if(socket == outputs[0] && in->link == NULL) { + if(in->link == NULL) { if(from == SHADER_SOCKET_FLOAT) { if(to == SHADER_SOCKET_INT) - /* float to int */ + /* float to int */ return false; else - /* float to float3 */ + /* float to float3 */ *optimized_value = make_float3(value.x, value.x, value.x); } else if(from == SHADER_SOCKET_INT) { if(to == SHADER_SOCKET_FLOAT) - /* int to float */ + /* int to float */ return false; else - /* int to vector/point/normal */ + /* int to vector/point/normal */ return false; } else if(to == SHADER_SOCKET_FLOAT) { if(from == SHADER_SOCKET_COLOR) - /* color to float */ + /* color to float */ optimized_value->x = linear_rgb_to_gray(value); else - /* vector/point/normal to float */ + /* vector/point/normal to float */ optimized_value->x = average(value); } else if(to == SHADER_SOCKET_INT) { if(from == SHADER_SOCKET_COLOR) - /* color to int */ + /* color to int */ return false; else - /* vector/point/normal to int */ + /* vector/point/normal to int */ return false; } else { @@ -1687,6 +1693,9 @@ bool ConvertNode::constant_fold(ShaderOutput *socket, float3 *optimized_value) void ConvertNode::compile(SVMCompiler& compiler) { + /* constant folding should eliminate proxy nodes */ + assert(from != to); + ShaderInput *in = inputs[0]; ShaderOutput *out = outputs[0]; @@ -1753,6 +1762,9 @@ void ConvertNode::compile(SVMCompiler& compiler) void ConvertNode::compile(OSLCompiler& compiler) { + /* constant folding should eliminate proxy nodes */ + assert(from != to); + if(from == SHADER_SOCKET_FLOAT) compiler.add(this, "node_convert_from_float"); else if(from == SHADER_SOCKET_INT) @@ -1769,26 +1781,6 @@ void ConvertNode::compile(OSLCompiler& compiler) assert(0); } -/* Proxy */ - -ProxyNode::ProxyNode(ShaderSocketType type_) -: ShaderNode("proxy") -{ - type = type_; - special_type = SHADER_SPECIAL_TYPE_PROXY; - - add_input("Input", type); - add_output("Output", type); -} - -void ProxyNode::compile(SVMCompiler& /*compiler*/) -{ -} - -void ProxyNode::compile(OSLCompiler& /*compiler*/) -{ -} - /* BSDF Closure */ BsdfNode::BsdfNode(bool scattering_) @@ -2285,8 +2277,6 @@ bool SubsurfaceScatteringNode::has_bssrdf_bump() EmissionNode::EmissionNode() : ShaderNode("emission") { - special_type = SHADER_SPECIAL_TYPE_EMISSION; - add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f)); add_input("Strength", SHADER_SOCKET_FLOAT, 10.0f); add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM); @@ -2315,13 +2305,20 @@ void EmissionNode::compile(OSLCompiler& compiler) compiler.add(this, "node_emission"); } +bool EmissionNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput * /*socket*/, float3 * /*optimized_value*/) +{ + ShaderInput *color_in = input("Color"); + ShaderInput *strength_in = input("Strength"); + + return ((!color_in->link && color_in->value == make_float3(0.0f, 0.0f, 0.0f)) || + (!strength_in->link && strength_in->value.x == 0.0f)); +} + /* Background Closure */ BackgroundNode::BackgroundNode() : ShaderNode("background") { - special_type = SHADER_SPECIAL_TYPE_BACKGROUND; - add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f)); add_input("Strength", SHADER_SOCKET_FLOAT, 1.0f); add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM); @@ -2350,6 +2347,15 @@ void BackgroundNode::compile(OSLCompiler& compiler) compiler.add(this, "node_background"); } +bool BackgroundNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput * /*socket*/, float3 * /*optimized_value*/) +{ + ShaderInput *color_in = input("Color"); + ShaderInput *strength_in = input("Strength"); + + return ((!color_in->link && color_in->value == make_float3(0.0f, 0.0f, 0.0f)) || + (!strength_in->link && strength_in->value.x == 0.0f)); +} + /* Holdout Closure */ HoldoutNode::HoldoutNode() @@ -3249,7 +3255,7 @@ ValueNode::ValueNode() add_output("Value", SHADER_SOCKET_FLOAT); } -bool ValueNode::constant_fold(ShaderOutput * /*socket*/, +bool ValueNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput * /*socket*/, float3 *optimized_value) { *optimized_value = make_float3(value, value, value); @@ -3280,7 +3286,7 @@ ColorNode::ColorNode() add_output("Color", SHADER_SOCKET_COLOR); } -bool ColorNode::constant_fold(ShaderOutput * /*socket*/, +bool ColorNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput * /*socket*/, float3 *optimized_value) { *optimized_value = value; @@ -3330,8 +3336,6 @@ void AddClosureNode::compile(OSLCompiler& compiler) MixClosureNode::MixClosureNode() : ShaderNode("mix_closure") { - special_type = SHADER_SPECIAL_TYPE_MIX_CLOSURE; - add_input("Fac", SHADER_SOCKET_FLOAT, 0.5f); add_input("Closure1", SHADER_SOCKET_CLOSURE); add_input("Closure2", SHADER_SOCKET_CLOSURE); @@ -3348,6 +3352,37 @@ void MixClosureNode::compile(OSLCompiler& compiler) compiler.add(this, "node_mix_closure"); } +bool MixClosureNode::constant_fold(ShaderGraph *graph, ShaderOutput * /*socket*/, float3 * /*optimized_value*/) +{ + ShaderInput *fac_in = input("Fac"); + ShaderInput *closure1_in = input("Closure1"); + ShaderInput *closure2_in = input("Closure2"); + ShaderOutput *closure_out = output("Closure"); + + /* remove useless mix closures nodes */ + if(closure1_in->link == closure2_in->link) { + graph->relink(this, closure_out, closure1_in->link); + return true; + } + + /* remove unused mix closure input when factor is 0.0 or 1.0 */ + /* check for closure links and make sure factor link is disconnected */ + if(closure1_in->link && closure2_in->link && !fac_in->link) { + /* factor 0.0 */ + if(fac_in->value.x == 0.0f) { + graph->relink(this, closure_out, closure1_in->link); + return true; + } + /* factor 1.0 */ + else if(fac_in->value.x == 1.0f) { + graph->relink(this, closure_out, closure2_in->link); + return true; + } + } + + return false; +} + /* Mix Closure */ MixClosureWeightNode::MixClosureWeightNode() @@ -3480,6 +3515,41 @@ void MixNode::compile(OSLCompiler& compiler) compiler.add(this, "node_mix"); } +bool MixNode::constant_fold(ShaderGraph *graph, ShaderOutput * /*socket*/, float3 * /*optimized_value*/) +{ + if(type != ustring("Mix")) { + return false; + } + + ShaderInput *fac_in = input("Fac"); + ShaderInput *color1_in = input("Color1"); + ShaderInput *color2_in = input("Color2"); + ShaderOutput *color_out = output("Color"); + + /* remove useless mix colors nodes */ + if(color1_in->link == color2_in->link) { + graph->relink(this, color_out, color1_in->link); + return true; + } + + /* remove unused mix color input when factor is 0.0 or 1.0 */ + /* check for color links and make sure factor link is disconnected */ + if(color1_in->link && color2_in->link && !fac_in->link) { + /* factor 0.0 */ + if(fac_in->value.x == 0.0f) { + graph->relink(this, color_out, color1_in->link); + return true; + } + /* factor 1.0 */ + else if(fac_in->value.x == 1.0f) { + graph->relink(this, color_out, color2_in->link); + return true; + } + } + + return false; +} + /* Combine RGB */ CombineRGBNode::CombineRGBNode() : ShaderNode("combine_rgb") @@ -3588,7 +3658,7 @@ GammaNode::GammaNode() add_output("Color", SHADER_SOCKET_COLOR); } -bool GammaNode::constant_fold(ShaderOutput *socket, float3 *optimized_value) +bool GammaNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput *socket, float3 *optimized_value) { ShaderInput *color_in = input("Color"); ShaderInput *gamma_in = input("Gamma"); @@ -3597,7 +3667,6 @@ bool GammaNode::constant_fold(ShaderOutput *socket, float3 *optimized_value) if(color_in->link == NULL && gamma_in->link == NULL) { *optimized_value = svm_math_gamma_color(color_in->value, gamma_in->value.x); - return true; } } @@ -4058,14 +4127,13 @@ BlackbodyNode::BlackbodyNode() add_output("Color", SHADER_SOCKET_COLOR); } -bool BlackbodyNode::constant_fold(ShaderOutput *socket, float3 *optimized_value) +bool BlackbodyNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput *socket, float3 *optimized_value) { ShaderInput *temperature_in = input("Temperature"); if(socket == output("Color")) { if(temperature_in->link == NULL) { *optimized_value = svm_math_blackbody_color(temperature_in->value.x); - return true; } } @@ -4165,7 +4233,7 @@ static ShaderEnum math_type_init() ShaderEnum MathNode::type_enum = math_type_init(); -bool MathNode::constant_fold(ShaderOutput *socket, float3 *optimized_value) +bool MathNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput *socket, float3 *optimized_value) { ShaderInput *value1_in = input("Value1"); ShaderInput *value2_in = input("Value2"); @@ -4242,7 +4310,7 @@ static ShaderEnum vector_math_type_init() ShaderEnum VectorMathNode::type_enum = vector_math_type_init(); -bool VectorMathNode::constant_fold(ShaderOutput *socket, float3 *optimized_value) +bool VectorMathNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput *socket, float3 *optimized_value) { ShaderInput *vector1_in = input("Vector1"); ShaderInput *vector2_in = input("Vector2"); @@ -4409,6 +4477,28 @@ void BumpNode::compile(OSLCompiler& compiler) compiler.add(this, "node_bump"); } +bool BumpNode::constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value) +{ + ShaderInput *height_in = input("Height"); + ShaderInput *normal_in = input("Normal"); + + if(height_in->link == NULL) { + if(normal_in->link == NULL) { + GeometryNode *geom = new GeometryNode(); + graph->add(geom); + graph->relink(this, outputs[0], geom->output("Normal")); + } + else { + graph->relink(this, outputs[0], normal_in->link); + } + return true; + } + + /* TODO(sergey): Ignore bump with zero strength. */ + + return false; +} + /* RGBCurvesNode */ RGBCurvesNode::RGBCurvesNode() diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index a5495ff3671..9e93f30e75e 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -70,15 +70,6 @@ public: /* Nodes */ -/* Any node which uses image manager's slot should be a subclass of this one. */ -class ImageSlotNode : public ShaderNode { -public: - ImageSlotNode(const char *name_) : ShaderNode(name_) { - special_type = SHADER_SPECIAL_TYPE_IMAGE_SLOT; - } - int slot; -}; - class TextureNode : public ShaderNode { public: TextureNode(const char *name_) : ShaderNode(name_) {} @@ -90,15 +81,13 @@ public: } }; -class ImageSlotTextureNode : public ImageSlotNode { +/* Any node which uses image manager's slot should be a subclass of this one. */ +class ImageSlotTextureNode : public TextureNode { public: - ImageSlotTextureNode(const char *name_) : ImageSlotNode(name_) {} - TextureMapping tex_mapping; - - virtual bool equals(const ShaderNode *other) { - return ShaderNode::equals(other) && - tex_mapping.equals(((const ImageSlotTextureNode*)other)->tex_mapping); + ImageSlotTextureNode(const char *name_) : TextureNode(name_) { + special_type = SHADER_SPECIAL_TYPE_IMAGE_SLOT; } + int slot; }; class ImageTextureNode : public ImageSlotTextureNode { @@ -372,7 +361,7 @@ public: ConvertNode(ShaderSocketType from, ShaderSocketType to, bool autoconvert = false); SHADER_NODE_BASE_CLASS(ConvertNode) - bool constant_fold(ShaderOutput *socket, float3 *optimized_value); + bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value); ShaderSocketType from, to; @@ -385,23 +374,6 @@ public: } }; -class ProxyNode : public ShaderNode { -public: - ProxyNode(ShaderSocketType type); - SHADER_NODE_BASE_CLASS(ProxyNode) - - ShaderSocketType type; - - virtual bool equals(const ShaderNode * /*other*/) - { - /* Proxy nodes are created for node groups and can't be duplicated - * actually. So in order to make code a bit more robust in obscure cases - * lets explicitly forbid de-duplication of proxy nodes for now. - */ - return false; - } -}; - class BsdfNode : public ShaderNode { public: BsdfNode(bool scattering = false); @@ -505,6 +477,7 @@ public: class EmissionNode : public ShaderNode { public: SHADER_NODE_CLASS(EmissionNode) + bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value); bool has_surface_emission() { return true; } }; @@ -512,6 +485,7 @@ public: class BackgroundNode : public ShaderNode { public: SHADER_NODE_CLASS(BackgroundNode) + bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value); }; class HoldoutNode : public ShaderNode { @@ -650,7 +624,7 @@ class ValueNode : public ShaderNode { public: SHADER_NODE_CLASS(ValueNode) - bool constant_fold(ShaderOutput *socket, float3 *optimized_value); + bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value); float value; @@ -665,7 +639,7 @@ class ColorNode : public ShaderNode { public: SHADER_NODE_CLASS(ColorNode) - bool constant_fold(ShaderOutput *socket, float3 *optimized_value); + bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value); float3 value; @@ -684,6 +658,7 @@ public: class MixClosureNode : public ShaderNode { public: SHADER_NODE_CLASS(MixClosureNode) + bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value); }; class MixClosureWeightNode : public ShaderNode { @@ -701,6 +676,7 @@ public: class MixNode : public ShaderNode { public: SHADER_NODE_CLASS(MixNode) + bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value); virtual int get_group() { return NODE_GROUP_LEVEL_3; } @@ -743,7 +719,7 @@ class GammaNode : public ShaderNode { public: SHADER_NODE_CLASS(GammaNode) - bool constant_fold(ShaderOutput *socket, float3 *optimized_value); + bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value); virtual int get_group() { return NODE_GROUP_LEVEL_1; } }; @@ -834,7 +810,7 @@ public: class BlackbodyNode : public ShaderNode { public: SHADER_NODE_CLASS(BlackbodyNode) - bool constant_fold(ShaderOutput *socket, float3 *optimized_value); + bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value); virtual int get_group() { return NODE_GROUP_LEVEL_3; } }; @@ -843,7 +819,7 @@ class MathNode : public ShaderNode { public: SHADER_NODE_CLASS(MathNode) virtual int get_group() { return NODE_GROUP_LEVEL_1; } - bool constant_fold(ShaderOutput *socket, float3 *optimized_value); + bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value); bool use_clamp; @@ -878,7 +854,7 @@ class VectorMathNode : public ShaderNode { public: SHADER_NODE_CLASS(VectorMathNode) virtual int get_group() { return NODE_GROUP_LEVEL_1; } - bool constant_fold(ShaderOutput *socket, float3 *optimized_value); + bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value); ustring type; static ShaderEnum type_enum; @@ -916,6 +892,7 @@ public: class BumpNode : public ShaderNode { public: SHADER_NODE_CLASS(BumpNode) + bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value); bool has_spatial_varying() { return true; } virtual int get_feature() { return NODE_FEATURE_BUMP; diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index cb3cb8b9b1b..964ed8db3f7 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -483,11 +483,11 @@ bool OSLCompiler::node_skip_input(ShaderNode *node, ShaderInput *input) if(strcmp(input->name, "Normal") == 0) return true; } - else if(node->name == ustring("bump")) { + else if(node->special_type == SHADER_SPECIAL_TYPE_BUMP) { if(strcmp(input->name, "Height") == 0) return true; } - else if(current_type == SHADER_TYPE_DISPLACEMENT && input->link && input->link->parent->name == ustring("bump")) + else if(current_type == SHADER_TYPE_DISPLACEMENT && input->link && input->link->parent->special_type == SHADER_SPECIAL_TYPE_BUMP) return true; return false; diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index 09a6061abea..797f31ce92d 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -175,7 +175,7 @@ void Shader::set_graph(ShaderGraph *graph_) * are needed, since the node attribute callbacks check if their sockets * are connected but proxy nodes should not count */ if(graph_) - graph_->remove_unneeded_nodes(); + graph_->remove_proxy_nodes(); /* assign graph */ delete graph; diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index 56fb57e9667..350ef921bc1 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -365,7 +365,7 @@ uint SVMCompiler::attribute(AttributeStandard std) bool SVMCompiler::node_skip_input(ShaderNode * /*node*/, ShaderInput *input) { /* nasty exception .. */ - if(current_type == SHADER_TYPE_DISPLACEMENT && input->link && input->link->parent->name == ustring("bump")) + if(current_type == SHADER_TYPE_DISPLACEMENT && input->link && input->link->parent->special_type == SHADER_SPECIAL_TYPE_BUMP) return true; return false; -- cgit v1.2.3