diff options
Diffstat (limited to 'source/blender/nodes/shader')
46 files changed, 653 insertions, 612 deletions
diff --git a/source/blender/nodes/shader/node_shader_tree.cc b/source/blender/nodes/shader/node_shader_tree.cc index 03baebfd28b..d917106807c 100644 --- a/source/blender/nodes/shader/node_shader_tree.cc +++ b/source/blender/nodes/shader/node_shader_tree.cc @@ -16,11 +16,12 @@ #include "DNA_workspace_types.h" #include "DNA_world_types.h" -#include "BLI_alloca.h" +#include "BLI_array.hh" #include "BLI_linklist.h" #include "BLI_listbase.h" #include "BLI_threads.h" #include "BLI_utildefines.h" +#include "BLI_vector.hh" #include "BLT_translation.h" @@ -47,11 +48,8 @@ #include "node_shader_util.hh" #include "node_util.h" -struct nTreeTags { - float ssr_id, sss_id; -}; - -static void ntree_shader_tag_nodes(bNodeTree *ntree, bNode *output_node, nTreeTags *tags); +using blender::Array; +using blender::Vector; static bool shader_tree_poll(const bContext *C, bNodeTreeType *UNUSED(treetype)) { @@ -250,6 +248,18 @@ static bNodeSocket *ntree_shader_node_find_output(bNode *node, const char *ident return ntree_shader_node_find_socket(&node->outputs, identifier); } +/* Find input socket at a specific position. */ +static bNodeSocket *ntree_shader_node_input_get(bNode *node, int n) +{ + return reinterpret_cast<bNodeSocket *>(BLI_findlink(&node->inputs, n)); +} + +/* Find output socket at a specific position. */ +static bNodeSocket *ntree_shader_node_output_get(bNode *node, int n) +{ + return reinterpret_cast<bNodeSocket *>(BLI_findlink(&node->outputs, n)); +} + /* Return true on success. */ static bool ntree_shader_expand_socket_default(bNodeTree *localtree, bNode *node, @@ -522,125 +532,21 @@ static void ntree_shader_groups_flatten(bNodeTree *localtree) BKE_ntree_update_main_tree(G.main, localtree, nullptr); } -/* Check whether shader has a displacement. - * - * Will also return a node and its socket which is connected to a displacement - * output. Additionally, link which is attached to the displacement output is - * also returned. - */ -static bool ntree_shader_has_displacement(bNodeTree *ntree, - bNode *output_node, - bNode **r_node, - bNodeSocket **r_socket, - bNodeLink **r_link) -{ - if (output_node == nullptr) { - /* We can't have displacement without output node, apparently. */ - return false; - } - /* Make sure sockets links pointers are correct. */ - BKE_ntree_update_main_tree(G.main, ntree, nullptr); - bNodeSocket *displacement = ntree_shader_node_find_input(output_node, "Displacement"); - - if (displacement == nullptr) { - /* Non-cycles node is used as an output. */ - return false; - } - - if ((displacement->link != nullptr) && !(displacement->link->flag & NODE_LINK_MUTED)) { - *r_node = displacement->link->fromnode; - *r_socket = displacement->link->fromsock; - *r_link = displacement->link; - return true; - } - return false; -} - -static void ntree_shader_relink_node_normal(bNodeTree *ntree, - bNode *node, - bNode *node_from, - bNodeSocket *socket_from) -{ - /* TODO(sergey): Can we do something smarter here than just a name-based - * matching? - */ - LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { - if (STREQ(sock->identifier, "Normal") && sock->link == nullptr) { - /* It's a normal input and nothing is connected to it. */ - nodeAddLink(ntree, node_from, socket_from, node, sock); - } - else if (sock->link) { - bNodeLink *link = sock->link; - if (ELEM(link->fromnode->type, SH_NODE_NEW_GEOMETRY, SH_NODE_TEX_COORD) && - STREQ(link->fromsock->identifier, "Normal")) { - /* Linked to a geometry node normal output. */ - nodeAddLink(ntree, node_from, socket_from, node, sock); - } - } - } -} - -/* 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) -{ - LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - if (node == node_from) { - /* Don't connect node itself! */ - continue; - } - if (node->tmp_flag == -2) { - /* This node is used inside the displacement tree. Skip to avoid cycles. */ - continue; - } - ntree_shader_relink_node_normal(ntree, node, node_from, socket_from); - } -} - -static void ntree_shader_bypass_bump_link(bNodeTree *ntree, bNode *bump_node, bNodeLink *bump_link) -{ - /* Bypass bump nodes. This replicates cycles "implicit" behavior. */ - bNodeSocket *bump_normal_input = ntree_shader_node_find_input(bump_node, "Normal"); - bNode *fromnode; - bNodeSocket *fromsock; - /* Default to builtin normals if there is no link. */ - if (bump_normal_input->link) { - fromsock = bump_normal_input->link->fromsock; - fromnode = bump_normal_input->link->fromnode; - } - else { - fromnode = nodeAddStaticNode(nullptr, ntree, SH_NODE_NEW_GEOMETRY); - fromsock = ntree_shader_node_find_output(fromnode, "Normal"); - } - /* Bypass the bump node by creating a link between the previous and next node. */ - nodeAddLink(ntree, fromnode, fromsock, bump_link->tonode, bump_link->tosock); - nodeRemLink(ntree, bump_link); -} - -static void ntree_shader_bypass_tagged_bump_nodes(bNodeTree *ntree) -{ - /* Bypass bump links inside copied nodes */ - 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); - } - } - BKE_ntree_update_main_tree(G.main, ntree, nullptr); -} +struct branchIterData { + bool (*node_filter)(const bNode *node); + int node_count; +}; static bool ntree_branch_count_and_tag_nodes(bNode *fromnode, bNode *tonode, void *userdata) { - int *node_count = (int *)userdata; - if (fromnode->tmp_flag == -1) { - fromnode->tmp_flag = *node_count; - (*node_count)++; + branchIterData *iter = (branchIterData *)userdata; + if (fromnode->tmp_flag == -1 && (iter->node_filter == nullptr || iter->node_filter(fromnode))) { + fromnode->tmp_flag = iter->node_count; + iter->node_count++; } - if (tonode->tmp_flag == -1) { - tonode->tmp_flag = *node_count; - (*node_count)++; + if (tonode->tmp_flag == -1 && (iter->node_filter == nullptr || iter->node_filter(tonode))) { + tonode->tmp_flag = iter->node_count; + iter->node_count++; } return true; } @@ -650,6 +556,7 @@ static bool ntree_branch_count_and_tag_nodes(bNode *fromnode, bNode *tonode, voi * Returns input node copy. */ static bNode *ntree_shader_copy_branch(bNodeTree *ntree, bNode *start_node, + bool (*node_filter)(const bNode *node), void (*callback)(bNode *node, int user_data), int user_data) { @@ -659,10 +566,12 @@ static bNode *ntree_shader_copy_branch(bNodeTree *ntree, } /* Count and tag all nodes inside the displacement branch of the tree. */ start_node->tmp_flag = 0; - int node_count = 1; - nodeChainIterBackwards(ntree, start_node, ntree_branch_count_and_tag_nodes, &node_count, 1); + branchIterData iter_data; + iter_data.node_filter = node_filter; + iter_data.node_count = 1; + nodeChainIterBackwards(ntree, start_node, ntree_branch_count_and_tag_nodes, &iter_data, 1); /* Make a full copy of the branch */ - bNode **nodes_copy = static_cast<bNode **>(MEM_mallocN(sizeof(bNode *) * node_count, __func__)); + Array<bNode *> nodes_copy(iter_data.node_count); LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->tmp_flag >= 0) { int id = node->tmp_flag; @@ -690,225 +599,447 @@ static bNode *ntree_shader_copy_branch(bNodeTree *ntree, } /* Per node callback. */ if (callback) { - for (int i = 0; i < node_count; i++) { + for (int i = 0; i < iter_data.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) +/* Generate emission node to convert regular data to closure sockets. + * Returns validity of the tree. + */ +static bool ntree_shader_implicit_closure_cast(bNodeTree *ntree) { - /* Replace displacement socket/node/link. */ - bNode *tonode = displacement_link->tonode; - bNodeSocket *tosock = displacement_link->tosock; - displacement_node = ntree_shader_copy_branch(ntree, displacement_node, nullptr, 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); - - BKE_ntree_update_main_tree(G.main, ntree, nullptr); + bool modified = false; + LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) { + if ((link->fromsock->type != SOCK_SHADER) && (link->tosock->type == SOCK_SHADER)) { + bNode *emission_node = nodeAddStaticNode(NULL, ntree, SH_NODE_EMISSION); + bNodeSocket *in_sock = ntree_shader_node_find_input(emission_node, "Color"); + bNodeSocket *out_sock = ntree_shader_node_find_output(emission_node, "Emission"); + nodeAddLink(ntree, link->fromnode, link->fromsock, emission_node, in_sock); + nodeAddLink(ntree, emission_node, out_sock, link->tonode, link->tosock); + nodeRemLink(ntree, link); + modified = true; + } + else if ((link->fromsock->type == SOCK_SHADER) && (link->tosock->type != SOCK_SHADER)) { + /* Meh. Not directly visible to the user. But better than nothing. */ + fprintf(stderr, "Shader Nodetree Error: Invalid implicit socket conversion\n"); + BKE_ntree_update_main_tree(G.main, ntree, nullptr); + return false; + } + } + if (modified) { + BKE_ntree_update_main_tree(G.main, ntree, nullptr); + } + return true; } -/* Re-link displacement output to unconnected normal sockets via bump node. - * This way material with have proper displacement in the viewport. - */ -static void ntree_shader_relink_displacement(bNodeTree *ntree, bNode *output_node) -{ - bNode *displacement_node; - bNodeSocket *displacement_socket; - bNodeLink *displacement_link; - if (!ntree_shader_has_displacement( - ntree, output_node, &displacement_node, &displacement_socket, &displacement_link)) { - /* There is no displacement output connected, nothing to re-link. */ - return; - } - - /* Copy the whole displacement branch to avoid cyclic dependency - * and issue when bypassing bump nodes. */ - ntree_shader_copy_branch_displacement( - ntree, displacement_node, displacement_socket, displacement_link); - /* Bypass bump nodes inside the copied branch to mimic cycles behavior. */ - ntree_shader_bypass_tagged_bump_nodes(ntree); - - /* Displacement Node may have changed because of branch copy and bump bypass. */ - ntree_shader_has_displacement( - ntree, output_node, &displacement_node, &displacement_socket, &displacement_link); - - /* We have to disconnect displacement output socket, otherwise we'll have - * cycles in the Cycles material :) - */ - nodeRemLink(ntree, displacement_link); - - /* Convert displacement vector to bump height. */ - bNode *dot_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_VECTOR_MATH); - bNode *geo_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_NEW_GEOMETRY); - bNodeSocket *normal_socket = ntree_shader_node_find_output(geo_node, "Normal"); - bNodeSocket *dot_input1 = static_cast<bNodeSocket *>(dot_node->inputs.first); - bNodeSocket *dot_input2 = static_cast<bNodeSocket *>(dot_input1->next); - dot_node->custom1 = NODE_VECTOR_MATH_DOT_PRODUCT; - - 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"); - - /* We can't connect displacement to normal directly, use bump node for that - * and hope that it gives good enough approximation. - */ - bNode *bump_node = nodeAddStaticNode(nullptr, ntree, SH_NODE_BUMP); - bNodeSocket *bump_input_socket = ntree_shader_node_find_input(bump_node, "Height"); - bNodeSocket *bump_output_socket = ntree_shader_node_find_output(bump_node, "Normal"); - BLI_assert(bump_input_socket != nullptr); - BLI_assert(bump_output_socket != nullptr); - /* Connect bump node to where displacement output was originally - * connected to. - */ - nodeAddLink(ntree, displacement_node, displacement_socket, bump_node, bump_input_socket); - - /* Tag as part of the new displacement tree. */ - dot_node->tmp_flag = -2; - geo_node->tmp_flag = -2; - bump_node->tmp_flag = -2; - - BKE_ntree_update_main_tree(G.main, ntree, nullptr); - - /* Connect all free-standing Normal inputs and relink geometry/coordinate nodes. */ - ntree_shader_link_builtin_normal(ntree, bump_node, bump_output_socket); - /* We modified the tree, it needs to be updated now. */ - BKE_ntree_update_main_tree(G.main, ntree, nullptr); +/* Socket already has a link to it. Add weights together. */ +static void ntree_weight_tree_merge_weight(bNodeTree *ntree, + bNode *UNUSED(fromnode), + bNodeSocket *fromsock, + bNode **tonode, + bNodeSocket **tosock) +{ + bNode *addnode = nodeAddStaticNode(NULL, ntree, SH_NODE_MATH); + addnode->custom1 = NODE_MATH_ADD; + addnode->tmp_flag = -2; /* Copy */ + bNodeSocket *addsock_out = ntree_shader_node_output_get(addnode, 0); + bNodeSocket *addsock_in0 = ntree_shader_node_input_get(addnode, 0); + bNodeSocket *addsock_in1 = ntree_shader_node_input_get(addnode, 1); + bNodeLink *oldlink = fromsock->link; + nodeAddLink(ntree, oldlink->fromnode, oldlink->fromsock, addnode, addsock_in0); + nodeAddLink(ntree, *tonode, *tosock, addnode, addsock_in1); + nodeRemLink(ntree, oldlink); + *tonode = addnode; + *tosock = addsock_out; } -static void node_tag_branch_as_derivative(bNode *node, int dx) +static bool ntree_weight_tree_tag_nodes(bNode *fromnode, bNode *tonode, void *userdata) { - if (dx) { - node->branch_tag = 1; + int *node_count = (int *)userdata; + bool to_node_from_weight_tree = ELEM(tonode->type, + SH_NODE_ADD_SHADER, + SH_NODE_MIX_SHADER, + SH_NODE_OUTPUT_WORLD, + SH_NODE_OUTPUT_MATERIAL, + SH_NODE_SHADERTORGB); + if (tonode->tmp_flag == -1 && to_node_from_weight_tree) { + tonode->tmp_flag = *node_count; + *node_count += (tonode->type == SH_NODE_MIX_SHADER) ? 4 : 1; } - else { - node->branch_tag = 2; + if (fromnode->tmp_flag == -1 && ELEM(fromnode->type, SH_NODE_ADD_SHADER, SH_NODE_MIX_SHADER)) { + fromnode->tmp_flag = *node_count; + *node_count += (fromnode->type == SH_NODE_MIX_SHADER) ? 4 : 1; } + return to_node_from_weight_tree; } -static bool ntree_shader_bump_branches(bNode *fromnode, bNode *UNUSED(tonode), void *userdata) +/* Invert evaluation order of the weight tree (add & mix closure nodes) to feed the closure nodes + * with their respective weights. */ +static void ntree_shader_weight_tree_invert(bNodeTree *ntree, bNode *output_node) { - bNodeTree *ntree = (bNodeTree *)userdata; + bNodeLink *displace_link = NULL; + bNodeSocket *displace_output = ntree_shader_node_find_input(output_node, "Displacement"); + if (displace_output && displace_output->link) { + /* Remove any displacement link to avoid tagging it later on. */ + displace_link = displace_output->link; + displace_output->link = NULL; + } + bNodeLink *thickness_link = NULL; + bNodeSocket *thickness_output = ntree_shader_node_find_input(output_node, "Thickness"); + if (thickness_output && thickness_output->link) { + /* Remove any thickness link to avoid tagging it later on. */ + thickness_link = thickness_output->link; + thickness_output->link = NULL; + } + /* Init tmp flag. */ + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + node->tmp_flag = -1; + } + /* Tag nodes from the weight tree. Only tag output node and mix/add shader nodes. */ + output_node->tmp_flag = 0; + int node_count = 1; + nodeChainIterBackwards(ntree, output_node, ntree_weight_tree_tag_nodes, &node_count, 0); + /* Make a mirror copy of the weight tree. */ + Array<bNode *> nodes_copy(node_count); + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (node->tmp_flag >= 0) { + int id = node->tmp_flag; - if (fromnode->type == SH_NODE_BUMP) { - bNodeSocket *height_dx_sock, *height_dy_sock, *bump_socket, *bump_dx_socket, *bump_dy_socket; - bNode *bump = fromnode; - 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. */ + switch (node->type) { + case SH_NODE_SHADERTORGB: + case SH_NODE_OUTPUT_WORLD: + case SH_NODE_OUTPUT_MATERIAL: { + /* Start the tree with full weight. */ + nodes_copy[id] = nodeAddStaticNode(NULL, ntree, SH_NODE_VALUE); + nodes_copy[id]->tmp_flag = -2; /* Copy */ + ((bNodeSocketValueFloat *)ntree_shader_node_output_get(nodes_copy[id], 0)->default_value) + ->value = 1.0f; + break; + } + case SH_NODE_ADD_SHADER: { + /* Simple passthrough node. Each original inputs will get the same weight. */ + /* TODO(fclem) Better use some kind of reroute node? */ + nodes_copy[id] = nodeAddStaticNode(NULL, ntree, SH_NODE_MATH); + nodes_copy[id]->custom1 = NODE_MATH_ADD; + nodes_copy[id]->tmp_flag = -2; /* Copy */ + ((bNodeSocketValueFloat *)ntree_shader_node_input_get(nodes_copy[id], 0)->default_value) + ->value = 0.0f; + break; + } + case SH_NODE_MIX_SHADER: { + /* We need multiple nodes to emulate the mix node in reverse. */ + bNode *fromnode, *tonode; + bNodeSocket *fromsock, *tosock; + int id_start = id; + /* output = (factor * input_weight) */ + nodes_copy[id] = nodeAddStaticNode(NULL, ntree, SH_NODE_MATH); + nodes_copy[id]->custom1 = NODE_MATH_MULTIPLY; + nodes_copy[id]->tmp_flag = -2; /* Copy */ + id++; + /* output = ((1.0 - factor) * input_weight) <=> (input_weight - factor * input_weight) */ + nodes_copy[id] = nodeAddStaticNode(NULL, ntree, SH_NODE_MATH); + nodes_copy[id]->custom1 = NODE_MATH_SUBTRACT; + nodes_copy[id]->tmp_flag = -2; /* Copy */ + id++; + /* Node sanitizes the input mix factor by clamping it. */ + nodes_copy[id] = nodeAddStaticNode(NULL, ntree, SH_NODE_MATH); + nodes_copy[id]->custom1 = NODE_MATH_ADD; + nodes_copy[id]->custom2 = SHD_MATH_CLAMP; + nodes_copy[id]->tmp_flag = -2; /* Copy */ + ((bNodeSocketValueFloat *)ntree_shader_node_input_get(nodes_copy[id], 0)->default_value) + ->value = 0.0f; + /* Copy default value if no link present. */ + bNodeSocket *fac_sock = ntree_shader_node_find_input(node, "Fac"); + if (!fac_sock->link) { + float default_value = ((bNodeSocketValueFloat *)fac_sock->default_value)->value; + bNodeSocket *dst_sock = ntree_shader_node_input_get(nodes_copy[id], 1); + ((bNodeSocketValueFloat *)dst_sock->default_value)->value = default_value; + } + id++; + /* Reroute the weight input to the 3 processing nodes. Simplify linking later-on. */ + /* TODO(fclem) Better use some kind of reroute node? */ + nodes_copy[id] = nodeAddStaticNode(NULL, ntree, SH_NODE_MATH); + nodes_copy[id]->custom1 = NODE_MATH_ADD; + nodes_copy[id]->tmp_flag = -2; /* Copy */ + ((bNodeSocketValueFloat *)ntree_shader_node_input_get(nodes_copy[id], 0)->default_value) + ->value = 0.0f; + id++; + /* Link between nodes for the substraction. */ + fromnode = nodes_copy[id_start]; + tonode = nodes_copy[id_start + 1]; + fromsock = ntree_shader_node_output_get(fromnode, 0); + tosock = ntree_shader_node_input_get(tonode, 1); + nodeAddLink(ntree, fromnode, fromsock, tonode, tosock); + /* Link mix input to first node. */ + fromnode = nodes_copy[id_start + 2]; + tonode = nodes_copy[id_start]; + fromsock = ntree_shader_node_output_get(fromnode, 0); + tosock = ntree_shader_node_input_get(tonode, 1); + nodeAddLink(ntree, fromnode, fromsock, tonode, tosock); + /* Link weight input to both multiply nodes. */ + fromnode = nodes_copy[id_start + 3]; + fromsock = ntree_shader_node_output_get(fromnode, 0); + tonode = nodes_copy[id_start]; + tosock = ntree_shader_node_input_get(tonode, 0); + nodeAddLink(ntree, fromnode, fromsock, tonode, tosock); + tonode = nodes_copy[id_start + 1]; + tosock = ntree_shader_node_input_get(tonode, 0); + nodeAddLink(ntree, fromnode, fromsock, tonode, tosock); + break; + } + default: + BLI_assert(0); + break; + } } - 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. */ + } + /* Recreate links between copied nodes. */ + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (node->tmp_flag >= 0) { + /* Naming can be confusing here. We use original nodelink name for from/to prefix. + * The final link is in reversed order. */ + int socket_index; + LISTBASE_FOREACH_INDEX (bNodeSocket *, sock, &node->inputs, socket_index) { + bNodeSocket *tosock; + bNode *tonode; + + switch (node->type) { + case SH_NODE_SHADERTORGB: + case SH_NODE_OUTPUT_WORLD: + case SH_NODE_OUTPUT_MATERIAL: + case SH_NODE_ADD_SHADER: { + tonode = nodes_copy[node->tmp_flag]; + tosock = ntree_shader_node_output_get(tonode, 0); + break; + } + case SH_NODE_MIX_SHADER: { + if (socket_index == 0) { + /* Mix Factor. */ + tonode = nodes_copy[node->tmp_flag + 2]; + tosock = ntree_shader_node_input_get(tonode, 1); + } + else if (socket_index == 1) { + /* Shader 1. */ + tonode = nodes_copy[node->tmp_flag + 1]; + tosock = ntree_shader_node_output_get(tonode, 0); + } + else { + /* Shader 2. */ + tonode = nodes_copy[node->tmp_flag]; + tosock = ntree_shader_node_output_get(tonode, 0); + } + break; + } + default: + BLI_assert(0); + break; + } + + if (sock->link) { + bNodeSocket *fromsock; + bNode *fromnode = sock->link->fromnode; + + switch (fromnode->type) { + case SH_NODE_ADD_SHADER: { + fromnode = nodes_copy[fromnode->tmp_flag]; + fromsock = ntree_shader_node_input_get(fromnode, 1); + if (fromsock->link) { + ntree_weight_tree_merge_weight(ntree, fromnode, fromsock, &tonode, &tosock); + } + break; + } + case SH_NODE_MIX_SHADER: { + fromnode = nodes_copy[fromnode->tmp_flag + 3]; + fromsock = ntree_shader_node_input_get(fromnode, 1); + if (fromsock->link) { + ntree_weight_tree_merge_weight(ntree, fromnode, fromsock, &tonode, &tosock); + } + break; + } + case SH_NODE_BACKGROUND: + case SH_NODE_BSDF_ANISOTROPIC: + case SH_NODE_BSDF_DIFFUSE: + case SH_NODE_BSDF_GLASS: + case SH_NODE_BSDF_GLOSSY: + case SH_NODE_BSDF_HAIR_PRINCIPLED: + case SH_NODE_BSDF_HAIR: + case SH_NODE_BSDF_PRINCIPLED: + case SH_NODE_BSDF_REFRACTION: + case SH_NODE_BSDF_TOON: + case SH_NODE_BSDF_TRANSLUCENT: + case SH_NODE_BSDF_TRANSPARENT: + case SH_NODE_BSDF_VELVET: + case SH_NODE_EEVEE_SPECULAR: + case SH_NODE_EMISSION: + case SH_NODE_HOLDOUT: + case SH_NODE_SUBSURFACE_SCATTERING: + case SH_NODE_VOLUME_ABSORPTION: + case SH_NODE_VOLUME_PRINCIPLED: + case SH_NODE_VOLUME_SCATTER: + fromsock = ntree_shader_node_find_input(fromnode, "Weight"); + if (fromsock->link) { + ntree_weight_tree_merge_weight(ntree, fromnode, fromsock, &tonode, &tosock); + } + break; + default: + fromsock = sock->link->fromsock; + break; + } + + /* Manually add the link to the socket to avoid calling + * BKE_ntree_update_main_tree(G.main, oop, nullptr. */ + fromsock->link = nodeAddLink(ntree, fromnode, fromsock, tonode, tosock); + BLI_assert(fromsock->link); + } + } } } - return true; + /* Restore displacement & thickness link. */ + if (displace_link) { + nodeAddLink( + ntree, displace_link->fromnode, displace_link->fromsock, output_node, displace_output); + } + if (thickness_link) { + nodeAddLink( + ntree, thickness_link->fromnode, thickness_link->fromsock, output_node, thickness_output); + } + BKE_ntree_update_main_tree(G.main, ntree, nullptr); } -static bool ntree_tag_bsdf_cb(bNode *fromnode, bNode *UNUSED(tonode), void *userdata) +static bool closure_node_filter(const bNode *node) { - switch (fromnode->type) { + switch (node->type) { + case SH_NODE_ADD_SHADER: + case SH_NODE_MIX_SHADER: + case SH_NODE_BACKGROUND: case SH_NODE_BSDF_ANISOTROPIC: - case SH_NODE_EEVEE_SPECULAR: - case SH_NODE_BSDF_GLOSSY: + case SH_NODE_BSDF_DIFFUSE: case SH_NODE_BSDF_GLASS: - fromnode->ssr_id = ((nTreeTags *)userdata)->ssr_id; - ((nTreeTags *)userdata)->ssr_id += 1; - break; - case SH_NODE_SUBSURFACE_SCATTERING: - fromnode->sss_id = ((nTreeTags *)userdata)->sss_id; - ((nTreeTags *)userdata)->sss_id += 1; - break; + case SH_NODE_BSDF_GLOSSY: + case SH_NODE_BSDF_HAIR_PRINCIPLED: + case SH_NODE_BSDF_HAIR: case SH_NODE_BSDF_PRINCIPLED: - fromnode->ssr_id = ((nTreeTags *)userdata)->ssr_id; - fromnode->sss_id = ((nTreeTags *)userdata)->sss_id; - ((nTreeTags *)userdata)->sss_id += 1; - ((nTreeTags *)userdata)->ssr_id += 1; - break; + case SH_NODE_BSDF_REFRACTION: + case SH_NODE_BSDF_TOON: + case SH_NODE_BSDF_TRANSLUCENT: + case SH_NODE_BSDF_TRANSPARENT: + case SH_NODE_BSDF_VELVET: + case SH_NODE_EEVEE_SPECULAR: + case SH_NODE_EMISSION: + case SH_NODE_HOLDOUT: + case SH_NODE_SUBSURFACE_SCATTERING: + case SH_NODE_VOLUME_ABSORPTION: + case SH_NODE_VOLUME_PRINCIPLED: + case SH_NODE_VOLUME_SCATTER: + return true; default: - /* We could return false here but since we - * allow the use of Closure as RGBA, we can have - * BSDF nodes linked to other BSDF nodes. */ - break; + return false; } +} +static bool shader_to_rgba_node_gather(bNode *UNUSED(fromnode), bNode *tonode, void *userdata) +{ + Vector<bNode *> &shader_to_rgba_nodes = *(Vector<bNode *> *)userdata; + if (tonode->tmp_flag == -1 && tonode->type == SH_NODE_SHADERTORGB) { + tonode->tmp_flag = 0; + shader_to_rgba_nodes.append(tonode); + } return true; } -/* EEVEE: Scan the ntree to set the Screen Space Reflection - * layer id of every specular node AND the Subsurface Scattering id of every SSS node. - */ -void ntree_shader_tag_nodes(bNodeTree *ntree, bNode *output_node, nTreeTags *tags) +/* Shader to rgba needs their associated closure duplicated and the weight tree generated for. */ +static void ntree_shader_shader_to_rgba_branch(bNodeTree *ntree, bNode *output_node) { - if (output_node == nullptr) { - return; + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + node->tmp_flag = -1; } - /* Make sure sockets links pointers are correct. */ - BKE_ntree_update_main_tree(G.main, ntree, nullptr); + /* First gather the shader_to_rgba nodes linked to the ouput. This is separate to avoid + * conflicting usage of the node->tmp_flag. */ + Vector<bNode *> shader_to_rgba_nodes; + nodeChainIterBackwards(ntree, output_node, shader_to_rgba_node_gather, &shader_to_rgba_nodes, 0); + + for (bNode *shader_to_rgba : shader_to_rgba_nodes) { + bNodeSocket *closure_input = ntree_shader_node_input_get(shader_to_rgba, 0); + if (closure_input->link == nullptr) { + continue; + } + bNode *start_node = closure_input->link->fromnode; + bNode *start_node_copy = ntree_shader_copy_branch( + ntree, start_node, closure_node_filter, nullptr, 0); + /* Replace node copy link. This assumes that every node possibly connected to the closure input + * has only one ouput. */ + bNodeSocket *closure_output = ntree_shader_node_output_get(start_node_copy, 0); + nodeRemLink(ntree, closure_input->link); + nodeAddLink(ntree, start_node_copy, closure_output, shader_to_rgba, closure_input); + BKE_ntree_update_main_tree(G.main, ntree, nullptr); + + ntree_shader_weight_tree_invert(ntree, shader_to_rgba); + } +} - nodeChainIterBackwards(ntree, output_node, ntree_tag_bsdf_cb, tags, 0); +static bool ntree_branch_node_tag(bNode *fromnode, bNode *tonode, void *UNUSED(userdata)) +{ + fromnode->tmp_flag = 1; + tonode->tmp_flag = 1; + return true; } -void ntreeGPUMaterialNodes(bNodeTree *localtree, - GPUMaterial *mat, - bool *has_surface_output, - bool *has_volume_output) +/* Avoid adding more node execution when multiple outputs are present. */ +/* NOTE(@fclem): This is also a workaround for the old EEVEE SSS implementation where only the + * first executed SSS node gets a SSS profile. */ +static void ntree_shader_pruned_unused(bNodeTree *ntree, bNode *output_node) { - bNodeTreeExec *exec; + bool changed = false; - bNode *output = ntreeShaderOutputNode(localtree, SHD_OUTPUT_EEVEE); + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + node->tmp_flag = 0; + } - ntree_shader_groups_remove_muted_links(localtree); - ntree_shader_groups_expand_inputs(localtree); + /* Avoid deleting the output node if it is the only node in the tree. */ + output_node->tmp_flag = 1; - ntree_shader_groups_flatten(localtree); + nodeChainIterBackwards(ntree, output_node, ntree_branch_node_tag, nullptr, 0); - if (output == nullptr) { - /* Search again, now including flattened nodes. */ - output = ntreeShaderOutputNode(localtree, SHD_OUTPUT_EEVEE); + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (node->type == SH_NODE_OUTPUT_AOV) { + nodeChainIterBackwards(ntree, node, ntree_branch_node_tag, nullptr, 0); + } } - /* 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, 0); - LISTBASE_FOREACH (bNode *, node, &localtree->nodes) { - if (node->type == SH_NODE_OUTPUT_AOV) { - nodeChainIterBackwards(localtree, node, ntree_shader_bump_branches, localtree, 0); - nTreeTags tags = {}; - tags.ssr_id = 1.0; - tags.sss_id = 1.0; - ntree_shader_tag_nodes(localtree, node, &tags); + LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) { + if (node->tmp_flag == 0) { + ntreeFreeLocalNode(ntree, node); + changed = true; } } - /* TODO(fclem): consider moving this to the gpu shader tree evaluation. */ - nTreeTags tags = {}; - tags.ssr_id = 1.0; - tags.sss_id = 1.0; - ntree_shader_tag_nodes(localtree, output, &tags); + if (changed) { + BKE_ntree_update_main_tree(G.main, ntree, nullptr); + } +} + +void ntreeGPUMaterialNodes(bNodeTree *localtree, GPUMaterial *mat) +{ + bNodeTreeExec *exec; + + ntree_shader_groups_remove_muted_links(localtree); + ntree_shader_groups_expand_inputs(localtree); + ntree_shader_groups_flatten(localtree); + + bNode *output = ntreeShaderOutputNode(localtree, SHD_OUTPUT_EEVEE); + + /* Tree is valid if it contains no undefined implicit socket type cast. */ + bool valid_tree = ntree_shader_implicit_closure_cast(localtree); + + if (valid_tree && output != NULL) { + ntree_shader_pruned_unused(localtree, output); + ntree_shader_shader_to_rgba_branch(localtree, output); + ntree_shader_weight_tree_invert(localtree, output); + } exec = ntreeShaderBeginExecTree(localtree); ntreeExecGPUNodes(exec, mat, output); @@ -918,23 +1049,6 @@ void ntreeGPUMaterialNodes(bNodeTree *localtree, } } ntreeShaderEndExecTree(exec); - - /* EEVEE: Find which material domain was used (volume, surface ...). */ - *has_surface_output = false; - *has_volume_output = false; - - if (output != nullptr) { - bNodeSocket *surface_sock = ntree_shader_node_find_input(output, "Surface"); - bNodeSocket *volume_sock = ntree_shader_node_find_input(output, "Volume"); - - if (surface_sock != nullptr) { - *has_surface_output = (nodeCountSocketLinks(localtree, surface_sock) > 0); - } - - if (volume_sock != nullptr) { - *has_volume_output = (nodeCountSocketLinks(localtree, volume_sock) > 0); - } - } } bNodeTreeExec *ntreeShaderBeginExecTree_internal(bNodeExecContext *context, diff --git a/source/blender/nodes/shader/node_shader_util.cc b/source/blender/nodes/shader/node_shader_util.cc index 728e2760f9a..c47b69e6b69 100644 --- a/source/blender/nodes/shader/node_shader_util.cc +++ b/source/blender/nodes/shader/node_shader_util.cc @@ -284,26 +284,15 @@ void ntreeExecGPUNodes(bNodeTreeExec *exec, GPUMaterial *mat, bNode *output_node } } -void node_shader_gpu_bump_tex_coord(GPUMaterial *mat, bNode *node, GPUNodeLink **link) +void node_shader_gpu_bump_tex_coord(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeLink **link) { - if (node->branch_tag == 1) { - /* Add one time the value for derivative to the input vector. */ - GPU_link(mat, "dfdx_v3", *link, link); - } - else if (node->branch_tag == 2) { - /* Add one time the value for derivative to the input vector. */ - GPU_link(mat, "dfdy_v3", *link, link); - } - else { - /* nothing to do, reference center value. */ - } + GPU_link(mat, "differentiate_texco", *link, link); } void node_shader_gpu_default_tex_coord(GPUMaterial *mat, bNode *node, GPUNodeLink **link) { if (!*link) { *link = GPU_attribute(mat, CD_ORCO, ""); - GPU_link(mat, "generated_texco", GPU_builtin(GPU_VIEW_POSITION), *link, link); node_shader_gpu_bump_tex_coord(mat, node, link); } } diff --git a/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.cc b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.cc index a24b4379e69..1e8df2e985d 100644 --- a/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.cc +++ b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.cc @@ -36,7 +36,7 @@ static int node_shader_gpu_ambient_occlusion(GPUMaterial *mat, GPU_link(mat, "world_normals_get", &in[2].link); } - GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE); + GPU_material_flag_set(mat, GPU_MATFLAG_AO); float inverted = (node->custom2 & SHD_AO_INSIDE) ? 1.0f : 0.0f; float f_samples = divide_ceil_u(node->custom1, 4); diff --git a/source/blender/nodes/shader/nodes/node_shader_background.cc b/source/blender/nodes/shader/nodes/node_shader_background.cc index f5d3b6811f1..ea5c1f541ea 100644 --- a/source/blender/nodes/shader/nodes/node_shader_background.cc +++ b/source/blender/nodes/shader/nodes/node_shader_background.cc @@ -9,6 +9,7 @@ static void node_declare(NodeDeclarationBuilder &b) { b.add_input<decl::Color>(N_("Color")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); b.add_input<decl::Float>(N_("Strength")).default_value(1.0f).min(0.0f).max(1000000.0f); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("Background")); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bevel.cc b/source/blender/nodes/shader/nodes/node_shader_bevel.cc index 8bce38baf73..4ae60af9974 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bevel.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bevel.cc @@ -32,11 +32,7 @@ static int gpu_shader_bevel(GPUMaterial *mat, GPUNodeStack *out) { if (!in[1].link) { - GPU_link(mat, - "direction_transform_m4v3", - GPU_builtin(GPU_VIEW_NORMAL), - GPU_builtin(GPU_INVERSE_VIEW_MATRIX), - &in[1].link); + GPU_link(mat, "world_normals_get", &in[1].link); } return GPU_stack_link(mat, node, "node_bevel", in, out); diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.cc index 13b4a034a51..761a833f377 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.cc @@ -24,6 +24,7 @@ static void node_declare(NodeDeclarationBuilder &b) .subtype(PROP_FACTOR); b.add_input<decl::Vector>(N_("Normal")).hide_value(); b.add_input<decl::Vector>(N_("Tangent")).hide_value(); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("BSDF")); } @@ -51,13 +52,8 @@ static int node_shader_gpu_bsdf_anisotropic(GPUMaterial *mat, float use_multi_scatter = (node->custom1 == SHD_GLOSSY_MULTI_GGX) ? 1.0f : 0.0f; - return GPU_stack_link(mat, - node, - "node_bsdf_anisotropic", - in, - out, - GPU_constant(&use_multi_scatter), - GPU_constant(&node->ssr_id)); + return GPU_stack_link( + mat, node, "node_bsdf_anisotropic", in, out, GPU_constant(&use_multi_scatter)); } } // namespace blender::nodes::node_shader_bsdf_anisotropic_cc diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.cc index 3f025b2ba39..5975e04450e 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.cc @@ -14,6 +14,7 @@ static void node_declare(NodeDeclarationBuilder &b) .max(1.0f) .subtype(PROP_FACTOR); b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("BSDF")); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.cc index a1e5b705438..95869f13b7e 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.cc @@ -15,6 +15,7 @@ static void node_declare(NodeDeclarationBuilder &b) .subtype(PROP_FACTOR); b.add_input<decl::Float>(N_("IOR")).default_value(1.45f).min(0.0f).max(1000.0f); b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("BSDF")); } @@ -37,17 +38,11 @@ static int node_shader_gpu_bsdf_glass(GPUMaterial *mat, GPU_link(mat, "set_value_zero", &in[1].link); } - GPU_material_flag_set(mat, (eGPUMatFlag)(GPU_MATFLAG_GLOSSY | GPU_MATFLAG_REFRACT)); + GPU_material_flag_set(mat, GPU_MATFLAG_GLOSSY | GPU_MATFLAG_REFRACT); float use_multi_scatter = (node->custom1 == SHD_GLOSSY_MULTI_GGX) ? 1.0f : 0.0f; - return GPU_stack_link(mat, - node, - "node_bsdf_glass", - in, - out, - GPU_constant(&use_multi_scatter), - GPU_constant(&node->ssr_id)); + return GPU_stack_link(mat, node, "node_bsdf_glass", in, out, GPU_constant(&use_multi_scatter)); } } // namespace blender::nodes::node_shader_bsdf_glass_cc diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.cc index 9f0e172a5fe..07062a9730e 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.cc @@ -14,6 +14,7 @@ static void node_declare(NodeDeclarationBuilder &b) .max(1.0f) .subtype(PROP_FACTOR); b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("BSDF")); } @@ -40,13 +41,7 @@ static int node_shader_gpu_bsdf_glossy(GPUMaterial *mat, float use_multi_scatter = (node->custom1 == SHD_GLOSSY_MULTI_GGX) ? 1.0f : 0.0f; - return GPU_stack_link(mat, - node, - "node_bsdf_glossy", - in, - out, - GPU_constant(&use_multi_scatter), - GPU_constant(&node->ssr_id)); + return GPU_stack_link(mat, node, "node_bsdf_glossy", in, out, GPU_constant(&use_multi_scatter)); } } // namespace blender::nodes::node_shader_bsdf_glossy_cc diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_hair.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_hair.cc index ef87f380bb9..1a1ba13e886 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_hair.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_hair.cc @@ -27,6 +27,7 @@ static void node_declare(NodeDeclarationBuilder &b) .max(1.0f) .subtype(PROP_FACTOR); b.add_input<decl::Vector>(N_("Tangent")).hide_value(); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("BSDF")); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.cc index edae03bbd31..6495dcfffba 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.cc @@ -60,6 +60,7 @@ static void node_declare(NodeDeclarationBuilder &b) .max(1.0f) .subtype(PROP_FACTOR); b.add_input<decl::Float>(N_("Random")).hide_value(); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("BSDF")); } @@ -108,6 +109,15 @@ static void node_shader_update_hair_principled(bNodeTree *ntree, bNode *node) } } +static int node_shader_gpu_hair_principled(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + return GPU_stack_link(mat, node, "node_bsdf_hair_principled", in, out); +} + } // namespace blender::nodes::node_shader_bsdf_hair_principled_cc /* node type definition */ @@ -124,6 +134,7 @@ void register_node_type_sh_bsdf_hair_principled() node_type_size_preset(&ntype, NODE_SIZE_LARGE); node_type_init(&ntype, file_ns::node_shader_init_hair_principled); node_type_update(&ntype, file_ns::node_shader_update_hair_principled); + node_type_gpu(&ntype, file_ns::node_shader_gpu_hair_principled); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc index ba98a797f2a..a63c7aede04 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc @@ -103,6 +103,7 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_input<decl::Vector>(N_("Normal")).hide_value(); b.add_input<decl::Vector>(N_("Clearcoat Normal")).hide_value(); b.add_input<decl::Vector>(N_("Tangent")).hide_value(); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("BSDF")); } @@ -128,8 +129,6 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { - GPUNodeLink *sss_scale; - /* Normals */ if (!in[22].link) { GPU_link(mat, "world_normals_get", &in[22].link); @@ -145,36 +144,17 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, if (!in[24].link) { GPUNodeLink *orco = GPU_attribute(CD_ORCO, ""); GPU_link(mat, "tangent_orco_z", orco, &in[24].link); - GPU_link(mat, - "node_tangent", - GPU_builtin(GPU_WORLD_NORMAL), - in[24].link, - GPU_builtin(GPU_OBJECT_MATRIX), - &in[24].link); + GPU_link(mat, "node_tangent", in[24].link, &in[24].link); } #endif bool use_diffuse = socket_not_one(6) && socket_not_one(17); - bool use_subsurf = socket_not_zero(1) && use_diffuse && node->sss_id > 0; + bool use_subsurf = socket_not_zero(1) && use_diffuse; bool use_refract = socket_not_one(6) && socket_not_zero(17); + bool use_transparency = socket_not_one(21); bool use_clear = socket_not_zero(14); - /* SSS Profile */ - if (use_subsurf) { - bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&node->original->inputs, 2); - bNodeSocketValueRGBA *socket_data = (bNodeSocketValueRGBA *)socket->default_value; - /* For some reason it seems that the socket value is in ARGB format. */ - GPU_material_sss_profile_create(mat, &socket_data->value[1]); - } - - if (in[2].link) { - sss_scale = in[2].link; - } - else { - GPU_link(mat, "set_rgb_one", &sss_scale); - } - - uint flag = GPU_MATFLAG_GLOSSY; + eGPUMaterialFlag flag = GPU_MATFLAG_GLOSSY; if (use_diffuse) { flag |= GPU_MATFLAG_DIFFUSE; } @@ -182,28 +162,37 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, flag |= GPU_MATFLAG_REFRACT; } if (use_subsurf) { - flag |= GPU_MATFLAG_SSS; + flag |= GPU_MATFLAG_SUBSURFACE; + } + if (use_transparency) { + flag |= GPU_MATFLAG_TRANSPARENT; + } + + if (use_subsurf) { + bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&node->original->inputs, 2); + bNodeSocketValueRGBA *socket_data = (bNodeSocketValueRGBA *)socket->default_value; + /* For some reason it seems that the socket value is in ARGB format. */ + use_subsurf = GPU_material_sss_profile_create(mat, &socket_data->value[1]); } - float f_use_diffuse = use_diffuse ? 1.0f : 0.0f; - float f_use_clearcoat = use_clear ? 1.0f : 0.0f; - float f_use_refraction = use_refract ? 1.0f : 0.0f; float use_multi_scatter = (node->custom1 == SHD_GLOSSY_MULTI_GGX) ? 1.0f : 0.0f; + float use_sss = (use_subsurf) ? 1.0f : 0.0f; + float use_diffuse_f = (use_diffuse) ? 1.0f : 0.0f; + float use_clear_f = (use_clear) ? 1.0f : 0.0f; + float use_refract_f = (use_refract) ? 1.0f : 0.0f; - GPU_material_flag_set(mat, (eGPUMatFlag)flag); + GPU_material_flag_set(mat, flag); return GPU_stack_link(mat, node, "node_bsdf_principled", in, out, - GPU_constant(&f_use_diffuse), - GPU_constant(&f_use_clearcoat), - GPU_constant(&f_use_refraction), + GPU_constant(&use_diffuse_f), + GPU_constant(&use_clear_f), + GPU_constant(&use_refract_f), GPU_constant(&use_multi_scatter), - GPU_constant(&node->ssr_id), - GPU_constant(&node->sss_id), - sss_scale); + GPU_uniform(&use_sss)); } static void node_shader_update_principled(bNodeTree *ntree, bNode *node) diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.cc index 73f58477b67..e814eb223e5 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.cc @@ -15,6 +15,7 @@ static void node_declare(NodeDeclarationBuilder &b) .subtype(PROP_FACTOR); b.add_input<decl::Float>(N_("IOR")).default_value(1.45f).min(0.0f).max(1000.0f); b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("BSDF")); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_toon.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_toon.cc index 9cb7c4c3bbb..c1c092e89c7 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_toon.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_toon.cc @@ -22,6 +22,7 @@ static void node_declare(NodeDeclarationBuilder &b) .max(1.0f) .subtype(PROP_FACTOR); b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("BSDF")); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.cc index 19e61d8140d..fd0dd9f93de 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.cc @@ -9,6 +9,7 @@ static void node_declare(NodeDeclarationBuilder &b) { b.add_input<decl::Color>(N_("Color")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("BSDF")); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.cc index 57fd7e3ef3b..291b3fdb2be 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.cc @@ -8,6 +8,7 @@ namespace blender::nodes::node_shader_bsdf_transparent_cc { static void node_declare(NodeDeclarationBuilder &b) { b.add_input<decl::Color>(N_("Color")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("BSDF")); } @@ -17,6 +18,9 @@ static int node_shader_gpu_bsdf_transparent(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { + if (in[0].link || !is_zero_v3(in[0].vec)) { + GPU_material_flag_set(mat, GPU_MATFLAG_TRANSPARENT); + } return GPU_stack_link(mat, node, "node_bsdf_transparent", in, out); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.cc index 75bdb5b6f54..c86d70aecbf 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.cc @@ -14,6 +14,7 @@ static void node_declare(NodeDeclarationBuilder &b) .max(1.0f) .subtype(PROP_FACTOR); b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("BSDF")); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bump.cc b/source/blender/nodes/shader/nodes/node_shader_bump.cc index 5dd27e64ce3..ad2c56d96b5 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bump.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bump.cc @@ -27,8 +27,6 @@ static void node_declare(NodeDeclarationBuilder &b) .min(-1000.0f) .max(1000.0f) .hide_value(); - b.add_input<decl::Float>(N_("Height_dx")).default_value(1.0f).unavailable(); - b.add_input<decl::Float>(N_("Height_dy")).default_value(1.0f).unavailable(); b.add_input<decl::Vector>(N_("Normal")).min(-1.0f).max(1.0f).hide_value(); b.add_output<decl::Vector>(N_("Normal")); } @@ -46,23 +44,26 @@ static int gpu_shader_bump(GPUMaterial *mat, { /* If there is no Height input, the node becomes a no-op. */ if (!in[2].link) { - if (!in[5].link) { + if (!in[3].link) { return GPU_link(mat, "world_normals_get", &out[0].link); } else { /* Actually running the bump code would normalize, but Cycles handles it as total no-op. */ - return GPU_link(mat, "vector_copy", in[5].link, &out[0].link); + return GPU_link(mat, "vector_copy", in[3].link, &out[0].link); } } - if (!in[5].link) { - GPU_link(mat, "world_normals_get", &in[5].link); + if (!in[3].link) { + GPU_link(mat, "world_normals_get", &in[3].link); } + const char *height_function = GPU_material_split_sub_function(mat, GPU_FLOAT, &in[2].link); + + GPUNodeLink *dheight = GPU_differentiate_float_function(height_function); + float invert = (node->custom1) ? -1.0 : 1.0; - return GPU_stack_link( - mat, node, "node_bump", in, out, GPU_builtin(GPU_VIEW_POSITION), GPU_constant(&invert)); + return GPU_stack_link(mat, node, "node_bump", in, out, dheight, GPU_constant(&invert)); } } // namespace blender::nodes::node_shader_bump_cc diff --git a/source/blender/nodes/shader/nodes/node_shader_camera.cc b/source/blender/nodes/shader/nodes/node_shader_camera.cc index 9d2858f56f7..99c82582456 100644 --- a/source/blender/nodes/shader/nodes/node_shader_camera.cc +++ b/source/blender/nodes/shader/nodes/node_shader_camera.cc @@ -22,11 +22,7 @@ static int gpu_shader_camera(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { - GPUNodeLink *viewvec; - - viewvec = GPU_builtin(GPU_VIEW_POSITION); - GPU_link(mat, "invert_z", viewvec, &viewvec); - return GPU_stack_link(mat, node, "camera", in, out, viewvec); + return GPU_stack_link(mat, node, "camera", in, out); } } // namespace blender::nodes::node_shader_camera_cc diff --git a/source/blender/nodes/shader/nodes/node_shader_displacement.cc b/source/blender/nodes/shader/nodes/node_shader_displacement.cc index 88d1fac13a4..6591396adda 100644 --- a/source/blender/nodes/shader/nodes/node_shader_displacement.cc +++ b/source/blender/nodes/shader/nodes/node_shader_displacement.cc @@ -33,16 +33,11 @@ static int gpu_shader_displacement(GPUMaterial *mat, GPUNodeStack *out) { if (!in[3].link) { - GPU_link(mat, - "direction_transform_m4v3", - GPU_builtin(GPU_VIEW_NORMAL), - GPU_builtin(GPU_INVERSE_VIEW_MATRIX), - &in[3].link); + GPU_link(mat, "world_normals_get", &in[3].link); } if (node->custom1 == SHD_SPACE_OBJECT) { - return GPU_stack_link( - mat, node, "node_displacement_object", in, out, GPU_builtin(GPU_OBJECT_MATRIX)); + return GPU_stack_link(mat, node, "node_displacement_object", in, out); } return GPU_stack_link(mat, node, "node_displacement_world", in, out); diff --git a/source/blender/nodes/shader/nodes/node_shader_eevee_specular.cc b/source/blender/nodes/shader/nodes/node_shader_eevee_specular.cc index c4aed523f61..d68b0c0c37c 100644 --- a/source/blender/nodes/shader/nodes/node_shader_eevee_specular.cc +++ b/source/blender/nodes/shader/nodes/node_shader_eevee_specular.cc @@ -33,9 +33,12 @@ static void node_declare(NodeDeclarationBuilder &b) .subtype(PROP_FACTOR); b.add_input<decl::Vector>(N_("Clear Coat Normal")).hide_value(); b.add_input<decl::Float>(N_("Ambient Occlusion")).hide_value(); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("BSDF")); } +#define socket_not_zero(sock) (in[sock].link || (clamp_f(in[sock].vec[0], 0.0f, 1.0f) > 1e-5f)) + static int node_shader_gpu_eevee_specular(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), @@ -59,9 +62,11 @@ static int node_shader_gpu_eevee_specular(GPUMaterial *mat, GPU_link(mat, "set_value", GPU_constant(&one), &in[9].link); } - GPU_material_flag_set(mat, static_cast<eGPUMatFlag>(GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_GLOSSY)); + GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_GLOSSY); + + float use_clear = (socket_not_zero(6)) ? 1.0f : 0.0f; - return GPU_stack_link(mat, node, "node_eevee_specular", in, out, GPU_constant(&node->ssr_id)); + return GPU_stack_link(mat, node, "node_eevee_specular", in, out, GPU_constant(&use_clear)); } } // namespace blender::nodes::node_shader_eevee_specular_cc diff --git a/source/blender/nodes/shader/nodes/node_shader_emission.cc b/source/blender/nodes/shader/nodes/node_shader_emission.cc index d4d88857cd2..be98f096ce5 100644 --- a/source/blender/nodes/shader/nodes/node_shader_emission.cc +++ b/source/blender/nodes/shader/nodes/node_shader_emission.cc @@ -9,6 +9,7 @@ static void node_declare(NodeDeclarationBuilder &b) { b.add_input<decl::Color>(N_("Color")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); b.add_input<decl::Float>(N_("Strength")).default_value(1.0f).min(0.0f).max(1000000.0f); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("Emission")); } @@ -18,7 +19,8 @@ static int node_shader_gpu_emission(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { - return GPU_stack_link(mat, node, "node_emission", in, out, GPU_builtin(GPU_VIEW_NORMAL)); + GPU_material_flag_set(mat, GPU_MATFLAG_EMISSION); + return GPU_stack_link(mat, node, "node_emission", in, out); } } // namespace blender::nodes::node_shader_emission_cc diff --git a/source/blender/nodes/shader/nodes/node_shader_fresnel.cc b/source/blender/nodes/shader/nodes/node_shader_fresnel.cc index 47b2c6b97d4..7b771d7dafd 100644 --- a/source/blender/nodes/shader/nodes/node_shader_fresnel.cc +++ b/source/blender/nodes/shader/nodes/node_shader_fresnel.cc @@ -19,14 +19,10 @@ static int node_shader_gpu_fresnel(GPUMaterial *mat, GPUNodeStack *out) { if (!in[1].link) { - in[1].link = GPU_builtin(GPU_VIEW_NORMAL); - } - else { - GPU_link( - mat, "direction_transform_m4v3", in[1].link, GPU_builtin(GPU_VIEW_MATRIX), &in[1].link); + GPU_link(mat, "world_normals_get", &in[1].link); } - return GPU_stack_link(mat, node, "node_fresnel", in, out, GPU_builtin(GPU_VIEW_POSITION)); + return GPU_stack_link(mat, node, "node_fresnel", in, out); } } // namespace blender::nodes::node_shader_fresnel_cc diff --git a/source/blender/nodes/shader/nodes/node_shader_geometry.cc b/source/blender/nodes/shader/nodes/node_shader_geometry.cc index 5bd984ddfc4..47df932f9d4 100644 --- a/source/blender/nodes/shader/nodes/node_shader_geometry.cc +++ b/source/blender/nodes/shader/nodes/node_shader_geometry.cc @@ -24,29 +24,17 @@ static int node_shader_gpu_geometry(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { - /* HACK: Don't request GPU_BARYCENTRIC_TEXCO if not used because it will + /* HACK: Don't request GPU_MATFLAG_BARYCENTRIC if not used because it will * trigger the use of geometry shader (and the performance penalty it implies). */ - const 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); if (out[5].hasoutput) { GPU_material_flag_set(mat, GPU_MATFLAG_BARYCENTRIC); } /* Opti: don't request orco if not needed. */ + const float val[4] = {0.0f, 0.0f, 0.0f, 0.0f}; GPUNodeLink *orco_link = (!out[2].hasoutput) ? GPU_constant(val) : GPU_attribute(mat, CD_ORCO, ""); - const bool success = GPU_stack_link(mat, - node, - "node_geometry", - in, - out, - GPU_builtin(GPU_VIEW_POSITION), - GPU_builtin(GPU_WORLD_NORMAL), - orco_link, - GPU_builtin(GPU_OBJECT_MATRIX), - GPU_builtin(GPU_INVERSE_VIEW_MATRIX), - bary_link); + const bool success = GPU_stack_link(mat, node, "node_geometry", in, out, orco_link); int i; LISTBASE_FOREACH_INDEX (bNodeSocket *, sock, &node->outputs, i) { @@ -55,7 +43,7 @@ static int node_shader_gpu_geometry(GPUMaterial *mat, * This is the case for interpolated, non linear functions. * The resulting vector can still be a bit wrong but not as much. * (see T70644) */ - if (node->branch_tag != 0 && ELEM(i, 1, 2, 4)) { + if (ELEM(i, 1, 2, 4)) { GPU_link(mat, "vector_math_normalize", out[i].link, diff --git a/source/blender/nodes/shader/nodes/node_shader_holdout.cc b/source/blender/nodes/shader/nodes/node_shader_holdout.cc index b1a9ce75e1f..6a21fab28db 100644 --- a/source/blender/nodes/shader/nodes/node_shader_holdout.cc +++ b/source/blender/nodes/shader/nodes/node_shader_holdout.cc @@ -7,6 +7,7 @@ namespace blender::nodes::node_shader_holdout_cc { static void node_declare(NodeDeclarationBuilder &b) { + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("Holdout")); } diff --git a/source/blender/nodes/shader/nodes/node_shader_layer_weight.cc b/source/blender/nodes/shader/nodes/node_shader_layer_weight.cc index b5097e71657..69825e472fb 100644 --- a/source/blender/nodes/shader/nodes/node_shader_layer_weight.cc +++ b/source/blender/nodes/shader/nodes/node_shader_layer_weight.cc @@ -20,14 +20,10 @@ static int node_shader_gpu_layer_weight(GPUMaterial *mat, GPUNodeStack *out) { if (!in[1].link) { - in[1].link = GPU_builtin(GPU_VIEW_NORMAL); - } - else { - GPU_link( - mat, "direction_transform_m4v3", in[1].link, GPU_builtin(GPU_VIEW_MATRIX), &in[1].link); + GPU_link(mat, "world_normals_get", &in[1].link); } - return GPU_stack_link(mat, node, "node_layer_weight", in, out, GPU_builtin(GPU_VIEW_POSITION)); + return GPU_stack_link(mat, node, "node_layer_weight", in, out); } } // namespace blender::nodes::node_shader_layer_weight_cc diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.cc b/source/blender/nodes/shader/nodes/node_shader_normal_map.cc index f8a5e342ae3..d51d8def945 100644 --- a/source/blender/nodes/shader/nodes/node_shader_normal_map.cc +++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.cc @@ -83,18 +83,16 @@ static int gpu_shader_normal_map(GPUMaterial *mat, GPU_link(mat, color_to_normal_fnc_name, newnormal, &newnormal); switch (nm->space) { case SHD_SPACE_TANGENT: + GPU_material_flag_set(mat, GPU_MATFLAG_OBJECT_INFO); GPU_link(mat, "node_normal_map", - GPU_builtin(GPU_OBJECT_INFO), GPU_attribute(mat, CD_TANGENT, nm->uv_map), - GPU_builtin(GPU_WORLD_NORMAL), newnormal, &newnormal); break; case SHD_SPACE_OBJECT: case SHD_SPACE_BLENDER_OBJECT: - GPU_link( - mat, "direction_transform_m4v3", newnormal, GPU_builtin(GPU_OBJECT_MATRIX), &newnormal); + GPU_link(mat, "normal_transform_object_to_world", newnormal, &newnormal); break; case SHD_SPACE_WORLD: case SHD_SPACE_BLENDER_WORLD: @@ -102,8 +100,7 @@ static int gpu_shader_normal_map(GPUMaterial *mat, break; } - GPUNodeLink *oldnormal = GPU_builtin(GPU_WORLD_NORMAL); - GPU_link(mat, "node_normal_map_mix", strength, newnormal, oldnormal, &out[0].link); + GPU_link(mat, "node_normal_map_mix", strength, newnormal, &out[0].link); return true; } diff --git a/source/blender/nodes/shader/nodes/node_shader_object_info.cc b/source/blender/nodes/shader/nodes/node_shader_object_info.cc index 03c1a018d37..8985ab6d0e9 100644 --- a/source/blender/nodes/shader/nodes/node_shader_object_info.cc +++ b/source/blender/nodes/shader/nodes/node_shader_object_info.cc @@ -23,15 +23,8 @@ static int node_shader_gpu_object_info(GPUMaterial *mat, { Material *ma = GPU_material_get_material(mat); float index = ma ? ma->index : 0.0f; - return GPU_stack_link(mat, - node, - "node_object_info", - in, - out, - GPU_builtin(GPU_OBJECT_MATRIX), - GPU_builtin(GPU_OBJECT_COLOR), - GPU_builtin(GPU_OBJECT_INFO), - GPU_constant(&index)); + GPU_material_flag_set(mat, GPU_MATFLAG_OBJECT_INFO); + return GPU_stack_link(mat, node, "node_object_info", in, out, GPU_constant(&index)); } } // namespace blender::nodes::node_shader_object_info_cc diff --git a/source/blender/nodes/shader/nodes/node_shader_output_aov.cc b/source/blender/nodes/shader/nodes/node_shader_output_aov.cc index c0a116675ab..78dabc5c1c2 100644 --- a/source/blender/nodes/shader/nodes/node_shader_output_aov.cc +++ b/source/blender/nodes/shader/nodes/node_shader_output_aov.cc @@ -35,12 +35,16 @@ static int node_shader_gpu_output_aov(GPUMaterial *mat, { GPUNodeLink *outlink; NodeShaderOutputAOV *aov = (NodeShaderOutputAOV *)node->storage; - /* Keep in sync with `renderpass_lib.glsl#render_pass_aov_hash` and - * `EEVEE_renderpasses_aov_hash`. */ - unsigned int hash = BLI_hash_string(aov->name) << 1; - GPU_stack_link(mat, node, "node_output_aov", in, out, &outlink); - GPU_material_add_output_link_aov(mat, outlink, hash); + uint hash = BLI_hash_string(aov->name); + /* WORKAROUND: We don't support int/uint constants for now. So make sure the aliasing works. + * We cast back to uint in GLSL. */ + BLI_STATIC_ASSERT(sizeof(float) == sizeof(uint), + "GPUCodegen: AOV hash needs float and uint to be the same size."); + GPUNodeLink *hash_link = GPU_constant((float *)&hash); + GPU_material_flag_set(mat, GPU_MATFLAG_AOV); + GPU_stack_link(mat, node, "node_output_aov", in, out, hash_link, &outlink); + GPU_material_add_output_link_aov(mat, outlink, hash); return true; } diff --git a/source/blender/nodes/shader/nodes/node_shader_output_material.cc b/source/blender/nodes/shader/nodes/node_shader_output_material.cc index 3329ab7f8a0..54475d547da 100644 --- a/source/blender/nodes/shader/nodes/node_shader_output_material.cc +++ b/source/blender/nodes/shader/nodes/node_shader_output_material.cc @@ -12,39 +12,33 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_input<decl::Shader>(N_("Surface")); b.add_input<decl::Shader>(N_("Volume")); b.add_input<decl::Vector>(N_("Displacement")).hide_value(); + b.add_input<decl::Float>(N_("Thickness")).hide_value(); } static int node_shader_gpu_output_material(GPUMaterial *mat, - bNode *node, + bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, - GPUNodeStack *out) + GPUNodeStack *UNUSED(out)) { - GPUNodeLink *outlink, *alpha_threshold_link, *shadow_threshold_link; - Material *ma = GPU_material_get_material(mat); - - static float no_alpha_threshold = -1.0f; - if (ma) { - alpha_threshold_link = GPU_uniform((ma->blend_method == MA_BM_CLIP) ? &ma->alpha_threshold : - &no_alpha_threshold); - shadow_threshold_link = GPU_uniform((ma->blend_shadow == MA_BS_CLIP) ? &ma->alpha_threshold : - &no_alpha_threshold); + GPUNodeLink *outlink_surface, *outlink_volume, *outlink_displacement, *outlink_thickness; + /* Passthrough node in order to do the right socket conversions (important for displacement). */ + if (in[0].link) { + GPU_link(mat, "node_output_material_surface", in[0].link, &outlink_surface); + GPU_material_output_surface(mat, outlink_surface); } - else { - alpha_threshold_link = GPU_uniform(&no_alpha_threshold); - shadow_threshold_link = GPU_uniform(&no_alpha_threshold); + if (in[1].link) { + GPU_link(mat, "node_output_material_volume", in[1].link, &outlink_volume); + GPU_material_output_volume(mat, outlink_volume); + } + if (in[2].link) { + GPU_link(mat, "node_output_material_displacement", in[2].link, &outlink_displacement); + GPU_material_output_displacement(mat, outlink_displacement); + } + if (in[3].link) { + GPU_link(mat, "node_output_material_thickness", in[3].link, &outlink_thickness); + GPU_material_output_thickness(mat, outlink_thickness); } - - GPU_stack_link(mat, - node, - "node_output_material", - in, - out, - alpha_threshold_link, - shadow_threshold_link, - &outlink); - GPU_material_output_link(mat, outlink); - return true; } diff --git a/source/blender/nodes/shader/nodes/node_shader_output_world.cc b/source/blender/nodes/shader/nodes/node_shader_output_world.cc index 77146876d9d..b0cf4c80bc5 100644 --- a/source/blender/nodes/shader/nodes/node_shader_output_world.cc +++ b/source/blender/nodes/shader/nodes/node_shader_output_world.cc @@ -12,16 +12,20 @@ static void node_declare(NodeDeclarationBuilder &b) } static int node_shader_gpu_output_world(GPUMaterial *mat, - bNode *node, + bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, - GPUNodeStack *out) + GPUNodeStack *UNUSED(out)) { - GPUNodeLink *outlink; - - GPU_stack_link(mat, node, "node_output_world", in, out, &outlink); - GPU_material_output_link(mat, outlink); - + GPUNodeLink *outlink_surface, *outlink_volume; + if (in[0].link) { + GPU_link(mat, "node_output_world_surface", in[0].link, &outlink_surface); + GPU_material_output_surface(mat, outlink_surface); + } + if (in[1].link) { + GPU_link(mat, "node_output_world_volume", in[1].link, &outlink_volume); + GPU_material_output_volume(mat, outlink_volume); + } return true; } diff --git a/source/blender/nodes/shader/nodes/node_shader_particle_info.cc b/source/blender/nodes/shader/nodes/node_shader_particle_info.cc index 66e859a8c69..71adbd5e5c4 100644 --- a/source/blender/nodes/shader/nodes/node_shader_particle_info.cc +++ b/source/blender/nodes/shader/nodes/node_shader_particle_info.cc @@ -28,16 +28,9 @@ static int gpu_shader_particle_info(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { - - return GPU_stack_link(mat, - node, - "particle_info", - in, - out, - GPU_builtin(GPU_PARTICLE_SCALAR_PROPS), - GPU_builtin(GPU_PARTICLE_LOCATION), - GPU_builtin(GPU_PARTICLE_VELOCITY), - GPU_builtin(GPU_PARTICLE_ANG_VELOCITY)); + GPU_material_flag_set(mat, GPU_MATFLAG_OBJECT_INFO); + /* TODO(fclem) Pass particle data in obinfo. */ + return GPU_stack_link(mat, node, "particle_info", in, out); } } // namespace blender::nodes::node_shader_particle_info_cc diff --git a/source/blender/nodes/shader/nodes/node_shader_shader_to_rgb.cc b/source/blender/nodes/shader/nodes/node_shader_shader_to_rgb.cc index 11dfa03ea40..0404158a803 100644 --- a/source/blender/nodes/shader/nodes/node_shader_shader_to_rgb.cc +++ b/source/blender/nodes/shader/nodes/node_shader_shader_to_rgb.cc @@ -18,9 +18,7 @@ static int node_shader_gpu_shadertorgb(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { - /* Because node_shader_to_rgba is using fallback_cubemap() - * we need to tag material as glossy. */ - GPU_material_flag_set(mat, GPU_MATFLAG_GLOSSY); + GPU_material_flag_set(mat, GPU_MATFLAG_SHADER_TO_RGBA); return GPU_stack_link(mat, node, "node_shader_to_rgba", in, out); } diff --git a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.cc b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.cc index 17173ef020a..e3ff4c28604 100644 --- a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.cc +++ b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.cc @@ -25,6 +25,7 @@ static void node_declare(NodeDeclarationBuilder &b) .max(1.0f) .subtype(PROP_FACTOR); b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("BSSRDF")); } @@ -49,19 +50,16 @@ static int node_shader_gpu_subsurface_scattering(GPUMaterial *mat, GPU_link(mat, "world_normals_get", &in[5].link); } - if (node->sss_id > 0) { - bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&node->original->inputs, 2); - bNodeSocketValueRGBA *socket_data = (bNodeSocketValueRGBA *)socket->default_value; - /* For some reason it seems that the socket value is in ARGB format. */ - GPU_material_sss_profile_create(mat, &socket_data->value[1]); + bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&node->original->inputs, 2); + bNodeSocketValueRGBA *socket_data = (bNodeSocketValueRGBA *)socket->default_value; + /* For some reason it seems that the socket value is in ARGB format. */ + bool use_subsurf = GPU_material_sss_profile_create(mat, &socket_data->value[1]); - /* 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, (eGPUMatFlag)(GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_SSS)); - } + float use_sss = (use_subsurf) ? 1.0f : 0.0f; + + GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_SUBSURFACE); - return GPU_stack_link( - mat, node, "node_subsurface_scattering", in, out, GPU_constant(&node->sss_id)); + return GPU_stack_link(mat, node, "node_subsurface_scattering", in, out, GPU_uniform(&use_sss)); } static void node_shader_update_subsurface_scattering(bNodeTree *ntree, bNode *node) diff --git a/source/blender/nodes/shader/nodes/node_shader_tangent.cc b/source/blender/nodes/shader/nodes/node_shader_tangent.cc index 25489632594..8e27ebed21b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tangent.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tangent.cc @@ -73,14 +73,7 @@ static int node_shader_gpu_tangent(GPUMaterial *mat, GPU_link(mat, "tangent_orco_z", orco, &orco); } - return GPU_stack_link(mat, - node, - "node_tangent", - in, - out, - GPU_builtin(GPU_WORLD_NORMAL), - orco, - GPU_builtin(GPU_OBJECT_MATRIX)); + return GPU_stack_link(mat, node, "node_tangent", in, out, orco); } } // namespace blender::nodes::node_shader_tangent_cc diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_coord.cc b/source/blender/nodes/shader/nodes/node_shader_tex_coord.cc index ac986787d65..ae683386bac 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_coord.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_coord.cc @@ -35,24 +35,18 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat, { Object *ob = (Object *)node->id; - GPUNodeLink *inv_obmat = (ob != nullptr) ? GPU_uniform(&ob->imat[0][0]) : - GPU_builtin(GPU_INVERSE_OBJECT_MATRIX); + /* Use special matrix to let the shader branch to using the render object's matrix. */ + float dummy_matrix[4][4]; + dummy_matrix[3][3] = 0.0f; + GPUNodeLink *inv_obmat = (ob != NULL) ? GPU_uniform(&ob->imat[0][0]) : + GPU_uniform(&dummy_matrix[0][0]); /* Opti: don't request orco if not needed. */ - const float default_coords[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - GPUNodeLink *orco = (!out[0].hasoutput) ? GPU_constant(default_coords) : - GPU_attribute(mat, CD_ORCO, ""); + float4 zero(0.0f); + GPUNodeLink *orco = (!out[0].hasoutput) ? GPU_constant(zero) : GPU_attribute(mat, CD_ORCO, ""); GPUNodeLink *mtface = GPU_attribute(mat, CD_MTFACE, ""); - GPUNodeLink *viewpos = GPU_builtin(GPU_VIEW_POSITION); - GPUNodeLink *worldnor = GPU_builtin(GPU_WORLD_NORMAL); - GPUNodeLink *texcofacs = GPU_builtin(GPU_CAMERA_TEXCO_FACTORS); - if (out[0].hasoutput) { - GPU_link(mat, "generated_from_orco", orco, &orco); - } - - GPU_stack_link( - mat, node, "node_tex_coord", in, out, viewpos, worldnor, inv_obmat, texcofacs, orco, mtface); + GPU_stack_link(mat, node, "node_tex_coord", in, out, inv_obmat, orco, mtface); int i; LISTBASE_FOREACH_INDEX (bNodeSocket *, sock, &node->outputs, i) { @@ -61,7 +55,7 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat, * This is the case for interpolated, non linear functions. * The resulting vector can still be a bit wrong but not as much. * (see T70644) */ - if (node->branch_tag != 0 && ELEM(i, 1, 6)) { + if (ELEM(i, 1, 6)) { GPU_link(mat, "vector_math_normalize", out[i].link, diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.cc b/source/blender/nodes/shader/nodes/node_shader_tex_environment.cc index 41456091e1d..dbff092234b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.cc @@ -44,15 +44,13 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, GPUNodeLink *outalpha; - if (!ima) { + /* HACK(fclem): For lookdev mode: do not compile an empty environment and just create an empty + * texture entry point. We manually bind to it after DRW_shgroup_add_material_resources(). */ + if (!ima && !GPU_material_flag_get(mat, GPU_MATFLAG_LOOKDEV_HACK)) { return GPU_stack_link(mat, node, "node_tex_environment_empty", in, out); } - 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_default_tex_coord(mat, node, &in[0].link); node_shader_gpu_tex_mapping(mat, node, in, out); /* Compute texture coordinate. */ @@ -92,7 +90,7 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, /* Sample texture with correct interpolation. */ GPU_link(mat, gpu_fn, in[0].link, GPU_image(mat, ima, iuser, sampler), &out[0].link, &outalpha); - if (out[0].hasoutput) { + if (out[0].hasoutput && ima) { 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. */ diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.cc b/source/blender/nodes/shader/nodes/node_shader_tex_image.cc index 19b5a50cd6b..d97f7d0375d 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.cc @@ -88,13 +88,11 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, } case SHD_PROJ_BOX: { gpu_node_name = use_cubic ? "tex_box_sample_cubic" : "tex_box_sample_linear"; - GPUNodeLink *wnor, *col1, *col2, *col3; - GPUNodeLink *vnor = GPU_builtin(GPU_WORLD_NORMAL); - GPUNodeLink *ob_mat = GPU_builtin(GPU_OBJECT_MATRIX); + GPUNodeLink *vnor, *wnor, *col1, *col2, *col3; GPUNodeLink *blend = GPU_uniform(&tex->projection_blend); GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state); - /* equivalent to normal_world_to_object */ - GPU_link(mat, "normal_transform_transposed_m4v3", vnor, ob_mat, &wnor); + GPU_link(mat, "world_normals_get", &vnor); + GPU_link(mat, "normal_transform_world_to_object", vnor, &wnor); GPU_link(mat, gpu_node_name, in[0].link, wnor, gpu_image, &col1, &col2, &col3); GPU_link(mat, "tex_box_blend", wnor, col1, col2, col3, blend, &out[0].link, &out[1].link); break; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.cc b/source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.cc index f628d1ec77b..fcd1d4973ff 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.cc @@ -65,7 +65,7 @@ static void node_shader_buts_tex_pointdensity(uiLayout *layout, static void node_shader_init_tex_pointdensity(bNodeTree *UNUSED(ntree), bNode *node) { - NodeShaderTexPointDensity *point_density = MEM_cnew<NodeShaderTexPointDensity>("new pd node"); + NodeShaderTexPointDensity *point_density = MEM_new<NodeShaderTexPointDensity>("new pd node"); point_density->resolution = 100; point_density->radius = 0.3f; point_density->space = SHD_POINTDENSITY_SPACE_OBJECT; @@ -79,7 +79,7 @@ static void node_shader_free_tex_pointdensity(bNode *node) PointDensity *pd = &point_density->pd; RE_point_density_free(pd); BKE_texture_pointdensity_free_data(pd); - memset(pd, 0, sizeof(*pd)); + *pd = dna::shallow_zero_initialize(); MEM_freeN(point_density); } @@ -90,7 +90,7 @@ static void node_shader_copy_tex_pointdensity(bNodeTree *UNUSED(dest_ntree), dest_node->storage = MEM_dupallocN(src_node->storage); NodeShaderTexPointDensity *point_density = (NodeShaderTexPointDensity *)dest_node->storage; PointDensity *pd = &point_density->pd; - memset(pd, 0, sizeof(*pd)); + *pd = dna::shallow_zero_initialize(); } } // namespace blender::nodes::node_shader_tex_pointdensity_cc diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_displacement.cc b/source/blender/nodes/shader/nodes/node_shader_vector_displacement.cc index 04cf0b72f32..9996e91177a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vector_displacement.cc +++ b/source/blender/nodes/shader/nodes/node_shader_vector_displacement.cc @@ -24,23 +24,20 @@ static int gpu_shader_vector_displacement(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { - if (node->custom1 == SHD_SPACE_TANGENT) { - return GPU_stack_link(mat, - node, - "node_vector_displacement_tangent", - in, - out, - GPU_attribute(mat, CD_TANGENT, ""), - GPU_builtin(GPU_WORLD_NORMAL), - GPU_builtin(GPU_OBJECT_MATRIX), - GPU_builtin(GPU_VIEW_MATRIX)); + switch (node->custom1) { + case SHD_SPACE_TANGENT: + return GPU_stack_link(mat, + node, + "node_vector_displacement_tangent", + in, + out, + GPU_attribute(mat, CD_TANGENT, "")); + case SHD_SPACE_OBJECT: + return GPU_stack_link(mat, node, "node_vector_displacement_object", in, out); + case SHD_SPACE_WORLD: + default: + return GPU_stack_link(mat, node, "node_vector_displacement_world", in, out); } - if (node->custom1 == SHD_SPACE_OBJECT) { - return GPU_stack_link( - mat, node, "node_vector_displacement_object", in, out, GPU_builtin(GPU_OBJECT_MATRIX)); - } - - return GPU_stack_link(mat, node, "node_vector_displacement_world", in, out); } } // namespace blender::nodes::node_shader_vector_displacement_cc diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc b/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc index a041492fb13..b35f686e331 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc +++ b/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc @@ -69,9 +69,9 @@ static int gpu_shader_vector_rotate(GPUMaterial *mat, return 0; } -static float3 sh_node_vector_rotate_around_axis(const float3 vector, - const float3 center, - const float3 axis, +static float3 sh_node_vector_rotate_around_axis(const float3 &vector, + const float3 ¢er, + const float3 &axis, const float angle) { float3 result = vector - center; @@ -81,9 +81,9 @@ static float3 sh_node_vector_rotate_around_axis(const float3 vector, return result + center; } -static float3 sh_node_vector_rotate_euler(const float3 vector, - const float3 center, - const float3 rotation, +static float3 sh_node_vector_rotate_euler(const float3 &vector, + const float3 ¢er, + const float3 &rotation, const bool invert) { float mat[3][3]; @@ -105,13 +105,15 @@ static const fn::MultiFunction *get_multi_function(bNode &node) case NODE_VECTOR_ROTATE_TYPE_AXIS: { if (invert) { static fn::CustomMF_SI_SI_SI_SI_SO<float3, float3, float3, float, float3> fn{ - "Rotate Axis", [](float3 in, float3 center, float3 axis, float angle) { + "Rotate Axis", + [](const float3 &in, const float3 ¢er, const float3 &axis, float angle) { return sh_node_vector_rotate_around_axis(in, center, axis, -angle); }}; return &fn; } static fn::CustomMF_SI_SI_SI_SI_SO<float3, float3, float3, float, float3> fn{ - "Rotate Axis", [](float3 in, float3 center, float3 axis, float angle) { + "Rotate Axis", + [](const float3 &in, const float3 ¢er, const float3 &axis, float angle) { return sh_node_vector_rotate_around_axis(in, center, axis, angle); }}; return &fn; @@ -120,13 +122,13 @@ static const fn::MultiFunction *get_multi_function(bNode &node) float3 axis = float3(1.0f, 0.0f, 0.0f); if (invert) { static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> fn{ - "Rotate X-Axis", [=](float3 in, float3 center, float angle) { + "Rotate X-Axis", [=](const float3 &in, const float3 ¢er, float angle) { return sh_node_vector_rotate_around_axis(in, center, axis, -angle); }}; return &fn; } static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> fn{ - "Rotate X-Axis", [=](float3 in, float3 center, float angle) { + "Rotate X-Axis", [=](const float3 &in, const float3 ¢er, float angle) { return sh_node_vector_rotate_around_axis(in, center, axis, angle); }}; return &fn; @@ -135,13 +137,13 @@ static const fn::MultiFunction *get_multi_function(bNode &node) float3 axis = float3(0.0f, 1.0f, 0.0f); if (invert) { static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> fn{ - "Rotate Y-Axis", [=](float3 in, float3 center, float angle) { + "Rotate Y-Axis", [=](const float3 &in, const float3 ¢er, float angle) { return sh_node_vector_rotate_around_axis(in, center, axis, -angle); }}; return &fn; } static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> fn{ - "Rotate Y-Axis", [=](float3 in, float3 center, float angle) { + "Rotate Y-Axis", [=](const float3 &in, const float3 ¢er, float angle) { return sh_node_vector_rotate_around_axis(in, center, axis, angle); }}; return &fn; @@ -150,13 +152,13 @@ static const fn::MultiFunction *get_multi_function(bNode &node) float3 axis = float3(0.0f, 0.0f, 1.0f); if (invert) { static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> fn{ - "Rotate Z-Axis", [=](float3 in, float3 center, float angle) { + "Rotate Z-Axis", [=](const float3 &in, const float3 ¢er, float angle) { return sh_node_vector_rotate_around_axis(in, center, axis, -angle); }}; return &fn; } static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> fn{ - "Rotate Z-Axis", [=](float3 in, float3 center, float angle) { + "Rotate Z-Axis", [=](const float3 &in, const float3 ¢er, float angle) { return sh_node_vector_rotate_around_axis(in, center, axis, angle); }}; return &fn; @@ -164,13 +166,13 @@ static const fn::MultiFunction *get_multi_function(bNode &node) case NODE_VECTOR_ROTATE_TYPE_EULER_XYZ: { if (invert) { static fn::CustomMF_SI_SI_SI_SO<float3, float3, float3, float3> fn{ - "Rotate Euler", [](float3 in, float3 center, float3 rotation) { + "Rotate Euler", [](const float3 &in, const float3 ¢er, const float3 &rotation) { return sh_node_vector_rotate_euler(in, center, rotation, true); }}; return &fn; } static fn::CustomMF_SI_SI_SI_SO<float3, float3, float3, float3> fn{ - "Rotate Euler", [](float3 in, float3 center, float3 rotation) { + "Rotate Euler", [](const float3 &in, const float3 ¢er, const float3 &rotation) { return sh_node_vector_rotate_euler(in, center, rotation, false); }}; return &fn; diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_transform.cc b/source/blender/nodes/shader/nodes/node_shader_vector_transform.cc index d610e1309a7..de588f9005f 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vector_transform.cc +++ b/source/blender/nodes/shader/nodes/node_shader_vector_transform.cc @@ -43,7 +43,7 @@ static void node_shader_init_vect_transform(bNodeTree *UNUSED(ntree), bNode *nod node->storage = vect; } -static GPUNodeLink *get_gpulink_matrix_from_to(short from, short to) +static const char *get_gpufn_name_from_to(short from, short to, bool is_direction) { switch (from) { case SHD_VECT_TRANSFORM_SPACE_OBJECT: @@ -51,9 +51,11 @@ static GPUNodeLink *get_gpulink_matrix_from_to(short from, short to) case SHD_VECT_TRANSFORM_SPACE_OBJECT: return nullptr; case SHD_VECT_TRANSFORM_SPACE_WORLD: - return GPU_builtin(GPU_OBJECT_MATRIX); + return is_direction ? "direction_transform_object_to_world" : + "point_transform_object_to_world"; case SHD_VECT_TRANSFORM_SPACE_CAMERA: - return GPU_builtin(GPU_LOC_TO_VIEW_MATRIX); + return is_direction ? "direction_transform_object_to_view" : + "point_transform_object_to_view"; } break; case SHD_VECT_TRANSFORM_SPACE_WORLD: @@ -61,9 +63,11 @@ static GPUNodeLink *get_gpulink_matrix_from_to(short from, short to) case SHD_VECT_TRANSFORM_SPACE_WORLD: return nullptr; case SHD_VECT_TRANSFORM_SPACE_CAMERA: - return GPU_builtin(GPU_VIEW_MATRIX); + return is_direction ? "direction_transform_world_to_view" : + "point_transform_world_to_view"; case SHD_VECT_TRANSFORM_SPACE_OBJECT: - return GPU_builtin(GPU_INVERSE_OBJECT_MATRIX); + return is_direction ? "direction_transform_world_to_object" : + "point_transform_world_to_object"; } break; case SHD_VECT_TRANSFORM_SPACE_CAMERA: @@ -71,14 +75,17 @@ static GPUNodeLink *get_gpulink_matrix_from_to(short from, short to) case SHD_VECT_TRANSFORM_SPACE_CAMERA: return nullptr; case SHD_VECT_TRANSFORM_SPACE_WORLD: - return GPU_builtin(GPU_INVERSE_VIEW_MATRIX); + return is_direction ? "direction_transform_view_to_world" : + "point_transform_view_to_world"; case SHD_VECT_TRANSFORM_SPACE_OBJECT: - return GPU_builtin(GPU_INVERSE_LOC_TO_VIEW_MATRIX); + return is_direction ? "direction_transform_view_to_object" : + "point_transform_view_to_object"; } break; } - return nullptr; + return NULL; } + static int gpu_shader_vect_transform(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), @@ -86,11 +93,6 @@ static int gpu_shader_vect_transform(GPUMaterial *mat, GPUNodeStack *out) { struct GPUNodeLink *inputlink; - struct GPUNodeLink *fromto; - - const char *vtransform = "direction_transform_m4v3"; - const char *ptransform = "point_transform_m4v3"; - const char *func_name = nullptr; NodeShaderVectTransform *nodeprop = (NodeShaderVectTransform *)node->storage; @@ -101,17 +103,20 @@ static int gpu_shader_vect_transform(GPUMaterial *mat, inputlink = GPU_constant(in[0].vec); } - fromto = get_gpulink_matrix_from_to(nodeprop->convert_from, nodeprop->convert_to); + const bool is_direction = (nodeprop->type != SHD_VECT_TRANSFORM_TYPE_POINT); + const char *func_name = get_gpufn_name_from_to( + nodeprop->convert_from, nodeprop->convert_to, is_direction); - func_name = (nodeprop->type == SHD_VECT_TRANSFORM_TYPE_POINT) ? ptransform : vtransform; - if (fromto) { + if (func_name) { /* For cycles we have inverted Z */ /* TODO: pass here the correct matrices */ if (nodeprop->convert_from == SHD_VECT_TRANSFORM_SPACE_CAMERA && nodeprop->convert_to != SHD_VECT_TRANSFORM_SPACE_CAMERA) { GPU_link(mat, "invert_z", inputlink, &inputlink); } - GPU_link(mat, func_name, inputlink, fromto, &out[0].link); + + GPU_link(mat, func_name, inputlink, &out[0].link); + if (nodeprop->convert_to == SHD_VECT_TRANSFORM_SPACE_CAMERA && nodeprop->convert_from != SHD_VECT_TRANSFORM_SPACE_CAMERA) { GPU_link(mat, "invert_z", out[0].link, &out[0].link); diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_absorption.cc b/source/blender/nodes/shader/nodes/node_shader_volume_absorption.cc index e0fef6b0d19..930fa6e5fb9 100644 --- a/source/blender/nodes/shader/nodes/node_shader_volume_absorption.cc +++ b/source/blender/nodes/shader/nodes/node_shader_volume_absorption.cc @@ -9,6 +9,7 @@ static void node_declare(NodeDeclarationBuilder &b) { b.add_input<decl::Color>(N_("Color")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); b.add_input<decl::Float>(N_("Density")).default_value(1.0f).min(0.0f).max(1000.0f); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("Volume")); } diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_principled.cc b/source/blender/nodes/shader/nodes/node_shader_volume_principled.cc index 980782f571c..d414b4b2ef7 100644 --- a/source/blender/nodes/shader/nodes/node_shader_volume_principled.cc +++ b/source/blender/nodes/shader/nodes/node_shader_volume_principled.cc @@ -27,6 +27,7 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_input<decl::Color>(N_("Blackbody Tint")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); b.add_input<decl::Float>(N_("Temperature")).default_value(1000.0f).min(0.0f).max(6500.0f); b.add_input<decl::String>(N_("Temperature Attribute")); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("Volume")); } diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_scatter.cc b/source/blender/nodes/shader/nodes/node_shader_volume_scatter.cc index 6408efb769d..0c6859ad1fb 100644 --- a/source/blender/nodes/shader/nodes/node_shader_volume_scatter.cc +++ b/source/blender/nodes/shader/nodes/node_shader_volume_scatter.cc @@ -14,6 +14,7 @@ static void node_declare(NodeDeclarationBuilder &b) .min(-1.0f) .max(1.0f) .subtype(PROP_FACTOR); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("Volume")); } diff --git a/source/blender/nodes/shader/nodes/node_shader_wireframe.cc b/source/blender/nodes/shader/nodes/node_shader_wireframe.cc index 1204c3a678f..6a1acda3353 100644 --- a/source/blender/nodes/shader/nodes/node_shader_wireframe.cc +++ b/source/blender/nodes/shader/nodes/node_shader_wireframe.cc @@ -28,17 +28,11 @@ static int node_shader_gpu_wireframe(GPUMaterial *mat, GPU_material_flag_set(mat, GPU_MATFLAG_BARYCENTRIC); /* node->custom1 is use_pixel_size */ if (node->custom1) { - return GPU_stack_link( - mat, node, "node_wireframe_screenspace", in, out, GPU_builtin(GPU_BARYCENTRIC_TEXCO)); + return GPU_stack_link(mat, node, "node_wireframe_screenspace", in, out); + } + else { + return GPU_stack_link(mat, node, "node_wireframe", in, out); } - - return GPU_stack_link(mat, - node, - "node_wireframe", - in, - out, - GPU_builtin(GPU_BARYCENTRIC_TEXCO), - GPU_builtin(GPU_BARYCENTRIC_DIST)); } } // namespace blender::nodes::node_shader_wireframe_cc |