Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2022-04-14 19:47:58 +0300
committerClément Foucault <foucault.clem@gmail.com>2022-04-14 19:47:58 +0300
commit80859a6cb2726a39fb22cb49f06e0355dc9390a7 (patch)
treefd3f8ead5a247a79ea11e4aacc720843bbc5e2c2 /source/blender/nodes
parent66dc4d4efb88ecf2d18bfa08ab9c43b024ebd2fb (diff)
GPU: Make nodetree GLSL Codegen render engine agnostic
This commit removes all EEVEE specific code from the `gpu_shader_material*.glsl` files. It defines a clear interface to evaluate the closure nodes leaving more flexibility to the render engine. Some of the long standing workaround are fixed: - bump mapping support is no longer duplicating a lot of node and is instead compiled into a function call. - bump rewiring to Normal socket is no longer needed as we now use a global `g_data.N` for that. Closure sampling with upstread weight eval is now supported if the engine needs it. This also makes all the material GLSL sources use `GPUSource` for better debugging experience. The `GPUFunction` parsing now happens in `GPUSource` creation. The whole `GPUCodegen` now uses the `ShaderCreateInfo` and is object type agnostic. Is has also been rewritten in C++. This patch changes a view behavior for EEVEE: - Mix shader node factor imput is now clamped. - Tangent Vector displacement behavior is now matching cycles. - The chosen BSDF used for SSR might change. - Hair shading may have very small changes on very large hairs when using hair polygon stripes. - ShaderToRGB node will remove any SSR and SSS form a shader. - SSS radius input now is no longer a scaling factor but defines an average radius. The SSS kernel "shape" (radii) are still defined by the socket default values. Appart from the listed changes no other regressions are expected.
Diffstat (limited to 'source/blender/nodes')
-rw-r--r--source/blender/nodes/NOD_shader.h5
-rw-r--r--source/blender/nodes/shader/node_shader_tree.cc735
-rw-r--r--source/blender/nodes/shader/node_shader_util.cc15
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.cc2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_background.cc1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bevel.cc6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.cc10
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.cc1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_glass.cc11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.cc9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_hair.cc1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.cc11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc61
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.cc1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_toon.cc1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.cc1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.cc4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.cc1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bump.cc17
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_camera.cc6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_displacement.cc9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_eevee_specular.cc9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_emission.cc4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_fresnel.cc8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_geometry.cc20
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_holdout.cc1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_layer_weight.cc8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_normal_map.cc9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_object_info.cc11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output_aov.cc14
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output_material.cc44
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output_world.cc18
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_particle_info.cc13
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_shader_to_rgb.cc4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.cc20
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tangent.cc9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_coord.cc24
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_environment.cc12
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_image.cc8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vector_displacement.cc29
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vector_transform.cc39
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_volume_absorption.cc1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_volume_principled.cc1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_volume_scatter.cc1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_wireframe.cc14
45 files changed, 634 insertions, 595 deletions
diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h
index f1c08f6a589..4996f12e27d 100644
--- a/source/blender/nodes/NOD_shader.h
+++ b/source/blender/nodes/NOD_shader.h
@@ -144,10 +144,7 @@ struct bNode *ntreeShaderOutputNode(struct bNodeTree *ntree, int target);
/**
* This one needs to work on a local tree.
*/
-void ntreeGPUMaterialNodes(struct bNodeTree *localtree,
- struct GPUMaterial *mat,
- bool *has_surface_output,
- bool *has_volume_output);
+void ntreeGPUMaterialNodes(struct bNodeTree *localtree, struct GPUMaterial *mat);
#ifdef __cplusplus
}
diff --git a/source/blender/nodes/shader/node_shader_tree.cc b/source/blender/nodes/shader/node_shader_tree.cc
index 03baebfd28b..42a31f39041 100644
--- a/source/blender/nodes/shader/node_shader_tree.cc
+++ b/source/blender/nodes/shader/node_shader_tree.cc
@@ -21,6 +21,7 @@
#include "BLI_listbase.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
+#include "BLI_vector.hh"
#include "BLT_translation.h"
@@ -47,11 +48,7 @@
#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::Vector;
static bool shader_tree_poll(const bContext *C, bNodeTreeType *UNUSED(treetype))
{
@@ -250,6 +247,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 +531,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 +555,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 +565,13 @@ 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__));
+ bNode **nodes_copy = static_cast<bNode **>(
+ MEM_mallocN(sizeof(bNode *) * iter_data.node_count, __func__));
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->tmp_flag >= 0) {
int id = node->tmp_flag;
@@ -690,7 +599,7 @@ 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);
}
}
@@ -699,216 +608,441 @@ static bNode *ntree_shader_copy_branch(bNodeTree *ntree,
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. */
+ bNode **nodes_copy = static_cast<bNode **>(MEM_mallocN(sizeof(bNode *) * node_count, __func__));
+ 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);
+
+ MEM_freeN(nodes_copy);
}
-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 +1052,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_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_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