[Bf-blender-cvs] [ffd5e1e6acd] master: Eevee: Use manual derivatives for better quality bump.
Clément Foucault
noreply at git.blender.org
Fri Sep 6 16:59:27 CEST 2019
Commit: ffd5e1e6acd296a187e7af016f9d7f8a9f209f87
Author: Clément Foucault
Date: Mon Aug 19 20:33:17 2019 +0200
Branches: master
https://developer.blender.org/rBffd5e1e6acd296a187e7af016f9d7f8a9f209f87
Eevee: Use manual derivatives for better quality bump.
We basically duplicate the height map branch plugged into the bump node,
and tag each node in each branch as dx/dy/ref using `branch_tag`.
Then we add a one pixel offset on the texture coordinates if the node is
tagged as dx or dy.
The dx/dy branches are plugged into (new) hidden sockets on the bump node.
This match cycles bump better but have a performance impact. Also, complex
nodetrees can now become instruction limited and not compile anymore.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D5531
===================================================================
M source/blender/gpu/shaders/material/gpu_shader_material_bump.glsl
M source/blender/makesdna/DNA_node_types.h
M source/blender/nodes/shader/node_shader_tree.c
M source/blender/nodes/shader/node_shader_util.c
M source/blender/nodes/shader/node_shader_util.h
M source/blender/nodes/shader/nodes/node_shader_bump.c
M source/blender/nodes/shader/nodes/node_shader_tex_brick.c
M source/blender/nodes/shader/nodes/node_shader_tex_checker.c
M source/blender/nodes/shader/nodes/node_shader_tex_coord.c
M source/blender/nodes/shader/nodes/node_shader_tex_environment.c
M source/blender/nodes/shader/nodes/node_shader_tex_gradient.c
M source/blender/nodes/shader/nodes/node_shader_tex_image.c
M source/blender/nodes/shader/nodes/node_shader_tex_magic.c
M source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
M source/blender/nodes/shader/nodes/node_shader_tex_noise.c
M source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c
M source/blender/nodes/shader/nodes/node_shader_tex_wave.c
===================================================================
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_bump.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_bump.glsl
index 1137e5acdc6..fabc070b0bc 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_bump.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_bump.glsl
@@ -1,5 +1,22 @@
-void node_bump(
- float strength, float dist, float height, vec3 N, vec3 surf_pos, float invert, out vec3 result)
+void dfdx_v3(vec3 v, out vec3 dy)
+{
+ dy = v + abs(dFdx(v));
+}
+
+void dfdy_v3(vec3 v, out vec3 dy)
+{
+ dy = v + abs(dFdy(v));
+}
+
+void node_bump(float strength,
+ float dist,
+ float height,
+ float height_dx,
+ float height_dy,
+ vec3 N,
+ vec3 surf_pos,
+ float invert,
+ out vec3 result)
{
N = mat3(ViewMatrix) * normalize(N);
dist *= gl_FrontFacing ? invert : -invert;
@@ -14,8 +31,8 @@ void node_bump(
/* Compute surface gradient and determinant. */
float det = dot(dPdx, Rx);
- float dHdx = dFdx(height);
- float dHdy = dFdy(height);
+ float dHdx = height_dx - height;
+ float dHdy = height_dy - height;
vec3 surfgrad = dHdx * Rx + dHdy * Ry;
strength = max(strength, 0.0);
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index ee5e9a13f66..6d2b278472f 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -276,7 +276,8 @@ typedef struct bNode {
short preview_xsize, preview_ysize;
/** Used at runtime when going through the tree. Initialize before use. */
short tmp_flag;
- char _pad2[2];
+ /** Used at runtime to tag derivatives branches. EEVEE only. */
+ short branch_tag;
/** Runtime during drawing. */
struct uiBlock *block;
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index 41f13087f67..a21ed6aa4cc 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -713,19 +713,22 @@ static bool ntree_branch_count_and_tag_nodes(bNode *fromnode,
return true;
}
-static void ntree_shader_copy_branch_displacement(bNodeTree *ntree,
- bNode *displacement_node,
- bNodeSocket *displacement_socket,
- bNodeLink *displacement_link)
+/* Create a copy of a branch starting from a given node.
+ * callback is executed once for every copied node.
+ * Returns input node copy. */
+static bNode *ntree_shader_copy_branch(bNodeTree *ntree,
+ bNode *start_node,
+ void (*callback)(bNode *node, int user_data),
+ int user_data)
{
/* Init tmp flag. */
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
node->tmp_flag = -1;
}
/* Count and tag all nodes inside the displacement branch of the tree. */
- displacement_node->tmp_flag = 0;
+ start_node->tmp_flag = 0;
int node_count = 1;
- nodeChainIter(ntree, displacement_node, ntree_branch_count_and_tag_nodes, &node_count, true);
+ nodeChainIter(ntree, start_node, ntree_branch_count_and_tag_nodes, &node_count, true);
/* Make a full copy of the branch */
bNode **nodes_copy = MEM_mallocN(sizeof(bNode *) * node_count, __func__);
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
@@ -755,15 +758,30 @@ static void ntree_shader_copy_branch_displacement(bNodeTree *ntree,
nodeAddLink(ntree, fromnode, fromsock, tonode, tosock);
}
}
+ /* Per node callback. */
+ if (callback) {
+ for (int i = 0; i < node_count; i++) {
+ callback(nodes_copy[i], user_data);
+ }
+ }
+ bNode *start_node_copy = nodes_copy[start_node->tmp_flag];
+ MEM_freeN(nodes_copy);
+ return start_node_copy;
+}
+
+static void ntree_shader_copy_branch_displacement(bNodeTree *ntree,
+ bNode *displacement_node,
+ bNodeSocket *displacement_socket,
+ bNodeLink *displacement_link)
+{
/* Replace displacement socket/node/link. */
bNode *tonode = displacement_link->tonode;
bNodeSocket *tosock = displacement_link->tosock;
- displacement_node = nodes_copy[displacement_node->tmp_flag];
+ displacement_node = ntree_shader_copy_branch(ntree, displacement_node, NULL, 0);
displacement_socket = ntree_shader_node_find_output(displacement_node,
displacement_socket->identifier);
nodeRemLink(ntree, displacement_link);
nodeAddLink(ntree, displacement_node, displacement_socket, tonode, tosock);
- MEM_freeN(nodes_copy);
ntreeUpdateTree(G.main, ntree);
}
@@ -838,6 +856,47 @@ static void ntree_shader_relink_displacement(bNodeTree *ntree, bNode *output_nod
ntreeUpdateTree(G.main, ntree);
}
+static void node_tag_branch_as_derivative(bNode *node, int dx)
+{
+ if (dx) {
+ node->branch_tag = 1;
+ }
+ else {
+ node->branch_tag = 2;
+ }
+}
+
+static bool ntree_shader_bump_branches(bNode *UNUSED(fromnode),
+ bNode *tonode,
+ void *userdata,
+ const bool UNUSED(reversed))
+{
+ bNodeTree *ntree = (bNodeTree *)userdata;
+
+ if (tonode->type == SH_NODE_BUMP) {
+ bNodeSocket *height_dx_sock, *height_dy_sock, *bump_socket, *bump_dx_socket, *bump_dy_socket;
+ bNode *bump = tonode;
+ bump_socket = ntree_shader_node_find_input(bump, "Height");
+ bump_dx_socket = ntree_shader_node_find_input(bump, "Height_dx");
+ bump_dy_socket = ntree_shader_node_find_input(bump, "Height_dy");
+ if (bump_dx_socket->link) {
+ /* Avoid reconnecting the same bump twice. */
+ }
+ else if (bump_socket && bump_socket->link) {
+ bNodeLink *link = bump_socket->link;
+ bNode *height = link->fromnode;
+ bNode *height_dx = ntree_shader_copy_branch(ntree, height, node_tag_branch_as_derivative, 1);
+ bNode *height_dy = ntree_shader_copy_branch(ntree, height, node_tag_branch_as_derivative, 0);
+ height_dx_sock = ntree_shader_node_find_output(height_dx, link->fromsock->identifier);
+ height_dy_sock = ntree_shader_node_find_output(height_dy, link->fromsock->identifier);
+ nodeAddLink(ntree, height_dx, height_dx_sock, bump, bump_dx_socket);
+ nodeAddLink(ntree, height_dy, height_dy_sock, bump, bump_dy_socket);
+ /* We could end iter here, but other bump node could be plugged into other input sockets. */
+ }
+ }
+ return true;
+}
+
static bool ntree_tag_bsdf_cb(bNode *fromnode,
bNode *UNUSED(tonode),
void *userdata,
@@ -925,6 +984,10 @@ void ntreeGPUMaterialNodes(bNodeTree *localtree,
*/
ntree_shader_relink_displacement(localtree, output);
+ /* Duplicate bump height branches for manual derivatives.
+ */
+ nodeChainIter(localtree, output, ntree_shader_bump_branches, localtree, true);
+
/* TODO(fclem): consider moving this to the gpu shader tree evaluation. */
nTreeTags tags = {
.ssr_id = 1.0,
diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c
index a2b18b61480..cf58846a051 100644
--- a/source/blender/nodes/shader/node_shader_util.c
+++ b/source/blender/nodes/shader/node_shader_util.c
@@ -258,6 +258,30 @@ void ntreeExecGPUNodes(bNodeTreeExec *exec, GPUMaterial *mat, bNode *output_node
}
}
+void node_shader_gpu_bump_tex_coord(GPUMaterial *mat, bNode *node, GPUNodeLink **link)
+{
+ if (node->branch_tag == 1) {
+ /* Add one time the value fo derivative to the input vector. */
+ GPU_link(mat, "dfdx_v3", *link, link);
+ }
+ else if (node->branch_tag == 2) {
+ /* Add one time the value fo derivative to the input vector. */
+ GPU_link(mat, "dfdy_v3", *link, link);
+ }
+ else {
+ /* nothing to do, reference center value. */
+ }
+}
+
+void node_shader_gpu_default_tex_coord(GPUMaterial *mat, bNode *node, GPUNodeLink **link)
+{
+ if (!*link) {
+ *link = GPU_attribute(CD_ORCO, "");
+ GPU_link(mat, "generated_texco", GPU_builtin(GPU_VIEW_POSITION), *link, link);
+ node_shader_gpu_bump_tex_coord(mat, node, link);
+ }
+}
+
void node_shader_gpu_tex_mapping(GPUMaterial *mat,
bNode *node,
GPUNodeStack *in,
diff --git a/source/blender/nodes/shader/node_shader_util.h b/source/blender/nodes/shader/node_shader_util.h
index a3c553b983b..9719d0b36f5 100644
--- a/source/blender/nodes/shader/node_shader_util.h
+++ b/source/blender/nodes/shader/node_shader_util.h
@@ -84,6 +84,12 @@ void nodestack_get_vec(float *in, short type_in, bNodeStack *ns);
void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, struct bNodeStack *ns);
void node_data_from_gpu_stack(struct bNodeStack *ns, struct GPUNodeStack *gs);
+void node_shader_gpu_bump_tex_coord(struct GPUMaterial *mat,
+ struct bNode *node,
+ struct GPUNodeLink **link);
+void node_shader_gpu_default_tex_coord(struct GPUMaterial *mat,
+ struct bNode *node,
+ struct GPUNodeLink **link);
void node_shader_gpu_tex_mapping(struct GPUMaterial *mat,
struct bNode *node,
struct GPUNodeStack *in,
diff --git a/source/blender/nodes/shader/nodes/node_shader_bump.c b/source/blender/nodes/shader/nodes/node_shader_bump.c
index d17edae35df..384701d2ddf 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bump.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bump.c
@@ -24,32 +24,17 @@
#include "node_shader_util.h"
/* **************** BUMP ******************** */
+/* clang-format off */
static bNodeSocketTemplate sh_node_bump_in[] = {
{SOCK_FLOAT, 1, N_("Strength"), 1.0f, 0.0f, 0.0f, 0
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list