[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