Blender  V3.3
node_shader_util.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2005 Blender Foundation. All rights reserved. */
3 
8 #include "DNA_node_types.h"
9 
10 #include "node_shader_util.hh"
11 
13 
14 #include "node_exec.h"
15 
16 bool sh_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree, const char **r_disabled_hint)
17 {
18  if (!STREQ(ntree->idname, "ShaderNodeTree")) {
19  *r_disabled_hint = TIP_("Not a shader node tree");
20  return false;
21  }
22  return true;
23 }
24 
25 static bool sh_fn_poll_default(bNodeType *UNUSED(ntype),
27  const char **r_disabled_hint)
28 {
29  if (!STR_ELEM(ntree->idname, "ShaderNodeTree", "GeometryNodeTree")) {
30  *r_disabled_hint = TIP_("Not a shader or geometry node tree");
31  return false;
32  }
33  return true;
34 }
35 
36 void sh_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass)
37 {
38  node_type_base(ntype, type, name, nclass);
39 
40  ntype->poll = sh_node_poll_default;
43 }
44 
45 void sh_fn_node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
46 {
47  sh_node_type_base(ntype, type, name, nclass);
48  ntype->poll = sh_fn_poll_default;
50 }
51 
52 /* ****** */
53 
54 static void nodestack_get_vec(float *in, short type_in, bNodeStack *ns)
55 {
56  const float *from = ns->vec;
57 
58  if (type_in == SOCK_FLOAT) {
59  if (ns->sockettype == SOCK_FLOAT) {
60  *in = *from;
61  }
62  else {
63  *in = (from[0] + from[1] + from[2]) / 3.0f;
64  }
65  }
66  else if (type_in == SOCK_VECTOR) {
67  if (ns->sockettype == SOCK_FLOAT) {
68  in[0] = from[0];
69  in[1] = from[0];
70  in[2] = from[0];
71  }
72  else {
73  copy_v3_v3(in, from);
74  }
75  }
76  else { /* type_in==SOCK_RGBA */
77  if (ns->sockettype == SOCK_RGBA) {
78  copy_v4_v4(in, from);
79  }
80  else if (ns->sockettype == SOCK_FLOAT) {
81  in[0] = from[0];
82  in[1] = from[0];
83  in[2] = from[0];
84  in[3] = 1.0f;
85  }
86  else {
87  copy_v3_v3(in, from);
88  in[3] = 1.0f;
89  }
90  }
91 }
92 
94 {
95  memset(gs, 0, sizeof(*gs));
96 
97  if (ns == nullptr) {
98  /* node_get_stack() will generate nullptr bNodeStack pointers
99  * for unknown/unsupported types of sockets. */
100  zero_v4(gs->vec);
101  gs->link = nullptr;
102  gs->type = GPU_NONE;
103  gs->hasinput = false;
104  gs->hasoutput = false;
105  gs->sockettype = type;
106  }
107  else {
108  nodestack_get_vec(gs->vec, type, ns);
109  gs->link = (GPUNodeLink *)ns->data;
110 
111  if (type == SOCK_FLOAT) {
112  gs->type = GPU_FLOAT;
113  }
114  else if (type == SOCK_INT) {
115  gs->type = GPU_FLOAT; /* HACK: Support as float. */
116  }
117  else if (type == SOCK_VECTOR) {
118  gs->type = GPU_VEC3;
119  }
120  else if (type == SOCK_RGBA) {
121  gs->type = GPU_VEC4;
122  }
123  else if (type == SOCK_SHADER) {
124  gs->type = GPU_CLOSURE;
125  }
126  else {
127  gs->type = GPU_NONE;
128  }
129 
130  gs->hasinput = ns->hasinput && ns->data;
131  /* XXX Commented out the ns->data check here, as it seems it's not always set,
132  * even though there *is* a valid connection/output... But that might need
133  * further investigation.
134  */
135  gs->hasoutput = ns->hasoutput /*&& ns->data*/;
136  gs->sockettype = ns->sockettype;
137  }
138 }
139 
141 {
142  copy_v4_v4(ns->vec, gs->vec);
143  ns->data = gs->link;
144  ns->sockettype = gs->sockettype;
145 }
146 
148 {
149  int i;
150  LISTBASE_FOREACH_INDEX (bNodeSocket *, socket, sockets, i) {
151  node_gpu_stack_from_data(&gs[i], socket->type, ns[i]);
152  }
153 
154  gs[i].end = true;
155 }
156 
158 {
159  int i;
160  LISTBASE_FOREACH_INDEX (bNodeSocket *, socket, sockets, i) {
161  node_data_from_gpu_stack(ns[i], &gs[i]);
162  }
163 }
164 
165 bool nodeSupportsActiveFlag(const bNode *node, int sub_activity)
166 {
168  switch (sub_activity) {
169  case NODE_ACTIVE_TEXTURE:
170  return node->typeinfo->nclass == NODE_CLASS_TEXTURE;
173  }
174  return false;
175 }
176 
177 static bNode *node_get_active(bNodeTree *ntree, int sub_activity)
178 {
180  /* this is the node we texture paint and draw in textured draw */
181  bNode *inactivenode = nullptr, *activetexnode = nullptr, *activegroup = nullptr;
182  bool hasgroup = false;
183 
184  if (!ntree) {
185  return nullptr;
186  }
187 
189  if (node->flag & sub_activity) {
190  activetexnode = node;
191  /* if active we can return immediately */
192  if (node->flag & NODE_ACTIVE) {
193  return node;
194  }
195  }
196  else if (!inactivenode && nodeSupportsActiveFlag(node, sub_activity)) {
197  inactivenode = node;
198  }
199  else if (node->type == NODE_GROUP) {
200  if (node->flag & NODE_ACTIVE) {
201  activegroup = node;
202  }
203  else {
204  hasgroup = true;
205  }
206  }
207  }
208 
209  /* first, check active group for textures */
210  if (activegroup) {
211  bNode *tnode = node_get_active((bNodeTree *)activegroup->id, sub_activity);
212  /* active node takes priority, so ignore any other possible nodes here */
213  if (tnode) {
214  return tnode;
215  }
216  }
217 
218  if (activetexnode) {
219  return activetexnode;
220  }
221 
222  if (hasgroup) {
223  /* node active texture node in this tree, look inside groups */
225  if (node->type == NODE_GROUP) {
226  bNode *tnode = node_get_active((bNodeTree *)node->id, sub_activity);
227  if (tnode && ((tnode->flag & sub_activity) || !inactivenode)) {
228  return tnode;
229  }
230  }
231  }
232  }
233 
234  return inactivenode;
235 }
236 
238 {
240 }
241 
243 {
245 }
246 
248 {
249  bNodeExec *nodeexec;
250  bNode *node;
251  int n;
252  bNodeStack *stack;
253  bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */
254  bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */
255  GPUNodeStack gpuin[MAX_SOCKET + 1], gpuout[MAX_SOCKET + 1];
256  bool do_it;
257 
258  stack = exec->stack;
259 
260  for (n = 0, nodeexec = exec->nodeexec; n < exec->totnodes; n++, nodeexec++) {
261  node = nodeexec->node;
262 
263  do_it = false;
264  /* for groups, only execute outputs for edited group */
265  if (node->typeinfo->nclass == NODE_CLASS_OUTPUT) {
266  if ((output_node != nullptr) && (node == output_node)) {
267  do_it = true;
268  }
269  }
270  else {
271  do_it = true;
272  }
273 
274  if (do_it) {
275  if (node->typeinfo->gpu_fn) {
276  node_get_stack(node, stack, nsin, nsout);
277  gpu_stack_from_data_list(gpuin, &node->inputs, nsin);
278  gpu_stack_from_data_list(gpuout, &node->outputs, nsout);
279  if (node->typeinfo->gpu_fn(mat, node, &nodeexec->data, gpuin, gpuout)) {
280  data_from_gpu_stack_list(&node->outputs, nsout, gpuout);
281  }
282  }
283  }
284  }
285 }
286 
288 {
289  GPU_link(mat, "differentiate_texco", *link, link);
290 }
291 
293 {
294  if (!*link) {
295  *link = GPU_attribute(mat, CD_ORCO, "");
297  }
298 }
299 
301  bNode *node,
302  GPUNodeStack *in,
304 {
305  NodeTexBase *base = (NodeTexBase *)node->storage;
306  TexMapping *texmap = &base->tex_mapping;
307  float domin = (texmap->flag & TEXMAP_CLIP_MIN) != 0;
308  float domax = (texmap->flag & TEXMAP_CLIP_MAX) != 0;
309 
310  if (domin || domax || !(texmap->flag & TEXMAP_UNIT_MATRIX)) {
311  static float max[3] = {FLT_MAX, FLT_MAX, FLT_MAX};
312  static float min[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
313  GPUNodeLink *tmin, *tmax, *tmat0, *tmat1, *tmat2, *tmat3;
314 
315  tmin = GPU_uniform((domin) ? texmap->min : min);
316  tmax = GPU_uniform((domax) ? texmap->max : max);
317  tmat0 = GPU_uniform((float *)texmap->mat[0]);
318  tmat1 = GPU_uniform((float *)texmap->mat[1]);
319  tmat2 = GPU_uniform((float *)texmap->mat[2]);
320  tmat3 = GPU_uniform((float *)texmap->mat[3]);
321 
322  GPU_link(mat, "mapping_mat4", in[0].link, tmat0, tmat1, tmat2, tmat3, tmin, tmax, &in[0].link);
323 
324  if (texmap->type == TEXMAP_TYPE_NORMAL) {
325  GPU_link(mat, "vector_normalize", in[0].link, &in[0].link);
326  }
327  }
328 }
329 
331 {
333  data->r[0] = xyz_to_rgb[0];
334  data->r[1] = xyz_to_rgb[3];
335  data->r[2] = xyz_to_rgb[6];
336  data->g[0] = xyz_to_rgb[1];
337  data->g[1] = xyz_to_rgb[4];
338  data->g[2] = xyz_to_rgb[7];
339  data->b[0] = xyz_to_rgb[2];
340  data->b[1] = xyz_to_rgb[5];
341  data->b[2] = xyz_to_rgb[8];
342 }
#define NODE_CLASS_OUTPUT
Definition: BKE_node.h:346
void node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass)
Definition: node.cc:4277
#define MAX_SOCKET
Definition: BKE_node.h:30
#define NODE_CLASS_TEXTURE
Definition: BKE_node.h:355
#define SH_NODE_ATTRIBUTE
Definition: BKE_node.h:1106
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
Definition: BLI_listbase.h:344
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void zero_v4(float r[4])
#define STR_ELEM(...)
Definition: BLI_string.h:539
#define UNUSED(x)
#define ELEM(...)
#define STREQ(a, b)
#define TIP_(msgid)
#define NODE_ACTIVE_TEXTURE
#define NODE_ACTIVE_PAINT_CANVAS
@ SOCK_INT
@ SOCK_VECTOR
@ SOCK_SHADER
@ SOCK_FLOAT
@ SOCK_RGBA
#define NODE_ACTIVE
#define TEXMAP_TYPE_NORMAL
#define TEXMAP_UNIT_MATRIX
#define TEXMAP_CLIP_MIN
#define TEXMAP_CLIP_MAX
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
GPUNodeLink * GPU_attribute(GPUMaterial *mat, eCustomDataType type, const char *name)
GPUNodeLink * GPU_uniform(const float *num)
@ GPU_VEC4
Definition: GPU_material.h:52
@ GPU_NONE
Definition: GPU_material.h:48
@ GPU_CLOSURE
Definition: GPU_material.h:64
@ GPU_VEC3
Definition: GPU_material.h:51
@ GPU_FLOAT
Definition: GPU_material.h:49
bool GPU_link(GPUMaterial *mat, const char *name,...)
const float * IMB_colormanagement_get_xyz_to_scene_linear(void)
NODE_GROUP
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block SH_NODE_TEX_IMAGE
OperationNode * node
StackEntry * from
bNodeTree * ntree
void search_link_ops_for_basic_node(GatherLinkSearchOpParams &params)
static const pxr::TfToken out("out", pxr::TfToken::Immortal)
color xyz_to_rgb(float x, float y, float z)
Definition: node_color.h:63
void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out)
Definition: node_exec.cc:36
bNode * nodeGetActiveTexture(bNodeTree *ntree)
void node_shader_gpu_tex_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *UNUSED(out))
bool sh_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree, const char **r_disabled_hint)
void node_shader_gpu_default_tex_coord(GPUMaterial *mat, bNode *node, GPUNodeLink **link)
void node_data_from_gpu_stack(bNodeStack *ns, GPUNodeStack *gs)
static bool sh_fn_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree, const char **r_disabled_hint)
void node_shader_gpu_bump_tex_coord(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeLink **link)
static void nodestack_get_vec(float *in, short type_in, bNodeStack *ns)
void get_XYZ_to_RGB_for_gpu(XYZ_to_RGB *data)
void ntreeExecGPUNodes(bNodeTreeExec *exec, GPUMaterial *mat, bNode *output_node)
static void gpu_stack_from_data_list(GPUNodeStack *gs, ListBase *sockets, bNodeStack **ns)
void sh_fn_node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
bool nodeSupportsActiveFlag(const bNode *node, int sub_activity)
bNode * nodeGetActivePaintCanvas(bNodeTree *ntree)
static void data_from_gpu_stack_list(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs)
void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, bNodeStack *ns)
void sh_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass)
static bNode * node_get_active(bNodeTree *ntree, int sub_activity)
static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
void node_insert_link_default(bNodeTree *ntree, bNode *node, bNodeLink *link)
Definition: node_util.c:326
#define min(a, b)
Definition: sort.c:35
struct GPUNodeLink * link
Definition: GPU_material.h:106
eGPUType type
Definition: GPU_material.h:104
float vec[4]
Definition: GPU_material.h:105
short sockettype
Definition: GPU_material.h:109
TexMapping tex_mapping
bNodeExecData data
Definition: node_exec.h:32
struct bNode * node
Definition: node_exec.h:31
short hasoutput
short hasinput
short sockettype
float vec[4]
char idname[64]
ListBase nodes
Defines a node type.
Definition: BKE_node.h:226
bool(* poll)(struct bNodeType *ntype, struct bNodeTree *nodetree, const char **r_disabled_hint)
Definition: BKE_node.h:292
NodeGatherSocketLinkOperationsFunction gather_link_search_ops
Definition: BKE_node.h:335
void(* insert_link)(struct bNodeTree *ntree, struct bNode *node, struct bNodeLink *link)
Definition: BKE_node.h:301
float max