Blender V5.0
shader_graph.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#pragma once
6
7#include "graph/node.h"
8#include "graph/node_type.h"
9
10#include "kernel/types.h"
11
12#include "util/map.h"
13#include "util/param.h"
14#include "util/set.h"
15#include "util/string.h"
16#include "util/types.h"
18#include "util/vector.h"
19
21
23class Scene;
24class Shader;
25class ShaderInput;
26class ShaderOutput;
27class ShaderNode;
28class ShaderGraph;
29class SVMCompiler;
30class OSLCompiler;
31class OutputNode;
32class ConstantFolder;
33class MD5Hash;
34
35/* Bump
36 *
37 * For bump mapping, a node may be evaluated multiple times, using different
38 * samples to reconstruct the normal, this indicates the sample position */
39
41
42/* Identifiers for some special node types.
43 *
44 * The graph needs to identify these in the clean function.
45 * Cannot use dynamic_cast, as this is disabled for OSL. */
46
61
62/* Input
63 *
64 * Input socket for a shader node. May be linked to an output or not. If not
65 * linked, it will either get a fixed default value, or e.g. a texture
66 * coordinate. */
67
69 public:
70 ShaderInput(const SocketType &socket_type_, ShaderNode *parent_)
71 : socket_type(socket_type_), parent(parent_)
72
73 {
74 }
75
76 ustring name() const
77 {
78 return socket_type.ui_name;
79 }
80 int flags() const
81 {
82 return socket_type.flags;
83 }
85 {
86 return socket_type.type;
87 }
88
89 void set(const float f)
90 {
91 ((Node *)parent)->set(socket_type, f);
92 }
93 void set(const float3 f)
94 {
95 ((Node *)parent)->set(socket_type, f);
96 }
97 void set(const int f)
98 {
99 ((Node *)parent)->set(socket_type, f);
100 }
101
102 void disconnect();
103
106 ShaderOutput *link = nullptr;
107 int stack_offset = SVM_STACK_INVALID; /* for SVM compiler */
108
109 /* Keeps track of whether a constant was folded in this socket, to avoid over-optimizing when the
110 * link is null. */
111 bool constant_folded_in = false;
112};
113
114/* Output
115 *
116 * Output socket for a shader node. */
117
119 public:
120 ShaderOutput(const SocketType &socket_type_, ShaderNode *parent_)
121 : socket_type(socket_type_), parent(parent_)
122 {
123 }
124
125 ustring name() const
126 {
127 return socket_type.ui_name;
128 }
130 {
131 return socket_type.type;
132 }
133
134 void disconnect();
135
139 int stack_offset = SVM_STACK_INVALID; /* for SVM compiler */
140};
141
142/* Node
143 *
144 * Shader node in graph, with input and output sockets. This is the virtual
145 * base class for all node types. */
146
147class ShaderNode : public Node {
148 public:
149 explicit ShaderNode(const NodeType *type);
150 ShaderNode(const ShaderNode &other);
151
154
155 ShaderInput *input(const char *name);
156 ShaderOutput *output(const char *name);
157 ShaderInput *input(ustring name);
158 ShaderOutput *output(ustring name);
159
160 virtual ShaderNode *clone(ShaderGraph *graph) const = 0;
161 virtual void attributes(Shader *shader, AttributeRequestSet *attributes);
162 virtual void compile(SVMCompiler &compiler) = 0;
163 virtual void compile(OSLCompiler &compiler) = 0;
164
165 /* Expand node into additional nodes. */
166 virtual void expand(ShaderGraph * /* graph */) {}
167
168 /* ** Node optimization ** */
169 /* Check whether the node can be replaced with single constant. */
170 virtual void constant_fold(const ConstantFolder & /*folder*/) {}
171
172 /* Simplify settings used by artists to the ones which are simpler to
173 * evaluate in the kernel but keep the final result unchanged.
174 */
175 virtual void simplify_settings(Scene * /*scene*/) {};
176
177 virtual bool has_surface_emission()
178 {
179 return false;
180 }
182 {
183 return false;
184 }
185 virtual bool has_surface_bssrdf()
186 {
187 return false;
188 }
189 virtual bool has_bump()
190 {
191 return false;
192 }
193 virtual bool has_bssrdf_bump()
194 {
195 return false;
196 }
197 virtual bool has_spatial_varying()
198 {
199 return false;
200 }
202 {
203 return false;
204 }
205 virtual bool has_volume_support()
206 {
207 return false;
208 }
209 /* True if the node only multiplies or adds a constant values. */
210 virtual bool is_linear_operation()
211 {
212 return false;
213 }
214
217
218 /* index in graph node array */
219 int id = -1;
220 /* for bump mapping utility */
222 float bump_filter_width = 0.0f;
223 /* special node type */
225
226 /* ** Selective nodes compilation ** */
227
228 /* TODO(sergey): More explicitly mention in the function names
229 * that those functions are for selective compilation only?
230 */
231
232 /* Node feature are used to disable huge nodes inside the group,
233 * so it's possible to disable huge nodes inside of the required
234 * nodes group.
235 */
237 {
239 }
240
241 /* Get closure ID to which the node compiles into. */
243 {
244 return CLOSURE_NONE_ID;
245 }
246
247 /* Check whether settings of the node equals to another one.
248 *
249 * This is mainly used to check whether two nodes can be merged
250 * together. Meaning, runtime stuff like node id and unbound slots
251 * will be ignored for comparison.
252 *
253 * NOTE: If some node can't be de-duplicated for whatever reason it
254 * is to be handled in the subclass.
255 */
256 virtual bool equals(const ShaderNode &other);
257
258 protected:
259 /* Disconnect the input with the given name if it is connected.
260 * Used to optimize away unused inputs. */
261 void disconnect_unused_input(const char *name);
262};
263
264/* Node definition utility macros */
265
266#define SHADER_NODE_CLASS(type) \
267 NODE_DECLARE \
268 type(); \
269 ShaderNode *clone(ShaderGraph *graph) const override \
270 { \
271 return graph->create_node<type>(*this); \
272 } \
273 void compile(SVMCompiler &compiler) override; \
274 void compile(OSLCompiler &compiler) override;
275
276#define SHADER_NODE_NO_CLONE_CLASS(type) \
277 NODE_DECLARE \
278 type(); \
279 void compile(SVMCompiler &compiler) override; \
280 void compile(OSLCompiler &compiler) override;
281
282#define SHADER_NODE_BASE_CLASS(type) \
283 ShaderNode *clone(ShaderGraph *graph) const override \
284 { \
285 return graph->create_node<type>(*this); \
286 } \
287 void compile(SVMCompiler &compiler) override; \
288 void compile(OSLCompiler &compiler) override;
289
291 public:
292 bool operator()(const ShaderNode *n1, const ShaderNode *n2) const
293 {
294 return n1->id < n2->id;
295 }
296};
297
299 public:
300 bool operator()(const std::pair<ShaderNode *, bool> p1,
301 const std::pair<ShaderNode *, bool> p2) const
302 {
303 return p1.first->id < p2.first->id || (p1.first->id == p2.first->id && p1.second < p2.second);
304 }
305};
306
307using ShaderNodeSet = set<ShaderNode *, ShaderNodeIDComparator>;
308using ShaderNodeMap = map<ShaderNode *, ShaderNode *, ShaderNodeIDComparator>;
309
310/* Graph
311 *
312 * Shader graph of nodes. Also does graph manipulations for default inputs,
313 * bump mapping from displacement, and possibly other things in the future. */
314
315class ShaderGraph : public NodeOwner {
316 public:
322
323 ShaderGraph();
324 ~ShaderGraph() override;
325
327
328 void connect(ShaderOutput *from, ShaderInput *to);
329 void disconnect(ShaderOutput *from);
330 void disconnect(ShaderInput *to);
331 void relink(ShaderInput *from, ShaderInput *to);
332 void relink(ShaderOutput *from, ShaderOutput *to);
333 void relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to);
334
335 void remove_proxy_nodes();
337 void simplify(Scene *scene);
338 void finalize(Scene *scene, bool do_bump = false, bool bump_in_object_space = false);
339
340 int get_num_closures();
341
342 void dump_graph(const char *filename);
343
344 /* Create node from class and add it to the shader graph. */
345 template<typename T, typename... Args> T *create_node(Args &&...args)
346 {
347 unique_ptr<T> node = make_unique<T>(args...);
348 T *node_ptr = node.get();
349 this->add_node(std::move(node));
350 return node_ptr;
351 }
352
353 /* Create OSL node from class and add it to the shader graph. */
354 template<typename T, typename... Args> T *create_osl_node(void *node_memory, Args &&...args)
355 {
356 T *node_ptr = new (node_memory) T(args...);
357 unique_ptr<T> node(node_ptr);
358 this->add_node(std::move(node));
359 return node_ptr;
360 }
361
362 /* Create node from node type and add it to the shader graph. */
363 ShaderNode *create_node(const NodeType *node_type)
364 {
365 unique_ptr<Node> node = node_type->create(node_type);
366 unique_ptr<ShaderNode> shader_node(static_cast<ShaderNode *>(node.release()));
367 ShaderNode *shader_node_ptr = shader_node.get();
368 this->add_node(std::move(shader_node));
369 return shader_node_ptr;
370 }
371
372 protected:
373 using NodePair = pair<ShaderNode *const, ShaderNode *>;
374
375 void add_node(unique_ptr<ShaderNode> &&node);
376
377 void find_dependencies(ShaderNodeSet &dependencies, ShaderInput *input);
378 void clear_nodes();
380
381 void break_cycles(ShaderNode *node, vector<bool> &visited, vector<bool> &on_stack);
382 void bump_from_displacement(bool use_object_space);
383 void refine_bump_nodes();
384 void expand();
385 void default_inputs(bool do_osl);
386 void transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume);
387
388 /* Graph simplification routines. */
389 void clean(Scene *scene);
390 void constant_fold(Scene *scene);
391 void simplify_settings(Scene *scene);
392 void deduplicate_nodes();
394};
395
unsigned int uint
Definition md5.h:19
void find_dependencies(ShaderNodeSet &dependencies, ShaderInput *input)
string displacement_hash
OutputNode * output()
unique_ptr_vector< ShaderNode > nodes
void simplify(Scene *scene)
T * create_node(Args &&...args)
void add_node(unique_ptr< ShaderNode > &&node)
void disconnect(ShaderOutput *from)
size_t num_node_ids
void break_cycles(ShaderNode *node, vector< bool > &visited, vector< bool > &on_stack)
void copy_nodes(ShaderNodeSet &nodes, ShaderNodeMap &nnodemap)
void clean(Scene *scene)
void finalize(Scene *scene, bool do_bump=false, bool bump_in_object_space=false)
void compute_displacement_hash()
void default_inputs(bool do_osl)
ShaderNode * create_node(const NodeType *node_type)
void connect(ShaderOutput *from, ShaderInput *to)
void relink(ShaderInput *from, ShaderInput *to)
T * create_osl_node(void *node_memory, Args &&...args)
void optimize_volume_output()
void constant_fold(Scene *scene)
void transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume)
void deduplicate_nodes()
void remove_proxy_nodes()
void simplify_settings(Scene *scene)
void bump_from_displacement(bool use_object_space)
~ShaderGraph() override
pair< ShaderNode *const, ShaderNode * > NodePair
void refine_bump_nodes()
void dump_graph(const char *filename)
ustring name() const
ShaderInput(const SocketType &socket_type_, ShaderNode *parent_)
SocketType::Type type() const
ShaderOutput * link
bool constant_folded_in
void set(const float3 f)
void disconnect()
ShaderNode * parent
void set(const int f)
void set(const float f)
int flags() const
const SocketType & socket_type
bool operator()(const std::pair< ShaderNode *, bool > p1, const std::pair< ShaderNode *, bool > p2) const
bool operator()(const ShaderNode *n1, const ShaderNode *n2) const
ShaderInput * input(const char *name)
virtual bool has_surface_transparent()
virtual bool has_surface_emission()
void remove_input(ShaderInput *input)
virtual uint get_feature()
ShaderNodeSpecialType special_type
virtual void simplify_settings(Scene *)
virtual bool has_bssrdf_bump()
virtual bool has_spatial_varying()
virtual bool has_volume_support()
virtual ClosureType get_closure_type()
virtual ShaderNode * clone(ShaderGraph *graph) const =0
virtual bool equals(const ShaderNode &other)
float bump_filter_width
void disconnect_unused_input(const char *name)
virtual bool has_attribute_dependency()
virtual void constant_fold(const ConstantFolder &)
virtual bool has_bump()
virtual bool is_linear_operation()
virtual void expand(ShaderGraph *)
ShaderNode(const NodeType *type)
void create_inputs_outputs(const NodeType *type)
unique_ptr_vector< ShaderInput > inputs
ShaderBump bump
virtual bool has_surface_bssrdf()
virtual void compile(OSLCompiler &compiler)=0
virtual void compile(SVMCompiler &compiler)=0
virtual void attributes(Shader *shader, AttributeRequestSet *attributes)
unique_ptr_vector< ShaderOutput > outputs
vector< ShaderInput * > links
ShaderOutput(const SocketType &socket_type_, ShaderNode *parent_)
ustring name() const
const SocketType & socket_type
ShaderNode * parent
SocketType::Type type() const
#define SVM_STACK_INVALID
#define KERNEL_FEATURE_NODE_BUMP
#define CCL_NAMESPACE_END
#define input
#define output
ClosureType
@ CLOSURE_NONE_ID
#define T
const char * name
ShaderNodeSpecialType
@ SHADER_SPECIAL_TYPE_LIGHT_PATH
@ SHADER_SPECIAL_TYPE_PROXY
@ SHADER_SPECIAL_TYPE_IMAGE_SLOT
@ SHADER_SPECIAL_TYPE_GEOMETRY
@ SHADER_SPECIAL_TYPE_OUTPUT_AOV
@ SHADER_SPECIAL_TYPE_COMBINE_CLOSURE
@ SHADER_SPECIAL_TYPE_BUMP
@ SHADER_SPECIAL_TYPE_AUTOCONVERT
@ SHADER_SPECIAL_TYPE_NONE
@ SHADER_SPECIAL_TYPE_OUTPUT
@ SHADER_SPECIAL_TYPE_CLOSURE
@ SHADER_SPECIAL_TYPE_OSL
set< ShaderNode *, ShaderNodeIDComparator > ShaderNodeSet
map< ShaderNode *, ShaderNode *, ShaderNodeIDComparator > ShaderNodeMap
ShaderBump
@ SHADER_BUMP_CENTER
@ SHADER_BUMP_DX
@ SHADER_BUMP_DY
@ SHADER_BUMP_NONE
CreateFunc create
Definition node_type.h:130
const NodeType * type
Definition graph/node.h:178
ustring name
Definition graph/node.h:177
Node(const NodeType *type, ustring name=ustring())