Skip to content
Open
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
1 change: 1 addition & 0 deletions source/JsMaterialX/JsMaterialXGenShader/JsGenOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ EMSCRIPTEN_BINDINGS(GenOptions)
ems::class_<mx::GenOptions>("GenOptions")
.property("shaderInterfaceType", &mx::GenOptions::shaderInterfaceType)
.property("fileTextureVerticalFlip", &mx::GenOptions::fileTextureVerticalFlip)
.property("hwTexcoordVerticalFlip", &mx::GenOptions::hwTexcoordVerticalFlip)
.property("targetColorSpaceOverride", &mx::GenOptions::targetColorSpaceOverride)
.property("targetDistanceUnit", &mx::GenOptions::targetDistanceUnit)
.property("addUpstreamDependencies", &mx::GenOptions::addUpstreamDependencies)
Expand Down
17 changes: 16 additions & 1 deletion source/MaterialXGenHw/Nodes/HwTexCoordNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,24 @@ void HwTexCoordNode::emitFunctionCall(const ShaderNode& node, GenContext& contex
VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA);
const string prefix = shadergen.getVertexDataPrefix(vertexData);
ShaderPort* texcoord = vertexData[variable];

const string inTexcoord = HW::T_IN_TEXCOORD + "_" + index;
const bool flipV = context.getOptions().hwTexcoordVerticalFlip;

auto emitTexcoordAssign = [&](const string& lhs) {
if (flipV)
{
if (output->getType() == Type::VECTOR2)
return lhs + " = vec2(" + inTexcoord + ".x, 1.0 - " + inTexcoord + ".y)";
else
return lhs + " = vec3(" + inTexcoord + ".x, 1.0 - " + inTexcoord + ".y, " + inTexcoord + ".z)";
}
return lhs + " = " + inTexcoord;
};

if (!texcoord->isEmitted())
{
shadergen.emitLine(prefix + texcoord->getVariable() + " = " + HW::T_IN_TEXCOORD + "_" + index, stage);
shadergen.emitLine(emitTexcoordAssign(prefix + texcoord->getVariable()), stage);
texcoord->setEmitted();
}
}
Expand Down
6 changes: 6 additions & 0 deletions source/MaterialXGenShader/GenOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class MX_GENSHADER_API GenOptions
GenOptions() :
shaderInterfaceType(SHADER_INTERFACE_COMPLETE),
fileTextureVerticalFlip(false),
hwTexcoordVerticalFlip(false),
addUpstreamDependencies(true),
libraryPrefix("libraries"),
emitColorTransforms(true),
Expand Down Expand Up @@ -117,6 +118,11 @@ class MX_GENSHADER_API GenOptions
/// texture space convention. By default this option is false.
bool fileTextureVerticalFlip;

/// If true the y-component of texture coordinates will be flipped at
/// the texcoord node output, before entering the shader graph. This
/// affects all downstream UV consumers. By default this option is false.
bool hwTexcoordVerticalFlip;

/// An optional override for the target color space.
/// Shader fragments will be generated to transform
/// input values and textures into this color space.
Expand Down
7 changes: 7 additions & 0 deletions source/MaterialXGraphEditor/RenderView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,9 @@ void RenderView::loadMesh(const mx::FilePath& filename)
_geometryHandler->clearGeometry();
if (_geometryHandler->loadGeometry(filename))
{
const bool hwTexcoordVerticalFlip = _geometryHandler->requiresTexcoordVerticalFlip(filename);
const bool reloadRequired = _genContext.getOptions().hwTexcoordVerticalFlip != hwTexcoordVerticalFlip;
_genContext.getOptions().hwTexcoordVerticalFlip = hwTexcoordVerticalFlip;
_meshFilename = filename;
if (_splitByUdims)
{
Expand Down Expand Up @@ -299,6 +302,10 @@ void RenderView::loadMesh(const mx::FilePath& filename)
_imageHandler->releaseRenderResources(_shadowMap);
_shadowMap = nullptr;
}
if (reloadRequired && !_materials.empty())
{
reloadShaders();
}
}
}

Expand Down
9 changes: 3 additions & 6 deletions source/MaterialXRender/CgltfLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -396,13 +396,10 @@ bool CgltfLoader::load(const FilePath& filePath, MeshList& meshList, bool texcoo
for (cgltf_size v = 0; v < desiredVectorSize; v++)
{
float floatValue = (v < vectorSize) ? input[v] : 0.0f;
// Perform v-flip
if (isTexCoordStream && v == 1)
// Preserve texture coordinates unless a data-level flip is requested.
if (isTexCoordStream && v == 1 && texcoordVerticalFlip)
{
if (!texcoordVerticalFlip)
{
floatValue = 1.0f - floatValue;
}
floatValue = 1.0f - floatValue;
}
buffer.push_back(floatValue);
}
Expand Down
5 changes: 5 additions & 0 deletions source/MaterialXRender/CgltfLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ class MX_RENDER_API CgltfLoader : public GeometryLoader
/// Load geometry from file path
bool load(const FilePath& filePath, MeshList& meshList, bool texcoordVerticalFlip = false) override;

bool requiresTexcoordVerticalFlip() const override
{
return true;
}

private:
unsigned int _debugLevel;
};
Expand Down
13 changes: 13 additions & 0 deletions source/MaterialXRender/GeometryHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,19 @@ bool GeometryHandler::loadGeometry(const FilePath& filePath, bool texcoordVertic
return loaded;
}

bool GeometryHandler::requiresTexcoordVerticalFlip(const FilePath& filePath) const
{
std::pair<GeometryLoaderMap::const_iterator, GeometryLoaderMap::const_iterator> range;
string extension = filePath.getExtension();
range = _geometryLoaders.equal_range(extension);
for (auto it = range.second; it != range.first;)
{
--it;
return it->second->requiresTexcoordVerticalFlip();
}
return false;
}

MeshPtr GeometryHandler::findParentMesh(MeshPartitionPtr part)
{
for (MeshPtr mesh : getMeshes())
Expand Down
11 changes: 11 additions & 0 deletions source/MaterialXRender/GeometryHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ class MX_RENDER_API GeometryLoader
/// @return True if load was successful
virtual bool load(const FilePath& filePath, MeshList& meshList, bool texcoordVerticalFlip = false) = 0;

/// Return true if this loader's source texture coordinate convention
/// requires a vertical flip for hardware shader generation.
virtual bool requiresTexcoordVerticalFlip() const
{
return false;
}

protected:
// List of supported string extensions
StringSet _extensions;
Expand Down Expand Up @@ -95,6 +102,10 @@ class MX_RENDER_API GeometryHandler
/// @param texcoordVerticalFlip Flip texture coordinates in V. Default is to not flip.
bool loadGeometry(const FilePath& filePath, bool texcoordVerticalFlip = false);

/// Return true if the loader for the given file expects a vertical texture
/// coordinate flip for hardware shader generation.
bool requiresTexcoordVerticalFlip(const FilePath& filePath) const;

/// Get list of meshes
const MeshList& getMeshes() const
{
Expand Down
48 changes: 48 additions & 0 deletions source/MaterialXTest/MaterialXRender/Render.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include <MaterialXTest/MaterialXRender/RenderUtil.h>

#include <MaterialXRender/ShaderRenderer.h>
#include <MaterialXRender/CgltfLoader.h>
#include <MaterialXRender/Mesh.h>
#include <MaterialXRender/StbImageLoader.h>
#include <MaterialXRender/TinyObjLoader.h>
#include <MaterialXRender/Types.h>
Expand Down Expand Up @@ -114,6 +116,37 @@ void testGeomHandler(GeomHandlerTestOptions& options)
CHECK(loadFailed == 0);
}

mx::MeshFloatBuffer loadTexcoords(mx::GeometryLoaderPtr loader, const mx::FilePath& filePath, bool texcoordVerticalFlip)
{
mx::MeshList meshes;
REQUIRE(loader->load(filePath, meshes, texcoordVerticalFlip));
REQUIRE(!meshes.empty());

mx::MeshStreamPtr texcoordStream = meshes[0]->getStream(mx::MeshStream::TEXCOORD_ATTRIBUTE, 0);
REQUIRE(texcoordStream);
return texcoordStream->getData();
}

void testTexcoordVerticalFlip(mx::GeometryLoaderPtr loader, const mx::FilePath& filePath)
{
const size_t texcoordStride = 2;
mx::MeshFloatBuffer texcoords = loadTexcoords(loader, filePath, false);
mx::MeshFloatBuffer flippedTexcoords = loadTexcoords(loader, filePath, true);
REQUIRE(texcoords.size() == flippedTexcoords.size());
REQUIRE(texcoords.size() >= texcoordStride);

bool foundNonBoundaryTexcoord = false;
for (size_t i = 1; i < texcoords.size(); i += texcoordStride)
{
CHECK(std::abs(flippedTexcoords[i] - (1.0f - texcoords[i])) < 1e-6f);
if (texcoords[i] > 0.0f && texcoords[i] < 1.0f)
{
foundNonBoundaryTexcoord = true;
}
}
CHECK(foundNonBoundaryTexcoord);
}

TEST_CASE("Render: Geometry Handler Load", "[rendercore]")
{
std::ofstream geomHandlerLog;
Expand Down Expand Up @@ -149,6 +182,21 @@ TEST_CASE("Render: Geometry Handler Load", "[rendercore]")
geomHandlerLog.close();
}

TEST_CASE("Render: Geometry Loader Texcoord Flip", "[rendercore]")
{
mx::FileSearchPath searchPath = mx::getDefaultDataSearchPath();
mx::FilePath geometryPath = searchPath.find("resources/Geometry/");

testTexcoordVerticalFlip(mx::TinyObjLoader::create(), geometryPath / "sphere.obj");
testTexcoordVerticalFlip(mx::CgltfLoader::create(), geometryPath / "shaderball.glb");

mx::GeometryHandlerPtr handler = mx::GeometryHandler::create();
handler->addLoader(mx::TinyObjLoader::create());
handler->addLoader(mx::CgltfLoader::create());
CHECK(!handler->requiresTexcoordVerticalFlip(geometryPath / "sphere.obj"));
CHECK(handler->requiresTexcoordVerticalFlip(geometryPath / "shaderball.glb"));
}

struct ImageHandlerTestOptions
{
mx::ImageHandlerPtr imageHandler;
Expand Down
7 changes: 7 additions & 0 deletions source/MaterialXView/Viewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1275,6 +1275,9 @@ void Viewer::loadMesh(const mx::FilePath& filename)
_geometryHandler->clearGeometry();
if (_geometryHandler->loadGeometry(filename))
{
const bool hwTexcoordVerticalFlip = _geometryHandler->requiresTexcoordVerticalFlip(filename);
const bool reloadRequired = _genContext.getOptions().hwTexcoordVerticalFlip != hwTexcoordVerticalFlip;
_genContext.getOptions().hwTexcoordVerticalFlip = hwTexcoordVerticalFlip;
_meshFilename = filename;
if (_splitByUdims)
{
Expand Down Expand Up @@ -1308,6 +1311,10 @@ void Viewer::loadMesh(const mx::FilePath& filename)
}

invalidateShadowMap();
if (reloadRequired && !_materials.empty())
{
reloadShaders();
}
}
else
{
Expand Down
Loading