Cycles: change material output displacement to vector.
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
This commit is contained in:
parent
4a5ee1a5a2
commit
b129ea843a
|
@ -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()
|
||||
|
|
|
@ -16,10 +16,8 @@
|
|||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -154,7 +154,7 @@ public:
|
|||
|
||||
void *surface;
|
||||
void *volume;
|
||||
float displacement;
|
||||
float3 displacement;
|
||||
float3 normal;
|
||||
|
||||
/* Don't allow output node de-duplication. */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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, "" }
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue