diff --git a/libraries/pbrlib/genmdl/pbrlib_genmdl_impl.mtlx b/libraries/pbrlib/genmdl/pbrlib_genmdl_impl.mtlx
index 8da18c0fb2..416d5cc25b 100644
--- a/libraries/pbrlib/genmdl/pbrlib_genmdl_impl.mtlx
+++ b/libraries/pbrlib/genmdl/pbrlib_genmdl_impl.mtlx
@@ -72,14 +72,17 @@
-
-
+
+
+
-
-
+
+
+
+
diff --git a/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx b/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx
index e2784d65c7..f860ae7226 100644
--- a/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx
+++ b/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx
@@ -611,7 +611,9 @@
-
+
+
+
diff --git a/source/MaterialXGenMdl/MdlSyntax.cpp b/source/MaterialXGenMdl/MdlSyntax.cpp
index fcd1212a42..260eb3e38a 100644
--- a/source/MaterialXGenMdl/MdlSyntax.cpp
+++ b/source/MaterialXGenMdl/MdlSyntax.cpp
@@ -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)";
}
};
diff --git a/source/MaterialXGenMdl/mdl/materialx/core.mdl b/source/MaterialXGenMdl/mdl/materialx/core.mdl
index c146442fdf..ddcea572e4 100644
--- a/source/MaterialXGenMdl/mdl/materialx/core.mdl
+++ b/source/MaterialXGenMdl/mdl/materialx/core.mdl
@@ -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::*;
diff --git a/source/MaterialXGenMdl/mdl/materialx/pbrlib.mdl b/source/MaterialXGenMdl/mdl/materialx/pbrlib.mdl
index 684d78d4f5..23c13e3cad 100644
--- a/source/MaterialXGenMdl/mdl/materialx/pbrlib.mdl
+++ b/source/MaterialXGenMdl/mdl/materialx/pbrlib.mdl
@@ -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;
@@ -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
@@ -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(
@@ -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") ]],
@@ -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
)
);
@@ -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
)
@@ -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
)
);
diff --git a/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl b/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl
index d33e4881dc..b73e881fcb 100644
--- a/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl
+++ b/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl
@@ -7,12 +7,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;
using core import *;
import swizzle::*;
@@ -2781,7 +2781,7 @@ float mx_overlay(float mxp_fg, float mxp_bg)
{
return (mxp_fg < 0.5) ? (2 * mxp_fg * mxp_bg) : (1 - (1 - mxp_fg) * (1 - mxp_bg));
}
-float2 mx_overlay(float2 mxp_fg, float2 mxp_bg)
+float2 mx_overlay(float2 mxp_fg, float2 mxp_bg) [[ anno::unused() ]]
{
return float2(
mx_overlay(mxp_fg.x, mxp_bg.x),
@@ -2964,35 +2964,81 @@ export color4 mx_mix_color4_color4(
return mk_color4(::math::lerp(mk_float4(mxp_bg), mk_float4(mxp_fg), mk_float4(mxp_mix)));
}
+// mix all parts of the material, bsdf, edf, and vdf, geometry
export material mx_mix_surfaceshader(
- material mxp_fg [[ anno::unused() ]],
- material mxp_bg,
- float mxp_mix = float(0.0) [[ anno::unused() ]]
-)
- [[
- anno::description("Node Group: compositing")
- ]]
-= mxp_bg; // TODO
+ material mxp_fg = material() [[ anno::usage( "materialx:surfaceshader") ]],
+ material mxp_bg = material() [[ anno::usage( "materialx:surfaceshader") ]],
+ float mxp_mix = 0.0
+) [[
+ anno::description("Node Group: compositing"),
+ anno::usage( "materialx:surfaceshader")
+]]
+= material(
+ surface: material_surface(
+ scattering: df::weighted_layer(
+ weight: mxp_mix,
+ layer: mxp_fg.surface.scattering,
+ base: mxp_bg.surface.scattering
+ ),
+ 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_displacementshader(
- material mxp_fg [[ anno::unused() ]],
- material mxp_bg,
- float mxp_mix = float(0.0) [[ anno::unused() ]]
-)
- [[
- anno::description("Node Group: compositing")
- ]]
-= mxp_bg; // TODO
+ // we need to carry volume properties along for SSS
+ ior: mxp_fg.ior, // NOTE: IOR is uniform, cannot mix here
+ volume: material_volume(
+ scattering: df::clamped_mix(
+ df::vdf_component[](
+ df::vdf_component( mxp_mix, mxp_fg.volume.scattering),
+ df::vdf_component( 1.0 - mxp_mix, mxp_bg.volume.scattering))
+ ),
+ absorption_coefficient: mxp_mix * mxp_fg.volume.absorption_coefficient +
+ (1.0 - mxp_mix) * mxp_bg.volume.absorption_coefficient,
+ scattering_coefficient: mxp_mix * mxp_fg.volume.scattering_coefficient +
+ (1.0 - mxp_mix) * mxp_bg.volume.scattering_coefficient
+ ),
+ geometry: material_geometry(
+ displacement: mxp_mix * mxp_fg.geometry.displacement +
+ (1.0 - mxp_mix) * mxp_bg.geometry.displacement,
+ cutout_opacity: mxp_mix * mxp_fg.geometry.cutout_opacity +
+ (1.0 - mxp_mix) * mxp_bg.geometry.cutout_opacity,
+ normal: mxp_mix * mxp_fg.geometry.normal +
+ (1.0 - mxp_mix) * mxp_bg.geometry.normal
+ )
+);
export material mx_mix_volumeshader(
- material mxp_fg [[ anno::unused() ]],
- material mxp_bg,
- float mxp_mix = float(0.0) [[ anno::unused() ]]
-)
- [[
- anno::description("Node Group: compositing")
- ]]
-= mxp_bg; // TODO
+ material mxp_fg = material() [[ anno::usage( "materialx:volumeshader") ]],
+ material mxp_bg = material() [[ anno::usage( "materialx:volumeshader") ]],
+ float mxp_mix = 0.0
+) [[
+ anno::description("Node Group: compositing"),
+ anno::usage( "materialx:volumeshader")
+]]
+= mx_mix_surfaceshader(
+ mxp_fg: mxp_fg,
+ mxp_bg: mxp_bg,
+ mxp_mix: mxp_mix);
+
+export material mx_mix_displacementshader(
+ material mxp_fg = material() [[ anno::usage( "materialx:displacementshader") ]],
+ material mxp_bg = material() [[ anno::usage( "materialx:displacementshader") ]],
+ float mxp_mix = 0.0
+) [[
+ anno::description("Node Group: compositing"),
+ anno::usage( "materialx:displacementshader")
+]]
+= mx_mix_surfaceshader(
+ mxp_fg: mxp_fg,
+ mxp_bg: mxp_bg,
+ mxp_mix: mxp_mix);
export float mx_ifgreater_float(
float mxp_value1 = float(1.0),
diff --git a/source/MaterialXTest/MaterialXGenMdl/GenMdl.h b/source/MaterialXTest/MaterialXGenMdl/GenMdl.h
index 5b635baa9c..32989afce9 100644
--- a/source/MaterialXTest/MaterialXGenMdl/GenMdl.h
+++ b/source/MaterialXTest/MaterialXGenMdl/GenMdl.h
@@ -72,7 +72,8 @@ class MdlShaderGeneratorTester : public GenShaderUtil::ShaderGeneratorTester
{
"ambientocclusion", "arrayappend", "backfacing", "screen", "curveadjust", "displacementshader",
"volumeshader", "IM_constant_", "IM_dot_", "IM_geomattrvalue", "IM_angle",
- "geompropvalue", "surfacematerial", "volumematerial", "IM_absorption_vdf_", "IM_mix_vdf_",
+ "geompropvalue", "surfacematerial", "volumematerial",
+ "IM_absorption_vdf_", "IM_mix_vdf_", "IM_add_vdf_", "IM_multiply_vdf",
"IM_measured_edf_", "IM_blackbody_", "IM_conical_edf_",
"IM_displacement_", "IM_thin_surface_", "IM_volume_", "IM_light_"
};