2 * Copyright 2011-2016 Blender Foundation
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 #include "graph/node.h"
21 #include "graph/node_type.h"
23 #include "kernel/kernel_types.h"
25 #include "util/util_list.h"
26 #include "util/util_map.h"
27 #include "util/util_param.h"
28 #include "util/util_set.h"
29 #include "util/util_types.h"
30 #include "util/util_vector.h"
34 class AttributeRequestSet;
49 * For bump mapping, a node may be evaluated multiple times, using different
50 * samples to reconstruct the normal, this indicates the sample position */
59 /* Identifiers for some special node types.
61 * The graph needs to identify these in the clean function.
62 * Cannot use dynamic_cast, as this is disabled for OSL. */
64 enum ShaderNodeSpecialType {
65 SHADER_SPECIAL_TYPE_NONE,
66 SHADER_SPECIAL_TYPE_PROXY,
67 SHADER_SPECIAL_TYPE_AUTOCONVERT,
68 SHADER_SPECIAL_TYPE_GEOMETRY,
69 SHADER_SPECIAL_TYPE_SCRIPT,
70 SHADER_SPECIAL_TYPE_IMAGE_SLOT,
71 SHADER_SPECIAL_TYPE_CLOSURE,
72 SHADER_SPECIAL_TYPE_COMBINE_CLOSURE,
73 SHADER_SPECIAL_TYPE_OUTPUT,
74 SHADER_SPECIAL_TYPE_BUMP,
79 * Input socket for a shader node. May be linked to an output or not. If not
80 * linked, it will either get a fixed default value, or e.g. a texture
85 ShaderInput(const SocketType& socket_type_, ShaderNode* parent_)
86 : socket_type(socket_type_), parent(parent_), link(NULL), stack_offset(SVM_STACK_INVALID)
89 ustring name() { return socket_type.ui_name; }
90 int flags() { return socket_type.flags; }
91 SocketType::Type type() { return socket_type.type; }
93 void set(float f) { ((Node*)parent)->set(socket_type, f); }
94 void set(float3 f) { ((Node*)parent)->set(socket_type, f); }
96 const SocketType& socket_type;
99 int stack_offset; /* for SVM compiler */
104 * Output socket for a shader node. */
108 ShaderOutput(const SocketType& socket_type_, ShaderNode* parent_)
109 : socket_type(socket_type_), parent(parent_), stack_offset(SVM_STACK_INVALID)
112 ustring name() { return socket_type.ui_name; }
113 SocketType::Type type() { return socket_type.type; }
115 const SocketType& socket_type;
117 vector<ShaderInput*> links;
118 int stack_offset; /* for SVM compiler */
123 * Shader node in graph, with input and output sockets. This is the virtual
124 * base class for all node types. */
126 class ShaderNode : public Node {
128 explicit ShaderNode(const NodeType *type);
129 virtual ~ShaderNode();
131 void create_inputs_outputs(const NodeType *type);
133 ShaderInput *input(const char *name);
134 ShaderOutput *output(const char *name);
135 ShaderInput *input(ustring name);
136 ShaderOutput *output(ustring name);
138 virtual ShaderNode *clone() const = 0;
139 virtual void attributes(Shader *shader, AttributeRequestSet *attributes);
140 virtual void compile(SVMCompiler& compiler) = 0;
141 virtual void compile(OSLCompiler& compiler) = 0;
143 /* ** Node optimization ** */
144 /* Check whether the node can be replaced with single constant. */
145 virtual void constant_fold(const ConstantFolder& /*folder*/) {}
147 /* Simplify settings used by artists to the ones which are simpler to
148 * evaluate in the kernel but keep the final result unchanged.
150 virtual void simplify_settings(Scene * /*scene*/) {};
152 virtual bool has_surface_emission() { return false; }
153 virtual bool has_surface_transparent() { return false; }
154 virtual bool has_surface_bssrdf() { return false; }
155 virtual bool has_bump() { return false; }
156 virtual bool has_bssrdf_bump() { return false; }
157 virtual bool has_spatial_varying() { return false; }
158 virtual bool has_object_dependency() { return false; }
159 virtual bool has_attribute_dependency() { return false; }
160 virtual bool has_integrator_dependency() { return false; }
161 virtual bool has_volume_support() { return false; }
162 virtual bool has_raytrace() { return false; }
163 vector<ShaderInput*> inputs;
164 vector<ShaderOutput*> outputs;
166 int id; /* index in graph node array */
167 ShaderBump bump; /* for bump mapping utility */
169 ShaderNodeSpecialType special_type; /* special node type */
171 /* ** Selective nodes compilation ** */
173 /* TODO(sergey): More explicitly mention in the function names
174 * that those functions are for selective compilation only?
177 /* Nodes are split into several groups, group of level 0 contains
178 * nodes which are most commonly used, further levels are extension
179 * of previous one and includes less commonly used nodes.
181 virtual int get_group() { return NODE_GROUP_LEVEL_0; }
183 /* Node feature are used to disable huge nodes inside the group,
184 * so it's possible to disable huge nodes inside of the required
187 virtual int get_feature() { return bump == SHADER_BUMP_NONE ? 0 : NODE_FEATURE_BUMP; }
189 /* Get closure ID to which the node compiles into. */
190 virtual ClosureType get_closure_type() { return CLOSURE_NONE_ID; }
192 /* Check whether settings of the node equals to another one.
194 * This is mainly used to check whether two nodes can be merged
195 * together. Meaning, runtime stuff like node id and unbound slots
196 * will be ignored for comparison.
198 * NOTE: If some node can't be de-duplicated for whatever reason it
199 * is to be handled in the subclass.
201 virtual bool equals(const ShaderNode& other);
205 /* Node definition utility macros */
207 #define SHADER_NODE_CLASS(type) \
210 virtual ShaderNode *clone() const { return new type(*this); } \
211 virtual void compile(SVMCompiler& compiler); \
212 virtual void compile(OSLCompiler& compiler); \
214 #define SHADER_NODE_NO_CLONE_CLASS(type) \
217 virtual void compile(SVMCompiler& compiler); \
218 virtual void compile(OSLCompiler& compiler); \
220 #define SHADER_NODE_BASE_CLASS(type) \
221 virtual ShaderNode *clone() const { return new type(*this); } \
222 virtual void compile(SVMCompiler& compiler); \
223 virtual void compile(OSLCompiler& compiler); \
225 class ShaderNodeIDComparator
228 bool operator()(const ShaderNode *n1, const ShaderNode *n2) const
230 return n1->id < n2->id;
234 typedef set<ShaderNode*, ShaderNodeIDComparator> ShaderNodeSet;
235 typedef map<ShaderNode*, ShaderNode*, ShaderNodeIDComparator> ShaderNodeMap;
239 * Shader graph of nodes. Also does graph manipulations for default inputs,
240 * bump mapping from displacement, and possibly other things in the future. */
244 list<ShaderNode*> nodes;
248 string displacement_hash;
253 ShaderNode *add(ShaderNode *node);
254 OutputNode *output();
256 void connect(ShaderOutput *from, ShaderInput *to);
257 void disconnect(ShaderOutput *from);
258 void disconnect(ShaderInput *to);
259 void relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to);
261 void remove_proxy_nodes();
262 void compute_displacement_hash();
263 void simplify(Scene *scene);
264 void finalize(Scene *scene,
265 bool do_bump = false,
266 bool do_simplify = false,
267 bool bump_in_object_space = false);
269 int get_num_closures();
271 void dump_graph(const char *filename);
274 typedef pair<ShaderNode* const, ShaderNode*> NodePair;
276 void find_dependencies(ShaderNodeSet& dependencies, ShaderInput *input);
278 void copy_nodes(ShaderNodeSet& nodes, ShaderNodeMap& nnodemap);
280 void break_cycles(ShaderNode *node, vector<bool>& visited, vector<bool>& on_stack);
281 void bump_from_displacement(bool use_object_space);
282 void refine_bump_nodes();
283 void default_inputs(bool do_osl);
284 void transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume);
286 /* Graph simplification routines. */
287 void clean(Scene *scene);
288 void constant_fold(Scene *scene);
289 void simplify_settings(Scene *scene);
290 void deduplicate_nodes();
291 void verify_volume_output();
296 #endif /* __GRAPH_H__ */