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:
authorL. E. Segovia <leonardo.segovia@cs.uns.edu.ar>2018-07-18 12:14:43 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2018-07-18 14:59:06 +0300
commit5078b9d2d08a34ae3786100c2301ea960165e7f2 (patch)
tree64d375c93428292fbba4f58c8ab4f097874eeefb /intern/cycles/render
parent566b319335563888e252b2186c93606ad41ff216 (diff)
Cycles: add Principled Hair BSDF.
This is a physically-based, easy-to-use shader for rendering hair and fur, with controls for melanin, roughness and randomization. Based on the paper "A Practical and Controllable Hair and Fur Model for Production Path Tracing". Implemented by Leonardo E. Segovia and Lukas Stockner, part of Google Summer of Code 2018.
Diffstat (limited to 'intern/cycles/render')
-rw-r--r--intern/cycles/render/graph.cpp3
-rw-r--r--intern/cycles/render/nodes.cpp133
-rw-r--r--intern/cycles/render/nodes.h39
3 files changed, 175 insertions, 0 deletions
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index 78a2039c423..3a9e2981418 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -1091,6 +1091,9 @@ int ShaderGraph::get_num_closures()
else if(CLOSURE_IS_VOLUME(closure_type)) {
num_closures += VOLUME_STACK_SIZE;
}
+ else if(closure_type == CLOSURE_BSDF_HAIR_PRINCIPLED_ID) {
+ num_closures += 4;
+ }
else {
++num_closures;
}
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 986004433e4..96e7459a48c 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -3092,6 +3092,139 @@ void PrincipledVolumeNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_principled_volume");
}
+/* Principled Hair BSDF Closure */
+
+NODE_DEFINE(PrincipledHairBsdfNode)
+{
+ NodeType* type = NodeType::add("principled_hair_bsdf", create, NodeType::SHADER);
+
+ /* Color parametrization specified as enum. */
+ static NodeEnum parametrization_enum;
+ parametrization_enum.insert("Direct coloring", NODE_PRINCIPLED_HAIR_REFLECTANCE);
+ parametrization_enum.insert("Melanin concentration", NODE_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION);
+ parametrization_enum.insert("Absorption coefficient", NODE_PRINCIPLED_HAIR_DIRECT_ABSORPTION);
+ SOCKET_ENUM(parametrization, "Parametrization", parametrization_enum, NODE_PRINCIPLED_HAIR_REFLECTANCE);
+
+ /* Initialize sockets to their default values. */
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.017513f, 0.005763f, 0.002059f));
+ SOCKET_IN_FLOAT(melanin, "Melanin", 0.8f);
+ SOCKET_IN_FLOAT(melanin_redness, "Melanin Redness", 1.0f);
+ SOCKET_IN_COLOR(tint, "Tint", make_float3(1.f, 1.f, 1.f));
+ SOCKET_IN_VECTOR(absorption_coefficient, "Absorption Coefficient", make_float3(0.245531f, 0.52f, 1.365f), SocketType::VECTOR);
+
+ SOCKET_IN_FLOAT(offset, "Offset", 2.f*M_PI_F/180.f);
+ SOCKET_IN_FLOAT(roughness, "Roughness", 0.3f);
+ SOCKET_IN_FLOAT(radial_roughness, "Radial Roughness", 0.3f);
+ SOCKET_IN_FLOAT(coat, "Coat", 0.0f);
+ SOCKET_IN_FLOAT(ior, "IOR", 1.55f);
+
+ SOCKET_IN_FLOAT(random_roughness, "Random Roughness", 0.0f);
+ SOCKET_IN_FLOAT(random_color, "Random Color", 0.0f);
+ SOCKET_IN_FLOAT(random, "Random", 0.0f);
+
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+
+ return type;
+}
+
+PrincipledHairBsdfNode::PrincipledHairBsdfNode()
+: BsdfBaseNode(node_type)
+{
+ closure = CLOSURE_BSDF_HAIR_PRINCIPLED_ID;
+}
+
+/* Enable retrieving Hair Info -> Random if Random isn't linked. */
+void PrincipledHairBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
+{
+ if(!input("Random")->link) {
+ attributes->add(ATTR_STD_CURVE_RANDOM);
+ }
+ ShaderNode::attributes(shader, attributes);
+}
+
+/* Prepares the input data for the SVM shader. */
+void PrincipledHairBsdfNode::compile(SVMCompiler& compiler)
+{
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, make_float3(1.0f, 1.0f, 1.0f));
+
+ ShaderInput *roughness_in = input("Roughness");
+ ShaderInput *radial_roughness_in = input("Radial Roughness");
+ ShaderInput *random_roughness_in = input("Random Roughness");
+ ShaderInput *offset_in = input("Offset");
+ ShaderInput *coat_in = input("Coat");
+ ShaderInput *ior_in = input("IOR");
+ ShaderInput *melanin_in = input("Melanin");
+ ShaderInput *melanin_redness_in = input("Melanin Redness");
+ ShaderInput *random_color_in = input("Random Color");
+
+ int color_ofs = compiler.stack_assign(input("Color"));
+ int tint_ofs = compiler.stack_assign(input("Tint"));
+ int absorption_coefficient_ofs = compiler.stack_assign(input("Absorption Coefficient"));
+
+ ShaderInput *random_in = input("Random");
+ int attr_random = random_in->link ? SVM_STACK_INVALID : compiler.attribute(ATTR_STD_CURVE_RANDOM);
+
+ /* Encode all parameters into data nodes. */
+ compiler.add_node(NODE_CLOSURE_BSDF,
+ /* Socket IDs can be packed 4 at a time into a single data packet */
+ compiler.encode_uchar4(closure,
+ compiler.stack_assign_if_linked(roughness_in),
+ compiler.stack_assign_if_linked(radial_roughness_in),
+ compiler.closure_mix_weight_offset()),
+ /* The rest are stored as unsigned integers */
+ __float_as_uint(roughness),
+ __float_as_uint(radial_roughness));
+
+ compiler.add_node(compiler.stack_assign_if_linked(input("Normal")),
+ compiler.encode_uchar4(
+ compiler.stack_assign_if_linked(offset_in),
+ compiler.stack_assign_if_linked(ior_in),
+ color_ofs,
+ parametrization),
+ __float_as_uint(offset),
+ __float_as_uint(ior));
+
+ compiler.add_node(
+ compiler.encode_uchar4(
+ compiler.stack_assign_if_linked(coat_in),
+ compiler.stack_assign_if_linked(melanin_in),
+ compiler.stack_assign_if_linked(melanin_redness_in),
+ absorption_coefficient_ofs),
+ __float_as_uint(coat),
+ __float_as_uint(melanin),
+ __float_as_uint(melanin_redness));
+
+ compiler.add_node(
+ compiler.encode_uchar4(
+ tint_ofs,
+ compiler.stack_assign_if_linked(random_in),
+ compiler.stack_assign_if_linked(random_color_in),
+ compiler.stack_assign_if_linked(random_roughness_in)),
+ __float_as_uint(random),
+ __float_as_uint(random_color),
+ __float_as_uint(random_roughness));
+
+ compiler.add_node(
+ compiler.encode_uchar4(
+ SVM_STACK_INVALID,
+ SVM_STACK_INVALID,
+ SVM_STACK_INVALID,
+ SVM_STACK_INVALID),
+ attr_random,
+ SVM_STACK_INVALID,
+ SVM_STACK_INVALID);
+}
+
+/* Prepares the input data for the OSL shader. */
+void PrincipledHairBsdfNode::compile(OSLCompiler& compiler)
+{
+ compiler.parameter(this, "parametrization");
+ compiler.add(this, "node_principled_hair_bsdf");
+}
+
/* Hair BSDF Closure */
NODE_DEFINE(HairBsdfNode)
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index ebe6db6e362..28bbe2de05a 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -608,6 +608,45 @@ public:
float temperature;
};
+/* Interface between the I/O sockets and the SVM/OSL backend. */
+class PrincipledHairBsdfNode : public BsdfBaseNode {
+public:
+ SHADER_NODE_CLASS(PrincipledHairBsdfNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+
+ /* Longitudinal roughness. */
+ float roughness;
+ /* Azimuthal roughness. */
+ float radial_roughness;
+ /* Randomization factor for roughnesses. */
+ float random_roughness;
+ /* Longitudinal roughness factor for only the diffuse bounce (shiny undercoat). */
+ float coat;
+ /* Index of reflection. */
+ float ior;
+ /* Cuticle tilt angle. */
+ float offset;
+ /* Direct coloring's color. */
+ float3 color;
+ /* Melanin concentration. */
+ float melanin;
+ /* Melanin redness ratio. */
+ float melanin_redness;
+ /* Dye color. */
+ float3 tint;
+ /* Randomization factor for melanin quantities. */
+ float random_color;
+ /* Absorption coefficient (unfiltered). */
+ float3 absorption_coefficient;
+
+ float3 normal;
+ float surface_mix_weight;
+ /* If linked, here will be the given random number. */
+ float random;
+ /* Selected coloring parametrization. */
+ NodePrincipledHairParametrization parametrization;
+};
+
class HairBsdfNode : public BsdfNode {
public:
SHADER_NODE_CLASS(HairBsdfNode)