From 6b74cbcecdd59d30b0d7834b740059c16e3d29ae Mon Sep 17 00:00:00 2001 From: Kai Rohmer Date: Tue, 11 Jul 2023 15:34:14 +0200 Subject: [PATCH 1/4] Add support for the fileTextureVerticalFlip option in the MDL generation --- .../stdlib/genmdl/stdlib_genmdl_impl.mtlx | 12 ++--- source/MaterialXGenMdl/MdlShaderGenerator.cpp | 9 ++++ source/MaterialXGenMdl/Nodes/ImageNodeMdl.cpp | 50 +++++++++++++++++ source/MaterialXGenMdl/Nodes/ImageNodeMdl.h | 36 +++++++++++++ .../MaterialXGenMdl/mdl/materialx/stdlib.mdl | 54 ++++++++++++++++--- .../MaterialXTest/MaterialXGenMdl/GenMdl.cpp | 3 ++ 6 files changed, 152 insertions(+), 12 deletions(-) create mode 100644 source/MaterialXGenMdl/Nodes/ImageNodeMdl.cpp create mode 100644 source/MaterialXGenMdl/Nodes/ImageNodeMdl.h diff --git a/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx b/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx index ab0d776936..a2d630fbba 100644 --- a/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx +++ b/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx @@ -22,22 +22,22 @@ - + - + - + - + - + - + diff --git a/source/MaterialXGenMdl/MdlShaderGenerator.cpp b/source/MaterialXGenMdl/MdlShaderGenerator.cpp index dddf1f2f13..94c0761c75 100644 --- a/source/MaterialXGenMdl/MdlShaderGenerator.cpp +++ b/source/MaterialXGenMdl/MdlShaderGenerator.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -187,6 +188,14 @@ MdlShaderGenerator::MdlShaderGenerator() : // registerImplementation("IM_sheen_bsdf_" + MdlShaderGenerator::TARGET, LayerableNodeMdl::create); + + // + registerImplementation("IM_image_float_" + MdlShaderGenerator::TARGET, ImageNodeMdl::create); + registerImplementation("IM_image_color3_" + MdlShaderGenerator::TARGET, ImageNodeMdl::create); + registerImplementation("IM_image_color4_" + MdlShaderGenerator::TARGET, ImageNodeMdl::create); + registerImplementation("IM_image_vector2_" + MdlShaderGenerator::TARGET, ImageNodeMdl::create); + registerImplementation("IM_image_vector3_" + MdlShaderGenerator::TARGET, ImageNodeMdl::create); + registerImplementation("IM_image_vector4_" + MdlShaderGenerator::TARGET, ImageNodeMdl::create); } ShaderPtr MdlShaderGenerator::generate(const string& name, ElementPtr element, GenContext& context) const diff --git a/source/MaterialXGenMdl/Nodes/ImageNodeMdl.cpp b/source/MaterialXGenMdl/Nodes/ImageNodeMdl.cpp new file mode 100644 index 0000000000..502711fe01 --- /dev/null +++ b/source/MaterialXGenMdl/Nodes/ImageNodeMdl.cpp @@ -0,0 +1,50 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include +#include + +MATERIALX_NAMESPACE_BEGIN + +const string ImageNodeMdl::FLIP_V = "flip_v"; + +ShaderNodeImplPtr ImageNodeMdl::create() +{ + return std::make_shared(); +} + +void ImageNodeMdl::addInputs(ShaderNode& node, GenContext& context) const +{ + BASE::addInputs(node, context); + node.addInput(ImageNodeMdl::FLIP_V, Type::BOOLEAN)->setUniform(); +} + +bool ImageNodeMdl::isEditable(const ShaderInput& input) const +{ + if (input.getName() == ImageNodeMdl::FLIP_V) + { + return false; + } + return BASE::isEditable(input); +} + +void ImageNodeMdl::emitFunctionCall(const ShaderNode& _node, GenContext& context, ShaderStage& stage) const +{ + DEFINE_SHADER_STAGE(stage, Stage::PIXEL) + { + ShaderNode& node = const_cast(_node); + ShaderInput* flipUInput = node.getInput(ImageNodeMdl::FLIP_V); + ValuePtr value = TypedValue::createValue(context.getOptions().fileTextureVerticalFlip); + if (flipUInput) + { + flipUInput->setValue(value); + } + BASE::emitFunctionCall(_node, context, stage); + } +} + +MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenMdl/Nodes/ImageNodeMdl.h b/source/MaterialXGenMdl/Nodes/ImageNodeMdl.h new file mode 100644 index 0000000000..59736c7b8d --- /dev/null +++ b/source/MaterialXGenMdl/Nodes/ImageNodeMdl.h @@ -0,0 +1,36 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef MATERIALX_IMAGENODEMDL_H +#define MATERIALX_IMAGENODEMDL_H + +#include + +#include "SourceCodeNodeMdl.h" + +MATERIALX_NAMESPACE_BEGIN + + +/// Image node implementation for MDL +class MX_GENMDL_API ImageNodeMdl : public SourceCodeNodeMdl +{ + using BASE = SourceCodeNodeMdl; + + public: + static const string FLIP_V; ///< the empty string "" + + static ShaderNodeImplPtr create(); + + void addInputs(ShaderNode& node, GenContext& context) const override; + + bool isEditable(const ShaderInput& input) const override; + + void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; +}; + + +MATERIALX_NAMESPACE_END + +#endif diff --git a/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl b/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl index bce4a44ea5..3c43a5b77c 100644 --- a/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl +++ b/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl @@ -139,6 +139,11 @@ export float mx_image_float( anno::description("Enumeration {constant,clamp,periodic,mirror}."), anno::display_name("Frame End Action"), anno::unused() + ]], + uniform bool mxp_flip_v = false + [[ + anno::usage("for applying the 'fileTextureVerticalFlip' shader generator option."), + anno::hidden() ]] ) [[ @@ -153,7 +158,9 @@ export float mx_image_float( return mxp_default; float returnValue = ::tex::lookup_float(tex: mxp_file, - coord: mxp_texcoord, + coord: mxp_flip_v + ? float2(mxp_texcoord.x, 1.0f - mxp_texcoord.y) + : mxp_texcoord, wrap_u: map_addressmode(mxp_uaddressmode), wrap_v: map_addressmode(mxp_vaddressmode)); return returnValue; @@ -207,6 +214,11 @@ export color mx_image_color3( anno::description("Enumeration {constant,clamp,periodic,mirror}."), anno::display_name("Frame End Action"), anno::unused() + ]], + uniform bool mxp_flip_v = false + [[ + anno::usage("for applying the 'fileTextureVerticalFlip' shader generator option."), + anno::hidden() ]] ) [[ @@ -221,7 +233,9 @@ export color mx_image_color3( return mxp_default; color returnValue = ::tex::lookup_color(tex: mxp_file, - coord: mxp_texcoord, + coord: mxp_flip_v + ? float2(mxp_texcoord.x, 1.0f - mxp_texcoord.y) + : mxp_texcoord, wrap_u: map_addressmode(mxp_uaddressmode), wrap_v: map_addressmode(mxp_vaddressmode)); return returnValue; @@ -275,6 +289,11 @@ export color4 mx_image_color4( anno::description("Enumeration {constant,clamp,periodic,mirror}."), anno::display_name("Frame End Action"), anno::unused() + ]], + uniform bool mxp_flip_v = false + [[ + anno::usage("for applying the 'fileTextureVerticalFlip' shader generator option."), + anno::hidden() ]] ) [[ @@ -289,7 +308,9 @@ export color4 mx_image_color4( return mxp_default; color4 returnValue = mk_color4( ::tex::lookup_float4(tex: mxp_file, - coord: mxp_texcoord, + coord: mxp_flip_v + ? float2(mxp_texcoord.x, 1.0f - mxp_texcoord.y) + : mxp_texcoord, wrap_u: map_addressmode(mxp_uaddressmode), wrap_v: map_addressmode(mxp_vaddressmode))); return returnValue; @@ -343,6 +364,11 @@ export float2 mx_image_vector2( anno::description("Enumeration {constant,clamp,periodic,mirror}."), anno::display_name("Frame End Action"), anno::unused() + ]], + uniform bool mxp_flip_v = false + [[ + anno::usage("for applying the 'fileTextureVerticalFlip' shader generator option."), + anno::hidden() ]] ) [[ @@ -357,7 +383,9 @@ export float2 mx_image_vector2( return mxp_default; float2 returnValue = ::tex::lookup_float2(tex: mxp_file, - coord: mxp_texcoord, + coord: mxp_flip_v + ? float2(mxp_texcoord.x, 1.0f - mxp_texcoord.y) + : mxp_texcoord, wrap_u: map_addressmode(mxp_uaddressmode), wrap_v: map_addressmode(mxp_vaddressmode)); return returnValue; @@ -411,6 +439,11 @@ export float3 mx_image_vector3( anno::description("Enumeration {constant,clamp,periodic,mirror}."), anno::display_name("Frame End Action"), anno::unused() + ]], + uniform bool mxp_flip_v = false + [[ + anno::usage("for applying the 'fileTextureVerticalFlip' shader generator option."), + anno::hidden() ]] ) [[ @@ -425,7 +458,9 @@ export float3 mx_image_vector3( return mxp_default; float3 returnValue = ::tex::lookup_float3(tex: mxp_file, - coord: mxp_texcoord, + coord: mxp_flip_v + ? float2(mxp_texcoord.x, 1.0f - mxp_texcoord.y) + : mxp_texcoord, wrap_u: map_addressmode(mxp_uaddressmode), wrap_v: map_addressmode(mxp_vaddressmode)); return returnValue; @@ -479,6 +514,11 @@ export float4 mx_image_vector4( anno::description("Enumeration {constant,clamp,periodic,mirror}."), anno::display_name("Frame End Action"), anno::unused() + ]], + uniform bool mxp_flip_v = false + [[ + anno::usage("for applying the 'fileTextureVerticalFlip' shader generator option."), + anno::hidden() ]] ) [[ @@ -493,7 +533,9 @@ export float4 mx_image_vector4( return mxp_default; float4 returnValue = ::tex::lookup_float4(tex: mxp_file, - coord: mxp_texcoord, + coord: mxp_flip_v + ? float2(mxp_texcoord.x, 1.0f - mxp_texcoord.y) + : mxp_texcoord, wrap_u: map_addressmode(mxp_uaddressmode), wrap_v: map_addressmode(mxp_vaddressmode)); return returnValue; diff --git a/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp b/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp index 1a3e127cde..815706742f 100644 --- a/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp +++ b/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp @@ -289,6 +289,9 @@ void MdlShaderGeneratorTester::compileSource(const std::vector& so renderCommand += " --hdr \"" + iblFile + "\" --hdr_rotate 90"; // set scene renderCommand += " --uv_scale 0.5 1.0 --uv_offset 0.0 0.0 --uv_repeat --uv_flip"; + renderCommand += " --uv_flip"; // this will flip the v coordinate of the vertices, which flips the all + // UV operations. In contrast, the fileTextureVerticalFlip option will + // only flip the image access nodes. renderCommand += " --camera 0 0 3 0 0 0 --fov 45"; // set the material From 79ccb9c72e88d9a7494502afdfca17f334bf242b Mon Sep 17 00:00:00 2001 From: Kai Rohmer Date: Wed, 2 Aug 2023 11:34:53 +0200 Subject: [PATCH 2/4] match test suite results by introducing flips of UVs of the mesh and additionally for texture lookups. this matches OSL and GLSL now. --- source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp b/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp index 815706742f..a0a24d5a4a 100644 --- a/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp +++ b/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp @@ -288,8 +288,8 @@ void MdlShaderGeneratorTester::compileSource(const std::vector& so std::string iblFile = (rootPath / "resources/lights/san_giuseppe_bridge.hdr").asString(); renderCommand += " --hdr \"" + iblFile + "\" --hdr_rotate 90"; // set scene - renderCommand += " --uv_scale 0.5 1.0 --uv_offset 0.0 0.0 --uv_repeat --uv_flip"; - renderCommand += " --uv_flip"; // this will flip the v coordinate of the vertices, which flips the all + renderCommand += " --uv_scale 0.5 1.0 --uv_offset 0.0 0.0 --uv_repeat"; + renderCommand += " --uv_flip"; // this will flip the v coordinate of the vertices, which flips all the // UV operations. In contrast, the fileTextureVerticalFlip option will // only flip the image access nodes. renderCommand += " --camera 0 0 3 0 0 0 --fov 45"; @@ -368,6 +368,19 @@ TEST_CASE("GenShader: MDL Shader Generation", "[genmdl]") mx::GenOptions genOptions; genOptions.targetColorSpaceOverride = "lin_rec709"; + + // Flipping the texture lookups for the test renderer only. + // This is because OSL testrender does not allow to change the UV layout of their sphere (yet) and the MaterialX test suite + // adopted to the OSL behavior in order to produce comparable results. This means that raw texture coordinates, or procedurals + // that use the texture coordinates, do not match what might be expected when reading the MaterialX spec: + // "[...] the image is mapped onto the geometry based on geometry UV coordinates, with the lower-left corner of an image + // mapping to the (0,0) UV coordinate [...]" + // This means for MDL: here, and only here in the test suite, we flip the UV coordinates of mesh using the `--uv_flip` option + // of the renderer, and to correct the image orientation, we apply `fileTextureVerticalFlip`. + // In regular MDL integrations this is not needed because MDL and MaterialX define the texture space equally with the origin + // at the bottom left. + genOptions.fileTextureVerticalFlip = true; + mx::FilePath optionsFilePath = searchPath.find("resources/Materials/TestSuite/_options.mtlx"); tester.validate(genOptions, optionsFilePath); } From b0f752819182909d711f00d081e049eedea7fd7f Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Tue, 31 Oct 2023 15:58:36 -0700 Subject: [PATCH 3/4] Remove extra newlines Signed-off-by: Jonathan Stone --- source/MaterialXGenMdl/Nodes/ImageNodeMdl.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/MaterialXGenMdl/Nodes/ImageNodeMdl.h b/source/MaterialXGenMdl/Nodes/ImageNodeMdl.h index 59736c7b8d..fe88b2ce09 100644 --- a/source/MaterialXGenMdl/Nodes/ImageNodeMdl.h +++ b/source/MaterialXGenMdl/Nodes/ImageNodeMdl.h @@ -12,7 +12,6 @@ MATERIALX_NAMESPACE_BEGIN - /// Image node implementation for MDL class MX_GENMDL_API ImageNodeMdl : public SourceCodeNodeMdl { @@ -30,7 +29,6 @@ class MX_GENMDL_API ImageNodeMdl : public SourceCodeNodeMdl void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; }; - MATERIALX_NAMESPACE_END #endif From 337e7d28cda8e8924f23ee5abcec0f8fd86c93b7 Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Tue, 31 Oct 2023 16:02:18 -0700 Subject: [PATCH 4/4] Minor update to comment Signed-off-by: Jonathan Stone --- source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp b/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp index a0a24d5a4a..22ad0d456e 100644 --- a/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp +++ b/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp @@ -371,7 +371,7 @@ TEST_CASE("GenShader: MDL Shader Generation", "[genmdl]") // Flipping the texture lookups for the test renderer only. // This is because OSL testrender does not allow to change the UV layout of their sphere (yet) and the MaterialX test suite - // adopted to the OSL behavior in order to produce comparable results. This means that raw texture coordinates, or procedurals + // adopts the OSL behavior in order to produce comparable results. This means that raw texture coordinates, or procedurals // that use the texture coordinates, do not match what might be expected when reading the MaterialX spec: // "[...] the image is mapped onto the geometry based on geometry UV coordinates, with the lower-left corner of an image // mapping to the (0,0) UV coordinate [...]"