Blender V4.5
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
60
61/* Input
62 *
63 * Input socket for a shader node. May be linked to an output or not. If not
64 * linked, it will either get a fixed default value, or e.g. a texture
65 * coordinate. */
66
68 public:
69 ShaderInput(const SocketType &socket_type_, ShaderNode *parent_)
70 : socket_type(socket_type_), parent(parent_)
71
72 {
73 }
74
75 ustring name() const
76 {
77 return socket_type.ui_name;
78 }
79 int flags() const
80 {
81 return socket_type.flags;
82 }
84 {
85 return socket_type.type;
86 }
87
88 void set(const float f)
89 {
90 ((Node *)parent)->set(socket_type, f);
91 }
92 void set(const float3 f)
93 {
94 ((Node *)parent)->set(socket_type, f);
95 }
96 void set(const int f)
97 {
98 ((Node *)parent)->set(socket_type, f);
99 }
100
101 void disconnect();
102
105 ShaderOutput *link = nullptr;
106 int stack_offset = SVM_STACK_INVALID; /* for SVM compiler */
107
108 /* Keeps track of whether a constant was folded in this socket, to avoid over-optimizing when the
109 * link is null. */
110 bool constant_folded_in = false;
111};
112
113/* Output
114 *
115 * Output socket for a shader node. */
116
118 public:
119 ShaderOutput(const SocketType &socket_type_, ShaderNode *parent_)
120 : socket_type(socket_type_), parent(parent_)
121 {
122 }
123
124 ustring name() const
125 {
126 return socket_type.ui_name;
127 }
129 {
130 return socket_type.type;
131 }
132
133 void disconnect();
134
138 int stack_offset = SVM_STACK_INVALID; /* for SVM compiler */
139};
140
141/* Node
142 *
143 * Shader node in graph, with input and output sockets. This is the virtual
144 * base class for all node types. */
145
146class ShaderNode : public Node {
147 public:
148 explicit ShaderNode(const NodeType *type);
149 ShaderNode(const ShaderNode &other);
150
153
154 ShaderInput *input(const char *name);
155 ShaderOutput *output(const char *name);
156 ShaderInput *input(ustring name);
157 ShaderOutput *output(ustring name);
158
159 virtual ShaderNode *clone(ShaderGraph *graph) const = 0;
160 virtual void attributes(Shader *shader, AttributeRequestSet *attributes);
161 virtual void compile(SVMCompiler &compiler) = 0;
162 virtual void compile(OSLCompiler &compiler) = 0;
163
164 /* Expand node into additional nodes. */
165 virtual void expand(ShaderGraph * /* graph */) {}
166
167 /* ** Node optimization ** */
168 /* Check whether the node can be replaced with single constant. */
169 virtual void constant_fold(const ConstantFolder & /*folder*/) {}
170
171 /* Simplify settings used by artists to the ones which are simpler to
172 * evaluate in the kernel but keep the final result unchanged.
173 */
174 virtual void simplify_settings(Scene * /*scene*/){};
175
176 virtual bool has_surface_emission()
177 {
178 return false;
179 }
181 {
182 return false;
183 }
184 virtual bool has_surface_bssrdf()
185 {
186 return false;
187 }
188 virtual bool has_bump()
189 {
190 return false;
191 }
192 virtual bool has_bssrdf_bump()
193 {
194 return false;
195 }
196 virtual bool has_spatial_varying()
197 {
198 return false;
199 }
201 {
202 return false;
203 }
204 virtual bool has_volume_support()
205 {
206 return false;
207 }
210
211 /* index in graph node array */
212 int id = -1;
213 /* for bump mapping utility */
215 float bump_filter_width = 0.0f;
216 /* special node type */
218
219 /* ** Selective nodes compilation ** */
220
221 /* TODO(sergey): More explicitly mention in the function names
222 * that those functions are for selective compilation only?
223 */
224
225 /* Node feature are used to disable huge nodes inside the group,
226 * so it's possible to disable huge nodes inside of the required
227 * nodes group.
228 */
229 virtual int get_feature()
230 {
232 }
233
234 /* Get closure ID to which the node compiles into. */
236 {
237 return CLOSURE_NONE_ID;
238 }
239
240 /* Check whether settings of the node equals to another one.
241 *
242 * This is mainly used to check whether two nodes can be merged
243 * together. Meaning, runtime stuff like node id and unbound slots
244 * will be ignored for comparison.
245 *
246 * NOTE: If some node can't be de-duplicated for whatever reason it
247 * is to be handled in the subclass.
248 */
249 virtual bool equals(const ShaderNode &other);
250};
251
252/* Node definition utility macros */
253
254#define SHADER_NODE_CLASS(type) \
255 NODE_DECLARE \
256 type(); \
257 ShaderNode *clone(ShaderGraph *graph) const override \
258 { \
259 return graph->create_node<type>(*this); \
260 } \
261 void compile(SVMCompiler &compiler) override; \
262 void compile(OSLCompiler &compiler) override;
263
264#define SHADER_NODE_NO_CLONE_CLASS(type) \
265 NODE_DECLARE \
266 type(); \
267 void compile(SVMCompiler &compiler) override; \
268 void compile(OSLCompiler &compiler) override;
269
270#define SHADER_NODE_BASE_CLASS(type) \
271 ShaderNode *clone(ShaderGraph *graph) const override \
272 { \
273 return graph->create_node<type>(*this); \
274 } \
275 void compile(SVMCompiler &compiler) override; \
276 void compile(OSLCompiler &compiler) override;
277
279 public:
280 bool operator()(const ShaderNode *n1, const ShaderNode *n2) const
281 {
282 return n1->id < n2->id;
283 }
284};
285
286using ShaderNodeSet = set<ShaderNode *, ShaderNodeIDComparator>;
287using ShaderNodeMap = map<ShaderNode *, ShaderNode *, ShaderNodeIDComparator>;
288
289/* Graph
290 *
291 * Shader graph of nodes. Also does graph manipulations for default inputs,
292 * bump mapping from displacement, and possibly other things in the future. */
293
294class ShaderGraph : public NodeOwner {
295 public:
301
302 ShaderGraph();
303 ~ShaderGraph() override;
304
306
307 void connect(ShaderOutput *from, ShaderInput *to);
308 void disconnect(ShaderOutput *from);
309 void disconnect(ShaderInput *to);
310 void relink(ShaderInput *from, ShaderInput *to);
311 void relink(ShaderOutput *from, ShaderOutput *to);
312 void relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to);
313
314 void remove_proxy_nodes();
316 void simplify(Scene *scene);
317 void finalize(Scene *scene, bool do_bump = false, bool bump_in_object_space = false);
318
319 int get_num_closures();
320
321 void dump_graph(const char *filename);
322
323 /* Create node from class and add it to the shader graph. */
324 template<typename T, typename... Args> T *create_node(Args &&...args)
325 {
326 unique_ptr<T> node = make_unique<T>(args...);
327 T *node_ptr = node.get();
328 this->add_node(std::move(node));
329 return node_ptr;
330 }
331
332 /* Create OSL node from class and add it to the shader graph. */
333 template<typename T, typename... Args> T *create_osl_node(void *node_memory, Args &&...args)
334 {
335 T *node_ptr = new (node_memory) T(args...);
336 unique_ptr<T> node(node_ptr);
337 this->add_node(std::move(node));
338 return node_ptr;
339 }
340
341 /* Create node from node type and add it to the shader graph. */
342 ShaderNode *create_node(const NodeType *node_type)
343 {
344 unique_ptr<Node> node = node_type->create(node_type);
345 unique_ptr<ShaderNode> shader_node(static_cast<ShaderNode *>(node.release()));
346 ShaderNode *shader_node_ptr = shader_node.get();
347 this->add_node(std::move(shader_node));
348 return shader_node_ptr;
349 }
350
351 protected:
352 using NodePair = pair<ShaderNode *const, ShaderNode *>;
353
354 void add_node(unique_ptr<ShaderNode> &&node);
355
356 void find_dependencies(ShaderNodeSet &dependencies, ShaderInput *input);
357 void clear_nodes();
359
360 void break_cycles(ShaderNode *node, vector<bool> &visited, vector<bool> &on_stack);
361 void bump_from_displacement(bool use_object_space);
362 void refine_bump_nodes();
363 void expand();
364 void default_inputs(bool do_osl);
365 void transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume);
366
367 /* Graph simplification routines. */
368 void clean(Scene *scene);
369 void constant_fold(Scene *scene);
370 void simplify_settings(Scene *scene);
371 void deduplicate_nodes();
373};
374
Definition md5.h:19
void find_dependencies(ShaderNodeSet &dependencies, ShaderInput *input)
string displacement_hash
OutputNode * output()
unique_ptr_vector< ShaderNode > nodes
void verify_volume_output()
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 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 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)
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)
virtual int get_feature()
float bump_filter_width
virtual bool has_attribute_dependency()
virtual void constant_fold(const ConstantFolder &)
virtual bool has_bump()
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
ShaderNodeSpecialType
@ 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:127
const NodeType * type
Definition graph/node.h:178
ustring name
Definition graph/node.h:177
Node(const NodeType *type, ustring name=ustring())