Cycles: change material output displacement to vector.
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Sat, 20 Jan 2018 01:01:07 +0000 (02:01 +0100)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Tue, 23 Jan 2018 11:49:35 +0000 (12:49 +0100)
Previously only scalar displacement along the normal was supported,
now displacement can go in any direction. For backwards compatibility,
a Displacement node will be automatically inserted in existing files.

This will make it possible to support vector displacement maps in the
future. It's already possible to use them to some extent, but requires
a manual shader node setup. For tangent space maps the right tangent
may also not be available yet, depends on the map.

Differential Revision: https://developer.blender.org/D3015

intern/cycles/blender/addon/version_update.py
intern/cycles/kernel/shaders/node_output_displacement.osl
intern/cycles/kernel/svm/svm_displace.h
intern/cycles/render/graph.cpp
intern/cycles/render/nodes.cpp
intern/cycles/render/nodes.h
source/blender/blenkernel/BKE_blender_version.h
source/blender/gpu/shaders/gpu_shader_material.glsl
source/blender/nodes/shader/node_shader_tree.c
source/blender/nodes/shader/nodes/node_shader_output_material.c

index efd794461d6d5c6edd2f7596518e3a8a6e2d60ed..26cdecd2d522519820f828ef6d46b51d09ab13a0 100644 (file)
@@ -89,6 +89,47 @@ def foreach_cycles_node(callback):
                                     traversed)
 
 
+def displacement_node_insert(material, nodetree, traversed):
+    if nodetree in traversed:
+        return
+    traversed.add(nodetree)
+
+    for node in nodetree.nodes:
+        if node.bl_idname == 'ShaderNodeGroup':
+            displacement_node_insert(material, node.node_tree, traversed)
+
+    # Gather links to replace
+    displacement_links = []
+    for link in nodetree.links:
+        if link.to_node.bl_idname == 'ShaderNodeOutputMaterial' and \
+           link.from_node.bl_idname != 'ShaderNodeDisplacement' and \
+           link.to_socket.identifier == 'Displacement':
+           displacement_links.append(link)
+
+    # Replace links with displacement node
+    for link in displacement_links:
+        from_node = link.from_node
+        from_socket = link.from_socket
+        to_node = link.to_node
+        to_socket = link.to_socket
+
+        nodetree.links.remove(link)
+
+        node = nodetree.nodes.new(type='ShaderNodeDisplacement')
+        node.location[0] = 0.5 * (from_node.location[0] + to_node.location[0]);
+        node.location[1] = 0.5 * (from_node.location[1] + to_node.location[1]);
+        node.inputs['Scale'].default_value = 0.1
+
+        nodetree.links.new(from_socket, node.inputs['Height'])
+        nodetree.links.new(node.outputs['Displacement'], to_socket)
+
+def displacement_nodes_insert():
+    traversed = set()
+    for material in bpy.data.materials:
+        if check_is_new_shading_material(material):
+            displacement_node_insert(material, material.node_tree, traversed)
+
+
 def mapping_node_order_flip(node):
     """
     Flip euler order of mapping shader node
@@ -315,3 +356,6 @@ def do_versions(self):
                 cscene.blur_glossy = 0.0
             if not cscene.is_property_set("sample_clamp_indirect"):
                 cscene.sample_clamp_indirect = 0.0
+
+    if bpy.data.version <= (2, 79, 1):
+        displacement_nodes_insert()
index 294b8dd6bf222d7ff71041594ccf5454823337e0..5dbef0244fe9a3ef4a04b272ff8c5ab28dee7aa7 100644 (file)
 
 #include "stdosl.h"
 
-displacement node_output_displacement(float Displacement = 0.0)
+displacement node_output_displacement(vector Displacement = 0.0)
 {
-       vector dP = normalize(transform("object", N));
-       dP *= Displacement * 0.1; /* todo: get rid of this factor */
-       P += transform("object", "world", dP);
+       P += Displacement;
 }
 
index 1ac2c8fd52e36534ef6a308b7bd0df7790197ea7..3066a3646844ffd84be96135822295468cda6683 100644 (file)
@@ -83,15 +83,7 @@ ccl_device void svm_node_set_bump(KernelGlobals *kg, ShaderData *sd, float *stac
 
 ccl_device void svm_node_set_displacement(KernelGlobals *kg, ShaderData *sd, float *stack, uint fac_offset)
 {
-       float d = stack_load_float(stack, fac_offset);
-
-       float3 dP = sd->N;
-       object_inverse_normal_transform(kg, sd, &dP);
-
-       dP *= d*0.1f; /* todo: get rid of this factor */
-
-       object_dir_transform(kg, sd, &dP);
-
+       float3 dP = stack_load_float3(stack, fac_offset);
        sd->P += dP;
 }
 
index 56434b39da5d88af67818f5cdc3aced942cdc0b9..fb2e34c2fc70e834d8a69413f512739f27ffb679 100644 (file)
@@ -526,10 +526,10 @@ void ShaderGraph::constant_fold()
         * that happens to ensure there is still a valid graph for displacement.
         */
        if(has_displacement && !output()->input("Displacement")->link) {
-               ValueNode *value = (ValueNode*)add(new ValueNode());
+               ColorNode *value = (ColorNode*)add(new ColorNode());
                value->value = output()->displacement;
 
-               connect(value->output("Value"), output()->input("Displacement"));
+               connect(value->output("Color"), output()->input("Displacement"));
        }
 }
 
@@ -861,7 +861,7 @@ void ShaderGraph::bump_from_displacement(bool use_object_space)
 
        if(!displacement_in->link)
                return;
-       
+
        /* find dependencies for the given input */
        ShaderNodeSet nodes_displace;
        find_dependencies(nodes_displace, displacement_in);
@@ -893,15 +893,34 @@ void ShaderGraph::bump_from_displacement(bool use_object_space)
        /* add bump node and connect copied graphs to it */
        BumpNode *bump = (BumpNode*)add(new BumpNode());
        bump->use_object_space = use_object_space;
+       bump->distance = 1.0f;
 
        ShaderOutput *out = displacement_in->link;
        ShaderOutput *out_center = nodes_center[out->parent]->output(out->name());
        ShaderOutput *out_dx = nodes_dx[out->parent]->output(out->name());
        ShaderOutput *out_dy = nodes_dy[out->parent]->output(out->name());
 
-       connect(out_center, bump->input("SampleCenter"));
-       connect(out_dx, bump->input("SampleX"));
-       connect(out_dy, bump->input("SampleY"));
+       /* convert displacement vector to height */
+       VectorMathNode *dot_center = (VectorMathNode*)add(new VectorMathNode());
+       VectorMathNode *dot_dx = (VectorMathNode*)add(new VectorMathNode());
+       VectorMathNode *dot_dy = (VectorMathNode*)add(new VectorMathNode());
+
+       dot_center->type = NODE_VECTOR_MATH_DOT_PRODUCT;
+       dot_dx->type = NODE_VECTOR_MATH_DOT_PRODUCT;
+       dot_dy->type = NODE_VECTOR_MATH_DOT_PRODUCT;
+
+       GeometryNode *geom = (GeometryNode*)add(new GeometryNode());
+       connect(geom->output("Normal"), dot_center->input("Vector2"));
+       connect(geom->output("Normal"), dot_dx->input("Vector2"));
+       connect(geom->output("Normal"), dot_dy->input("Vector2"));
+
+       connect(out_center, dot_center->input("Vector1"));
+       connect(out_dx, dot_dx->input("Vector1"));
+       connect(out_dy, dot_dy->input("Vector1"));
+
+       connect(dot_center->output("Value"), bump->input("SampleCenter"));
+       connect(dot_dx->output("Value"), bump->input("SampleX"));
+       connect(dot_dy->output("Value"), bump->input("SampleY"));
        
        /* connect the bump out to the set normal in: */
        connect(bump->output("Normal"), set_normal->input("Direction"));
index 87e8ec3d3ccaa9e4183b7b472b71baf76002dd4f..14c0dbab9f3f0f1f354da40ad9af806206a1ac5a 100644 (file)
@@ -4780,7 +4780,7 @@ NODE_DEFINE(OutputNode)
 
        SOCKET_IN_CLOSURE(surface, "Surface");
        SOCKET_IN_CLOSURE(volume, "Volume");
-       SOCKET_IN_FLOAT(displacement, "Displacement", 0.0f);
+       SOCKET_IN_VECTOR(displacement, "Displacement", make_float3(0.0f, 0.0f, 0.0f));
        SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f));
 
        return type;
index d1f32bbf491d454386d446348f93f1c1683174bd..578451cbcfa324413d0dd4261cea351b5f4da1c4 100644 (file)
@@ -154,7 +154,7 @@ public:
 
        void *surface;
        void *volume;
-       float displacement;
+       float3 displacement;
        float3 normal;
 
        /* Don't allow output node de-duplication. */
index f95b1963a916a903a34c93858b9f7288dd74aa73..c99da724794862f5ab2d2fbb390510fabb3eee0b 100644 (file)
@@ -28,7 +28,7 @@
  * and keep comment above the defines.
  * Use STRINGIFY() rather than defining with quotes */
 #define BLENDER_VERSION         279
-#define BLENDER_SUBVERSION      1
+#define BLENDER_SUBVERSION      2
 /* Several breakages with 270, e.g. constraint deg vs rad */
 #define BLENDER_MINVERSION      270
 #define BLENDER_MINSUBVERSION   6
index b89317da84a5d553cd219e5162c0e2ffa3f6d48c..b54bd213b749722e30e6eeb4a34e8c9d4f67613d 100644 (file)
@@ -3823,7 +3823,7 @@ void node_displacement(float height, float dist, vec3 N, out vec3 result)
 
 /* output */
 
-void node_output_material(vec4 surface, vec4 volume, float displacement, out vec4 result)
+void node_output_material(vec4 surface, vec4 volume, vec3 displacement, out vec4 result)
 {
        result = surface;
 }
index b4cdb1585264f2e45852f5cfefd4e7efb2f13e56..8fa074c5cb7aef4b46e22a0699bd52a3b2ac5416 100644 (file)
@@ -449,6 +449,21 @@ static void ntree_shader_relink_displacement(bNodeTree *ntree,
         * cycles in the Cycles material :)
         */
        nodeRemLink(ntree, displacement_link);
+
+       /* Convert displacement vector to bump height. */
+       bNode *dot_node = nodeAddStaticNode(NULL, ntree, SH_NODE_VECT_MATH);
+       bNode *geo_node = nodeAddStaticNode(NULL, ntree, SH_NODE_NEW_GEOMETRY);
+       dot_node->custom1 = 3; /* dot product */
+
+       nodeAddLink(ntree,
+                   displacement_node, displacement_socket,
+                   dot_node, dot_node->inputs.first);
+       nodeAddLink(ntree,
+                   geo_node, ntree_shader_node_find_output(geo_node, "Normal"),
+                   dot_node, dot_node->inputs.last);
+       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.
         */
index 336536b21ee693186f2e37f53d032040d3408cd2..aeb8b546eeda48e419957fd46800d19580fc6a96 100644 (file)
@@ -32,7 +32,7 @@
 static bNodeSocketTemplate sh_node_output_material_in[] = {
        {       SOCK_SHADER, 1, N_("Surface")},
        {       SOCK_SHADER, 1, N_("Volume")},
-       {       SOCK_FLOAT, 1, N_("Displacement"),      0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
+       {       SOCK_VECTOR, 1, N_("Displacement"),     0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
        {       -1, 0, ""       }
 };