diff options
Diffstat (limited to 'source/blender/nodes/shader')
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); +} |