Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2016-05-02 01:05:16 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2016-05-05 22:43:46 +0300
commitdd8bfa0929f9f1ae940e7da0468fbdd6744e50bb (patch)
treeb4bfab7872a9ce0ea32f25cfe46547e41d5de601 /intern/cycles/render
parent2cfadecf97b8c7be5e24ea387c8aef34e9f0a1e9 (diff)
Code refactor: reduce special node types, use generic constant folding.
Diffstat (limited to 'intern/cycles/render')
-rw-r--r--intern/cycles/render/graph.cpp187
-rw-r--r--intern/cycles/render/graph.h10
-rw-r--r--intern/cycles/render/mesh.cpp2
-rw-r--r--intern/cycles/render/nodes.cpp186
-rw-r--r--intern/cycles/render/nodes.h57
-rw-r--r--intern/cycles/render/osl.cpp4
-rw-r--r--intern/cycles/render/shader.cpp2
-rw-r--r--intern/cycles/render/svm.cpp2
8 files changed, 191 insertions, 259 deletions
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<ShaderInput*> inputs, vector<ShaderInput*> 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<ShaderInput*> 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<bool> 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<ProxyNode*>(node);
+ ConvertNode *proxy = static_cast<ConvertNode*>(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<ShaderInput*> 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<ShaderInput*> 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<BackgroundNode*>(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<ShaderInput*> 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<EmissionNode*>(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<ShaderInput*> 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<BumpNode*>(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<ShaderInput*> 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<MixClosureNode*>(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<ShaderInput*> 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<ShaderInput*> 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<ShaderInput*> 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<MixNode*>(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<ShaderInput*> 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<ShaderInput*> 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<ShaderInput*> 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<ShaderInput*> 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<bool>& visited, vector<b
void ShaderGraph::clean(Scene *scene)
{
- /* Graph simplification:
- * 1: Remove unnecessary nodes
- * 2: Constant folding
- * 3: Simplification
- * 4: De-duplication
- */
+ /* Graph simplification */
- /* 1: Remove proxy and unnecessary nodes. */
- remove_unneeded_nodes();
+ /* 1: Remove proxy nodes was already done. */
/* 2: Constant folding. */
constant_fold();
@@ -892,7 +761,7 @@ void ShaderGraph::refine_bump_nodes()
* to "center" input. */
foreach(ShaderNode *node, nodes) {
- if(node->name == 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<ShaderInput*> inputs, vector<ShaderInput*> 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<ImageSlotNode*>(node);
+ ImageSlotTextureNode *image_node = static_cast<ImageSlotTextureNode*>(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;