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:
Diffstat (limited to 'source/blender/nodes/shader')
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c433
-rw-r--r--source/blender/nodes/shader/node_shader_util.c30
-rw-r--r--source/blender/nodes/shader/node_shader_util.h6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_attribute.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bump.c35
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_common.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_curves.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_geometry.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_hueSatVal.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mapping.c102
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mixRgb.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_normal_map.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_brick.c10
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_checker.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_coord.c31
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_environment.c7
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_gradient.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_image.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_magic.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c91
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_noise.c41
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c145
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_wave.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_uvmap.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vectTransform.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vertex_color.c58
28 files changed, 586 insertions, 487 deletions
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index 60a6cc91630..92266600612 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -32,6 +32,7 @@
#include "DNA_linestyle_types.h"
#include "DNA_workspace_types.h"
+#include "BLI_linklist.h"
#include "BLI_listbase.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
@@ -212,115 +213,6 @@ void register_node_tree_type_sh(void)
/* GPU material from shader nodes */
-static void ntree_shader_link_builtin_normal(bNodeTree *ntree,
- bNode *node_from,
- bNodeSocket *socket_from,
- bNode *displacement_node,
- bNodeSocket *displacement_socket);
-
-static bNodeSocket *ntree_shader_node_find_input(bNode *node, const char *identifier);
-
-static bNode *ntree_group_output_node(bNodeTree *ntree);
-
-static bNode *ntree_shader_relink_output_from_group(bNodeTree *ntree,
- bNode *group_node,
- bNode *sh_output_node,
- int target)
-{
- int i;
- bNodeTree *group_ntree = (bNodeTree *)group_node->id;
-
- int sock_len = BLI_listbase_count(&sh_output_node->inputs);
- bNodeSocket **group_surface_sockets = BLI_array_alloca(group_surface_sockets, sock_len);
-
- /* Create output sockets to plug output connection to. */
- i = 0;
- for (bNodeSocket *sock = sh_output_node->inputs.first; sock; sock = sock->next, ++i) {
- group_surface_sockets[i] = ntreeAddSocketInterface(
- group_ntree, SOCK_OUT, sock->typeinfo->idname, sock->name);
- }
-
- bNode *group_output_node = ntree_group_output_node(group_ntree);
-
- /* If no group output node is present, we need to create one. */
- if (group_output_node == NULL) {
- group_output_node = nodeAddStaticNode(NULL, group_ntree, NODE_GROUP_OUTPUT);
- }
-
- /* Need to update tree so all node instances nodes gets proper sockets. */
- node_group_update(ntree, group_node);
- node_group_output_update(group_ntree, group_output_node);
- ntreeUpdateTree(G.main, group_ntree);
-
- /* Remove other shader output nodes so that only the new one can be selected as active. */
- for (bNode *node = ntree->nodes.first; node; node = node->next) {
- if (ELEM(node->type, SH_NODE_OUTPUT_MATERIAL, SH_NODE_OUTPUT_WORLD, SH_NODE_OUTPUT_LIGHT)) {
- ntreeFreeLocalNode(ntree, node);
- }
- }
-
- /* Create new shader output node outside the group. */
- bNode *new_output_node = nodeAddStaticNode(NULL, ntree, sh_output_node->type);
- new_output_node->custom1 = target;
-
- i = 0;
- for (bNodeSocket *sock = sh_output_node->inputs.first; sock; sock = sock->next, ++i) {
- if (sock->link != NULL) {
- /* Link the shader output node incoming link to the group output sockets */
- bNodeSocket *group_output_node_surface_input_sock = nodeFindSocket(
- group_output_node, SOCK_IN, group_surface_sockets[i]->identifier);
- nodeAddLink(group_ntree,
- sock->link->fromnode,
- sock->link->fromsock,
- group_output_node,
- group_output_node_surface_input_sock);
-
- /* Link the group output sockets to the new shader output node. */
- bNodeSocket *group_node_surface_output = nodeFindSocket(
- group_node, SOCK_OUT, group_surface_sockets[i]->identifier);
- bNodeSocket *output_node_surface_input = ntree_shader_node_find_input(new_output_node,
- sock->name);
-
- nodeAddLink(ntree,
- group_node,
- group_node_surface_output,
- new_output_node,
- output_node_surface_input);
- }
- }
-
- ntreeUpdateTree(G.main, group_ntree);
- ntreeUpdateTree(G.main, ntree);
-
- return new_output_node;
-}
-
-static bNode *ntree_shader_output_node_from_group(bNodeTree *ntree, int target)
-{
- bNode *output_node = NULL;
-
- /* Search if node groups do not contain valid output nodes (recursively). */
- for (bNode *node = ntree->nodes.first; node; node = node->next) {
- if (!ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
- continue;
- }
- if (node->id != NULL) {
- output_node = ntree_shader_output_node_from_group((bNodeTree *)node->id, target);
-
- if (output_node == NULL) {
- output_node = ntreeShaderOutputNode((bNodeTree *)node->id, target);
- }
-
- if (output_node != NULL) {
- /* Output is inside this group node. Create relink to make the output outside the group. */
- output_node = ntree_shader_relink_output_from_group(ntree, node, output_node, target);
- break;
- }
- }
- }
- return output_node;
-}
-
/* Find an output node of the shader tree.
*
* NOTE: it will only return output which is NOT in the group, which isn't how
@@ -368,28 +260,6 @@ bNode *ntreeShaderOutputNode(bNodeTree *ntree, int target)
return output_node;
}
-/* Find the active output node of a group nodetree.
- *
- * Does not return the shading output node but the group output node.
- */
-static bNode *ntree_group_output_node(bNodeTree *ntree)
-{
- /* Make sure we only have single node tagged as output. */
- ntreeSetOutput(ntree);
-
- /* Find output node that matches type and target. If there are
- * multiple, we prefer exact target match and active nodes. */
- bNode *output_node = NULL;
-
- for (bNode *node = ntree->nodes.first; node; node = node->next) {
- if ((node->type == NODE_GROUP_OUTPUT) && (node->flag & NODE_DO_OUTPUT)) {
- output_node = node;
- }
- }
-
- return output_node;
-}
-
/* Find socket with a specified identifier. */
static bNodeSocket *ntree_shader_node_find_socket(ListBase *sockets, const char *identifier)
{
@@ -520,6 +390,106 @@ static void ntree_shader_groups_expand_inputs(bNodeTree *localtree)
}
}
+static void flatten_group_do(bNodeTree *ntree, bNode *gnode)
+{
+ bNodeLink *link, *linkn, *tlink;
+ bNode *node, *nextnode;
+ bNodeTree *ngroup;
+ LinkNode *group_interface_nodes = NULL;
+
+ ngroup = (bNodeTree *)gnode->id;
+
+ /* Add the nodes into the ntree */
+ for (node = ngroup->nodes.first; node; node = nextnode) {
+ nextnode = node->next;
+ /* Remove interface nodes.
+ * This also removes remaining links to and from interface nodes.
+ * We must delay removal since sockets will reference this node. see: T52092 */
+ if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) {
+ BLI_linklist_prepend(&group_interface_nodes, node);
+ }
+ /* migrate node */
+ BLI_remlink(&ngroup->nodes, node);
+ BLI_addtail(&ntree->nodes, node);
+ /* ensure unique node name in the node tree */
+ nodeUniqueName(ntree, node);
+ }
+
+ /* Save first and last link to iterate over flattened group links. */
+ bNodeLink *glinks_first = ntree->links.last;
+
+ /* Add internal links to the ntree */
+ for (link = ngroup->links.first; link; link = linkn) {
+ linkn = link->next;
+ BLI_remlink(&ngroup->links, link);
+ BLI_addtail(&ntree->links, link);
+ }
+
+ bNodeLink *glinks_last = ntree->links.last;
+
+ /* restore external links to and from the gnode */
+ if (glinks_first != NULL) {
+ /* input links */
+ for (link = glinks_first->next; link != glinks_last->next; link = link->next) {
+ if (link->fromnode->type == NODE_GROUP_INPUT) {
+ const char *identifier = link->fromsock->identifier;
+ /* find external links to this input */
+ for (tlink = ntree->links.first; tlink != glinks_first->next; tlink = tlink->next) {
+ if (tlink->tonode == gnode && STREQ(tlink->tosock->identifier, identifier)) {
+ nodeAddLink(ntree, tlink->fromnode, tlink->fromsock, link->tonode, link->tosock);
+ }
+ }
+ }
+ }
+ /* output links */
+ for (tlink = ntree->links.first; tlink != glinks_first->next; tlink = tlink->next) {
+ if (tlink->fromnode == gnode) {
+ const char *identifier = tlink->fromsock->identifier;
+ /* find internal links to this output */
+ for (link = glinks_first->next; link != glinks_last->next; link = link->next) {
+ /* only use active output node */
+ if (link->tonode->type == NODE_GROUP_OUTPUT && (link->tonode->flag & NODE_DO_OUTPUT)) {
+ if (STREQ(link->tosock->identifier, identifier)) {
+ nodeAddLink(ntree, link->fromnode, link->fromsock, tlink->tonode, tlink->tosock);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ while (group_interface_nodes) {
+ node = BLI_linklist_pop(&group_interface_nodes);
+ ntreeFreeLocalNode(ntree, node);
+ }
+
+ ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
+}
+
+/* Flatten group to only have a simple single tree */
+static void ntree_shader_groups_flatten(bNodeTree *localtree)
+{
+ /* This is effectively recursive as the flattened groups will add
+ * nodes at the end of the list, which will also get evaluated. */
+ for (bNode *node = localtree->nodes.first, *node_next; node; node = node_next) {
+ if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id != NULL) {
+ flatten_group_do(localtree, node);
+ /* Continue even on new flattened nodes. */
+ node_next = node->next;
+ /* delete the group instance and its localtree. */
+ bNodeTree *ngroup = (bNodeTree *)node->id;
+ ntreeFreeLocalNode(localtree, node);
+ ntreeFreeTree(ngroup);
+ MEM_freeN(ngroup);
+ }
+ else {
+ node_next = node->next;
+ }
+ }
+
+ ntreeUpdateTree(G.main, localtree);
+}
+
/* Check whether shader has a displacement.
*
* Will also return a node and it's socket which is connected to a displacement
@@ -576,53 +546,10 @@ static void ntree_shader_relink_node_normal(bNodeTree *ntree,
}
}
-static void ntree_shader_link_builtin_group_normal(bNodeTree *ntree,
- bNode *group_node,
- bNode *node_from,
- bNodeSocket *socket_from,
- bNode *displacement_node,
- bNodeSocket *displacement_socket)
-{
- bNodeTree *group_ntree = (bNodeTree *)group_node->id;
- /* Create input socket to plug displacement connection to. */
- bNodeSocket *group_normal_socket = ntreeAddSocketInterface(
- group_ntree, SOCK_IN, "NodeSocketVector", "Normal");
- /* Need to update tree so all node instances nodes gets proper sockets. */
- bNode *group_input_node = ntreeFindType(group_ntree, NODE_GROUP_INPUT);
- node_group_update(ntree, group_node);
- if (group_input_node) {
- node_group_input_update(group_ntree, group_input_node);
- }
- ntreeUpdateTree(G.main, group_ntree);
- /* Assumes sockets are always added at the end. */
- bNodeSocket *group_node_normal_socket = group_node->inputs.last;
- if (displacement_node == group_node) {
- /* This should never happen as all displacement nodes are duplicated and tagged. */
- BLI_assert(0);
- }
- else if (group_input_node) {
- /* Connect group node normal input. */
- nodeAddLink(ntree, node_from, socket_from, group_node, group_node_normal_socket);
- BLI_assert(group_input_node != NULL);
- bNodeSocket *group_input_node_normal_socket = nodeFindSocket(
- group_input_node, SOCK_OUT, group_normal_socket->identifier);
- BLI_assert(group_input_node_normal_socket != NULL);
- /* Relink normals inside of the instanced tree. */
- ntree_shader_link_builtin_normal(group_ntree,
- group_input_node,
- group_input_node_normal_socket,
- displacement_node,
- displacement_socket);
- ntreeUpdateTree(G.main, group_ntree);
- }
-}
-
/* Use specified node and socket as an input for unconnected normal sockets. */
static void ntree_shader_link_builtin_normal(bNodeTree *ntree,
bNode *node_from,
- bNodeSocket *socket_from,
- bNode *displacement_node,
- bNodeSocket *displacement_socket)
+ bNodeSocket *socket_from)
{
for (bNode *node = ntree->nodes.first; node != NULL; node = node->next) {
if (node == node_from) {
@@ -633,16 +560,6 @@ static void ntree_shader_link_builtin_normal(bNodeTree *ntree,
/* This node is used inside the displacement tree. Skip to avoid cycles. */
continue;
}
- if ((ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) && node->id) {
- /* Special re-linking for group nodes. */
- ntree_shader_link_builtin_group_normal(
- ntree, node, node_from, socket_from, displacement_node, displacement_socket);
- continue;
- }
- if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) {
- /* Group inputs and outputs needs nothing special. */
- continue;
- }
ntree_shader_relink_node_normal(ntree, node, node_from, socket_from);
}
}
@@ -670,36 +587,17 @@ static void ntree_shader_bypass_bump_link(bNodeTree *ntree, bNode *bump_node, bN
static void ntree_shader_bypass_tagged_bump_nodes(bNodeTree *ntree)
{
/* Bypass bump links inside copied nodes */
- bNodeLink *link, *link_next;
- for (link = ntree->links.first; link; link = link_next) {
- /* link might be freed by ntree_shader_bypass_bump_link. */
- link_next = link->next;
+ LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
bNode *node = link->fromnode;
/* If node is a copy. */
if (node->tmp_flag == -2 && node->type == SH_NODE_BUMP) {
ntree_shader_bypass_bump_link(ntree, node, link);
}
}
- /* Do the same inside nodegroups. */
- LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
- /* If node is a copy. */
- if (node->tmp_flag == -2 && ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id) {
- bNodeTree *group_ntree = (bNodeTree *)node->id;
- /* Tag all nodes inside this group as copies. */
- LISTBASE_FOREACH (bNode *, group_node, &group_ntree->nodes) {
- group_node->tmp_flag = -2;
- }
- /* Recursive. */
- ntree_shader_bypass_tagged_bump_nodes(group_ntree);
- }
- }
ntreeUpdateTree(G.main, ntree);
}
-static bool ntree_branch_count_and_tag_nodes(bNode *fromnode,
- bNode *tonode,
- void *userdata,
- const bool UNUSED(reversed))
+static bool ntree_branch_count_and_tag_nodes(bNode *fromnode, bNode *tonode, void *userdata)
{
int *node_count = (int *)userdata;
if (fromnode->tmp_flag == -1) {
@@ -713,19 +611,22 @@ static bool ntree_branch_count_and_tag_nodes(bNode *fromnode,
return true;
}
-static void ntree_shader_copy_branch_displacement(bNodeTree *ntree,
- bNode *displacement_node,
- bNodeSocket *displacement_socket,
- bNodeLink *displacement_link)
+/* Create a copy of a branch starting from a given node.
+ * callback is executed once for every copied node.
+ * Returns input node copy. */
+static bNode *ntree_shader_copy_branch(bNodeTree *ntree,
+ bNode *start_node,
+ void (*callback)(bNode *node, int user_data),
+ int user_data)
{
/* Init tmp flag. */
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
node->tmp_flag = -1;
}
/* Count and tag all nodes inside the displacement branch of the tree. */
- displacement_node->tmp_flag = 0;
+ start_node->tmp_flag = 0;
int node_count = 1;
- nodeChainIter(ntree, displacement_node, ntree_branch_count_and_tag_nodes, &node_count, true);
+ nodeChainIterBackwards(ntree, start_node, ntree_branch_count_and_tag_nodes, &node_count);
/* Make a full copy of the branch */
bNode **nodes_copy = MEM_mallocN(sizeof(bNode *) * node_count, __func__);
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
@@ -733,9 +634,6 @@ static void ntree_shader_copy_branch_displacement(bNodeTree *ntree,
int id = node->tmp_flag;
nodes_copy[id] = BKE_node_copy_ex(ntree, node, LIB_ID_CREATE_NO_USER_REFCOUNT);
nodes_copy[id]->tmp_flag = -2; /* Copy */
- if (ELEM(nodes_copy[id]->type, NODE_GROUP, NODE_CUSTOM_GROUP) && nodes_copy[id]->id) {
- nodes_copy[id]->id = (ID *)ntreeLocalize((bNodeTree *)nodes_copy[id]->id);
- }
/* Make sure to clear all sockets links as they are invalid. */
LISTBASE_FOREACH (bNodeSocket *, sock, &nodes_copy[id]->inputs) {
sock->link = NULL;
@@ -755,15 +653,30 @@ static void ntree_shader_copy_branch_displacement(bNodeTree *ntree,
nodeAddLink(ntree, fromnode, fromsock, tonode, tosock);
}
}
+ /* Per node callback. */
+ if (callback) {
+ for (int i = 0; i < node_count; i++) {
+ callback(nodes_copy[i], user_data);
+ }
+ }
+ bNode *start_node_copy = nodes_copy[start_node->tmp_flag];
+ MEM_freeN(nodes_copy);
+ return start_node_copy;
+}
+
+static void ntree_shader_copy_branch_displacement(bNodeTree *ntree,
+ bNode *displacement_node,
+ bNodeSocket *displacement_socket,
+ bNodeLink *displacement_link)
+{
/* Replace displacement socket/node/link. */
bNode *tonode = displacement_link->tonode;
bNodeSocket *tosock = displacement_link->tosock;
- displacement_node = nodes_copy[displacement_node->tmp_flag];
+ displacement_node = ntree_shader_copy_branch(ntree, displacement_node, NULL, 0);
displacement_socket = ntree_shader_node_find_output(displacement_node,
displacement_socket->identifier);
nodeRemLink(ntree, displacement_link);
nodeAddLink(ntree, displacement_node, displacement_socket, tonode, tosock);
- MEM_freeN(nodes_copy);
ntreeUpdateTree(G.main, ntree);
}
@@ -802,10 +715,12 @@ static void ntree_shader_relink_displacement(bNodeTree *ntree, bNode *output_nod
bNode *dot_node = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH);
bNode *geo_node = nodeAddStaticNode(NULL, ntree, SH_NODE_NEW_GEOMETRY);
bNodeSocket *normal_socket = ntree_shader_node_find_output(geo_node, "Normal");
- dot_node->custom1 = 3; /* dot product */
+ bNodeSocket *dot_input1 = dot_node->inputs.first;
+ bNodeSocket *dot_input2 = dot_input1->next;
+ dot_node->custom1 = NODE_VECTOR_MATH_DOT_PRODUCT;
- nodeAddLink(ntree, displacement_node, displacement_socket, dot_node, dot_node->inputs.first);
- nodeAddLink(ntree, geo_node, normal_socket, dot_node, dot_node->inputs.last);
+ nodeAddLink(ntree, displacement_node, displacement_socket, dot_node, dot_input1);
+ nodeAddLink(ntree, geo_node, normal_socket, dot_node, dot_input2);
displacement_node = dot_node;
displacement_socket = ntree_shader_node_find_output(dot_node, "Value");
@@ -830,33 +745,52 @@ static void ntree_shader_relink_displacement(bNodeTree *ntree, bNode *output_nod
ntreeUpdateTree(G.main, ntree);
/* Connect all free-standing Normal inputs and relink geometry/coordinate nodes. */
- ntree_shader_link_builtin_normal(
- ntree, bump_node, bump_output_socket, displacement_node, displacement_socket);
+ ntree_shader_link_builtin_normal(ntree, bump_node, bump_output_socket);
/* We modified the tree, it needs to be updated now. */
ntreeUpdateTree(G.main, ntree);
}
-static bool ntree_tag_bsdf_cb(bNode *fromnode,
- bNode *UNUSED(tonode),
- void *userdata,
- const bool UNUSED(reversed))
+static void node_tag_branch_as_derivative(bNode *node, int dx)
{
- /* Don't evaluate nodes more than once. */
- if (fromnode->tmp_flag) {
- return true;
+ if (dx) {
+ node->branch_tag = 1;
+ }
+ else {
+ node->branch_tag = 2;
}
- fromnode->tmp_flag = 1;
+}
+
+static bool ntree_shader_bump_branches(bNode *UNUSED(fromnode), bNode *tonode, void *userdata)
+{
+ bNodeTree *ntree = (bNodeTree *)userdata;
+ if (tonode->type == SH_NODE_BUMP) {
+ bNodeSocket *height_dx_sock, *height_dy_sock, *bump_socket, *bump_dx_socket, *bump_dy_socket;
+ bNode *bump = tonode;
+ bump_socket = ntree_shader_node_find_input(bump, "Height");
+ bump_dx_socket = ntree_shader_node_find_input(bump, "Height_dx");
+ bump_dy_socket = ntree_shader_node_find_input(bump, "Height_dy");
+ if (bump_dx_socket->link) {
+ /* Avoid reconnecting the same bump twice. */
+ }
+ else if (bump_socket && bump_socket->link) {
+ bNodeLink *link = bump_socket->link;
+ bNode *height = link->fromnode;
+ bNode *height_dx = ntree_shader_copy_branch(ntree, height, node_tag_branch_as_derivative, 1);
+ bNode *height_dy = ntree_shader_copy_branch(ntree, height, node_tag_branch_as_derivative, 0);
+ height_dx_sock = ntree_shader_node_find_output(height_dx, link->fromsock->identifier);
+ height_dy_sock = ntree_shader_node_find_output(height_dy, link->fromsock->identifier);
+ nodeAddLink(ntree, height_dx, height_dx_sock, bump, bump_dx_socket);
+ nodeAddLink(ntree, height_dy, height_dy_sock, bump, bump_dy_socket);
+ /* We could end iter here, but other bump node could be plugged into other input sockets. */
+ }
+ }
+ return true;
+}
+
+static bool ntree_tag_bsdf_cb(bNode *fromnode, bNode *UNUSED(tonode), void *userdata)
+{
switch (fromnode->type) {
- case NODE_GROUP:
- case NODE_CUSTOM_GROUP:
- /* Recursive */
- if (fromnode->id != NULL) {
- bNodeTree *ntree = (bNodeTree *)fromnode->id;
- bNode *group_output = ntree_group_output_node(ntree);
- ntree_shader_tag_nodes(ntree, group_output, (nTreeTags *)userdata);
- }
- break;
case SH_NODE_BSDF_ANISOTROPIC:
case SH_NODE_EEVEE_SPECULAR:
case SH_NODE_BSDF_GLOSSY:
@@ -895,12 +829,7 @@ void ntree_shader_tag_nodes(bNodeTree *ntree, bNode *output_node, nTreeTags *tag
/* Make sure sockets links pointers are correct. */
ntreeUpdateTree(G.main, ntree);
- /* Reset visit flag. */
- for (bNode *node = ntree->nodes.first; node; node = node->next) {
- node->tmp_flag = 0;
- }
-
- nodeChainIter(ntree, output_node, ntree_tag_bsdf_cb, tags, true);
+ nodeChainIterBackwards(ntree, output_node, ntree_tag_bsdf_cb, tags);
}
/* This one needs to work on a local tree. */
@@ -911,18 +840,26 @@ void ntreeGPUMaterialNodes(bNodeTree *localtree,
{
bNodeTreeExec *exec;
- /* Extract output nodes from inside nodegroups. */
- ntree_shader_output_node_from_group(localtree, SHD_OUTPUT_EEVEE);
-
bNode *output = ntreeShaderOutputNode(localtree, SHD_OUTPUT_EEVEE);
ntree_shader_groups_expand_inputs(localtree);
+ ntree_shader_groups_flatten(localtree);
+
+ if (output == NULL) {
+ /* Search again, now including flattened nodes. */
+ output = ntreeShaderOutputNode(localtree, SHD_OUTPUT_EEVEE);
+ }
+
/* Perform all needed modifications on the tree in order to support
* displacement/bump mapping.
*/
ntree_shader_relink_displacement(localtree, output);
+ /* Duplicate bump height branches for manual derivatives.
+ */
+ nodeChainIterBackwards(localtree, output, ntree_shader_bump_branches, localtree);
+
/* TODO(fclem): consider moving this to the gpu shader tree evaluation. */
nTreeTags tags = {
.ssr_id = 1.0,
diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c
index 2e8f81979a8..9615c6f01e0 100644
--- a/source/blender/nodes/shader/node_shader_util.c
+++ b/source/blender/nodes/shader/node_shader_util.c
@@ -231,7 +231,7 @@ void ntreeExecGPUNodes(bNodeTreeExec *exec, GPUMaterial *mat, bNode *output_node
stack = exec->stack;
- for (n = 0, nodeexec = exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
+ for (n = 0, nodeexec = exec->nodeexec; n < exec->totnodes; n++, nodeexec++) {
node = nodeexec->node;
do_it = false;
@@ -258,6 +258,30 @@ void ntreeExecGPUNodes(bNodeTreeExec *exec, GPUMaterial *mat, bNode *output_node
}
}
+void node_shader_gpu_bump_tex_coord(GPUMaterial *mat, bNode *node, GPUNodeLink **link)
+{
+ if (node->branch_tag == 1) {
+ /* Add one time the value fo derivative to the input vector. */
+ GPU_link(mat, "dfdx_v3", *link, link);
+ }
+ else if (node->branch_tag == 2) {
+ /* Add one time the value fo derivative to the input vector. */
+ GPU_link(mat, "dfdy_v3", *link, link);
+ }
+ else {
+ /* nothing to do, reference center value. */
+ }
+}
+
+void node_shader_gpu_default_tex_coord(GPUMaterial *mat, bNode *node, GPUNodeLink **link)
+{
+ if (!*link) {
+ *link = GPU_attribute(CD_ORCO, "");
+ GPU_link(mat, "generated_texco", GPU_builtin(GPU_VIEW_POSITION), *link, link);
+ node_shader_gpu_bump_tex_coord(mat, node, link);
+ }
+}
+
void node_shader_gpu_tex_mapping(GPUMaterial *mat,
bNode *node,
GPUNodeStack *in,
@@ -280,10 +304,10 @@ void node_shader_gpu_tex_mapping(GPUMaterial *mat,
tmat2 = GPU_uniform((float *)texmap->mat[2]);
tmat3 = GPU_uniform((float *)texmap->mat[3]);
- GPU_link(mat, "mapping", in[0].link, tmat0, tmat1, tmat2, tmat3, tmin, tmax, &in[0].link);
+ GPU_link(mat, "mapping_mat4", in[0].link, tmat0, tmat1, tmat2, tmat3, tmin, tmax, &in[0].link);
if (texmap->type == TEXMAP_TYPE_NORMAL) {
- GPU_link(mat, "texco_norm", in[0].link, &in[0].link);
+ GPU_link(mat, "vector_normalize", in[0].link, &in[0].link);
}
}
}
diff --git a/source/blender/nodes/shader/node_shader_util.h b/source/blender/nodes/shader/node_shader_util.h
index a3c553b983b..9719d0b36f5 100644
--- a/source/blender/nodes/shader/node_shader_util.h
+++ b/source/blender/nodes/shader/node_shader_util.h
@@ -84,6 +84,12 @@ void nodestack_get_vec(float *in, short type_in, bNodeStack *ns);
void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, struct bNodeStack *ns);
void node_data_from_gpu_stack(struct bNodeStack *ns, struct GPUNodeStack *gs);
+void node_shader_gpu_bump_tex_coord(struct GPUMaterial *mat,
+ struct bNode *node,
+ struct GPUNodeLink **link);
+void node_shader_gpu_default_tex_coord(struct GPUMaterial *mat,
+ struct bNode *node,
+ struct GPUNodeLink **link);
void node_shader_gpu_tex_mapping(struct GPUMaterial *mat,
struct bNode *node,
struct GPUNodeStack *in,
diff --git a/source/blender/nodes/shader/nodes/node_shader_attribute.c b/source/blender/nodes/shader/nodes/node_shader_attribute.c
index c92ae28f2e6..ecb8c53c312 100644
--- a/source/blender/nodes/shader/nodes/node_shader_attribute.c
+++ b/source/blender/nodes/shader/nodes/node_shader_attribute.c
@@ -67,7 +67,14 @@ static int node_shader_gpu_attribute(GPUMaterial *mat,
}
else {
GPUNodeLink *cd_attr = GPU_attribute(CD_AUTO_FROM_NAME, attr->name);
- return GPU_stack_link(mat, node, "node_attribute", in, out, cd_attr);
+ GPU_stack_link(mat, node, "node_attribute", in, out, cd_attr);
+
+ /* for each output. */
+ for (int i = 0; sh_node_attribute_out[i].type != -1; i++) {
+ node_shader_gpu_bump_tex_coord(mat, node, &out[i].link);
+ }
+
+ return 1;
}
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
index 595ddf27d0a..3340054396d 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
@@ -120,6 +120,7 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat,
GPU_link(mat, "world_normals_get", &in[20].link);
}
+#if 0 /* Not used at the moment. */
/* Tangents */
if (!in[21].link) {
GPUNodeLink *orco = GPU_attribute(CD_ORCO, "");
@@ -131,6 +132,7 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat,
GPU_builtin(GPU_OBJECT_MATRIX),
&in[21].link);
}
+#endif
bool use_diffuse = socket_not_one(4) && socket_not_one(15);
bool use_subsurf = socket_not_zero(1) && use_diffuse && node->sss_id > 0;
diff --git a/source/blender/nodes/shader/nodes/node_shader_bump.c b/source/blender/nodes/shader/nodes/node_shader_bump.c
index d17edae35df..384701d2ddf 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bump.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bump.c
@@ -24,32 +24,17 @@
#include "node_shader_util.h"
/* **************** BUMP ******************** */
+/* clang-format off */
static bNodeSocketTemplate sh_node_bump_in[] = {
{SOCK_FLOAT, 1, N_("Strength"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{SOCK_FLOAT, 1, N_("Distance"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
- {SOCK_FLOAT,
- 1,
- N_("Height"),
- 1.0f,
- 1.0f,
- 1.0f,
- 1.0f,
- -1000.0f,
- 1000.0f,
- PROP_NONE,
- SOCK_HIDE_VALUE},
- {SOCK_VECTOR,
- 1,
- N_("Normal"),
- 0.0f,
- 0.0f,
- 0.0f,
- 1.0f,
- -1.0f,
- 1.0f,
- PROP_NONE,
- SOCK_HIDE_VALUE},
- {-1, 0, ""}};
+ {SOCK_FLOAT, 1, N_("Height"), 1.0f, 1.0f, 1.0f, 1.0f, -1000.0f, 1000.0f, PROP_NONE, SOCK_HIDE_VALUE},
+ {SOCK_FLOAT, 1, N_("Height_dx"), 1.0f, 1.0f, 1.0f, 1.0f, -1000.0f, 1000.0f, PROP_NONE, SOCK_UNAVAIL},
+ {SOCK_FLOAT, 1, N_("Height_dy"), 1.0f, 1.0f, 1.0f, 1.0f, -1000.0f, 1000.0f, PROP_NONE, SOCK_UNAVAIL},
+ {SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
+ {-1, 0, ""}
+};
+/* clang-format on */
static bNodeSocketTemplate sh_node_bump_out[] = {{SOCK_VECTOR, 0, "Normal"}, {-1, 0, ""}};
@@ -59,8 +44,8 @@ static int gpu_shader_bump(GPUMaterial *mat,
GPUNodeStack *in,
GPUNodeStack *out)
{
- if (!in[3].link) {
- GPU_link(mat, "world_normals_get", &in[3].link);
+ if (!in[5].link) {
+ GPU_link(mat, "world_normals_get", &in[5].link);
}
float invert = (node->custom1) ? -1.0 : 1.0;
diff --git a/source/blender/nodes/shader/nodes/node_shader_common.c b/source/blender/nodes/shader/nodes/node_shader_common.c
index 10f6aadbc5f..257caabcabf 100644
--- a/source/blender/nodes/shader/nodes/node_shader_common.c
+++ b/source/blender/nodes/shader/nodes/node_shader_common.c
@@ -98,7 +98,7 @@ static void group_copy_inputs(bNode *gnode, bNodeStack **in, bNodeStack *gstack)
for (node = ngroup->nodes.first; node; node = node->next) {
if (node->type == NODE_GROUP_INPUT) {
- for (sock = node->outputs.first, a = 0; sock; sock = sock->next, ++a) {
+ for (sock = node->outputs.first, a = 0; sock; sock = sock->next, a++) {
ns = node_get_socket_stack(gstack, sock);
if (ns) {
copy_stack(ns, in[a]);
@@ -120,7 +120,7 @@ static void group_move_outputs(bNode *gnode, bNodeStack **out, bNodeStack *gstac
for (node = ngroup->nodes.first; node; node = node->next) {
if (node->type == NODE_GROUP_OUTPUT && (node->flag & NODE_DO_OUTPUT)) {
- for (sock = node->inputs.first, a = 0; sock; sock = sock->next, ++a) {
+ for (sock = node->inputs.first, a = 0; sock; sock = sock->next, a++) {
ns = node_get_socket_stack(gstack, sock);
if (ns) {
move_stack(out[a], ns);
@@ -174,7 +174,7 @@ static void group_gpu_copy_inputs(bNode *gnode, GPUNodeStack *in, bNodeStack *gs
for (node = ngroup->nodes.first; node; node = node->next) {
if (node->type == NODE_GROUP_INPUT) {
- for (sock = node->outputs.first, a = 0; sock; sock = sock->next, ++a) {
+ for (sock = node->outputs.first, a = 0; sock; sock = sock->next, a++) {
ns = node_get_socket_stack(gstack, sock);
if (ns) {
/* convert the external gpu stack back to internal node stack data */
@@ -197,7 +197,7 @@ static void group_gpu_move_outputs(bNode *gnode, GPUNodeStack *out, bNodeStack *
for (node = ngroup->nodes.first; node; node = node->next) {
if (node->type == NODE_GROUP_OUTPUT && (node->flag & NODE_DO_OUTPUT)) {
- for (sock = node->inputs.first, a = 0; sock; sock = sock->next, ++a) {
+ for (sock = node->inputs.first, a = 0; sock; sock = sock->next, a++) {
ns = node_get_socket_stack(gstack, sock);
if (ns) {
/* convert the node stack data result back to gpu stack */
diff --git a/source/blender/nodes/shader/nodes/node_shader_curves.c b/source/blender/nodes/shader/nodes/node_shader_curves.c
index baf86951fe0..f5c89e6ba41 100644
--- a/source/blender/nodes/shader/nodes/node_shader_curves.c
+++ b/source/blender/nodes/shader/nodes/node_shader_curves.c
@@ -141,7 +141,7 @@ static int gpu_shader_curve_rgb(GPUMaterial *mat,
float ext_rgba[4][4];
float range_rgba[4];
- for (int a = 0; a < CM_TOT; ++a) {
+ for (int a = 0; a < CM_TOT; a++) {
const CurveMap *cm = &cumap->cm[a];
ext_rgba[a][0] = cm->mintable;
ext_rgba[a][2] = cm->maxtable;
diff --git a/source/blender/nodes/shader/nodes/node_shader_geometry.c b/source/blender/nodes/shader/nodes/node_shader_geometry.c
index df9a8ac8318..d94141c3699 100644
--- a/source/blender/nodes/shader/nodes/node_shader_geometry.c
+++ b/source/blender/nodes/shader/nodes/node_shader_geometry.c
@@ -41,9 +41,11 @@ static int node_shader_gpu_geometry(GPUMaterial *mat,
{
/* HACK: Don't request GPU_BARYCENTRIC_TEXCO if not used because it will
* trigger the use of geometry shader (and the performance penalty it implies). */
- float val[2] = {0.0f, 0.0f};
+ float val[4] = {0.0f, 0.0f, 0.0f, 0.0f};
GPUNodeLink *bary_link = (!out[5].hasoutput) ? GPU_constant(val) :
GPU_builtin(GPU_BARYCENTRIC_TEXCO);
+ /* Opti: don't request orco if not needed. */
+ GPUNodeLink *orco_link = (!out[2].hasoutput) ? GPU_constant(val) : GPU_attribute(CD_ORCO, "");
return GPU_stack_link(mat,
node,
@@ -52,7 +54,7 @@ static int node_shader_gpu_geometry(GPUMaterial *mat,
out,
GPU_builtin(GPU_VIEW_POSITION),
GPU_builtin(GPU_WORLD_NORMAL),
- GPU_attribute(CD_ORCO, ""),
+ orco_link,
GPU_builtin(GPU_OBJECT_MATRIX),
GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
bary_link);
diff --git a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c
index ea916d25ffd..21d2cdcb3b5 100644
--- a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c
+++ b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c
@@ -39,7 +39,7 @@ static bNodeSocketTemplate sh_node_hue_sat_out[] = {
/* note: it would be possible to use CMP version for both nodes */
static void do_hue_sat_fac(
- bNode *UNUSED(node), float *out, float hue, float sat, float val, float in[4], float fac)
+ bNode *UNUSED(node), float *out, float hue, float sat, float val, const float in[4], float fac)
{
if (fac != 0.0f && (hue != 0.5f || sat != 1.0f || val != 1.0f)) {
float col[3], hsv[3], mfac = 1.0f - fac;
diff --git a/source/blender/nodes/shader/nodes/node_shader_mapping.c b/source/blender/nodes/shader/nodes/node_shader_mapping.c
index eca0d96f2c8..d607fcdc7a1 100644
--- a/source/blender/nodes/shader/nodes/node_shader_mapping.c
+++ b/source/blender/nodes/shader/nodes/node_shader_mapping.c
@@ -25,7 +25,10 @@
/* **************** MAPPING ******************** */
static bNodeSocketTemplate sh_node_mapping_in[] = {
- {SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE},
+ {SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 1.0f, -FLT_MAX, FLT_MAX, PROP_NONE},
+ {SOCK_VECTOR, 1, N_("Location"), 0.0f, 0.0f, 0.0f, 1.0f, -FLT_MAX, FLT_MAX, PROP_TRANSLATION},
+ {SOCK_VECTOR, 1, N_("Rotation"), 0.0f, 0.0f, 0.0f, 1.0f, -FLT_MAX, FLT_MAX, PROP_EULER},
+ {SOCK_VECTOR, 1, N_("Scale"), 1.0f, 1.0f, 1.0f, 1.0f, -FLT_MAX, FLT_MAX, PROP_XYZ},
{-1, 0, ""},
};
@@ -34,91 +37,27 @@ static bNodeSocketTemplate sh_node_mapping_out[] = {
{-1, 0, ""},
};
-static void *node_shader_initexec_mapping(bNodeExecContext *UNUSED(context),
- bNode *node,
- bNodeInstanceKey UNUSED(key))
-{
- TexMapping *texmap = node->storage;
- BKE_texture_mapping_init(texmap);
- return NULL;
-}
-
-/* do the regular mapping options for blender textures */
-static void node_shader_exec_mapping(void *UNUSED(data),
- int UNUSED(thread),
- bNode *node,
- bNodeExecData *UNUSED(execdata),
- bNodeStack **in,
- bNodeStack **out)
-{
- TexMapping *texmap = node->storage;
- float *vec = out[0]->vec;
-
- /* stack order input: vector */
- /* stack order output: vector */
- nodestack_get_vec(vec, SOCK_VECTOR, in[0]);
- mul_m4_v3(texmap->mat, vec);
-
- if (texmap->flag & TEXMAP_CLIP_MIN) {
- if (vec[0] < texmap->min[0]) {
- vec[0] = texmap->min[0];
- }
- if (vec[1] < texmap->min[1]) {
- vec[1] = texmap->min[1];
- }
- if (vec[2] < texmap->min[2]) {
- vec[2] = texmap->min[2];
- }
- }
- if (texmap->flag & TEXMAP_CLIP_MAX) {
- if (vec[0] > texmap->max[0]) {
- vec[0] = texmap->max[0];
- }
- if (vec[1] > texmap->max[1]) {
- vec[1] = texmap->max[1];
- }
- if (vec[2] > texmap->max[2]) {
- vec[2] = texmap->max[2];
- }
- }
-
- if (texmap->type == TEXMAP_TYPE_NORMAL) {
- normalize_v3(vec);
- }
-}
-
-static void node_shader_init_mapping(bNodeTree *UNUSED(ntree), bNode *node)
-{
- node->storage = BKE_texture_mapping_add(TEXMAP_TYPE_POINT);
-}
-
static int gpu_shader_mapping(GPUMaterial *mat,
bNode *node,
bNodeExecData *UNUSED(execdata),
GPUNodeStack *in,
GPUNodeStack *out)
{
- TexMapping *texmap = node->storage;
- float domin = (texmap->flag & TEXMAP_CLIP_MIN) != 0;
- float domax = (texmap->flag & TEXMAP_CLIP_MAX) != 0;
- static float max[3] = {FLT_MAX, FLT_MAX, FLT_MAX};
- static float min[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
- GPUNodeLink *tmin, *tmax, *tmat0, *tmat1, *tmat2, *tmat3;
-
- tmin = GPU_uniform((domin) ? texmap->min : min);
- tmax = GPU_uniform((domax) ? texmap->max : max);
- tmat0 = GPU_uniform((float *)texmap->mat[0]);
- tmat1 = GPU_uniform((float *)texmap->mat[1]);
- tmat2 = GPU_uniform((float *)texmap->mat[2]);
- tmat3 = GPU_uniform((float *)texmap->mat[3]);
-
- GPU_stack_link(mat, node, "mapping", in, out, tmat0, tmat1, tmat2, tmat3, tmin, tmax);
-
- if (texmap->type == TEXMAP_TYPE_NORMAL) {
- GPU_link(mat, "texco_norm", out[0].link, &out[0].link);
- }
+ static const char *names[] = {
+ [NODE_MAPPING_TYPE_POINT] = "mapping_point",
+ [NODE_MAPPING_TYPE_TEXTURE] = "mapping_texture",
+ [NODE_MAPPING_TYPE_VECTOR] = "mapping_vector",
+ [NODE_MAPPING_TYPE_NORMAL] = "mapping_normal",
+ };
+
+ return GPU_stack_link(mat, node, names[node->custom1], in, out);
+}
- return true;
+static void node_shader_update_mapping(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ bNodeSocket *sock = nodeFindSocket(node, SOCK_IN, "Location");
+ nodeSetSocketAvailability(
+ sock, ELEM(node->custom1, NODE_MAPPING_TYPE_POINT, NODE_MAPPING_TYPE_TEXTURE));
}
void register_node_type_sh_mapping(void)
@@ -127,11 +66,8 @@ void register_node_type_sh_mapping(void)
sh_node_type_base(&ntype, SH_NODE_MAPPING, "Mapping", NODE_CLASS_OP_VECTOR, 0);
node_type_socket_templates(&ntype, sh_node_mapping_in, sh_node_mapping_out);
- node_type_size(&ntype, 320, 160, 360);
- node_type_init(&ntype, node_shader_init_mapping);
- node_type_storage(&ntype, "TexMapping", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, node_shader_initexec_mapping, NULL, node_shader_exec_mapping);
node_type_gpu(&ntype, gpu_shader_mapping);
+ node_type_update(&ntype, node_shader_update_mapping);
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c
index 872f4f9da9c..ae2184d8237 100644
--- a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c
+++ b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c
@@ -92,7 +92,7 @@ static int gpu_shader_mix_rgb(GPUMaterial *mat,
if (ret && node->custom2 & SHD_MIXRGB_CLAMP) {
float min[3] = {0.0f, 0.0f, 0.0f};
float max[3] = {1.0f, 1.0f, 1.0f};
- GPU_link(mat, "clamp_vec3", out[0].link, GPU_constant(min), GPU_constant(max), &out[0].link);
+ GPU_link(mat, "clamp_color", out[0].link, GPU_constant(min), GPU_constant(max), &out[0].link);
}
return ret;
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.c b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
index 712c64084cc..18015d94f03 100644
--- a/source/blender/nodes/shader/nodes/node_shader_normal_map.c
+++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
@@ -114,8 +114,8 @@ static int gpu_shader_normal_map(GPUMaterial *mat,
break;
}
- GPU_link(mat, "vector_math_mix", strength, realnorm, negnorm, &out[0].link);
- GPU_link(mat, "vect_normalize", out[0].link, &out[0].link);
+ GPU_link(mat, "vector_mix", strength, realnorm, negnorm, &out[0].link);
+ GPU_link(mat, "vector_normalize", out[0].link, &out[0].link);
return true;
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c
index 9a0a132b311..9f93dfd837b 100644
--- a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c
+++ b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c
@@ -61,8 +61,6 @@ static int node_shader_gpu_subsurface_scattering(GPUMaterial *mat,
GPU_link(mat, "world_normals_get", &in[5].link);
}
- GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_SSS);
-
if (node->sss_id > 0) {
bNodeSocket *socket = BLI_findlink(&node->original->inputs, 2);
bNodeSocketValueRGBA *socket_data = socket->default_value;
@@ -71,6 +69,10 @@ static int node_shader_gpu_subsurface_scattering(GPUMaterial *mat,
/* For some reason it seems that the socket value is in ARGB format. */
GPU_material_sss_profile_create(
mat, &socket_data->value[1], &node->original->custom1, &socket_data_sharp->value);
+
+ /* sss_id is 0 only the node is not connected to any output.
+ * In this case flagging the material would trigger a bug (see T68736). */
+ GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_SSS);
}
return GPU_stack_link(
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
index 92ade999650..9c86e78c3cd 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
@@ -157,11 +157,7 @@ static int node_shader_gpu_tex_brick(GPUMaterial *mat,
GPUNodeStack *in,
GPUNodeStack *out)
{
- if (!in[0].link) {
- in[0].link = GPU_attribute(CD_ORCO, "");
- GPU_link(mat, "generated_texco", GPU_builtin(GPU_VIEW_POSITION), in[0].link, &in[0].link);
- }
-
+ node_shader_gpu_default_tex_coord(mat, node, &in[0].link);
node_shader_gpu_tex_mapping(mat, node, in, out);
NodeTexBrick *tex = (NodeTexBrick *)node->storage;
float offset_freq = tex->offset_freq;
@@ -171,9 +167,9 @@ static int node_shader_gpu_tex_brick(GPUMaterial *mat,
"node_tex_brick",
in,
out,
- GPU_constant(&tex->offset),
+ GPU_uniform(&tex->offset),
GPU_constant(&offset_freq),
- GPU_constant(&tex->squash),
+ GPU_uniform(&tex->squash),
GPU_constant(&squash_freq));
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_checker.c b/source/blender/nodes/shader/nodes/node_shader_tex_checker.c
index 9dcb6057589..9b9138802fa 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_checker.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_checker.c
@@ -70,11 +70,7 @@ static int node_shader_gpu_tex_checker(GPUMaterial *mat,
GPUNodeStack *in,
GPUNodeStack *out)
{
- if (!in[0].link) {
- in[0].link = GPU_attribute(CD_ORCO, "");
- GPU_link(mat, "generated_texco", GPU_builtin(GPU_VIEW_POSITION), in[0].link, &in[0].link);
- }
-
+ node_shader_gpu_default_tex_coord(mat, node, &in[0].link);
node_shader_gpu_tex_mapping(mat, node, in, out);
return GPU_stack_link(mat, node, "node_tex_checker", in, out);
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
index 0e34f2ca9b1..068458b7e1f 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
@@ -45,22 +45,27 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat,
GPUNodeLink *inv_obmat = (ob != NULL) ? GPU_uniform(&ob->imat[0][0]) :
GPU_builtin(GPU_INVERSE_OBJECT_MATRIX);
- GPUNodeLink *orco = GPU_attribute(CD_ORCO, "");
+ /* Opti: don't request orco if not needed. */
+ GPUNodeLink *orco = (!out[0].hasoutput) ? GPU_constant((float[4]){0.0f, 0.0f, 0.0f, 0.0f}) :
+ GPU_attribute(CD_ORCO, "");
GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, "");
+ GPUNodeLink *viewpos = GPU_builtin(GPU_VIEW_POSITION);
+ GPUNodeLink *worldnor = GPU_builtin(GPU_WORLD_NORMAL);
+ GPUNodeLink *texcofacs = GPU_builtin(GPU_CAMERA_TEXCO_FACTORS);
- GPU_link(mat, "generated_from_orco", orco, &orco);
+ if (out[0].hasoutput) {
+ GPU_link(mat, "generated_from_orco", orco, &orco);
+ }
- return GPU_stack_link(mat,
- node,
- "node_tex_coord",
- in,
- out,
- GPU_builtin(GPU_VIEW_POSITION),
- GPU_builtin(GPU_WORLD_NORMAL),
- inv_obmat,
- GPU_builtin(GPU_CAMERA_TEXCO_FACTORS),
- orco,
- mtface);
+ GPU_stack_link(
+ mat, node, "node_tex_coord", in, out, viewpos, worldnor, inv_obmat, texcofacs, orco, mtface);
+
+ /* for each output. */
+ for (int i = 0; sh_node_tex_coord_out[i].type != -1; i++) {
+ node_shader_gpu_bump_tex_coord(mat, node, &out[i].link);
+ }
+
+ return 1;
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
index bd8355ec885..6c380efe0b2 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
@@ -75,6 +75,7 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat,
if (!in[0].link) {
GPU_link(mat, "node_tex_environment_texco", GPU_builtin(GPU_VIEW_POSITION), &in[0].link);
+ node_shader_gpu_bump_tex_coord(mat, node, &in[0].link);
}
node_shader_gpu_tex_mapping(mat, node, in, out);
@@ -124,15 +125,15 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat,
if (ELEM(ima->alpha_mode, IMA_ALPHA_IGNORE, IMA_ALPHA_CHANNEL_PACKED) ||
IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name)) {
/* Don't let alpha affect color output in these cases. */
- GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link);
+ GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link);
}
else {
/* Always output with premultiplied alpha. */
if (ima->alpha_mode == IMA_ALPHA_PREMUL) {
- GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link);
+ GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link);
}
else {
- GPU_link(mat, "tex_color_alpha_premultiply", out[0].link, &out[0].link);
+ GPU_link(mat, "color_alpha_premultiply", out[0].link, &out[0].link);
}
}
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c
index 9271ba72a05..7f266c06a1b 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c
@@ -68,11 +68,7 @@ static int node_shader_gpu_tex_gradient(GPUMaterial *mat,
GPUNodeStack *in,
GPUNodeStack *out)
{
- if (!in[0].link) {
- in[0].link = GPU_attribute(CD_ORCO, "");
- GPU_link(mat, "generated_texco", GPU_builtin(GPU_VIEW_POSITION), in[0].link, &in[0].link);
- }
-
+ node_shader_gpu_default_tex_coord(mat, node, &in[0].link);
node_shader_gpu_tex_mapping(mat, node, in, out);
NodeTexGradient *tex = (NodeTexGradient *)node->storage;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
index 6f3614e357d..a6dfb2636fc 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
@@ -118,6 +118,7 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
if (!*texco) {
*texco = GPU_attribute(CD_MTFACE, "");
+ node_shader_gpu_bump_tex_coord(mat, node, texco);
}
node_shader_gpu_tex_mapping(mat, node, in, out);
@@ -183,7 +184,7 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
if (ELEM(ima->alpha_mode, IMA_ALPHA_IGNORE, IMA_ALPHA_CHANNEL_PACKED) ||
IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name)) {
/* Don't let alpha affect color output in these cases. */
- GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link);
+ GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link);
}
else {
/* Output premultiplied alpha depending on alpha socket usage. This makes
@@ -192,18 +193,18 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
* not, then there will be no artifacts from zero alpha areas. */
if (ima->alpha_mode == IMA_ALPHA_PREMUL) {
if (out[1].hasoutput) {
- GPU_link(mat, "tex_color_alpha_unpremultiply", out[0].link, &out[0].link);
+ GPU_link(mat, "color_alpha_unpremultiply", out[0].link, &out[0].link);
}
else {
- GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link);
+ GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link);
}
}
else {
if (out[1].hasoutput) {
- GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link);
+ GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link);
}
else {
- GPU_link(mat, "tex_color_alpha_premultiply", out[0].link, &out[0].link);
+ GPU_link(mat, "color_alpha_premultiply", out[0].link, &out[0].link);
}
}
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_magic.c b/source/blender/nodes/shader/nodes/node_shader_tex_magic.c
index f5dc0435f27..d51594e549d 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_magic.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_magic.c
@@ -73,11 +73,7 @@ static int node_shader_gpu_tex_magic(GPUMaterial *mat,
NodeTexMagic *tex = (NodeTexMagic *)node->storage;
float depth = tex->depth;
- if (!in[0].link) {
- in[0].link = GPU_attribute(CD_ORCO, "");
- GPU_link(mat, "generated_texco", GPU_builtin(GPU_VIEW_POSITION), in[0].link, &in[0].link);
- }
-
+ node_shader_gpu_default_tex_coord(mat, node, &in[0].link);
node_shader_gpu_tex_mapping(mat, node, in, out);
return GPU_stack_link(mat, node, "node_tex_magic", in, out, GPU_constant(&depth));
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
index 250a1da3c23..daf4053f182 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
@@ -23,6 +23,7 @@
static bNodeSocketTemplate sh_node_tex_musgrave_in[] = {
{SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
+ {SOCK_FLOAT, 1, N_("W"), 0.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
{SOCK_FLOAT, 1, N_("Scale"), 5.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
{SOCK_FLOAT, 1, N_("Detail"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 16.0f},
{SOCK_FLOAT, 1, N_("Dimension"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
@@ -33,17 +34,6 @@ static bNodeSocketTemplate sh_node_tex_musgrave_in[] = {
};
static bNodeSocketTemplate sh_node_tex_musgrave_out[] = {
- {SOCK_RGBA,
- 0,
- N_("Color"),
- 0.0f,
- 0.0f,
- 0.0f,
- 0.0f,
- 0.0f,
- 1.0f,
- PROP_NONE,
- SOCK_NO_INTERNAL_LINK},
{SOCK_FLOAT,
0,
N_("Fac"),
@@ -64,6 +54,7 @@ static void node_shader_init_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *node)
BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
BKE_texture_colormapping_default(&tex->base.color_mapping);
tex->musgrave_type = SHD_MUSGRAVE_FBM;
+ tex->dimensions = 3;
node->storage = tex;
}
@@ -74,20 +65,81 @@ static int node_shader_gpu_tex_musgrave(GPUMaterial *mat,
GPUNodeStack *in,
GPUNodeStack *out)
{
- if (!in[0].link) {
- in[0].link = GPU_attribute(CD_ORCO, "");
- GPU_link(mat, "generated_texco", GPU_builtin(GPU_VIEW_POSITION), in[0].link, &in[0].link);
- }
-
+ node_shader_gpu_default_tex_coord(mat, node, &in[0].link);
node_shader_gpu_tex_mapping(mat, node, in, out);
NodeTexMusgrave *tex = (NodeTexMusgrave *)node->storage;
- float type = tex->musgrave_type;
+ int dimensions = tex->dimensions;
+ int type = tex->musgrave_type;
+
+ static const char *names[][5] = {
+ [SHD_MUSGRAVE_MULTIFRACTAL] =
+ {
+ "",
+ "node_tex_musgrave_multi_fractal_1d",
+ "node_tex_musgrave_multi_fractal_2d",
+ "node_tex_musgrave_multi_fractal_3d",
+ "node_tex_musgrave_multi_fractal_4d",
+ },
+ [SHD_MUSGRAVE_FBM] =
+ {
+ "",
+ "node_tex_musgrave_fBm_1d",
+ "node_tex_musgrave_fBm_2d",
+ "node_tex_musgrave_fBm_3d",
+ "node_tex_musgrave_fBm_4d",
+ },
+ [SHD_MUSGRAVE_HYBRID_MULTIFRACTAL] =
+ {
+ "",
+ "node_tex_musgrave_hybrid_multi_fractal_1d",
+ "node_tex_musgrave_hybrid_multi_fractal_2d",
+ "node_tex_musgrave_hybrid_multi_fractal_3d",
+ "node_tex_musgrave_hybrid_multi_fractal_4d",
+ },
+ [SHD_MUSGRAVE_RIDGED_MULTIFRACTAL] =
+ {
+ "",
+ "node_tex_musgrave_ridged_multi_fractal_1d",
+ "node_tex_musgrave_ridged_multi_fractal_2d",
+ "node_tex_musgrave_ridged_multi_fractal_3d",
+ "node_tex_musgrave_ridged_multi_fractal_4d",
+ },
+ [SHD_MUSGRAVE_HETERO_TERRAIN] =
+ {
+ "",
+ "node_tex_musgrave_hetero_terrain_1d",
+ "node_tex_musgrave_hetero_terrain_2d",
+ "node_tex_musgrave_hetero_terrain_3d",
+ "node_tex_musgrave_hetero_terrain_4d",
+ },
+ };
+
+ BLI_assert(type >= 0 && type < 5);
+ BLI_assert(dimensions > 0 && dimensions < 5);
+
+ return GPU_stack_link(mat, node, names[type][dimensions], in, out);
+}
+
+static void node_shader_update_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ NodeTexMusgrave *tex = (NodeTexMusgrave *)node->storage;
+
+ bNodeSocket *inVectorSock = nodeFindSocket(node, SOCK_IN, "Vector");
+ bNodeSocket *inWSock = nodeFindSocket(node, SOCK_IN, "W");
+ bNodeSocket *inOffsetSock = nodeFindSocket(node, SOCK_IN, "Offset");
+ bNodeSocket *inGainSock = nodeFindSocket(node, SOCK_IN, "Gain");
- return GPU_stack_link(mat, node, "node_tex_musgrave", in, out, GPU_constant(&type));
+ nodeSetSocketAvailability(inVectorSock, tex->dimensions != 1);
+ nodeSetSocketAvailability(inWSock, tex->dimensions == 1 || tex->dimensions == 4);
+ nodeSetSocketAvailability(inOffsetSock,
+ tex->musgrave_type != SHD_MUSGRAVE_MULTIFRACTAL &&
+ tex->musgrave_type != SHD_MUSGRAVE_FBM);
+ nodeSetSocketAvailability(inGainSock,
+ tex->musgrave_type == SHD_MUSGRAVE_HYBRID_MULTIFRACTAL &&
+ tex->musgrave_type != SHD_MUSGRAVE_RIDGED_MULTIFRACTAL);
}
-/* node type definition */
void register_node_type_sh_tex_musgrave(void)
{
static bNodeType ntype;
@@ -99,6 +151,7 @@ void register_node_type_sh_tex_musgrave(void)
node_type_storage(
&ntype, "NodeTexMusgrave", node_free_standard_storage, node_copy_standard_storage);
node_type_gpu(&ntype, node_shader_gpu_tex_musgrave);
+ node_type_update(&ntype, node_shader_update_tex_musgrave);
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
index 34c4b17f255..0b3b249c3d9 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
@@ -23,6 +23,7 @@
static bNodeSocketTemplate sh_node_tex_noise_in[] = {
{SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
+ {SOCK_FLOAT, 1, N_("W"), 0.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
{SOCK_FLOAT, 1, N_("Scale"), 5.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
{SOCK_FLOAT, 1, N_("Detail"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 16.0f},
{SOCK_FLOAT, 1, N_("Distortion"), 0.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
@@ -30,27 +31,27 @@ static bNodeSocketTemplate sh_node_tex_noise_in[] = {
};
static bNodeSocketTemplate sh_node_tex_noise_out[] = {
- {SOCK_RGBA,
+ {SOCK_FLOAT,
0,
- N_("Color"),
+ N_("Fac"),
0.0f,
0.0f,
0.0f,
0.0f,
0.0f,
1.0f,
- PROP_NONE,
+ PROP_FACTOR,
SOCK_NO_INTERNAL_LINK},
- {SOCK_FLOAT,
+ {SOCK_RGBA,
0,
- N_("Fac"),
+ N_("Color"),
0.0f,
0.0f,
0.0f,
0.0f,
0.0f,
1.0f,
- PROP_FACTOR,
+ PROP_NONE,
SOCK_NO_INTERNAL_LINK},
{-1, 0, ""},
};
@@ -60,6 +61,7 @@ static void node_shader_init_tex_noise(bNodeTree *UNUSED(ntree), bNode *node)
NodeTexNoise *tex = MEM_callocN(sizeof(NodeTexNoise), "NodeTexNoise");
BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
BKE_texture_colormapping_default(&tex->base.color_mapping);
+ tex->dimensions = 3;
node->storage = tex;
}
@@ -70,14 +72,28 @@ static int node_shader_gpu_tex_noise(GPUMaterial *mat,
GPUNodeStack *in,
GPUNodeStack *out)
{
- if (!in[0].link) {
- in[0].link = GPU_attribute(CD_ORCO, "");
- GPU_link(mat, "generated_texco", GPU_builtin(GPU_VIEW_POSITION), in[0].link, &in[0].link);
- }
-
+ node_shader_gpu_default_tex_coord(mat, node, &in[0].link);
node_shader_gpu_tex_mapping(mat, node, in, out);
- return GPU_stack_link(mat, node, "node_tex_noise", in, out);
+ NodeTexNoise *tex = (NodeTexNoise *)node->storage;
+ static const char *names[] = {
+ "",
+ "node_noise_texture_1d",
+ "node_noise_texture_2d",
+ "node_noise_texture_3d",
+ "node_noise_texture_4d",
+ };
+ return GPU_stack_link(mat, node, names[tex->dimensions], in, out);
+}
+
+static void node_shader_update_tex_noise(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ bNodeSocket *sockVector = nodeFindSocket(node, SOCK_IN, "Vector");
+ bNodeSocket *sockW = nodeFindSocket(node, SOCK_IN, "W");
+
+ NodeTexNoise *tex = (NodeTexNoise *)node->storage;
+ nodeSetSocketAvailability(sockVector, tex->dimensions != 1);
+ nodeSetSocketAvailability(sockW, tex->dimensions == 1 || tex->dimensions == 4);
}
/* node type definition */
@@ -91,6 +107,7 @@ void register_node_type_sh_tex_noise(void)
node_type_storage(
&ntype, "NodeTexNoise", node_free_standard_storage, node_copy_standard_storage);
node_type_gpu(&ntype, node_shader_gpu_tex_noise);
+ node_type_update(&ntype, node_shader_update_tex_noise);
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c
index e0b4de985d8..adcb93d7775 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c
@@ -23,12 +23,26 @@
static bNodeSocketTemplate sh_node_tex_voronoi_in[] = {
{SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
+ {SOCK_FLOAT, 1, N_("W"), 0.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
{SOCK_FLOAT, 1, N_("Scale"), 5.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
+ {SOCK_FLOAT, 1, N_("Smoothness"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{SOCK_FLOAT, 1, N_("Exponent"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 32.0f},
+ {SOCK_FLOAT, 1, N_("Randomness"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{-1, 0, ""},
};
static bNodeSocketTemplate sh_node_tex_voronoi_out[] = {
+ {SOCK_FLOAT,
+ 0,
+ N_("Distance"),
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 1.0f,
+ PROP_NONE,
+ SOCK_NO_INTERNAL_LINK},
{SOCK_RGBA,
0,
N_("Color"),
@@ -40,16 +54,28 @@ static bNodeSocketTemplate sh_node_tex_voronoi_out[] = {
1.0f,
PROP_NONE,
SOCK_NO_INTERNAL_LINK},
+ {SOCK_VECTOR,
+ 0,
+ N_("Position"),
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 1.0f,
+ PROP_NONE,
+ SOCK_NO_INTERNAL_LINK},
+ {SOCK_FLOAT, 0, N_("W"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{SOCK_FLOAT,
0,
- N_("Fac"),
+ N_("Radius"),
0.0f,
0.0f,
0.0f,
0.0f,
0.0f,
1.0f,
- PROP_FACTOR,
+ PROP_NONE,
SOCK_NO_INTERNAL_LINK},
{-1, 0, ""},
};
@@ -59,8 +85,8 @@ static void node_shader_init_tex_voronoi(bNodeTree *UNUSED(ntree), bNode *node)
NodeTexVoronoi *tex = MEM_callocN(sizeof(NodeTexVoronoi), "NodeTexVoronoi");
BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
BKE_texture_colormapping_default(&tex->base.color_mapping);
- tex->coloring = SHD_VORONOI_INTENSITY;
- tex->distance = SHD_VORONOI_DISTANCE;
+ tex->dimensions = 3;
+ tex->distance = SHD_VORONOI_EUCLIDEAN;
tex->feature = SHD_VORONOI_F1;
node->storage = tex;
@@ -72,46 +98,99 @@ static int node_shader_gpu_tex_voronoi(GPUMaterial *mat,
GPUNodeStack *in,
GPUNodeStack *out)
{
- if (!in[0].link) {
- in[0].link = GPU_attribute(CD_ORCO, "");
- GPU_link(mat, "generated_texco", GPU_builtin(GPU_VIEW_POSITION), in[0].link, &in[0].link);
- }
-
+ node_shader_gpu_default_tex_coord(mat, node, &in[0].link);
node_shader_gpu_tex_mapping(mat, node, in, out);
+ static const char *names[][5] = {
+ [SHD_VORONOI_F1] =
+ {
+ "",
+ "node_tex_voronoi_f1_1d",
+ "node_tex_voronoi_f1_2d",
+ "node_tex_voronoi_f1_3d",
+ "node_tex_voronoi_f1_4d",
+ },
+ [SHD_VORONOI_F2] =
+ {
+ "",
+ "node_tex_voronoi_f2_1d",
+ "node_tex_voronoi_f2_2d",
+ "node_tex_voronoi_f2_3d",
+ "node_tex_voronoi_f2_4d",
+ },
+ [SHD_VORONOI_SMOOTH_F1] =
+ {
+ "",
+ "node_tex_voronoi_smooth_f1_1d",
+ "node_tex_voronoi_smooth_f1_2d",
+ "node_tex_voronoi_smooth_f1_3d",
+ "node_tex_voronoi_smooth_f1_4d",
+ },
+ [SHD_VORONOI_DISTANCE_TO_EDGE] =
+ {
+ "",
+ "node_tex_voronoi_distance_to_edge_1d",
+ "node_tex_voronoi_distance_to_edge_2d",
+ "node_tex_voronoi_distance_to_edge_3d",
+ "node_tex_voronoi_distance_to_edge_4d",
+ },
+ [SHD_VORONOI_N_SPHERE_RADIUS] =
+ {
+ "",
+ "node_tex_voronoi_n_sphere_radius_1d",
+ "node_tex_voronoi_n_sphere_radius_2d",
+ "node_tex_voronoi_n_sphere_radius_3d",
+ "node_tex_voronoi_n_sphere_radius_4d",
+ },
+ };
+
NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
- float coloring = tex->coloring;
float metric = tex->distance;
- float feature = tex->feature;
-
- return GPU_stack_link(mat,
- node,
- "node_tex_voronoi",
- in,
- out,
- GPU_constant(&coloring),
- GPU_constant(&metric),
- GPU_constant(&feature));
+
+ BLI_assert(tex->feature >= 0 && tex->feature < 5);
+ BLI_assert(tex->dimensions > 0 && tex->dimensions < 5);
+
+ return GPU_stack_link(
+ mat, node, names[tex->feature][tex->dimensions], in, out, GPU_constant(&metric));
}
static void node_shader_update_tex_voronoi(bNodeTree *UNUSED(ntree), bNode *node)
{
+ bNodeSocket *inVectorSock = nodeFindSocket(node, SOCK_IN, "Vector");
+ bNodeSocket *inWSock = nodeFindSocket(node, SOCK_IN, "W");
+ bNodeSocket *inSmoothnessSock = nodeFindSocket(node, SOCK_IN, "Smoothness");
+ bNodeSocket *inExponentSock = nodeFindSocket(node, SOCK_IN, "Exponent");
+
+ bNodeSocket *outDistanceSock = nodeFindSocket(node, SOCK_OUT, "Distance");
+ bNodeSocket *outColorSock = nodeFindSocket(node, SOCK_OUT, "Color");
+ bNodeSocket *outPositionSock = nodeFindSocket(node, SOCK_OUT, "Position");
+ bNodeSocket *outWSock = nodeFindSocket(node, SOCK_OUT, "W");
+ bNodeSocket *outRadiusSock = nodeFindSocket(node, SOCK_OUT, "Radius");
+
NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
- bNodeSocket *sock;
-
- for (sock = node->inputs.first; sock; sock = sock->next) {
- if (STREQ(sock->name, "Exponent")) {
- if (tex->distance == SHD_VORONOI_MINKOWSKI) {
- sock->flag &= ~SOCK_UNAVAIL;
- }
- else {
- sock->flag |= SOCK_UNAVAIL;
- }
- }
- }
+
+ nodeSetSocketAvailability(inWSock, tex->dimensions == 1 || tex->dimensions == 4);
+ nodeSetSocketAvailability(inVectorSock, tex->dimensions != 1);
+ nodeSetSocketAvailability(
+ inExponentSock,
+ tex->distance == SHD_VORONOI_MINKOWSKI && tex->dimensions != 1 &&
+ !ELEM(tex->feature, SHD_VORONOI_DISTANCE_TO_EDGE, SHD_VORONOI_N_SPHERE_RADIUS));
+ nodeSetSocketAvailability(inSmoothnessSock, tex->feature == SHD_VORONOI_SMOOTH_F1);
+ nodeSetSocketAvailability(outDistanceSock, tex->feature != SHD_VORONOI_N_SPHERE_RADIUS);
+ nodeSetSocketAvailability(outColorSock,
+ tex->feature != SHD_VORONOI_DISTANCE_TO_EDGE &&
+ tex->feature != SHD_VORONOI_N_SPHERE_RADIUS);
+ nodeSetSocketAvailability(outPositionSock,
+ tex->feature != SHD_VORONOI_DISTANCE_TO_EDGE &&
+ tex->feature != SHD_VORONOI_N_SPHERE_RADIUS &&
+ tex->dimensions != 1);
+ nodeSetSocketAvailability(outWSock,
+ tex->feature != SHD_VORONOI_DISTANCE_TO_EDGE &&
+ tex->feature != SHD_VORONOI_N_SPHERE_RADIUS &&
+ (tex->dimensions == 1 || tex->dimensions == 4));
+ nodeSetSocketAvailability(outRadiusSock, tex->feature == SHD_VORONOI_N_SPHERE_RADIUS);
}
-/* node type definition */
void register_node_type_sh_tex_voronoi(void)
{
static bNodeType ntype;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_wave.c b/source/blender/nodes/shader/nodes/node_shader_tex_wave.c
index 65b78f2923d..b525f4897a9 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_wave.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_wave.c
@@ -72,11 +72,7 @@ static int node_shader_gpu_tex_wave(GPUMaterial *mat,
GPUNodeStack *in,
GPUNodeStack *out)
{
- if (!in[0].link) {
- in[0].link = GPU_attribute(CD_ORCO, "");
- GPU_link(mat, "generated_texco", GPU_builtin(GPU_VIEW_POSITION), in[0].link, &in[0].link);
- }
-
+ node_shader_gpu_default_tex_coord(mat, node, &in[0].link);
node_shader_gpu_tex_mapping(mat, node, in, out);
NodeTexWave *tex = (NodeTexWave *)node->storage;
diff --git a/source/blender/nodes/shader/nodes/node_shader_uvmap.c b/source/blender/nodes/shader/nodes/node_shader_uvmap.c
index 73fb022e476..a2e47735490 100644
--- a/source/blender/nodes/shader/nodes/node_shader_uvmap.c
+++ b/source/blender/nodes/shader/nodes/node_shader_uvmap.c
@@ -43,7 +43,11 @@ static int node_shader_gpu_uvmap(GPUMaterial *mat,
NodeShaderUVMap *attr = node->storage;
GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, attr->uv_map);
- return GPU_stack_link(mat, node, "node_uvmap", in, out, mtface);
+ GPU_stack_link(mat, node, "node_uvmap", in, out, mtface);
+
+ node_shader_gpu_bump_tex_coord(mat, node, &out[0].link);
+
+ return 1;
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_vectTransform.c b/source/blender/nodes/shader/nodes/node_shader_vectTransform.c
index fe0e7b1d638..563ef89162b 100644
--- a/source/blender/nodes/shader/nodes/node_shader_vectTransform.c
+++ b/source/blender/nodes/shader/nodes/node_shader_vectTransform.c
@@ -132,7 +132,7 @@ static int gpu_shader_vect_transform(GPUMaterial *mat,
}
if (nodeprop->type == SHD_VECT_TRANSFORM_TYPE_NORMAL) {
- GPU_link(mat, "vect_normalize", out[0].link, &out[0].link);
+ GPU_link(mat, "vector_normalize", out[0].link, &out[0].link);
}
return true;
diff --git a/source/blender/nodes/shader/nodes/node_shader_vertex_color.c b/source/blender/nodes/shader/nodes/node_shader_vertex_color.c
new file mode 100644
index 00000000000..8848fc37c66
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_vertex_color.c
@@ -0,0 +1,58 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ */
+
+#include "../node_shader_util.h"
+
+static bNodeSocketTemplate sh_node_vertex_color_out[] = {
+ {SOCK_RGBA, 0, N_("Color")},
+ {SOCK_FLOAT, 0, N_("Alpha")},
+ {-1, 0, ""},
+};
+
+static void node_shader_init_vertex_color(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ NodeShaderVertexColor *vertexColor = MEM_callocN(sizeof(NodeShaderVertexColor),
+ "NodeShaderVertexColor");
+ node->storage = vertexColor;
+}
+
+static int node_shader_gpu_vertex_color(GPUMaterial *mat,
+ bNode *node,
+ bNodeExecData *UNUSED(execdata),
+ GPUNodeStack *in,
+ GPUNodeStack *out)
+{
+ NodeShaderVertexColor *vertexColor = (NodeShaderVertexColor *)node->storage;
+ GPUNodeLink *vertexColorLink = GPU_attribute(CD_MCOL, vertexColor->layer_name);
+ return GPU_stack_link(mat, node, "node_vertex_color", in, out, vertexColorLink);
+}
+
+void register_node_type_sh_vertex_color(void)
+{
+ static bNodeType ntype;
+
+ sh_node_type_base(&ntype, SH_NODE_VERTEX_COLOR, "Vertex Color", NODE_CLASS_INPUT, 0);
+ node_type_socket_templates(&ntype, NULL, sh_node_vertex_color_out);
+ node_type_init(&ntype, node_shader_init_vertex_color);
+ node_type_storage(
+ &ntype, "NodeShaderVertexColor", node_free_standard_storage, node_copy_standard_storage);
+ node_type_gpu(&ntype, node_shader_gpu_vertex_color);
+
+ nodeRegisterType(&ntype);
+}