[Bf-blender-cvs] [6e8ab6d2139] soc-2018-hair-shader: Add hair dye to Melanin concentration mode

L. E. Segovia noreply at git.blender.org
Tue Jun 5 02:54:54 CEST 2018


Commit: 6e8ab6d2139590c5454f146746dc8d990b4d7e84
Author: L. E. Segovia
Date:   Tue Jun 5 00:54:03 2018 +0000
Branches: soc-2018-hair-shader
https://developer.blender.org/rB6e8ab6d2139590c5454f146746dc8d990b4d7e84

Add hair dye to Melanin concentration mode

This lets you dye the hair after the melanin, using d'Eon's mapping.
Set white (default) to apply no dye, and any other color to apply dye.
Inspired in V-Ray's new hair shader (https://www.chaosgroup.com/blog/v-ray-next-the-science-behind-the-new-hair-shader)

Ref T54796

===================================================================

M	intern/cycles/kernel/closure/bsdf_hair_principled.h
M	intern/cycles/kernel/shaders/node_principled_hair_bsdf.osl
M	intern/cycles/kernel/svm/svm_closure.h
M	intern/cycles/render/graph.cpp
M	intern/cycles/render/nodes.cpp
M	intern/cycles/render/nodes.h
M	source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.c

===================================================================

diff --git a/intern/cycles/kernel/closure/bsdf_hair_principled.h b/intern/cycles/kernel/closure/bsdf_hair_principled.h
index b63e7353772..7943b64bc00 100644
--- a/intern/cycles/kernel/closure/bsdf_hair_principled.h
+++ b/intern/cycles/kernel/closure/bsdf_hair_principled.h
@@ -94,6 +94,8 @@ ccl_device_inline float bessel_I0(float x)
 ccl_device_inline float log_bessel_I0(float x)
 {
 	if (x > 12.0f) {
+		// log(1/x) == -log(x) iff x > 0.
+		// This is only used with positive cosines
 		return x + 0.5f * (1.f / (8.0f * x) - M_LN_2PI_F - logf(x));
 	}
 	else {
diff --git a/intern/cycles/kernel/shaders/node_principled_hair_bsdf.osl b/intern/cycles/kernel/shaders/node_principled_hair_bsdf.osl
index e5c2e52d2a6..d3e4f01808f 100644
--- a/intern/cycles/kernel/shaders/node_principled_hair_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_principled_hair_bsdf.osl
@@ -24,6 +24,7 @@ shader node_principled_hair_bsdf(
 	color Color = 0.8,
 	float Melanin = 0.0,
 	float MelaninRedness = 1.3,
+	color Tint = 1.0,
 	color AbsorptionCoefficient = color(0.245531, 0.52, 1.365),
 	normal Normal = Ng,
 	string parametrization = "Absorption coefficient",
@@ -44,7 +45,11 @@ shader node_principled_hair_bsdf(
 		Sigma = -log3(max(AbsorptionCoefficient, 1e-5));
 	}
 	else if (parametrization == "Melanin concentration") {
-		Sigma = Melanin*color(0.419, 0.697, 1.37) + MelaninRedness*color(0.187, 0.4, 1.05);
+		color Melanin_Sigma = Melanin*color(0.419, 0.697, 1.37) + MelaninRedness*color(0.187, 0.4, 1.05);
+		float roughness_fac = (((((0.245*RoughnessU) + 5.574)*RoughnessU - 10.73)*RoughnessU + 2.532)*RoughnessU - 0.215)*RoughnessU + 5.969;
+		color Tint_Sigma = log3(Tint)/roughness_fac;
+		Tint_Sigma *= Tint_Sigma;
+		Sigma = Melanin_Sigma + Tint_Sigma;
 	}
 	else if (parametrization == "Direct coloring"){
 		float roughness_fac = (((((0.245*RoughnessU) + 5.574)*RoughnessU - 10.73)*RoughnessU + 2.532)*RoughnessU - 0.215)*RoughnessU + 5.969;
diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h
index bf7b96bc7e7..2807de3b2b6 100644
--- a/intern/cycles/kernel/svm/svm_closure.h
+++ b/intern/cycles/kernel/svm/svm_closure.h
@@ -724,6 +724,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
 #ifdef __HAIR__
 		case CLOSURE_BSDF_HAIR_PRINCIPLED_ID: {
 			uint4 data_node2 = read_node(kg, offset);
+			uint4 data_node3 = read_node(kg, offset);
 
 			float3 weight = sd->svm_closure_weight * mix_weight;
 
@@ -739,6 +740,9 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
 			float m0_roughness = (stack_valid(primary_reflection_roughness_ofs))? stack_load_float(stack, primary_reflection_roughness_ofs): __uint_as_float(data_node2.y);
 			float eumelanin = (stack_valid(eumelanin_ofs)) ? stack_load_float(stack, eumelanin_ofs) : __uint_as_float(data_node2.z);
 			float pheomelanin = (stack_valid(pheomelanin_ofs)) ? stack_load_float(stack, pheomelanin_ofs) : __uint_as_float(data_node2.w);
+			
+			uint tint_ofs;
+			decode_node_uchar4(data_node3.x, &tint_ofs, NULL, NULL, NULL);
 
 			PrincipledHairBSDF *bsdf = (PrincipledHairBSDF*)bsdf_alloc(sd, sizeof(PrincipledHairBSDF), weight);
 			if(bsdf) {
@@ -757,6 +761,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
 
 				float3 color = stack_load_float3(stack, color_ofs);
 				float3 absorption_coefficient = stack_load_float3(stack, absorption_coefficient_ofs);
+				float3 tint = stack_load_float3(stack, tint_ofs);
 				switch(parametrization) {
 					case NODE_PRINCIPLED_HAIR_DIRECT_ABSORPTION:
 						bsdf->sigma = absorption_coefficient;
@@ -764,9 +769,14 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
 					case NODE_PRINCIPLED_HAIR_PHYSICAL:
 						bsdf->sigma = -log3(max(absorption_coefficient, make_float3(1e-5f, 1e-5f, 1e-5f)));
 						break;
-					case NODE_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION:
-						bsdf->sigma = eumelanin*make_float3(0.419f, 0.697f, 1.37f) + pheomelanin*make_float3(0.187f, 0.4f, 1.05f);
+					case NODE_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION: {
+						float3 melanin_sigma = eumelanin*make_float3(0.419f, 0.697f, 1.37f) + pheomelanin*make_float3(0.187f, 0.4f, 1.05f);
+						float roughness_fac = (((((0.245f*param2) + 5.574f)*param2 - 10.73f)*param2 + 2.532f)*param2 - 0.215f)*param2 + 5.969f;
+						float3 tint_sigma =  log3(tint)/roughness_fac;
+						tint_sigma *= tint_sigma;
+						bsdf->sigma = melanin_sigma + tint_sigma;
 						break;
+					}
 					case NODE_PRINCIPLED_HAIR_REFLECTANCE: {
 						float roughness_fac = (((((0.245f*param2) + 5.574f)*param2 - 10.73f)*param2 + 2.532f)*param2 - 0.215f)*param2 + 5.969f;
 						bsdf->sigma = log3(color)/roughness_fac;
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index 074d5bc7254..fdc7c259dbb 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -1073,7 +1073,7 @@ int ShaderGraph::get_num_closures()
 			num_closures += VOLUME_STACK_SIZE;
 		}
 		else if(closure_type == CLOSURE_BSDF_HAIR_PRINCIPLED_ID) {
-			num_closures += 2;
+			num_closures += 3;
 		}
 		else {
 			++num_closures;
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 5d722001dc2..64dddfafcda 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -3045,6 +3045,7 @@ NODE_DEFINE(PrincipledHairBsdfNode)
 	SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
 	SOCKET_IN_FLOAT(eumelanin, "Melanin", 0.0f);
 	SOCKET_IN_FLOAT(pheomelanin, "Melanin Redness", 1.3f);
+	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_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);
@@ -3086,6 +3087,7 @@ void PrincipledHairBsdfNode::compile(SVMCompiler& compiler)
 	ShaderInput *pheomelanin_in = input("Melanin Redness");
 
 	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"));
 
 	compiler.add_node(NODE_CLOSURE_BSDF,
@@ -3114,6 +3116,16 @@ void PrincipledHairBsdfNode::compile(SVMCompiler& compiler)
 		__float_as_int(primary_reflection_roughness),
 		__float_as_int(eumelanin),
 		__float_as_int(pheomelanin));
+	
+	compiler.add_node(
+	  compiler.encode_uchar4(
+		 tint_ofs,
+		 SVM_STACK_INVALID,
+		 SVM_STACK_INVALID,
+		 SVM_STACK_INVALID),
+	  SVM_STACK_INVALID,
+	  SVM_STACK_INVALID,
+	  SVM_STACK_INVALID);
 }
 
 void PrincipledHairBsdfNode::compile(OSLCompiler& compiler)
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index c83682a9b99..9c938fbe89e 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -614,6 +614,7 @@ public:
 	float3 color;
 	float eumelanin;
 	float pheomelanin;
+	float3 tint;
 	float3 absorption_coefficient;
 
 	float3 normal;
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.c
index 346589f1b7d..0800646de41 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.c
@@ -33,6 +33,7 @@ static bNodeSocketTemplate sh_node_bsdf_hair_principled_in[] = {
 	{	SOCK_RGBA,   1, N_("Color"),						0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
 	{	SOCK_FLOAT,  1, N_("Melanin"),						0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 10.0f},
 	{	SOCK_FLOAT,  1, N_("Melanin Redness"),				1.3f, 0.0f, 0.0f, 0.0f, 0.0f, 10.0f},
+	{   SOCK_RGBA,   1, N_("Tint"),                         1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f},
 	// Benedikt Bitterli's default brownish hair with PHEOmelanin
 	// The absorption coefficient below is 1.3f * pheomelanin mapping
 	{	SOCK_VECTOR, 1, N_("Absorption Coefficient"),		0.245531f, 0.52f, 1.365f, 0.0f, 0.0f, 1000.0f},
@@ -84,6 +85,14 @@ static void node_shader_update_hair_principled(bNodeTree *UNUSED(ntree), bNode *
 				sock->flag |= SOCK_UNAVAIL;
 			}
 		}
+		else if (STREQ(sock->name, "Tint"))  {
+			if (parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION){
+				sock->flag &= ~SOCK_UNAVAIL;
+			}
+			else {
+				sock->flag |= SOCK_UNAVAIL;
+			}
+		}
 		else if (STREQ(sock->name, "Absorption Coefficient")) {
 			if ((parametrization == SHD_PRINCIPLED_HAIR_PHYSICAL) || (parametrization == SHD_PRINCIPLED_HAIR_DIRECT_ABSORPTION)){
 				sock->flag &= ~SOCK_UNAVAIL;



More information about the Bf-blender-cvs mailing list