Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: MaterialX Hair BSDF #1973

Closed
msuzuki-nvidia opened this issue Aug 15, 2024 · 1 comment
Closed

Proposal: MaterialX Hair BSDF #1973

msuzuki-nvidia opened this issue Aug 15, 2024 · 1 comment

Comments

@msuzuki-nvidia
Copy link
Contributor

MaterialX Hair BSDF Proposal

This document proposes a new MaterialX hair BSDF node and a set of support functions which
can be used to build an all purpose hair material model. The BSDF is based on the paper A Practical and Controllable Hair and Fur Model for Production Path Tracing (Chiang et al. 2016)1. The BSDF is widely used in visual effects and animation to model hair and fur and provides a physically grounded hair and fur shading model with artist friendly parameterization suitable for production quality rendering. The support functions are derived from the supporting literature and allow us to create parameterizations based on the melanin present in the hair strands or based on artist friendly normalized values.

BSDF

chiang_hair_bsdf: Constructs aggregated reflective and transmissive scattering based on the Chiang et al.1 hair shading model. This hair shading model categorizes the light paths according to the number of internal reflections. The first three categories (and their lobes) are labeled based on event types as R, TT, and TRT, where R denotes a reflection event and T denotes a transmission event. The first three are modeled as separate lobes with roughness parameters along the longitudinal and azimuthal directions, while all longer paths are implicitly accounted for in a fourth lobe in the model without additional parameters; the longitudinal roughness of the fourth lobe is set to the one of the third lobe, while the model needs no roughness parameter for the azimuthal direction.

Parameters

Parameters Type Range Default Description
tint_R color3 (0, 1) (1, 1, 1) Color multiplier for the first R-lobe.
tint_TT color3 (0, 1) (1, 1, 1) Color multiplier for the first TT-lobe.
tint_TRT color3 (0, 1) (1, 1, 1) Color multiplier for the first TRT-lobe.
roughness_R vector2 [0, ∞) (0.1, 0.1) Longitudinal and azimuthal roughness (ν, s) for the first R-lobe. With (0, 0) specifying pure specular scattering.
roughness_TT vector2 [0, ∞) (0.05, 0.05) Longitudinal and azimuthal roughness (ν, s) for the second TT-lobe. With (0, 0) specifying pure specular scattering.
roughness_TRT vector2 [0, ∞) (0.2, 0.2) Longitudinal and azimuthal roughness (ν, s) for the third TRT-lobe. With (0, 0) specifying pure specular scattering.
cuticle_angle float [0, 1] 0.5 Cuticle angle in radians, Values above 0.5 tilt the scales towards the root of the fiber. With 0.5 specifying no tilt.
absorption_coefficient vector3 (0, 0, 0) Absorption coefficient normalized to the hair fiber diameter.
ior float 1.55 Index of refraction. With 1.55 being the value for keratin as default.

Roughness

For artistically intuitive parameterization of roughness, we propose the following functions from Chiang et al.1 paper (eq. 7 and 8) for the BSDF.

Longitudinal Roughness

$compute\_v(\beta_M)=(0.726\beta_M+0.812\beta_M^2+3.7\beta_M^{20})^2$

Anisotropic Azimuthal Roughness

$compute\_s(\beta_N)=\sqrt{\pi/8}(0.265\beta_N+1.194\beta_N^2+5.372\beta_N^{22})$

(The constant $\sqrt{\pi/8}$ can be found in the Chiang et al.1 paper Appendix A. eq. 12)

Absorption

Absorption Coefficient from Color

To calculate the absorption coefficient we propose the following artistic friendly function from Chiang et al.1 (eq. 9).

$compute\_absorption\_from\_color(C,\beta_N)=(lnC/(5.969-0.215\beta_N+2.532\beta_N^2-10.73\beta_N^3+5.574\beta_N^4+0.245\beta_N^5))^2$

Absorption Coefficient from Melanin

For absorption based on pigments eumelanin and pheomelanin we use the work from An Energy-Conserving Hair Reflectance Model (d'Eon et al. 2011, Section 6.1)2 and propose the following absorption coefficient function based on melanin workflows.

$\mu_a=\rho_e\sigma_{a,e}+\rho_p\sigma_{a,p}$
$compute\_absorption\_from\_melanin(\rho_e,\rho_p)=\rho_e(0.419, 0.697, 1.37)+\rho_p(0.187, 0.4, 1.04)$

Linearization

Something to be discussed is that Melanin has a range of $[0, \infty)$. In our tests we implemented several normalizations and the results can be found here however we make no recommendations at this time. Blender makes use of a log function (Blender.org)3 which provides a pretty good result although it has some rapid changes in the upper range.

Practical Implementation

For purposes of discussion, we present a simple implementation in MDL45 with examples using the proposed functions. Additional implementations are also available.637

SimpleHairBase is a development material written in MDL and rendered in Omniverse for the purposes of exploring hair rendering. It is a hybrid of the Chiang et al.1 and d’Eon et al.2 methods and provides Users the option to calculate absorption using either the artists friendly function or the melanin function. The material defaults to isotropic roughness but we provide the option to enable azimuthal roughness. Overall the model allows our Users a wide range of flexibility when rendering hair and we believe the proposed components allow for a reasonable means for exchange.

// Public parameters for SimpleHairBase
export material SimpleHairBase
(
	float base_color_weight = 1.0,
	color base_color = color(1.0),
	float melanin_concentration = 1.0,
	float melanin_redness = 0.5,
	float specular_reflection_roughness = 0.1,
	bool specular_reflection_anisotropic_roughness = false,
	float specular_reflection_azimuthal_roughness = 0.2,
	uniform float specular_reflection_ior = 1.55,
	float specular_reflection_shift = 0.5,
	color tint_R = color(1.0),
	color tint_TT = color(1.0),
	color tint_TRT = color(1.0)
)
= let {
	// Specular reflection
	float longitudinal_roughness = compute_v(specular_reflection_roughness);
	float azimuthal_roughness = specular_reflection_anisotropic_roughness ?
		compute_s(specular_reflection_azimuthal_roughness) :
		longitudinal_roughness;

	float2 roughness_r = (longitudinal_roughness, azimuthal_roughness);
	float2 roughness_tt = roughness_r * float2(0.25);  // Roughening/tightening of the different lobes
	float2 roughness_trt = roughness_r * float2(4.0);  // as described in Marschner et al. 2003's paper

	// Remapping cuticle angle [0, 1] to [-PI/2, +PI/2]
	float cutical_angle_in_radians = specular_reflection_shift * math::PI - (math::PI / 2.0);

	// Absorption from Melanin Concentration
	float melanin = -math::log(math::max(1 - melanin_concentration, 0.0001));
	float eumelanin = melanin * (1 - melanin_redness);
	float pheomelanin = melanin * melanin_redness;
	color melanin_sigma_a = compute_absorption_from_melanin(eumelanin, pheomelanin);

	// Absorption from Base Color
	color base_color_sigma_a = compute_absorption_from_color(
		base_color_weight * base_color,
		specular_reflection_anisotropic_roughness ? 
			specular_reflection_azimuthal_roughness :
			longitudinal_roughness
	);

	color absorption_coefficient = 
		base_color == color(1.0) && base_color_weight == 1.0f ?
			melanin_sigma_a :
			base_color_sigma_a;

	hair_bsdf hair = df::chiang_hair_bsdf(
		tint_R: tint_R,
		tint_TT: tint_TT,
		tint_TRT: tint_TRT,
		roughness_R: roughness_r,
		roughness_TT: roughness_tt,
		roughness_TRT: roughness_trt,
		cuticle_angle: cuticle_angle_in_radian,
		absorption_coefficient: absorption_coefficient,
		ior: math::max(specular_reflection_ior, 1.0f + 1.e-5)
	);

	// ... add diffuse component etc ...

} in material (
	thin_walled: true,
	hair: hair
);

Examples

Footnotes

  1. Matt J. Chiang, Benedikt Bitterli, Chuck Tappan, Brent Burley: A Practical and Controllable Hair and Fur Model for Production Path Tracing (2016), https://media.disneyanimation.com/uploads/production/publication_asset/152/asset/eurographics2016Fur_Smaller.pdf 2 3 4 5 6

  2. Eugene d'Eon, Guillaume Francois, Martin Hill, Joe Letteri, Jean-Marie Aubry: An Energy-Conserving Hair Reflectance Model (2011), https://eugenedeon.com/pdfs/egsrhair.pdf 2

  3. Blender.org: Principled Hair BSDF, https://docs.blender.org/manual/en/latest/render/shader\_nodes/shader/hair\_principled.html 2

  4. NVIDIA Corporation: NVIDIA Material Definition Language 1.8 (2023), https://raytracing-docs.nvidia.com/mdl/specification/MDL\_spec\_1.8.2\_24May2023.pdf

  5. NVIDIA Corporation: NVIDIA Material Definition Language SDK, https://github.com/NVIDIA/MDL-SDK/blob/master/src/mdl/jit/libbsdf/libbsdf_hair.h

  6. Benedikt Bitterli: The Tungsten Renderer, https://github.com/tunabrain/tungsten

  7. Matt Pharr: THE IMPLEMENTATION OF A HAIR SCATTERING MODEL (2016), https://pbrt.org/hair.pdf

jstone-lucasfilm pushed a commit that referenced this issue Sep 19, 2024
This PR provides Chiang hair BSDF model and related nodes proposed by #1973 

The nodes to add are:
- `<chiang_hair_bsdf>` : The BSDF
- `<chiang_hair_roughness>` : User friendly roughness mapping
- `<chiang_hair_absorption_from_color>` : Absorption coefficient mapping from user input color
- `<deon_hair_absorption_from_melanin>` : Absorption coefficient mapping from melanin parameters

It also include `simple_hair_default` material as a node graph example.
@jstone-lucasfilm
Copy link
Member

Major thanks to @msuzuki-nvidia for implementing this important feature in #1968!

Additional thanks to both @fpliu and @msuzuki-nvidia for developing the original proposal for this feature in MaterialX, and to @ld-kerley, @BrianSharpe, and others for their review and guidance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants