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@pandora.be>2012-10-10 19:56:43 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2012-10-10 19:56:43 +0400
commitfe09b24e86e340e733f91c8ed9fcc7b8519157f4 (patch)
treedfe21334e003d8e73ea993d5fcac54c19facd987 /intern/cycles/render
parente9a61cd29db61513dedeb4d656e7dadff7439b1a (diff)
Cycles: per-BSDF normal input and new Bump node.
Each BSDF node now has a Normal input, which can be used to set a custom normal for the BSDF, for example if you want to have only bump on one of the layers in a multilayer material. The Bump node can be used to generate a normal from a scalar value, the same as what happens when you connect a scalar value to the displacement output. Documentation has been updated with the latest changes: http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Nodes Patch by Agustin Benavidez, some implementation tweaks by me.
Diffstat (limited to 'intern/cycles/render')
-rw-r--r--intern/cycles/render/graph.cpp78
-rw-r--r--intern/cycles/render/graph.h1
-rw-r--r--intern/cycles/render/nodes.cpp58
-rw-r--r--intern/cycles/render/nodes.h5
4 files changed, 136 insertions, 6 deletions
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index c13102e9567..c1c976dc193 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -229,6 +229,8 @@ void ShaderGraph::finalize(bool do_bump, bool do_osl)
if(!finalized) {
clean();
default_inputs(do_osl);
+ refine_bump_nodes();
+
if(do_bump)
bump_from_displacement();
@@ -484,6 +486,61 @@ void ShaderGraph::default_inputs(bool do_osl)
add(texco);
}
+void ShaderGraph::refine_bump_nodes()
+{
+ /* we transverse the node graph looking for bump nodes, when we find them,
+ * like in bump_from_displacement(), we copy the sub-graph defined from "bump"
+ * input to the inputs "center","dx" and "dy" What is in "bump" input is moved
+ * to "center" input. */
+
+ foreach(ShaderNode *node, nodes) {
+ if(node->name == ustring("bump") && node->input("Height")->link) {
+ ShaderInput *bump_input = node->input("Height");
+ set<ShaderNode*> nodes_bump;
+
+ /* make 2 extra copies of the subgraph defined in Bump input */
+ map<ShaderNode*, ShaderNode*> nodes_dx;
+ map<ShaderNode*, ShaderNode*> nodes_dy;
+
+ /* find dependencies for the given input */
+ find_dependencies(nodes_bump, bump_input );
+
+ copy_nodes(nodes_bump, nodes_dx);
+ copy_nodes(nodes_bump, nodes_dy);
+
+ /* mark nodes to indicate they are use for bump computation, so
+ that any texture coordinates are shifted by dx/dy when sampling */
+ foreach(ShaderNode *node, nodes_bump)
+ node->bump = SHADER_BUMP_CENTER;
+ foreach(NodePair& pair, nodes_dx)
+ pair.second->bump = SHADER_BUMP_DX;
+ foreach(NodePair& pair, nodes_dy)
+ pair.second->bump = SHADER_BUMP_DY;
+
+ ShaderOutput *out = bump_input->link;
+ ShaderOutput *out_dx = nodes_dx[out->parent]->output(out->name);
+ ShaderOutput *out_dy = nodes_dy[out->parent]->output(out->name);
+
+ connect(out_dx, node->input("SampleX"));
+ connect(out_dy, node->input("SampleY"));
+
+ /* add generated nodes */
+ foreach(NodePair& pair, nodes_dx)
+ add(pair.second);
+ foreach(NodePair& pair, nodes_dy)
+ add(pair.second);
+
+ /* connect what is conected is bump to samplecenter input*/
+ connect(out , node->input("SampleCenter"));
+
+ /* bump input is just for connectivity purpose for the graph input,
+ * we reconected this input to samplecenter, so lets disconnect it
+ * from bump input */
+ disconnect(bump_input);
+ }
+ }
+}
+
void ShaderGraph::bump_from_displacement()
{
/* generate bump mapping automatically from displacement. bump mapping is
@@ -497,7 +554,7 @@ void ShaderGraph::bump_from_displacement()
* different shifted coordinates.
*
* these 3 displacement values are then fed into the bump node, which will
- * modify the normal. */
+ * output the the perturbed normal. */
ShaderInput *displacement_in = output()->input("Displacement");
@@ -526,6 +583,12 @@ void ShaderGraph::bump_from_displacement()
foreach(NodePair& pair, nodes_dy)
pair.second->bump = SHADER_BUMP_DY;
+ /* add set normal node and connect the bump normal ouput to the set normal
+ * output, so it can finally set the shader normal, note we are only doing
+ * this for bump from displacement, this will be the only bump allowed to
+ * overwrite the shader normal */
+ ShaderNode *set_normal = add(new SetNormalNode());
+
/* add bump node and connect copied graphs to it */
ShaderNode *bump = add(new BumpNode());
@@ -537,6 +600,9 @@ void ShaderGraph::bump_from_displacement()
connect(out_center, bump->input("SampleCenter"));
connect(out_dx, bump->input("SampleX"));
connect(out_dy, bump->input("SampleY"));
+
+ /* connect the bump out to the set normal in: */
+ connect(bump->output("Normal"), set_normal->input("Direction"));
/* connect bump output to normal input nodes that aren't set yet. actually
* this will only set the normal input to the geometry node that we created
@@ -544,8 +610,14 @@ void ShaderGraph::bump_from_displacement()
foreach(ShaderNode *node, nodes)
foreach(ShaderInput *input, node->inputs)
if(!input->link && input->default_value == ShaderInput::NORMAL)
- connect(bump->output("Normal"), input);
-
+ connect(set_normal->output("Normal"), input);
+
+ /* for displacement bump, clear the normal input in case the above loop
+ * connected the setnormal out to the bump normalin */
+ ShaderInput *bump_normal_in = bump->input("NormalIn");
+ if(bump_normal_in)
+ bump_normal_in->link = NULL;
+
/* finally, add the copied nodes to the graph. we can't do this earlier
* because we would create dependency cycles in the above loop */
foreach(NodePair& pair, nodes_center)
diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h
index d485ed02150..acafe1d5278 100644
--- a/intern/cycles/render/graph.h
+++ b/intern/cycles/render/graph.h
@@ -235,6 +235,7 @@ protected:
void break_cycles(ShaderNode *node, vector<bool>& visited, vector<bool>& on_stack);
void clean();
void bump_from_displacement();
+ void refine_bump_nodes();
void default_inputs(bool do_osl);
};
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index da31a528310..b4ef93a4ff8 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -1175,7 +1175,7 @@ BsdfNode::BsdfNode()
closure = ccl::CLOSURE_BSDF_DIFFUSE_ID;
add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
- add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true);
+ add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL);
add_output("BSDF", SHADER_SOCKET_CLOSURE);
}
@@ -1183,6 +1183,7 @@ BsdfNode::BsdfNode()
void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2)
{
ShaderInput *color_in = input("Color");
+ ShaderInput *normal_in = input("Normal");
if(color_in->link) {
compiler.stack_assign(color_in);
@@ -1203,6 +1204,10 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *
compiler.closure_mix_weight_offset()),
__float_as_int((param1)? param1->value.x: 0.0f),
__float_as_int((param2)? param2->value.x: 0.0f));
+
+ if(normal_in->link)
+ compiler.stack_assign(normal_in);
+ compiler.add_node(NODE_CLOSURE_BSDF, normal_in->stack_offset);
}
void BsdfNode::compile(SVMCompiler& compiler)
@@ -2215,7 +2220,7 @@ static ShaderEnum mix_type_init()
enm.insert("Burn", NODE_MIX_BURN);
enm.insert("Hue", NODE_MIX_HUE);
enm.insert("Saturation", NODE_MIX_SAT);
- enm.insert("Value", NODE_MIX_VAL );
+ enm.insert("Value", NODE_MIX_VAL);
enm.insert("Color", NODE_MIX_COLOR);
enm.insert("Soft Light", NODE_MIX_SOFT);
enm.insert("Linear Light", NODE_MIX_LINEAR);
@@ -2586,6 +2591,7 @@ OutputNode::OutputNode()
add_input("Surface", SHADER_SOCKET_CLOSURE);
add_input("Volume", SHADER_SOCKET_CLOSURE);
add_input("Displacement", SHADER_SOCKET_FLOAT);
+ add_input("Normal", SHADER_SOCKET_NORMAL);
}
void OutputNode::compile(SVMCompiler& compiler)
@@ -2733,9 +2739,15 @@ void VectorMathNode::compile(OSLCompiler& compiler)
BumpNode::BumpNode()
: ShaderNode("bump")
{
+ /* this input is used by the user, but after graph transform it is no longer
+ * used and moved to sampler center/x/y instead */
+ add_input("Height", SHADER_SOCKET_NORMAL);
+
add_input("SampleCenter", SHADER_SOCKET_FLOAT);
add_input("SampleX", SHADER_SOCKET_FLOAT);
add_input("SampleY", SHADER_SOCKET_FLOAT);
+ add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL);
+ add_input("Strength", SHADER_SOCKET_FLOAT, 0.1f);
add_output("Normal", SHADER_SOCKET_NORMAL);
}
@@ -2745,12 +2757,25 @@ void BumpNode::compile(SVMCompiler& compiler)
ShaderInput *center_in = input("SampleCenter");
ShaderInput *dx_in = input("SampleX");
ShaderInput *dy_in = input("SampleY");
+ ShaderInput *normal_in = input("NormalIn");
+ ShaderInput *intensity_in = input("Strength");
+ ShaderOutput *normal_out = output("Normal");
compiler.stack_assign(center_in);
compiler.stack_assign(dx_in);
compiler.stack_assign(dy_in);
+ compiler.stack_assign(intensity_in);
+ compiler.stack_assign(normal_out);
- compiler.add_node(NODE_SET_BUMP, center_in->stack_offset, dx_in->stack_offset, dy_in->stack_offset);
+ if(normal_in->link)
+ compiler.stack_assign(normal_in);
+
+ /* pack all parameters in the node */
+ compiler.add_node(NODE_SET_BUMP,
+ normal_in->stack_offset,
+ compiler.encode_uchar4(center_in->stack_offset, dx_in->stack_offset,
+ dy_in->stack_offset, intensity_in->stack_offset),
+ normal_out->stack_offset);
}
void BumpNode::compile(OSLCompiler& compiler)
@@ -2819,17 +2844,44 @@ void RGBRampNode::compile(OSLCompiler& compiler)
/* NB: cycles float3 type is actually 4 floats! need to use an explicit array */
float ramp_color[RAMP_TABLE_SIZE][3];
float ramp_alpha[RAMP_TABLE_SIZE];
+
for (int i = 0; i < RAMP_TABLE_SIZE; ++i) {
ramp_color[i][0] = ramp[i].x;
ramp_color[i][1] = ramp[i].y;
ramp_color[i][2] = ramp[i].z;
ramp_alpha[i] = ramp[i].w;
}
+
compiler.parameter_color_array("ramp_color", ramp_color, RAMP_TABLE_SIZE);
compiler.parameter_array("ramp_alpha", ramp_alpha, RAMP_TABLE_SIZE);
compiler.add(this, "node_rgb_ramp");
}
+/* Set Normal Node */
+
+SetNormalNode::SetNormalNode()
+: ShaderNode("set_normal")
+{
+ add_input("Direction", SHADER_SOCKET_VECTOR);
+ add_output("Normal", SHADER_SOCKET_NORMAL);
+}
+
+void SetNormalNode::compile(SVMCompiler& compiler)
+{
+ ShaderInput *direction_in = input("Direction");
+ ShaderOutput *normal_out = output("Normal");
+
+ compiler.stack_assign(direction_in);
+ compiler.stack_assign(normal_out);
+
+ compiler.add_node(NODE_CLOSURE_SET_NORMAL, direction_in->stack_offset, normal_out->stack_offset);
+}
+
+void SetNormalNode::compile(OSLCompiler& compiler)
+{
+ compiler.add(this, "set_normal");
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 6e5d7be0091..fbc61e12fd4 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -440,6 +440,11 @@ public:
float4 ramp[RAMP_TABLE_SIZE];
};
+class SetNormalNode : public ShaderNode {
+public:
+ SHADER_NODE_CLASS(SetNormalNode)
+};
+
CCL_NAMESPACE_END
#endif /* __NODES_H__ */