[Bf-blender-cvs] [5078b9d2d08] master: Cycles: add Principled Hair BSDF.

L. E. Segovia noreply at git.blender.org
Wed Jul 18 14:03:22 CEST 2018


Commit: 5078b9d2d08a34ae3786100c2301ea960165e7f2
Author: L. E. Segovia
Date:   Wed Jul 18 11:14:43 2018 +0200
Branches: master
https://developer.blender.org/rB5078b9d2d08a34ae3786100c2301ea960165e7f2

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.

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

M	intern/cycles/blender/blender_shader.cpp
M	intern/cycles/kernel/CMakeLists.txt
M	intern/cycles/kernel/closure/bsdf.h
A	intern/cycles/kernel/closure/bsdf_hair_principled.h
M	intern/cycles/kernel/geom/geom_curve.h
M	intern/cycles/kernel/geom/geom_curve_intersect.h
M	intern/cycles/kernel/kernel_compat_opencl.h
M	intern/cycles/kernel/kernel_volume.h
M	intern/cycles/kernel/osl/osl_closures.cpp
M	intern/cycles/kernel/osl/osl_closures.h
M	intern/cycles/kernel/shaders/CMakeLists.txt
A	intern/cycles/kernel/shaders/node_principled_hair_bsdf.osl
M	intern/cycles/kernel/shaders/stdosl.h
M	intern/cycles/kernel/svm/svm_closure.h
M	intern/cycles/kernel/svm/svm_types.h
M	intern/cycles/render/graph.cpp
M	intern/cycles/render/nodes.cpp
M	intern/cycles/render/nodes.h
M	intern/cycles/util/util_math.h
M	intern/cycles/util/util_math_float3.h
M	release/scripts/startup/nodeitems_builtins.py
M	source/blender/blenkernel/BKE_node.h
M	source/blender/blenkernel/intern/node.c
M	source/blender/editors/space_node/drawnode.c
M	source/blender/makesdna/DNA_node_types.h
M	source/blender/makesrna/intern/rna_nodetree.c
M	source/blender/nodes/CMakeLists.txt
M	source/blender/nodes/NOD_shader.h
M	source/blender/nodes/NOD_static_types.h
A	source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.c

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

diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 956f8f767a6..25e6db18588 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -524,6 +524,12 @@ static ShaderNode *add_node(Scene *scene,
 		}
 		node = hair;
 	}
+	else if(b_node.is_a(&RNA_ShaderNodeBsdfHairPrincipled)) {
+		BL::ShaderNodeBsdfHairPrincipled b_principled_hair_node(b_node);
+		PrincipledHairBsdfNode *principled_hair = new PrincipledHairBsdfNode();
+		principled_hair->parametrization = (NodePrincipledHairParametrization) get_enum(b_principled_hair_node.ptr, "parametrization", NODE_PRINCIPLED_HAIR_NUM, NODE_PRINCIPLED_HAIR_REFLECTANCE);
+		node = principled_hair;
+	}
 	else if(b_node.is_a(&RNA_ShaderNodeBsdfPrincipled)) {
 		BL::ShaderNodeBsdfPrincipled b_principled_node(b_node);
 		PrincipledBsdfNode *principled = new PrincipledBsdfNode();
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 092bec08a51..c4cad17429d 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -156,6 +156,7 @@ set(SRC_CLOSURE_HEADERS
 	closure/volume.h
 	closure/bsdf_principled_diffuse.h
 	closure/bsdf_principled_sheen.h
+    closure/bsdf_hair_principled.h
 )
 
 set(SRC_SVM_HEADERS
diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h
index f191b812f11..3a9629ea9d7 100644
--- a/intern/cycles/kernel/closure/bsdf.h
+++ b/intern/cycles/kernel/closure/bsdf.h
@@ -27,6 +27,7 @@
 #include "kernel/closure/bsdf_ashikhmin_shirley.h"
 #include "kernel/closure/bsdf_toon.h"
 #include "kernel/closure/bsdf_hair.h"
+#include "kernel/closure/bsdf_hair_principled.h"
 #include "kernel/closure/bsdf_principled_diffuse.h"
 #include "kernel/closure/bsdf_principled_sheen.h"
 #include "kernel/closure/bssrdf.h"
@@ -171,6 +172,10 @@ ccl_device_inline int bsdf_sample(KernelGlobals *kg,
 			label = bsdf_hair_transmission_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
 				eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
 			break;
+		case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
+			label = bsdf_principled_hair_sample(kg, sc, sd, randu, randv,
+				eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+			break;
 #ifdef __PRINCIPLED__
 		case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
 		case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
@@ -284,6 +289,9 @@ float3 bsdf_eval(KernelGlobals *kg,
 			case CLOSURE_BSDF_GLOSSY_TOON_ID:
 				eval = bsdf_glossy_toon_eval_reflect(sc, sd->I, omega_in, pdf);
 				break;
+			case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
+				eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf);
+				break;
 			case CLOSURE_BSDF_HAIR_REFLECTION_ID:
 				eval = bsdf_hair_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
 				break;
@@ -366,6 +374,9 @@ float3 bsdf_eval(KernelGlobals *kg,
 			case CLOSURE_BSDF_GLOSSY_TOON_ID:
 				eval = bsdf_glossy_toon_eval_transmit(sc, sd->I, omega_in, pdf);
 				break;
+			case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
+				eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf);
+				break;
 			case CLOSURE_BSDF_HAIR_REFLECTION_ID:
 				eval = bsdf_hair_reflection_eval_transmit(sc, sd->I, omega_in, pdf);
 				break;
@@ -424,6 +435,9 @@ ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness)
 		case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
 			bsdf_ashikhmin_shirley_blur(sc, roughness);
 			break;
+		case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
+			bsdf_principled_hair_blur(sc, roughness);
+			break;
 		default:
 			break;
 	}
diff --git a/intern/cycles/kernel/closure/bsdf_hair_principled.h b/intern/cycles/kernel/closure/bsdf_hair_principled.h
new file mode 100644
index 00000000000..4ee58089384
--- /dev/null
+++ b/intern/cycles/kernel/closure/bsdf_hair_principled.h
@@ -0,0 +1,502 @@
+/*
+ * Copyright 2018 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef __KERNEL_CPU__
+#include <fenv.h>
+#endif
+
+#include "kernel/kernel_color.h"
+
+#ifndef __BSDF_HAIR_PRINCIPLED_H__
+#define __BSDF_HAIR_PRINCIPLED_H__
+
+CCL_NAMESPACE_BEGIN
+
+typedef ccl_addr_space struct PrincipledHairExtra {
+	/* Geometry data. */
+	float4 geom;
+} PrincipledHairExtra;
+
+typedef ccl_addr_space struct PrincipledHairBSDF {
+	SHADER_CLOSURE_BASE;
+
+	/* Absorption coefficient. */
+	float3 sigma;
+	/* Variance of the underlying logistic distribution. */
+	float v;
+	/* Scale factor of the underlying logistic distribution. */
+	float s;
+	/* Cuticle tilt angle. */
+	float alpha;
+	/* IOR. */
+	float eta;
+	/* Effective variance for the diffuse bounce only. */
+	float m0_roughness;
+
+	/* Extra closure. */
+	PrincipledHairExtra *extra;
+} PrincipledHairBSDF;
+
+static_assert(sizeof(ShaderClosure) >= sizeof(PrincipledHairBSDF), "PrincipledHairBSDF is too large!");
+static_assert(sizeof(ShaderClosure) >= sizeof(PrincipledHairExtra), "PrincipledHairExtra is too large!");
+
+ccl_device_inline float cos_from_sin(const float s)
+{
+	return safe_sqrtf(1.0f - s*s);
+}
+
+/* Gives the change in direction in the normal plane for the given angles and p-th-order scattering. */
+ccl_device_inline float delta_phi(int p, float gamma_o, float gamma_t)
+{
+	return 2.0f * p * gamma_t - 2.0f * gamma_o + p * M_PI_F;
+}
+
+/* Remaps the given angle to [-pi, pi]. */
+ccl_device_inline float wrap_angle(float a)
+{
+	while(a > M_PI_F) {
+		a -= M_2PI_F;
+	}
+	while(a < -M_PI_F) {
+		a += M_2PI_F;
+	}
+	return a;
+}
+
+/* Logistic distribution function. */
+ccl_device_inline float logistic(float x, float s)
+{
+	float v = expf(-fabsf(x)/s);
+	return v / (s * sqr(1.0f + v));
+}
+
+/* Logistic cumulative density function. */
+ccl_device_inline float logistic_cdf(float x, float s)
+{
+	float arg = -x/s;
+	/* expf() overflows if arg >= 89.0. */
+	if(arg > 88.0f) {
+		return 0.0f;
+	}
+	else {
+		return 1.0f / (1.0f + expf(arg));
+	}
+}
+
+/* Numerical approximation to the Bessel function of the first kind. */
+ccl_device_inline float bessel_I0(float x)
+{
+	x = sqr(x);
+	float val = 1.0f + 0.25f*x;
+	float pow_x_2i = sqr(x);
+	uint64_t i_fac_2 = 1;
+	int pow_4_i = 16;
+	for(int i = 2; i < 10; i++) {
+		i_fac_2 *= i*i;
+		float newval = val + pow_x_2i / (pow_4_i * i_fac_2);
+		if(val == newval) {
+			return val;
+		}
+		val = newval;
+		pow_x_2i *= x;
+		pow_4_i *= 4;
+	}
+	return val;
+}
+
+/* Logarithm of the Bessel function of the first kind. */
+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 {
+		return logf(bessel_I0(x));
+	}
+}
+
+/* Logistic distribution limited to the interval [-pi, pi]. */
+ccl_device_inline float trimmed_logistic(float x, float s)
+{
+	/* The logistic distribution is symmetric and centered around zero,
+	 * so logistic_cdf(x, s) = 1 - logistic_cdf(-x, s).
+	 * Therefore, logistic_cdf(x, s)-logistic_cdf(-x, s) = 1 - 2*logistic_cdf(-x, s) */
+	float scaling_fac = 1.0f - 2.0f*logistic_cdf(-M_PI_F, s);
+	float val = logistic(x, s);
+	return safe_divide(val, scaling_fac);
+}
+
+/* Sampling function for the trimmed logistic function. */
+ccl_device_inline float sample_trimmed_logistic(float u, float s)
+{
+	float cdf_minuspi = logistic_cdf(-M_PI_F, s);
+	float x = -s*logf(1.0f / (u*(1.0f - 2.0f*cdf_minuspi) + cdf_minuspi) - 1.0f);
+	return clamp(x, -M_PI_F, M_PI_F);
+}
+
+/* Azimuthal scattering function Np. */
+ccl_device_inline float azimuthal_scattering(float phi,
+                                             int p,
+                                             float s,
+                                             float gamma_o,
+                                             float gamma_t)
+{
+	float phi_o = wrap_angle(phi - delta_phi(p, gamma_o, gamma_t));
+	float val = trimmed_logistic(phi_o, s);
+	return val;
+}
+
+/* Longitudinal scattering function Mp. */
+ccl_device_inline float longitudinal_scattering(float sin_theta_i,
+                                                float cos_theta_i,
+                                                float sin_theta_o,
+                                                float cos_theta_o,
+                                                float v)
+{
+	float inv_v = 1.0f/v;
+	float cos_arg = cos_theta_i * cos_theta_o * inv_v;
+	float sin_arg = sin_theta_i * sin_theta_o * inv_v;
+	if(v <= 0.1f) {
+		float i0 = log_bessel_I0(cos_arg);
+		float val = expf(i0 - sin_arg - inv_v + 0.6931f + logf(0.5f*inv_v));
+		return val;
+	}
+	else {
+		float i0 = bessel_I0(cos_arg);
+		float val = (expf(-sin_arg) * i0) / (sinhf(inv_v) * 2.0f * v);
+		return val;
+	}
+}
+
+/* Combine the three values using their luminances. */
+ccl_device_inline float4 combine_with_energy(KernelGlobals *kg, float3 c)
+{
+	return make_float4(c.x, c.y, c.z, linear_rgb_to_gray(kg, c));
+}
+
+#ifdef __HAIR__
+/* Set up the hair closure. */
+ccl_device int bsdf_principled_hair_setup(ShaderData *sd, PrincipledHairBSDF *bsdf)
+{
+	bsdf->type = CLOSURE_BSDF_HAIR_PRINCIPLED_ID;
+	bsdf->v = clamp(bsdf->v, 0.001f, 1.0f);
+	bsdf->s = clamp(bsdf->s, 0.001f, 1.0f);
+	/* Apply Primary Reflection Roughness modifier. */
+	bsdf->m0_roughness = clamp(bsdf->m0_roughness*bsdf->v, 0.001f, 1.0f);
+
+	/* Map from roughness_u and roughness_v to variance and scale factor. */
+	bsdf->v = sqr(0.726f*bsdf->v + 0.812f*sqr(bsdf->v) + 3.700f*pow20(bsdf->v));
+	bsdf->s =    (0.265f*bsdf->s + 1.194f*sqr(bsdf->s) + 5.372f*pow22(bsdf->s))*M_SQRT_PI_8_F;
+	bsdf->m0_roughness = sqr(0.726f*bsdf->m0_roughness + 0.812f*sqr(bsdf->m0_roughness) + 3.700f*pow20(bsdf->m0_roughness));
+
+	/* Compute local frame, aligned to cu

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list