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

Update MDL code generator to support MDL 1.7 #1273

Merged
merged 3 commits into from
Mar 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions libraries/pbrlib/genmdl/pbrlib_genmdl_impl.mtlx
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,17 @@
<implementation name="IM_mix_vdf_genmdl" nodedef="ND_mix_vdf" sourcecode="mx::pbrlib::mx_mix_vdf(mxp_fg:{{fg}}, mxp_bg:{{bg}}, mxp_mix:{{mix}})" target="genmdl" />

<!-- <add> -->
<implementation name="IM_add_bsdf_genmdl" nodedef="ND_add_bsdf" sourcecode="{{in1}}" target="genmdl" /> <!-- TODO: Implement properly -->
<implementation name="IM_add_edf_genmdl" nodedef="ND_add_edf" sourcecode="{{in2}}" target="genmdl" /> <!-- TODO: Implement properly -->
<implementation name="IM_add_bsdf_genmdl" nodedef="ND_add_bsdf" sourcecode="mx::pbrlib::mx_add_bsdf(mxp_in1:{{in1}}, mxp_in2:{{in2}})" target="genmdl" />
<implementation name="IM_add_edf_genmdl" nodedef="ND_add_edf" sourcecode="mx::pbrlib::mx_add_edf(mxp_in1:{{in1}}, mxp_in2:{{in2}})" target="genmdl" />
<implementation name="IM_add_vdf_genmdl" nodedef="ND_add_vdf" sourcecode="mx::pbrlib::mx_add_vdf(mxp_in1:{{in1}}, mxp_in2:{{in2}})" target="genmdl" />

<!-- <multiply> -->
<implementation name="IM_multiply_bsdfC_genmdl" nodedef="ND_multiply_bsdfC" sourcecode="mx::pbrlib::mx_multiply_bsdf_color3(mxp_in1:{{in1}}, mxp_in2:{{in2}})" target="genmdl" />
<implementation name="IM_multiply_bsdfF_genmdl" nodedef="ND_multiply_bsdfF" sourcecode="mx::pbrlib::mx_multiply_bsdf_float(mxp_in1:{{in1}}, mxp_in2:{{in2}})" target="genmdl" />
<implementation name="IM_multiply_edfC_genmdl" nodedef="ND_multiply_edfC" sourcecode="{{in1}}" target="genmdl" /> <!-- TODO: Implement properly -->
<implementation name="IM_multiply_edfF_genmdl" nodedef="ND_multiply_edfF" sourcecode="{{in1}}" target="genmdl" /> <!-- TODO: Implement properly -->
<implementation name="IM_multiply_edfC_genmdl" nodedef="ND_multiply_edfC" sourcecode="mx::pbrlib::mx_multiply_edf_color3(mxp_in1:{{in1}}, mxp_in2:{{in2}})" target="genmdl" />
<implementation name="IM_multiply_edfF_genmdl" nodedef="ND_multiply_edfF" sourcecode="mx::pbrlib::mx_multiply_edf_float(mxp_in1:{{in1}}, mxp_in2:{{in2}})" target="genmdl" />
<implementation name="IM_multiply_vdfC_genmdl" nodedef="ND_multiply_vdfC" sourcecode="mx::pbrlib::mx_multiply_vdf_color3(mxp_in1:{{in1}}, mxp_in2:{{in2}})" target="genmdl" />
<implementation name="IM_multiply_vdfF_genmdl" nodedef="ND_multiply_vdfF" sourcecode="mx::pbrlib::mx_multiply_vdf_float(mxp_in1:{{in1}}, mxp_in2:{{in2}})" target="genmdl" />

<!-- <roughness_anisotropy> -->
<implementation name="IM_roughness_anisotropy_genmdl" nodedef="ND_roughness_anisotropy" sourcecode="mx::pbrlib::mx_roughness_anisotropy(mxp_roughness:{{roughness}}, mxp_anisotropy:{{anisotropy}})" target="genmdl" />
Expand Down
4 changes: 3 additions & 1 deletion libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,9 @@
<implementation name="IM_mix_vector3_vector3_genmdl" nodedef="ND_mix_vector3_vector3" sourcecode="math::lerp({{bg}}, {{fg}}, {{mix}})" target="genmdl" />
<implementation name="IM_mix_vector4_genmdl" nodedef="ND_mix_vector4" sourcecode="math::lerp({{bg}}, {{fg}}, {{mix}})" target="genmdl" />
<implementation name="IM_mix_vector4_vector4_genmdl" nodedef="ND_mix_vector4_vector4" sourcecode="math::lerp({{bg}}, {{fg}}, {{mix}})" target="genmdl" />
<implementation name="IM_mix_surfaceshader_genmdl" nodedef="ND_mix_surfaceshader" sourcecode="mx::pbrlib::mx_mix_bsdf({{fg}}, {{bg}}, {{mix}})" target="genmdl" />
<implementation name="IM_mix_surfaceshader_genmdl" nodedef="ND_mix_surfaceshader" sourcecode="mx::stdlib::mx_mix_surfaceshader({{fg}}, {{bg}}, {{mix}})" target="genmdl" />
<implementation name="IM_mix_surfaceshader_genmdl" nodedef="ND_mix_volumeshader" sourcecode="mx::stdlib::mx_mix_volumeshader({{fg}}, {{bg}}, {{mix}})" target="genmdl" />
<implementation name="IM_mix_surfaceshader_genmdl" nodedef="ND_mix_displacementshader" sourcecode="mx::stdlib::mx_mix_displacementshader({{fg}}, {{bg}}, {{mix}})" target="genmdl" />

<!-- ======================================================================== -->
<!-- Conditional nodes -->
Expand Down
25 changes: 23 additions & 2 deletions source/MaterialXGenMdl/MdlSyntax.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,35 @@ class MdlFilenameTypeSyntax : public ScalarTypeSyntax
{
return getDefaultValue(true);
}
// handle the empty texture, the fileprefix is passed
// assuming it ends with a slash ...
if (outputValue.back() == '/')
{
return getDefaultValue(true);
}
// ... or the last segment does not have an extension suffix
size_t idx_s = outputValue.find_last_of('/');
size_t idx_d = outputValue.find_last_of('.');
if (idx_d == std::string::npos || (idx_s != std::string::npos && idx_s > idx_d))
{
return getDefaultValue(true);
}

// prefix a slash in order to make MDL resource paths absolute i.e. to be found
// in the root of an MDL search path
// do not add the slash in case the path is explicitly relative
string pathSeparator("");
FilePath path(outputValue);
if (!path.isAbsolute())
size_t len = outputValue.size();
if (!path.isAbsolute() &&
!(len > 2 && outputValue[0] == '.' && outputValue[1] == '.' && outputValue[2] == '/') &&
!(len > 1 && outputValue[0] == '.' && outputValue[1] == '/'))
{
pathSeparator = "/";
}
return getName() + "(\"" + pathSeparator + outputValue + "\", tex::gamma_linear)";

// MDL is using leading slashes as separator
return getName() + "(\"" + pathSeparator + path.asString(FilePath::FormatPosix) + "\", tex::gamma_linear)";
}
};

Expand Down
6 changes: 3 additions & 3 deletions source/MaterialXGenMdl/mdl/materialx/core.mdl
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@
// Document v1.37 REV2, January 19, 2020
// www.materialx.org
// in
// NVIDIA Material Definition Language 1.6
// NVIDIA Material Definition Language 1.7
// Language Specification
// Document version 1.6.1, December 16, 2019
// Document version 1.7.2, January 17, 2022
// www.nvidia.com/mdl

mdl 1.6;
mdl 1.7;

import ::math::*;
import ::tex::*;
Expand Down
113 changes: 59 additions & 54 deletions source/MaterialXGenMdl/mdl/materialx/pbrlib.mdl
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
// Document v1.37 REV2, July 16, 2019 (Revised October 17, 2019)
// see www.materialx.org
// in
// NVIDIA Material Definition Language 1.6
// NVIDIA Material Definition Language 1.7
// Language Specification
// Document version 1.6.1, December 16, 2019
// Document version 1.7.2, January 17, 2022
// www.nvidia.com/mdl

mdl 1.7;
Expand Down Expand Up @@ -313,33 +313,33 @@ export material mx_subsurface_bsdf(
)
);

// TODO: MDL's sheen BSDF has no possibility to configure the base BSDF, it is
// always a diffuse BSDF. Its color is configurable through the multiscatter
// tint and can be fed through the extra mxp_diffuse_tint input. A context
// analysis in the generator can map the color of the base to this input.
// To match with OSL, the sheen weight is scaled with average color as approximation of albedo.
// OSL uses the layer operator which mixes based on albedo.
export material mx_sheen_bsdf(
float mxp_weight = 1.0,
color mxp_color = color(1.0),
float mxp_roughness = 0.2,
float3 mxp_normal = state::normal(),
material mxp_base = material() [[ anno::usage( "materialx:bsdf") ]],
color mxp_diffuse_color = color(1.0) // color of the base layer, MDL supports only diffuse
material mxp_base = material(
surface: material_surface(
scattering: df::diffuse_reflection_bsdf(
))) [[ anno::usage( "materialx:bsdf") ]]
) [[
anno::usage( "materialx:bsdf")
]]
= material(
surface: material_surface(
// using the mix seems to fit OSL best, at least in the test cases
scattering: df::weighted_layer(
weight: mxp_weight,
weight: math::average(mxp_color) * mxp_weight,
layer: df::sheen_bsdf(
roughness: mxp_roughness,
tint: mxp_color,
multiscatter_tint: mxp_diffuse_color
multiscatter_tint: color(1.0),
multiscatter: mxp_base.surface.scattering
),
base: mxp_base.surface.scattering,
normal: mxp_normal
)
),
normal: mxp_normal)),
// we need to carry volume properties along for SSS
ior: mxp_base.ior,
volume: mxp_base.volume
Expand Down Expand Up @@ -541,15 +541,20 @@ export material mx_thin_surface(
)
);

// TODO: emissive volumes not supported in MDL 1.6, EDF will be ignored here
// MDL 1.7, Volumes do support emssion, but not as EDF, just emission intensity.
// A uniform emission DF is the only practical DF here.
export material mx_volume(
material mxp_vdf = material() [[ anno::usage( "materialx:vdf") ]],
material mxp_edf = material() [[ anno::usage( "materialx:edf"), anno::unused() ]]
material mxp_edf = material() [[ anno::usage( "materialx:edf") ]]
) [[
anno::usage( "materialx:volumeshader")
]]
= material(
volume: mxp_vdf.volume
volume: material_volume(
absorption_coefficient: mxp_vdf.volume.absorption_coefficient,
scattering_coefficient: mxp_vdf.volume.scattering_coefficient,
emission_intensity: mxp_edf.surface.emission.intensity
)
);

export material mx_light(
Expand Down Expand Up @@ -631,26 +636,24 @@ export material mx_mix_bsdf(

export material mx_mix_edf(
material mxp_fg = material() [[ anno::usage( "materialx:edf") ]],
material mxp_bg = material() [[ anno::usage( "materialx:edf"), anno::unused() ]],
float mxp_mix = 0.0 [[ anno::unused() ]]
material mxp_bg = material() [[ anno::usage( "materialx:edf") ]],
float mxp_mix = 0.0
) [[
anno::usage( "materialx:edf")
]]
= mxp_fg;
// TODO: mixing two EDFs fails with the df::clamped_mix since the weights are uniform in MDL
// = material(
// surface: material_surface(
// emission: material_emission(
// emission: df::clamped_mix(
// df::edf_component[](
// df::edf_component( mxp_mix, mxp_fg.surface.emission.emission),
// df::edf_component( 1.0 - mxp_mix, mxp_bg.surface.emission.emission))
// ),
// intensity: mxp_mix * mxp_fg.surface.emission.intensity +
// (1.0 - mxp_mix) * mxp_bg.surface.emission.intensity
// )
// )
// );
= material(
surface: material_surface(
emission: material_emission(
emission: df::clamped_mix(
df::edf_component[](
df::edf_component( mxp_mix, mxp_fg.surface.emission.emission),
df::edf_component( 1.0 - mxp_mix, mxp_bg.surface.emission.emission))
),
intensity: mxp_mix * mxp_fg.surface.emission.intensity +
(1.0 - mxp_mix) * mxp_bg.surface.emission.intensity
)
)
);

export material mx_mix_vdf(
material mxp_fg = material() [[ anno::usage( "materialx:vdf") ]],
Expand Down Expand Up @@ -685,23 +688,24 @@ export material mx_add_bsdf(
]]
= material(
surface: material_surface(
scattering: df::weighted_layer(
weight: 0.5,
layer: mxp_in1.surface.scattering,
base: mxp_in2.surface.scattering
scattering: df::unbounded_mix(
df::bsdf_component[](
df::bsdf_component( 1.0, mxp_in1.surface.scattering),
df::bsdf_component( 1.0, mxp_in2.surface.scattering)
)
)
),
// we need to carry volume properties along for SSS
volume: material_volume(
scattering: df::clamped_mix(
scattering: df::unbounded_mix(
df::vdf_component[](
df::vdf_component( 0.5, mxp_in1.volume.scattering),
df::vdf_component( 0.5, mxp_in2.volume.scattering))
df::vdf_component( 1.0, mxp_in1.volume.scattering),
df::vdf_component( 1.0, mxp_in2.volume.scattering))
),
absorption_coefficient: 0.5 * mxp_in1.volume.absorption_coefficient +
0.5 * mxp_in2.volume.absorption_coefficient,
scattering_coefficient: 0.5 * mxp_in1.volume.scattering_coefficient +
0.5 * mxp_in2.volume.scattering_coefficient
absorption_coefficient: mxp_in1.volume.absorption_coefficient +
mxp_in2.volume.absorption_coefficient,
scattering_coefficient: mxp_in1.volume.scattering_coefficient +
mxp_in2.volume.scattering_coefficient
)
);

Expand All @@ -718,10 +722,10 @@ export material mx_add_edf(
= material(
surface: material_surface(
emission: material_emission(
emission: df::clamped_mix(
emission: df::unbounded_mix(
df::edf_component[](
df::edf_component( 0.5, mxp_in1.surface.emission.emission),
df::edf_component( 0.5, mxp_in2.surface.emission.emission))
df::edf_component( 1.0, mxp_in1.surface.emission.emission),
df::edf_component( 1.0, mxp_in2.surface.emission.emission))
),
intensity: mxp_in1.surface.emission.intensity + mxp_in2.surface.emission.intensity
)
Expand All @@ -738,17 +742,18 @@ export material mx_add_vdf(
anno::usage( "materialx:vdf")
]]
= material(
// assuming mixing the IOR is the best we can do here
ior: 0.5 * mxp_in1.ior + 0.5 * mxp_in2.ior,
volume: material_volume(
scattering: df::clamped_mix(
scattering: df::unbounded_mix(
df::vdf_component[](
df::vdf_component( 0.5, mxp_in1.volume.scattering),
df::vdf_component( 0.5, mxp_in2.volume.scattering))
df::vdf_component( 1.0, mxp_in1.volume.scattering),
df::vdf_component( 1.0, mxp_in2.volume.scattering))
),
absorption_coefficient: 0.5 * mxp_in1.volume.absorption_coefficient +
0.5 * mxp_in2.volume.absorption_coefficient,
scattering_coefficient: 0.5 * mxp_in1.volume.scattering_coefficient +
0.5 * mxp_in2.volume.scattering_coefficient
absorption_coefficient: mxp_in1.volume.absorption_coefficient +
mxp_in2.volume.absorption_coefficient,
scattering_coefficient: mxp_in1.volume.scattering_coefficient +
mxp_in2.volume.scattering_coefficient
)
);

Expand Down
Loading