Skip to content

Commit

Permalink
Add hair nodes to MDL backend (AcademySoftwareFoundation#2059)
Browse files Browse the repository at this point in the history
This PR introduces support for hair nodes to the MDL backend.

Nodes to add:
- `<chiang_hair_bsdf>`
- `<deon_hair_absorption_from_melanin>`
- `<chiang_hair_absorption_from_color>`
- `<chiang_hair_roughness>`
  • Loading branch information
msuzuki-nvidia authored Oct 13, 2024
1 parent 4f380f3 commit 0ba2ad0
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 8 deletions.
12 changes: 12 additions & 0 deletions libraries/pbrlib/genmdl/pbrlib_genmdl_impl.mtlx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
<!-- <sheen_bsdf> -->
<implementation name="IM_sheen_bsdf_genmdl" nodedef="ND_sheen_bsdf" sourcecode="materialx::pbrlib_{{MDL_VERSION_SUFFIX}}::mx_sheen_bsdf(mxp_weight:{{weight}}, mxp_color:{{color}}, mxp_roughness:{{roughness}}, mxp_normal:{{normal}}, mxp_base:{{base}})" target="genmdl" />

<!-- <chiang_hair_bsdf> -->
<implementation name="IM_chiang_hair_bsdf_genmdl" nodedef="ND_chiang_hair_bsdf" sourcecode="materialx::pbrlib_{{MDL_VERSION_SUFFIX}}::mx_chiang_hairbsdf(mxp_tint_R:{{tint_R}}, mxp_tint_TT:{{tint_TT}}, mxp_tint_TRT:{{tint_TRT}}, mxp_ior:{{ior}}, mxp_roughness_R:{{roughness_R}}, mxp_roughness_TT:{{roughness_TT}}, mxp_roughness_TRT:{{roughness_TRT}}, mxp_cuticle_angle:{{cuticle_angle}}, mxp_absorption_coefficient:{{absorption_coefficient}}, mxp_curve_direction:{{curve_direction}})" target="genmdl" />

<!-- <uniform_edf> -->
<implementation name="IM_uniform_edf_genmdl" nodedef="ND_uniform_edf" sourcecode="materialx::pbrlib_{{MDL_VERSION_SUFFIX}}::mx_uniform_edf(mxp_color:{{color}})" target="genmdl" />

Expand Down Expand Up @@ -90,4 +93,13 @@
<!-- <blackbody> -->
<implementation name="IM_blackbody_genmdl" nodedef="ND_blackbody" sourcecode="materialx::pbrlib_{{MDL_VERSION_SUFFIX}}::mx_blackbody(mxp_temperature:{{temperature}})" target="genmdl" />

<!-- <deon_hair_absorption_from_melanin> -->
<implementation name="IM_deon_hair_absorption_from_melanin_genmdl" nodedef="ND_deon_hair_absorption_from_melanin" sourcecode="materialx::pbrlib_{{MDL_VERSION_SUFFIX}}::mx_deon_hair_absorption_from_melanin(mxp_melanin_concentration:{{melanin_concentration}}, mxp_melanin_redness:{{melanin_redness}}, mxp_eumelanin_color:{{eumelanin_color}}, mxp_pheomelanin_color:{{pheomelanin_color}})" function="mx_deon_hair_absorption_from_melanin" target="genmdl" />

<!-- <chiang_hair_absorption_from_color> -->
<implementation name="IM_chiang_hair_absorption_from_color_genmdl" nodedef="ND_chiang_hair_absorption_from_color" sourcecode="materialx::pbrlib_{{MDL_VERSION_SUFFIX}}::mx_chiang_hair_absorption_from_color(mxp_color:{{color}}, mxp_azimuthal_roughness:{{azimuthal_roughness}})" function="mx_chiang_hair_absorption_from_color" target="genmdl" />

<!-- <chiang_hair_roughness> -->
<implementation name="IM_chiang_hair_roughness_genmdl" nodedef="ND_chiang_hair_roughness" file="mx_hair_bsdf.glsl" sourcecode="materialx::pbrlib_{{MDL_VERSION_SUFFIX}}::mx_chiang_hair_roughness(mxp_longitudinal:{{longitudinal}}, mxp_azimuthal:{{azimuthal}}, mxp_scale_TT:{{scale_TT}}, mxp_scale_TRT:{{scale_TRT}})" target="genmdl" />

</materialx>
90 changes: 90 additions & 0 deletions source/MaterialXGenMdl/mdl/materialx/pbrlib_1_6.mdl
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,35 @@ export material mx_thin_film_bsdf(
volume: mxp_base.volume
);

export material mx_chiang_hair_bsdf(
// TODO: MDL's chiang_hair BSDF has no support tinting each lobes
color mxp_tint_R = color(1.0),
color mxp_tint_TT = color(1.0),
color mxp_tint_TRT = color(1.0),
float mxp_ior = 1.55,
float2 mxp_roughness_R = float2(0.1, 0.1),
float2 mxp_roughness_TT = float2(0.05, 0.05),
float2 mxp_roughness_TRT = float2(0.2, 0.2),
float mxp_cuticle_angle = 0.5,
float3 mxp_absorption_coefficient = float3(0.0),
// TODO: MDL's chiang_hair BSDF has no support user tangent vector
float3 mxp_curve_direction = state::texture_tangent_u(0)
) [[
anno::usage( "materialx:bsdf")
]]
= material(
hair: df::chiang_hair_bsdf(
diffuse_reflection_weight: 0.0,
diffuse_reflection_tint: color(0.0),
roughness_R: mxp_roughness_R,
roughness_TT: mxp_roughness_TT,
roughness_TRT: mxp_roughness_TRT,
cuticle_angle: mxp_cuticle_angle,
absorption_coefficient: mxp_absorption_coefficient,
ior: mxp_ior
)
);

// EDF Nodes

export material mx_uniform_edf(
Expand Down Expand Up @@ -980,3 +1009,64 @@ export mx_artistic_ior__result mx_artistic_ior(
color k = math::sqrt(k2);
return mx_artistic_ior__result(n,k);
}

export float3 mx_dion_hair_absorption_from_melanin(
float mxp_melanin_concentration = 0.25,
float mxp_melanin_redness = 0.5,
color mxp_eumelanin_color = color(0.657704, 0.498077, 0.254107),
color mxp_pheomelanin_color = color(0.829444, 0.67032, 0.349938)
) {
float melanin = -math::log(math::max(1.0 - mxp_melanin_concentration, 0.0001));
float eumelanin = melanin * (1.0 = mxp_melanin_redness);
float pheomelanin = melanin * mxp_melanin_redness;
return math::max(
eumelanin * -math::log(mxp_eumelanin_color) + pheomelanin * -math::log(mxp_pheomelanin_color),
float3(0.0)
);
}

export float3 mx_chiang_hair_absorption_from_color(
color mxp_color = color(1.0, 1.0, 1.0),
float mxp_azimuthal_roughness = 0.2
) {
float r2 = mxp_azimuthal_roughness * mxp_azimuthal_roughness;
float r4 = r2 * r2;
float r_fac =
5.969 -
(0.215 * mxp_azimuthal_roughness) +
(2.532 * r2) -
(10.73 * r2 * mxp_azimuthal_roughness) +
(5.574 * r4) +
(0.245 * r4 * mxp_azimuthal_roughness);
float3 sigma = math::log(math::min(math::max(mxp_color, 0.001), float3(1.0))) / r_fac;
return (sigma * sigma);
}

// Supportive struct type for the three outputs of mx_chiang_hair_roughness
export struct mx_chiang_hair_roughness__result {
float2 mxp_roughness_R;
float2 mxp_roughness_TT;
float2 mxp_roughness_TRT;
};

export mx_chiang_hair_roughness__result mx_chiang_hair_roughness(
float mxp_longitudinal = 0.1,
float mxp_azimuthal = 0.2,
float mxp_scale_TT = 0.5,
float mxp_scale_TRT = 2.0
) {
float lr = math::clamp(mxp_longitudinal, 0.001, 1.0);
float ar = math::clamp(mxp_azimuthal, 0.001, 1.0);

// longitudinal variance
float v = 0.726 * lr + 0.812 * lr * lr + 3.7 * math::pow(lr, 20);
v = v * v;

float s = 0.265 * ar + 1.194 * ar * ar + 5.372 * math::pow(ar, 22);

float2 roughness_R = float2(v, s);
float2 roughness_TT = float2(v * mxp_scale_TT * mxp_scale_TT, s);
float2 roughness_TRT = float2(v * mxp_scale_TRT * mxp_scale_TRT, s);

return mx_chiang_hair_roughness__result(roughness_R, roughness_TT, roughness_TRT);
}
6 changes: 1 addition & 5 deletions source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,8 @@ TEST_CASE("GenShader: MDL Implementation Check", "[genmdl]")
generatorSkipNodeTypes.insert("light");

mx::StringSet generatorSkipNodeDefs;
generatorSkipNodeDefs.insert("ND_chiang_hair_roughness");
generatorSkipNodeDefs.insert("ND_chiang_hair_absorption_from_color");
generatorSkipNodeDefs.insert("ND_deon_hair_absorption_from_melanin");
generatorSkipNodeDefs.insert("ND_chiang_hair_bsdf");

GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs, 35);
GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs, 31);
}


Expand Down
3 changes: 0 additions & 3 deletions source/MaterialXTest/MaterialXGenMdl/GenMdl.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,6 @@ class MdlShaderGeneratorTester : public GenShaderUtil::ShaderGeneratorTester
_skipFiles.insert("heighttonormal_in_nodegraph.mtlx");
}

_skipFiles.insert("hair_bsdf.mtlx");
_skipFiles.insert("hair_surfaceshader.mtlx");

ShaderGeneratorTester::addSkipFiles();
}

Expand Down

0 comments on commit 0ba2ad0

Please sign in to comment.