From 9c8b357827a5f3cd4c2f2215520a12f9bd4900f1 Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Wed, 6 Sep 2023 10:05:41 -0400 Subject: [PATCH 01/14] Modify glTF loader to load in multiple uv streams. Update Mesh to create "fallback" streams if not found (does similar action to Web Viewer) Change Glsl to create fallbacks if needed. --- source/MaterialXGraphEditor/RenderView.cpp | 15 -- source/MaterialXRender/CgltfLoader.cpp | 9 +- source/MaterialXRender/Mesh.cpp | 149 +++++++++++++++++- source/MaterialXRender/Mesh.h | 32 ++-- source/MaterialXRenderGlsl/GlslProgram.cpp | 12 +- .../MaterialXRender/RenderUtil.cpp | 22 +-- source/MaterialXView/Viewer.cpp | 15 -- .../PyMaterialX/PyMaterialXRender/PyMesh.cpp | 4 +- 8 files changed, 176 insertions(+), 82 deletions(-) diff --git a/source/MaterialXGraphEditor/RenderView.cpp b/source/MaterialXGraphEditor/RenderView.cpp index 176014ba65..214fd2044c 100644 --- a/source/MaterialXGraphEditor/RenderView.cpp +++ b/source/MaterialXGraphEditor/RenderView.cpp @@ -101,21 +101,6 @@ void applyModifiers(mx::DocumentPtr doc, const DocumentModifiers& modifiers) } } } - - // Remap unsupported texture coordinate indices. - for (mx::ElementPtr elem : doc->traverseTree()) - { - mx::NodePtr node = elem->asA(); - if (node && node->getCategory() == "texcoord") - { - mx::InputPtr index = node->getInput("index"); - mx::ValuePtr value = index ? index->getValue() : nullptr; - if (value && value->isA() && value->asA() != 0) - { - index->setValue(0); - } - } - } } void RenderView::setDocument(mx::DocumentPtr document) diff --git a/source/MaterialXRender/CgltfLoader.cpp b/source/MaterialXRender/CgltfLoader.cpp index 1c8ec598a6..40396d9e80 100644 --- a/source/MaterialXRender/CgltfLoader.cpp +++ b/source/MaterialXRender/CgltfLoader.cpp @@ -267,6 +267,7 @@ bool CgltfLoader::load(const FilePath& filePath, MeshList& meshList, bool texcoo MeshStreamPtr texcoordStream = nullptr; MeshStreamPtr vec4TangentStream = nullptr; int colorAttrIndex = 0; + int texcoordIndex = 0; // Read in vertex streams for (cgltf_size prim = 0; prim < primitive->attributes_count; prim++) @@ -277,12 +278,7 @@ bool CgltfLoader::load(const FilePath& filePath, MeshList& meshList, bool texcoo { continue; } - // Only load one stream of each type for now. cgltf_int streamIndex = attribute->index; - if (streamIndex != 0) - { - continue; - } // Get data as floats cgltf_size floatCount = cgltf_accessor_unpack_floats(accessor, NULL, 0); @@ -335,7 +331,7 @@ bool CgltfLoader::load(const FilePath& filePath, MeshList& meshList, bool texcoo } else if (isTexCoordStream) { - texcoordStream = MeshStream::create("i_" + MeshStream::TEXCOORD_ATTRIBUTE + "_0", MeshStream::TEXCOORD_ATTRIBUTE, 0); + texcoordStream = MeshStream::create("i_" + MeshStream::TEXCOORD_ATTRIBUTE + "_" + std::to_string(texcoordIndex), MeshStream::TEXCOORD_ATTRIBUTE, texcoordIndex); mesh->addStream(texcoordStream); if (vectorSize == 2) { @@ -343,6 +339,7 @@ bool CgltfLoader::load(const FilePath& filePath, MeshList& meshList, bool texcoo desiredVectorSize = 2; } geomStream = texcoordStream; + texcoordIndex++; } else { diff --git a/source/MaterialXRender/Mesh.cpp b/source/MaterialXRender/Mesh.cpp index 110829cd21..8d5cccd801 100644 --- a/source/MaterialXRender/Mesh.cpp +++ b/source/MaterialXRender/Mesh.cpp @@ -4,6 +4,7 @@ // #include +#include #include #include @@ -41,8 +42,17 @@ Mesh::Mesh(const string& name) : MeshStreamPtr Mesh::generateNormals(MeshStreamPtr positionStream) { + const string normalStreamName = "i_" + MeshStream::NORMAL_ATTRIBUTE; + + // Return if already exists + MeshStreamPtr normalStream = getStream(normalStreamName, false); + if (normalStream) + { + return normalStream; + } + // Create the normal stream. - MeshStreamPtr normalStream = MeshStream::create("i_" + MeshStream::NORMAL_ATTRIBUTE, MeshStream::NORMAL_ATTRIBUTE, 0); + normalStream = MeshStream::create(normalStreamName, MeshStream::NORMAL_ATTRIBUTE, 0); normalStream->resize(positionStream->getSize()); // Iterate through partitions. @@ -77,8 +87,18 @@ MeshStreamPtr Mesh::generateNormals(MeshStreamPtr positionStream) MeshStreamPtr Mesh::generateTextureCoordinates(MeshStreamPtr positionStream) { + const string texcoordStreamName = "i_" + MeshStream::TEXCOORD_ATTRIBUTE + "_0"; + + // Return if already exists + MeshStreamPtr texcoordStream = getStream(texcoordStreamName, false); + if (texcoordStream) + { + return texcoordStream; + } + + // Create stream from x,y of position stream + texcoordStream = MeshStream::create(texcoordStreamName, MeshStream::TEXCOORD_ATTRIBUTE, 0); size_t vertexCount = positionStream->getData().size() / MeshStream::STRIDE_3D; - MeshStreamPtr texcoordStream = MeshStream::create("i_" + MeshStream::TEXCOORD_ATTRIBUTE + "_0", MeshStream::TEXCOORD_ATTRIBUTE, 0); texcoordStream->setStride(MeshStream::STRIDE_2D); texcoordStream->resize(vertexCount); std::fill(texcoordStream->getData().begin(), texcoordStream->getData().end(), 0.0f); @@ -88,6 +108,15 @@ MeshStreamPtr Mesh::generateTextureCoordinates(MeshStreamPtr positionStream) MeshStreamPtr Mesh::generateTangents(MeshStreamPtr positionStream, MeshStreamPtr normalStream, MeshStreamPtr texcoordStream) { + const string tangentStreamName = "i_" + MeshStream::TANGENT_ATTRIBUTE; + + // Return if already exists + MeshStreamPtr tangentStream = getStream(tangentStreamName, false); + if (tangentStream) + { + return tangentStream; + } + size_t vertexCount = positionStream->getData().size() / positionStream->getStride(); size_t normalCount = normalStream->getData().size() / normalStream->getStride(); size_t texcoordCount = texcoordStream->getData().size() / texcoordStream->getStride(); @@ -97,7 +126,7 @@ MeshStreamPtr Mesh::generateTangents(MeshStreamPtr positionStream, MeshStreamPtr } // Create the tangent stream. - MeshStreamPtr tangentStream = MeshStream::create("i_" + MeshStream::TANGENT_ATTRIBUTE, MeshStream::TANGENT_ATTRIBUTE, 0); + tangentStream = MeshStream::create(tangentStreamName, MeshStream::TANGENT_ATTRIBUTE, 0); tangentStream->resize(positionStream->getSize()); std::fill(tangentStream->getData().begin(), tangentStream->getData().end(), 0.0f); @@ -172,12 +201,21 @@ MeshStreamPtr Mesh::generateTangents(MeshStreamPtr positionStream, MeshStreamPtr MeshStreamPtr Mesh::generateBitangents(MeshStreamPtr normalStream, MeshStreamPtr tangentStream) { + const string bitangentStreamName = "i_" + MeshStream::BITANGENT_ATTRIBUTE; + + // Return if already exists + MeshStreamPtr bitangentStream = getStream(bitangentStreamName, false); + if (bitangentStream) + { + return bitangentStream; + } + if (normalStream->getSize() != tangentStream->getSize()) { return nullptr; } - MeshStreamPtr bitangentStream = MeshStream::create("i_" + MeshStream::BITANGENT_ATTRIBUTE, MeshStream::BITANGENT_ATTRIBUTE, 0); + bitangentStream = MeshStream::create(bitangentStreamName, MeshStream::BITANGENT_ATTRIBUTE, 0); bitangentStream->resize(normalStream->getSize()); for (size_t i = 0; i < normalStream->getSize(); i++) @@ -217,7 +255,7 @@ void Mesh::mergePartitions() void Mesh::splitByUdims() { - MeshStreamPtr texcoords = getStream(MeshStream::TEXCOORD_ATTRIBUTE, 0); + MeshStreamPtr texcoords = getStream(MeshStream::TEXCOORD_ATTRIBUTE, 0, false); if (!texcoords) { return; @@ -311,4 +349,105 @@ void MeshStream::transform(const Matrix44 &matrix) } } +MeshStreamPtr Mesh::getStream(const string& name, bool returnFallbackStream) +{ + for (const auto& stream : _streams) + { + if (stream->getName() == name) + { + return stream; + } + } + if (returnFallbackStream) + { + const std::string POSITION_NAME("i_" + MeshStream::POSITION_ATTRIBUTE); + MeshStreamPtr positionStream = getStream(POSITION_NAME, false); + // Fail if there are no positions. + if (!positionStream) + { + return MeshStreamPtr(); + } + + MeshStreamPtr returnStream = nullptr; + bool needTexCoords = stringStartsWith(name, "i_" + MeshStream::TEXCOORD_ATTRIBUTE); + bool needNormals = stringStartsWith(name, "i_" + MeshStream::NORMAL_ATTRIBUTE); + bool needTangents = stringStartsWith(name, "i_" + MeshStream::TANGENT_ATTRIBUTE); + if (needTangents) + { + needNormals = true; + needTexCoords = true; + } + bool needBiTangents = stringStartsWith(name, "i_" + MeshStream::BITANGENT_ATTRIBUTE); + if (needBiTangents) + { + needNormals = true; + needTangents = true; + needTexCoords = true; + } + + // Return texcoord 0. If it does not exist then create it. + MeshStreamPtr texcoordStream = getStream("i_" + MeshStream::TEXCOORD_ATTRIBUTE + "_0"); + if (needTexCoords) + { + if (!texcoordStream) + { + texcoordStream = generateTextureCoordinates(positionStream); + if (texcoordStream) + { + addStream(texcoordStream); + } + } + returnStream = texcoordStream; + } + + MeshStreamPtr normalStream = nullptr; + if (needNormals) + { + normalStream = generateNormals(positionStream); + if (normalStream) + { + addStream(normalStream); + } + } + + MeshStreamPtr tangentStream = nullptr; + if (needTangents) + { + tangentStream = generateTangents(positionStream, normalStream, texcoordStream); + if (tangentStream) + { + addStream(tangentStream); + } + } + + if (needBiTangents) + { + MeshStreamPtr bitangentStream = generateBitangents(normalStream, tangentStream); + if (bitangentStream) + { + addStream(bitangentStream); + } + } + + // Return position as fallback color stream + if (stringStartsWith(name, "i_" + MeshStream::COLOR_ATTRIBUTE)) + { + returnStream = positionStream; + } + + return returnStream; + } + + return MeshStreamPtr(); +} + +MeshStreamPtr Mesh::getStream(const string& type, unsigned int index, bool returnFallbackStream) +{ + const string streamName = "i_" + type + "_" + std::to_string(index); + MeshStreamPtr foundStream = getStream(streamName, returnFallbackStream); + return foundStream; +} + + + MATERIALX_NAMESPACE_END diff --git a/source/MaterialXRender/Mesh.h b/source/MaterialXRender/Mesh.h index 7166ff73d3..731760c550 100644 --- a/source/MaterialXRender/Mesh.h +++ b/source/MaterialXRender/Mesh.h @@ -275,39 +275,25 @@ class MX_RENDER_API Mesh /// Get a mesh stream by name /// @param name Name of stream + /// @param returnFallbackStream If true will attempt to return fallback stream if it does not exist. Default is false. /// @return Reference to a mesh stream if found - MeshStreamPtr getStream(const string& name) const - { - for (const auto& stream : _streams) - { - if (stream->getName() == name) - { - return stream; - } - } - return MeshStreamPtr(); - } + MeshStreamPtr getStream(const string& name, bool returnFallbackStream = false); /// Get a mesh stream by type and index /// @param type Type of stream /// @param index Index of stream + /// @param generateIfMissing If true will attempt to return a fallback stream if it does not exist. Default is false /// @return Reference to a mesh stream if found - MeshStreamPtr getStream(const string& type, unsigned int index) const - { - for (const auto& stream : _streams) - { - if (stream->getType() == type && - stream->getIndex() == index) - { - return stream; - } - } - return MeshStreamPtr(); - } + MeshStreamPtr getStream(const string& type, unsigned int index, bool returnFallbackStream = false); /// Add a mesh stream void addStream(MeshStreamPtr stream) { + for (MeshStreamPtr s : _streams) + { + if (s->getName() == stream->getName()) + return; + } _streams.push_back(stream); } diff --git a/source/MaterialXRenderGlsl/GlslProgram.cpp b/source/MaterialXRenderGlsl/GlslProgram.cpp index 900cac0ef1..2f478ad962 100644 --- a/source/MaterialXRenderGlsl/GlslProgram.cpp +++ b/source/MaterialXRenderGlsl/GlslProgram.cpp @@ -255,7 +255,8 @@ void GlslProgram::bindAttribute(const GlslProgram::InputMap& inputs, MeshPtr mes unsigned int index = input.second->value ? input.second->value->asA() : 0; unsigned int stride = 0; - MeshStreamPtr stream = mesh->getStream(input.first); + bool generateIfMissing = true; + MeshStreamPtr stream = mesh->getStream(input.first, generateIfMissing); if (!stream) { throw ExceptionRenderError("Geometry buffer could not be retrieved for binding: " + input.first + ". Index: " + std::to_string(index)); @@ -1054,10 +1055,11 @@ int GlslProgram::mapTypeToOpenGLType(const TypeDesc* type) const GlslProgram::InputMap& GlslProgram::updateAttributesList() { - if (_attributeList.size() > 0) - { - return _attributeList; - } + //if (_attributeList.size() > 0) + //{ + // return _attributeList; + //} + _attributeList.clear(); if (_programId == UNDEFINED_OPENGL_RESOURCE_ID) { diff --git a/source/MaterialXTest/MaterialXRender/RenderUtil.cpp b/source/MaterialXTest/MaterialXRender/RenderUtil.cpp index af392a9a05..9113f2f48c 100644 --- a/source/MaterialXTest/MaterialXRender/RenderUtil.cpp +++ b/source/MaterialXTest/MaterialXRender/RenderUtil.cpp @@ -443,7 +443,7 @@ void ShaderRenderTester::addAdditionalTestStreams(mx::MeshPtr mesh) const std::string TEXCOORD_STREAM1_NAME("i_" + mx::MeshStream::TEXCOORD_ATTRIBUTE + "_1"); mx::MeshFloatBuffer* texCoordData2 = nullptr; - if (!mesh->getStream(TEXCOORD_STREAM1_NAME)) + if (!mesh->getStream(TEXCOORD_STREAM1_NAME, false)) { mx::MeshStreamPtr texCoordStream2 = mx::MeshStream::create(TEXCOORD_STREAM1_NAME, mx::MeshStream::TEXCOORD_ATTRIBUTE, 1); texCoordStream2->setStride(2); @@ -454,7 +454,7 @@ void ShaderRenderTester::addAdditionalTestStreams(mx::MeshPtr mesh) const std::string COLOR_STREAM0_NAME("i_" + mx::MeshStream::COLOR_ATTRIBUTE + "_0"); mx::MeshFloatBuffer* colorData1 = nullptr; - if (!mesh->getStream(COLOR_STREAM0_NAME)) + if (!mesh->getStream(COLOR_STREAM0_NAME, false)) { mx::MeshStreamPtr colorStream1 = mx::MeshStream::create(COLOR_STREAM0_NAME, mx::MeshStream::COLOR_ATTRIBUTE, 0); colorData1 = &(colorStream1->getData()); @@ -465,7 +465,7 @@ void ShaderRenderTester::addAdditionalTestStreams(mx::MeshPtr mesh) const std::string COLOR_STREAM1_NAME("i_" + mx::MeshStream::COLOR_ATTRIBUTE + "_1"); mx::MeshFloatBuffer* colorData2 = nullptr; - if (!mesh->getStream(COLOR_STREAM1_NAME)) + if (!mesh->getStream(COLOR_STREAM1_NAME, false)) { mx::MeshStreamPtr colorStream2 = mx::MeshStream::create(COLOR_STREAM1_NAME, mx::MeshStream::COLOR_ATTRIBUTE, 1); colorData2 = &(colorStream2->getData()); @@ -476,7 +476,7 @@ void ShaderRenderTester::addAdditionalTestStreams(mx::MeshPtr mesh) const std::string GEOM_INT_STREAM_NAME("i_" + mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE + "_geompropvalue_integer"); int32_t* geomIntData = nullptr; - if (!mesh->getStream(GEOM_INT_STREAM_NAME)) + if (!mesh->getStream(GEOM_INT_STREAM_NAME, false)) { mx::MeshStreamPtr geomIntStream = mx::MeshStream::create(GEOM_INT_STREAM_NAME, mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE, 0); geomIntStream->setStride(1); @@ -488,7 +488,7 @@ void ShaderRenderTester::addAdditionalTestStreams(mx::MeshPtr mesh) const std::string GEOM_FLOAT_STREAM_NAME("i_" + mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE + "_geompropvalue_float"); mx::MeshFloatBuffer* geomFloatData = nullptr; - if (!mesh->getStream(GEOM_FLOAT_STREAM_NAME)) + if (!mesh->getStream(GEOM_FLOAT_STREAM_NAME, false)) { mx::MeshStreamPtr geomFloatStream = mx::MeshStream::create(GEOM_FLOAT_STREAM_NAME, mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE, 1); geomFloatData = &(geomFloatStream->getData()); @@ -499,7 +499,7 @@ void ShaderRenderTester::addAdditionalTestStreams(mx::MeshPtr mesh) const std::string GEOM_VECTOR2_STREAM_NAME("i_" + mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE + "_geompropvalue_vector2"); mx::MeshFloatBuffer* geomVector2Data = nullptr; - if (!mesh->getStream(GEOM_VECTOR2_STREAM_NAME)) + if (!mesh->getStream(GEOM_VECTOR2_STREAM_NAME, false)) { mx::MeshStreamPtr geomVector2Stream = mx::MeshStream::create(GEOM_VECTOR2_STREAM_NAME, mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE, 1); geomVector2Data = &(geomVector2Stream->getData()); @@ -510,7 +510,7 @@ void ShaderRenderTester::addAdditionalTestStreams(mx::MeshPtr mesh) const std::string GEOM_VECTOR3_STREAM_NAME("i_" + mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE + "_geompropvalue_vector3"); mx::MeshFloatBuffer* geomVector3Data = nullptr; - if (!mesh->getStream(GEOM_VECTOR3_STREAM_NAME)) + if (!mesh->getStream(GEOM_VECTOR3_STREAM_NAME, false)) { mx::MeshStreamPtr geomVector3Stream = mx::MeshStream::create(GEOM_VECTOR3_STREAM_NAME, mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE, 1); geomVector3Data = &(geomVector3Stream->getData()); @@ -521,7 +521,7 @@ void ShaderRenderTester::addAdditionalTestStreams(mx::MeshPtr mesh) const std::string GEOM_VECTOR4_STREAM_NAME("i_" + mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE + "_geompropvalue_vector4"); mx::MeshFloatBuffer* geomVector4Data = nullptr; - if (!mesh->getStream(GEOM_VECTOR4_STREAM_NAME)) + if (!mesh->getStream(GEOM_VECTOR4_STREAM_NAME, false)) { mx::MeshStreamPtr geomVector4Stream = mx::MeshStream::create(GEOM_VECTOR4_STREAM_NAME, mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE, 1); geomVector4Data = &(geomVector4Stream->getData()); @@ -532,7 +532,7 @@ void ShaderRenderTester::addAdditionalTestStreams(mx::MeshPtr mesh) const std::string GEOM_COLOR2_STREAM_NAME("i_" + mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE + "_geompropvalue_color2"); mx::MeshFloatBuffer* geomColor2Data = nullptr; - if (!mesh->getStream(GEOM_COLOR2_STREAM_NAME)) + if (!mesh->getStream(GEOM_COLOR2_STREAM_NAME, false)) { mx::MeshStreamPtr geomColor2Stream = mx::MeshStream::create(GEOM_COLOR2_STREAM_NAME, mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE, 1); geomColor2Data = &(geomColor2Stream->getData()); @@ -543,7 +543,7 @@ void ShaderRenderTester::addAdditionalTestStreams(mx::MeshPtr mesh) const std::string GEOM_COLOR3_STREAM_NAME("i_" + mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE + "_geompropvalue_color3"); mx::MeshFloatBuffer* geomColor3Data = nullptr; - if (!mesh->getStream(GEOM_COLOR3_STREAM_NAME)) + if (!mesh->getStream(GEOM_COLOR3_STREAM_NAME, false)) { mx::MeshStreamPtr geomColor3Stream = mx::MeshStream::create(GEOM_COLOR3_STREAM_NAME, mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE, 1); geomColor3Data = &(geomColor3Stream->getData()); @@ -554,7 +554,7 @@ void ShaderRenderTester::addAdditionalTestStreams(mx::MeshPtr mesh) const std::string GEOM_COLOR4_STREAM_NAME("i_" + mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE + "_geompropvalue_color4"); mx::MeshFloatBuffer* geomColor4Data = nullptr; - if (!mesh->getStream(GEOM_COLOR4_STREAM_NAME)) + if (!mesh->getStream(GEOM_COLOR4_STREAM_NAME, false)) { mx::MeshStreamPtr geomColor4Stream = mx::MeshStream::create(GEOM_COLOR4_STREAM_NAME, mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE, 1); geomColor4Data = &(geomColor4Stream->getData()); diff --git a/source/MaterialXView/Viewer.cpp b/source/MaterialXView/Viewer.cpp index 6346658d07..880b186fc9 100644 --- a/source/MaterialXView/Viewer.cpp +++ b/source/MaterialXView/Viewer.cpp @@ -140,21 +140,6 @@ void applyModifiers(mx::DocumentPtr doc, const DocumentModifiers& modifiers) } } } - - // Remap unsupported texture coordinate indices. - for (mx::ElementPtr elem : doc->traverseTree()) - { - mx::NodePtr node = elem->asA(); - if (node && node->getCategory() == "texcoord") - { - mx::InputPtr index = node->getInput("index"); - mx::ValuePtr value = index ? index->getValue() : nullptr; - if (value && value->isA() && value->asA() != 0) - { - index->setValue(0); - } - } - } } // ViewDir implementation for GLSL diff --git a/source/PyMaterialX/PyMaterialXRender/PyMesh.cpp b/source/PyMaterialX/PyMaterialXRender/PyMesh.cpp index 5c26821436..3eb1937463 100644 --- a/source/PyMaterialX/PyMaterialXRender/PyMesh.cpp +++ b/source/PyMaterialX/PyMaterialXRender/PyMesh.cpp @@ -52,8 +52,8 @@ void bindPyMesh(py::module& mod) .def("setSourceUri", &mx::Mesh::setSourceUri) .def("hasSourceUri", &mx::Mesh::hasSourceUri) .def("getSourceUri", &mx::Mesh::getSourceUri) - .def("getStream", static_cast(&mx::Mesh::getStream)) - .def("getStream", static_cast (&mx::Mesh::getStream)) + .def("getStream", static_cast (&mx::Mesh::getStream)) + .def("getStream", static_cast (&mx::Mesh::getStream)) .def("addStream", &mx::Mesh::addStream) .def("setVertexCount", &mx::Mesh::setVertexCount) .def("getVertexCount", &mx::Mesh::getVertexCount) From 5f3ab5818d6f8cd10a57c5d931d0f274a469defb Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Wed, 6 Sep 2023 10:09:05 -0400 Subject: [PATCH 02/14] Change MSL to call getStream with fallback option turned on. --- source/MaterialXRenderMsl/MslPipelineStateObject.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/MaterialXRenderMsl/MslPipelineStateObject.mm b/source/MaterialXRenderMsl/MslPipelineStateObject.mm index 4f8378ae46..6842ff5fe0 100644 --- a/source/MaterialXRenderMsl/MslPipelineStateObject.mm +++ b/source/MaterialXRenderMsl/MslPipelineStateObject.mm @@ -372,7 +372,7 @@ int GetStrideOfMetalType(MTLDataType type) unsigned int index = input.second->value ? input.second->value->asA() : 0; unsigned int stride = 0; - MeshStreamPtr stream = mesh->getStream(input.first); + MeshStreamPtr stream = mesh->getStream(input.first, true); if (!stream) { errors.push_back("Geometry buffer could not be retrieved for binding: " + input.first + ". Index: " + std::to_string(index)); From 2581bf3cef304d7b2a9c1e686238d312e47c076b Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Thu, 7 Sep 2023 08:50:51 -0400 Subject: [PATCH 03/14] Fix return value for some streams. Fix docs. --- source/MaterialXRender/Mesh.cpp | 4 ++++ source/MaterialXRender/Mesh.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/source/MaterialXRender/Mesh.cpp b/source/MaterialXRender/Mesh.cpp index 8d5cccd801..5feff2a81d 100644 --- a/source/MaterialXRender/Mesh.cpp +++ b/source/MaterialXRender/Mesh.cpp @@ -407,6 +407,7 @@ MeshStreamPtr Mesh::getStream(const string& name, bool returnFallbackStream) if (normalStream) { addStream(normalStream); + returnStream = normalStream; } } @@ -417,6 +418,7 @@ MeshStreamPtr Mesh::getStream(const string& name, bool returnFallbackStream) if (tangentStream) { addStream(tangentStream); + returnStream = tangentStream; } } @@ -426,6 +428,7 @@ MeshStreamPtr Mesh::getStream(const string& name, bool returnFallbackStream) if (bitangentStream) { addStream(bitangentStream); + returnStream = bitangentStream; } } @@ -451,3 +454,4 @@ MeshStreamPtr Mesh::getStream(const string& type, unsigned int index, bool retur MATERIALX_NAMESPACE_END + diff --git a/source/MaterialXRender/Mesh.h b/source/MaterialXRender/Mesh.h index 731760c550..f2d46169a9 100644 --- a/source/MaterialXRender/Mesh.h +++ b/source/MaterialXRender/Mesh.h @@ -282,7 +282,7 @@ class MX_RENDER_API Mesh /// Get a mesh stream by type and index /// @param type Type of stream /// @param index Index of stream - /// @param generateIfMissing If true will attempt to return a fallback stream if it does not exist. Default is false + /// @param returnFallbackStream If true will attempt to return a fallback stream if it does not exist. Default is false. /// @return Reference to a mesh stream if found MeshStreamPtr getStream(const string& type, unsigned int index, bool returnFallbackStream = false); From ebbb765b0c2b7adc33b081e069f05fdd089a3c05 Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Tue, 12 Sep 2023 15:51:37 -0700 Subject: [PATCH 04/14] Clarify input name --- source/MaterialXRender/Mesh.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/MaterialXRender/Mesh.cpp b/source/MaterialXRender/Mesh.cpp index 5feff2a81d..637a9ec443 100644 --- a/source/MaterialXRender/Mesh.cpp +++ b/source/MaterialXRender/Mesh.cpp @@ -349,7 +349,7 @@ void MeshStream::transform(const Matrix44 &matrix) } } -MeshStreamPtr Mesh::getStream(const string& name, bool returnFallbackStream) +MeshStreamPtr Mesh::getStream(const string& name, bool allowFallback) { for (const auto& stream : _streams) { @@ -358,7 +358,7 @@ MeshStreamPtr Mesh::getStream(const string& name, bool returnFallbackStream) return stream; } } - if (returnFallbackStream) + if (allowFallback) { const std::string POSITION_NAME("i_" + MeshStream::POSITION_ATTRIBUTE); MeshStreamPtr positionStream = getStream(POSITION_NAME, false); @@ -444,10 +444,10 @@ MeshStreamPtr Mesh::getStream(const string& name, bool returnFallbackStream) return MeshStreamPtr(); } -MeshStreamPtr Mesh::getStream(const string& type, unsigned int index, bool returnFallbackStream) +MeshStreamPtr Mesh::getStream(const string& type, unsigned int index, bool allowFallback) { const string streamName = "i_" + type + "_" + std::to_string(index); - MeshStreamPtr foundStream = getStream(streamName, returnFallbackStream); + MeshStreamPtr foundStream = getStream(streamName, allowFallback); return foundStream; } From cf23227454939431f2310c813959e2d1649bff9e Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Tue, 12 Sep 2023 15:52:45 -0700 Subject: [PATCH 05/14] Clarify input name --- source/MaterialXRender/Mesh.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/MaterialXRender/Mesh.h b/source/MaterialXRender/Mesh.h index f2d46169a9..4359503ac6 100644 --- a/source/MaterialXRender/Mesh.h +++ b/source/MaterialXRender/Mesh.h @@ -275,16 +275,16 @@ class MX_RENDER_API Mesh /// Get a mesh stream by name /// @param name Name of stream - /// @param returnFallbackStream If true will attempt to return fallback stream if it does not exist. Default is false. + /// @param allowFallback If true will attempt to return fallback stream if it does not exist. Default is false. /// @return Reference to a mesh stream if found - MeshStreamPtr getStream(const string& name, bool returnFallbackStream = false); + MeshStreamPtr getStream(const string& name, bool allowFallback = false); /// Get a mesh stream by type and index /// @param type Type of stream /// @param index Index of stream - /// @param returnFallbackStream If true will attempt to return a fallback stream if it does not exist. Default is false. + /// @param allowFallback If true will attempt to return a fallback stream if it does not exist. Default is false. /// @return Reference to a mesh stream if found - MeshStreamPtr getStream(const string& type, unsigned int index, bool returnFallbackStream = false); + MeshStreamPtr getStream(const string& type, unsigned int index, bool allowFallback = false); /// Add a mesh stream void addStream(MeshStreamPtr stream) From 2510769b7587126e3ec072411ef998417ac9e9f4 Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Tue, 12 Sep 2023 16:50:29 -0700 Subject: [PATCH 06/14] Remove extra newlines --- source/MaterialXRender/Mesh.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/MaterialXRender/Mesh.cpp b/source/MaterialXRender/Mesh.cpp index 637a9ec443..f2ad50c91f 100644 --- a/source/MaterialXRender/Mesh.cpp +++ b/source/MaterialXRender/Mesh.cpp @@ -451,7 +451,5 @@ MeshStreamPtr Mesh::getStream(const string& type, unsigned int index, bool allow return foundStream; } - - MATERIALX_NAMESPACE_END From 8170c20ce46ba0f0977aaa2ca81a8ad2f0468d17 Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Thu, 14 Sep 2023 10:10:55 -0400 Subject: [PATCH 07/14] Cleanup code. Note this is not required for MSL as this check does not exist there (MslPipelineStateObject.mm). --- source/MaterialXRenderGlsl/GlslProgram.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/source/MaterialXRenderGlsl/GlslProgram.cpp b/source/MaterialXRenderGlsl/GlslProgram.cpp index 2f478ad962..9395c92ad4 100644 --- a/source/MaterialXRenderGlsl/GlslProgram.cpp +++ b/source/MaterialXRenderGlsl/GlslProgram.cpp @@ -1055,10 +1055,6 @@ int GlslProgram::mapTypeToOpenGLType(const TypeDesc* type) const GlslProgram::InputMap& GlslProgram::updateAttributesList() { - //if (_attributeList.size() > 0) - //{ - // return _attributeList; - //} _attributeList.clear(); if (_programId == UNDEFINED_OPENGL_RESOURCE_ID) From 1caad7a131d405ea27fb8b495f33264dac6233e9 Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Sat, 7 Oct 2023 12:07:24 -0700 Subject: [PATCH 08/14] Minor simplification --- source/MaterialXRenderGlsl/GlslProgram.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/MaterialXRenderGlsl/GlslProgram.cpp b/source/MaterialXRenderGlsl/GlslProgram.cpp index 9395c92ad4..9965b241aa 100644 --- a/source/MaterialXRenderGlsl/GlslProgram.cpp +++ b/source/MaterialXRenderGlsl/GlslProgram.cpp @@ -255,8 +255,7 @@ void GlslProgram::bindAttribute(const GlslProgram::InputMap& inputs, MeshPtr mes unsigned int index = input.second->value ? input.second->value->asA() : 0; unsigned int stride = 0; - bool generateIfMissing = true; - MeshStreamPtr stream = mesh->getStream(input.first, generateIfMissing); + MeshStreamPtr stream = mesh->getStream(input.first, true); if (!stream) { throw ExceptionRenderError("Geometry buffer could not be retrieved for binding: " + input.first + ". Index: " + std::to_string(index)); From a72fb9129040263c0e3e1f508c2a57c3d499c2de Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Tue, 5 Dec 2023 11:24:58 -0500 Subject: [PATCH 09/14] Review update to remove unneeded call with default arguments. --- source/MaterialXRender/Mesh.cpp | 13 +++++++------ .../MaterialXRender/RenderUtil.cpp | 18 +++++++++--------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/source/MaterialXRender/Mesh.cpp b/source/MaterialXRender/Mesh.cpp index d7d759463f..6bcee9632b 100644 --- a/source/MaterialXRender/Mesh.cpp +++ b/source/MaterialXRender/Mesh.cpp @@ -46,7 +46,7 @@ MeshStreamPtr Mesh::generateNormals(MeshStreamPtr positionStream) const string normalStreamName = "i_" + MeshStream::NORMAL_ATTRIBUTE; // Return if already exists - MeshStreamPtr normalStream = getStream(normalStreamName, false); + MeshStreamPtr normalStream = getStream(normalStreamName); if (normalStream) { return normalStream; @@ -91,7 +91,7 @@ MeshStreamPtr Mesh::generateTextureCoordinates(MeshStreamPtr positionStream) const string texcoordStreamName = "i_" + MeshStream::TEXCOORD_ATTRIBUTE + "_0"; // Return if already exists - MeshStreamPtr texcoordStream = getStream(texcoordStreamName, false); + MeshStreamPtr texcoordStream = getStream(texcoordStreamName); if (texcoordStream) { return texcoordStream; @@ -112,7 +112,7 @@ MeshStreamPtr Mesh::generateTangents(MeshStreamPtr positionStream, MeshStreamPtr const string tangentStreamName = "i_" + MeshStream::TANGENT_ATTRIBUTE; // Return if already exists - MeshStreamPtr tangentStream = getStream(tangentStreamName, false); + MeshStreamPtr tangentStream = getStream(tangentStreamName); if (tangentStream) { return tangentStream; @@ -205,7 +205,7 @@ MeshStreamPtr Mesh::generateBitangents(MeshStreamPtr normalStream, MeshStreamPtr const string bitangentStreamName = "i_" + MeshStream::BITANGENT_ATTRIBUTE; // Return if already exists - MeshStreamPtr bitangentStream = getStream(bitangentStreamName, false); + MeshStreamPtr bitangentStream = getStream(bitangentStreamName); if (bitangentStream) { return bitangentStream; @@ -256,7 +256,8 @@ void Mesh::mergePartitions() void Mesh::splitByUdims() { - MeshStreamPtr texcoords = getStream(MeshStream::TEXCOORD_ATTRIBUTE, 0, false); + const unsigned int texcoord_stream = 0; + MeshStreamPtr texcoords = getStream(MeshStream::TEXCOORD_ATTRIBUTE, texcoord_stream); if (!texcoords) { return; @@ -362,7 +363,7 @@ MeshStreamPtr Mesh::getStream(const string& name, bool allowFallback) if (allowFallback) { const std::string POSITION_NAME("i_" + MeshStream::POSITION_ATTRIBUTE); - MeshStreamPtr positionStream = getStream(POSITION_NAME, false); + MeshStreamPtr positionStream = getStream(POSITION_NAME); // Fail if there are no positions. if (!positionStream) { diff --git a/source/MaterialXTest/MaterialXRender/RenderUtil.cpp b/source/MaterialXTest/MaterialXRender/RenderUtil.cpp index 5256645518..64cfe00013 100644 --- a/source/MaterialXTest/MaterialXRender/RenderUtil.cpp +++ b/source/MaterialXTest/MaterialXRender/RenderUtil.cpp @@ -422,7 +422,7 @@ void ShaderRenderTester::addAdditionalTestStreams(mx::MeshPtr mesh) const std::string TEXCOORD_STREAM1_NAME("i_" + mx::MeshStream::TEXCOORD_ATTRIBUTE + "_1"); mx::MeshFloatBuffer* texCoordData2 = nullptr; - if (!mesh->getStream(TEXCOORD_STREAM1_NAME, false)) + if (!mesh->getStream(TEXCOORD_STREAM1_NAME)) { mx::MeshStreamPtr texCoordStream2 = mx::MeshStream::create(TEXCOORD_STREAM1_NAME, mx::MeshStream::TEXCOORD_ATTRIBUTE, 1); texCoordStream2->setStride(2); @@ -433,7 +433,7 @@ void ShaderRenderTester::addAdditionalTestStreams(mx::MeshPtr mesh) const std::string COLOR_STREAM0_NAME("i_" + mx::MeshStream::COLOR_ATTRIBUTE + "_0"); mx::MeshFloatBuffer* colorData1 = nullptr; - if (!mesh->getStream(COLOR_STREAM0_NAME, false)) + if (!mesh->getStream(COLOR_STREAM0_NAME)) { mx::MeshStreamPtr colorStream1 = mx::MeshStream::create(COLOR_STREAM0_NAME, mx::MeshStream::COLOR_ATTRIBUTE, 0); colorData1 = &(colorStream1->getData()); @@ -444,7 +444,7 @@ void ShaderRenderTester::addAdditionalTestStreams(mx::MeshPtr mesh) const std::string COLOR_STREAM1_NAME("i_" + mx::MeshStream::COLOR_ATTRIBUTE + "_1"); mx::MeshFloatBuffer* colorData2 = nullptr; - if (!mesh->getStream(COLOR_STREAM1_NAME, false)) + if (!mesh->getStream(COLOR_STREAM1_NAME)) { mx::MeshStreamPtr colorStream2 = mx::MeshStream::create(COLOR_STREAM1_NAME, mx::MeshStream::COLOR_ATTRIBUTE, 1); colorData2 = &(colorStream2->getData()); @@ -455,7 +455,7 @@ void ShaderRenderTester::addAdditionalTestStreams(mx::MeshPtr mesh) const std::string GEOM_INT_STREAM_NAME("i_" + mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE + "_geompropvalue_integer"); int32_t* geomIntData = nullptr; - if (!mesh->getStream(GEOM_INT_STREAM_NAME, false)) + if (!mesh->getStream(GEOM_INT_STREAM_NAME)) { mx::MeshStreamPtr geomIntStream = mx::MeshStream::create(GEOM_INT_STREAM_NAME, mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE, 0); geomIntStream->setStride(1); @@ -467,7 +467,7 @@ void ShaderRenderTester::addAdditionalTestStreams(mx::MeshPtr mesh) const std::string GEOM_FLOAT_STREAM_NAME("i_" + mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE + "_geompropvalue_float"); mx::MeshFloatBuffer* geomFloatData = nullptr; - if (!mesh->getStream(GEOM_FLOAT_STREAM_NAME, false)) + if (!mesh->getStream(GEOM_FLOAT_STREAM_NAME)) { mx::MeshStreamPtr geomFloatStream = mx::MeshStream::create(GEOM_FLOAT_STREAM_NAME, mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE, 1); geomFloatData = &(geomFloatStream->getData()); @@ -489,7 +489,7 @@ void ShaderRenderTester::addAdditionalTestStreams(mx::MeshPtr mesh) const std::string GEOM_VECTOR3_STREAM_NAME("i_" + mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE + "_geompropvalue_vector3"); mx::MeshFloatBuffer* geomVector3Data = nullptr; - if (!mesh->getStream(GEOM_VECTOR3_STREAM_NAME, false)) + if (!mesh->getStream(GEOM_VECTOR3_STREAM_NAME)) { mx::MeshStreamPtr geomVector3Stream = mx::MeshStream::create(GEOM_VECTOR3_STREAM_NAME, mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE, 1); geomVector3Data = &(geomVector3Stream->getData()); @@ -500,7 +500,7 @@ void ShaderRenderTester::addAdditionalTestStreams(mx::MeshPtr mesh) const std::string GEOM_VECTOR4_STREAM_NAME("i_" + mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE + "_geompropvalue_vector4"); mx::MeshFloatBuffer* geomVector4Data = nullptr; - if (!mesh->getStream(GEOM_VECTOR4_STREAM_NAME, false)) + if (!mesh->getStream(GEOM_VECTOR4_STREAM_NAME)) { mx::MeshStreamPtr geomVector4Stream = mx::MeshStream::create(GEOM_VECTOR4_STREAM_NAME, mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE, 1); geomVector4Data = &(geomVector4Stream->getData()); @@ -511,7 +511,7 @@ void ShaderRenderTester::addAdditionalTestStreams(mx::MeshPtr mesh) const std::string GEOM_COLOR2_STREAM_NAME("i_" + mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE + "_geompropvalue_color2"); mx::MeshFloatBuffer* geomColor2Data = nullptr; - if (!mesh->getStream(GEOM_COLOR2_STREAM_NAME, false)) + if (!mesh->getStream(GEOM_COLOR2_STREAM_NAME)) { mx::MeshStreamPtr geomColor2Stream = mx::MeshStream::create(GEOM_COLOR2_STREAM_NAME, mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE, 1); geomColor2Data = &(geomColor2Stream->getData()); @@ -522,7 +522,7 @@ void ShaderRenderTester::addAdditionalTestStreams(mx::MeshPtr mesh) const std::string GEOM_COLOR3_STREAM_NAME("i_" + mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE + "_geompropvalue_color3"); mx::MeshFloatBuffer* geomColor3Data = nullptr; - if (!mesh->getStream(GEOM_COLOR3_STREAM_NAME, false)) + if (!mesh->getStream(GEOM_COLOR3_STREAM_NAME)) { mx::MeshStreamPtr geomColor3Stream = mx::MeshStream::create(GEOM_COLOR3_STREAM_NAME, mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE, 1); geomColor3Data = &(geomColor3Stream->getData()); From 9cfb948a2cbe520c9c286af5cae1a4244a58f480 Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Tue, 30 Jan 2024 11:28:55 -0500 Subject: [PATCH 10/14] Change to perform existence test outside of the "generate" functions for streams. --- source/MaterialXRender/Mesh.cpp | 75 +++++++++++++-------------------- 1 file changed, 29 insertions(+), 46 deletions(-) diff --git a/source/MaterialXRender/Mesh.cpp b/source/MaterialXRender/Mesh.cpp index 6bcee9632b..a50e554bf4 100644 --- a/source/MaterialXRender/Mesh.cpp +++ b/source/MaterialXRender/Mesh.cpp @@ -45,15 +45,8 @@ MeshStreamPtr Mesh::generateNormals(MeshStreamPtr positionStream) { const string normalStreamName = "i_" + MeshStream::NORMAL_ATTRIBUTE; - // Return if already exists - MeshStreamPtr normalStream = getStream(normalStreamName); - if (normalStream) - { - return normalStream; - } - // Create the normal stream. - normalStream = MeshStream::create(normalStreamName, MeshStream::NORMAL_ATTRIBUTE, 0); + MeshStreamPtr normalStream = MeshStream::create(normalStreamName, MeshStream::NORMAL_ATTRIBUTE, 0); normalStream->resize(positionStream->getSize()); // Iterate through partitions. @@ -90,15 +83,8 @@ MeshStreamPtr Mesh::generateTextureCoordinates(MeshStreamPtr positionStream) { const string texcoordStreamName = "i_" + MeshStream::TEXCOORD_ATTRIBUTE + "_0"; - // Return if already exists - MeshStreamPtr texcoordStream = getStream(texcoordStreamName); - if (texcoordStream) - { - return texcoordStream; - } - // Create stream from x,y of position stream - texcoordStream = MeshStream::create(texcoordStreamName, MeshStream::TEXCOORD_ATTRIBUTE, 0); + MeshStreamPtr texcoordStream = MeshStream::create(texcoordStreamName, MeshStream::TEXCOORD_ATTRIBUTE, 0); size_t vertexCount = positionStream->getData().size() / MeshStream::STRIDE_3D; texcoordStream->setStride(MeshStream::STRIDE_2D); texcoordStream->resize(vertexCount); @@ -111,13 +97,6 @@ MeshStreamPtr Mesh::generateTangents(MeshStreamPtr positionStream, MeshStreamPtr { const string tangentStreamName = "i_" + MeshStream::TANGENT_ATTRIBUTE; - // Return if already exists - MeshStreamPtr tangentStream = getStream(tangentStreamName); - if (tangentStream) - { - return tangentStream; - } - size_t vertexCount = positionStream->getData().size() / positionStream->getStride(); size_t normalCount = normalStream->getData().size() / normalStream->getStride(); size_t texcoordCount = texcoordStream->getData().size() / texcoordStream->getStride(); @@ -127,7 +106,7 @@ MeshStreamPtr Mesh::generateTangents(MeshStreamPtr positionStream, MeshStreamPtr } // Create the tangent stream. - tangentStream = MeshStream::create(tangentStreamName, MeshStream::TANGENT_ATTRIBUTE, 0); + MeshStreamPtr tangentStream = MeshStream::create(tangentStreamName, MeshStream::TANGENT_ATTRIBUTE, 0); tangentStream->resize(positionStream->getSize()); std::fill(tangentStream->getData().begin(), tangentStream->getData().end(), 0.0f); @@ -204,19 +183,12 @@ MeshStreamPtr Mesh::generateBitangents(MeshStreamPtr normalStream, MeshStreamPtr { const string bitangentStreamName = "i_" + MeshStream::BITANGENT_ATTRIBUTE; - // Return if already exists - MeshStreamPtr bitangentStream = getStream(bitangentStreamName); - if (bitangentStream) - { - return bitangentStream; - } - if (normalStream->getSize() != tangentStream->getSize()) { return nullptr; } - bitangentStream = MeshStream::create(bitangentStreamName, MeshStream::BITANGENT_ATTRIBUTE, 0); + MeshStreamPtr bitangentStream = MeshStream::create(bitangentStreamName, MeshStream::BITANGENT_ATTRIBUTE, 0); bitangentStream->resize(normalStream->getSize()); for (size_t i = 0; i < normalStream->getSize(); i++) @@ -402,36 +374,47 @@ MeshStreamPtr Mesh::getStream(const string& name, bool allowFallback) returnStream = texcoordStream; } - MeshStreamPtr normalStream = nullptr; + MeshStreamPtr normalStream = getStream("i_" + MeshStream::NORMAL_ATTRIBUTE); if (needNormals) { - normalStream = generateNormals(positionStream); - if (normalStream) + if (!normalStream) { - addStream(normalStream); - returnStream = normalStream; + normalStream = generateNormals(positionStream); + if (normalStream) + { + addStream(normalStream); + } } + returnStream = normalStream; } - MeshStreamPtr tangentStream = nullptr; + MeshStreamPtr tangentStream = getStream("i_" + MeshStream::TANGENT_ATTRIBUTE); if (needTangents) { - tangentStream = generateTangents(positionStream, normalStream, texcoordStream); - if (tangentStream) + if (!tangentStream) { - addStream(tangentStream); - returnStream = tangentStream; + tangentStream = generateTangents(positionStream, normalStream, texcoordStream); + if (tangentStream) + { + addStream(tangentStream); + } } + returnStream = tangentStream; } + if (needBiTangents) { - MeshStreamPtr bitangentStream = generateBitangents(normalStream, tangentStream); - if (bitangentStream) + MeshStreamPtr bitangentStream = getStream("i_" + MeshStream::BITANGENT_ATTRIBUTE); + if (!!bitangentStream) { - addStream(bitangentStream); - returnStream = bitangentStream; + bitangentStream = generateBitangents(normalStream, tangentStream); + if (bitangentStream) + { + addStream(bitangentStream); + } } + returnStream = bitangentStream; } // Return position as fallback color stream From 9a0d7f0046c277c2d9e648b1610147853e0fc91f Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Tue, 30 Jan 2024 11:31:39 -0500 Subject: [PATCH 11/14] Merge (#50) * Web viewer formatting improvements and fixes (#1635) - Add colouring to items and folders which can be set vis CSS. This makes it easier to tell what areas are under what folders. - Fix string disable setting (was using old API). - Fix parenting of enum widgets to be under current folder instead of top level. * Add HwImplementation class This changelist adds an intermediate HwImplementation class, allowing the sharing of common features between node implementations in hardware shading languages. * Merge geometry node implementations This changelist merges the implementations of geometry nodes across hardware shading languages, allowing a greater degree of code sharing. * Merge application node implementations This changelist merges the implementations of application and NPR nodes across hardware shading languages, allowing a greater degree of code sharing. * Add vector2 variant of normalmap (#1355) The materialx specification defines the scale attribute of the normalmap to be either a float or a vector2 but the vector2 variant was missing from the implementation. This PR adds it. * Renderable logic improvements to web viewer (#1644) - Adds in proper parsing of renderable elements vs always just picking the first surface shader found. - The test suite files which have (multiple) nodegraph outputs and top level outputs will now load properly. - Adds in UI to mark folders as renderable (using a shaderball icon) - Adds in "soloing" capability to allow picking a renderable and have it show up on all geometry. When nothing is solo'ed the default material assignment is used. - Includes fixes for: - Dag path assignment matching . - Missing exposure of NodeGraph::getDownStreamPorts() in JS. - Addressing the big performance hit when binding materials to geometry in ThreeJS. The code by default is some quite slow code for reflection / debugging purposes which is now turned off. Chess set load is seconds vs minutes. This affects the 'solo'ing workflow significantly as each switch is a geometry re-bind. If the material is not already cached then slow code will be hit which can cause seconds to pass when selecting a new material -- which appears like a "hang" from a user perspective. * Fix irradiance generation in MaterialXView (#1647) This changelist fixes a regression to environment irradiance generation in MaterialXView, caused by a change to image caching logic for GLSL rendering in MaterialX 1.38.8. This fix restores the ability to render environment maps that are missing their pre-generated irradiance data, with irradiance being generated on the fly via spherical harmonics. * Add UI limits for useSpecularWorkflow and normal in UsdPreviewSurface (#1646) UsdPreviewSurface allows useSpecularWorkflow to be 0 or 1. Normals should have values between -1 to 1, inclusive. This PR puts these limits into place. * Unify noise unit tests This changelist merges two sets of noise unit tests into a single document, and aligns their implementations for clarity. * Static analysis optimizations This changelist addresses a handful of static analysis optimizations flagged by PVS-Studio and cppcheck, including the following: - Pass immutable std::string, FilePath, and FileSearchPath arguments by const reference. - Mark immutable ShaderGenerator references as const. - Prefer std::string::empty over comparison against an empty string. - Remove unused private methods Graph::findLinkId, Graph::findInput, and Graph::selectMaterial. - Remove variable assignments with no impact on code behavior. * Improvements to noise implementations (#1653) - Leverage node graphs to share the conversion aspects of noise implementations across languages. - Simplify noise unit tests to cover only unique implementations. * Fix shader generation typos This changelist fixes a handful of minor typos in shader generation, introduced in #1355 and #1553. * Add frame capture to web viewer (#1636) Add frame capture code to trigger on 'f' key. This is the same key as used for the desktop viewer. * Document format updates This changelist applies the mxformat.py script to the libraries and resources folders in the repository, updating formatting for a handful of documents. * Add versioning rules to Developer Guide (#1664) This changelist adds two new sections to the Developer Guide, describing the categories of changes to the MaterialX API and data libraries that are allowed in version upgrades. * Improve robustness of TypeDesc pointer comparisons (#1665) - The globals presets defined for TypeDesc are pointers which may not be shared between shared modules. This occurs for instance in Python where the pointers are declared locally for each module. - Any pointer comparison between the same TypeDesc preset can thus result in a failure status. * Improvements to smoothstep implementations - Leverage node graphs to share the conversion aspects of smoothstep implementations across languages. - Simplify smoothstep unit tests to cover only unique implementations. * Update changelog for recent work * Update comments in stdlib_ng.mtlx This changelist updates the comments in stdlib_ng, aligning them with the conventions for nodegraph definitions in the data libraries. * Fix orphaned links when deleting node in graph editor (#1667) This PR introduces fixes related to the removal of orphaned links when deleting a node in the Graph Editor: - remove the attribute `INTERFACE_NAME_ATTRIBUTE` of input pins that were connected to the deleted node (Fixes #1577) - iterate over all of the output pins instead of only handling the first one. (Fixes #1666) * Add facingratio node to nprlib (#1671) This changelist adds a `facingratio` node to the NPR data library, providing an additional intermediate node for building NPR graphs. * Add geometry drag & drop to web viewer (#1663) - Add support to recognize dropping of individual geometry (glb) files. - Minor cleanup to stop if no MTLX or GLB files loaded. * Apply JavaScript formatting This changelist applies automated formatting to the MaterialX JavaScript codebase, aligning it with the 4-space indentation and Allman braces used in MaterialX C++. * Add missing classification of VolumeShader nodes (#1675) ShaderNodes.cpp had missing classification information for Volume Shaders. This PR is a simple addition of that classification. * Add invert node to specification (#1676) The node exists in the standard library code, but is missing from the specification. * Improvements to facingratio - Fix syntax of input default values. - Use the invert node in facingratio for compactness. - Clarify the edge brighten example material. * Always build GLFW as a static library (#1680) Currently the embedded glfw build for MaterialXGraphEditor inherits the value of BUILD_SHARED_LIBS from MATERIALX_BUILD_SHARED_LIBS, but we're not installing libglfw, per #1245 the intention was to statically link. --------- Co-authored-by: Jonathan Stone Co-authored-by: mnikelsky Co-authored-by: Eric Haines Co-authored-by: Leo Belda Co-authored-by: Dhruv Govil Co-authored-by: ld-kerley <154285602+ld-kerley@users.noreply.github.com> --- CHANGELOG.md | 36 ++ documents/DeveloperGuide/MainPage.md | 19 +- .../Specification/MaterialX.Specification.md | 6 + .../browser/esslShaderGenerator.spec.js | 20 +- .../MaterialXTest/browser/karma.conf.js | 5 +- javascript/MaterialXTest/codeExamples.spec.js | 21 +- .../MaterialXTest/customBindings.spec.js | 41 +- javascript/MaterialXTest/document.spec.js | 21 +- javascript/MaterialXTest/element.spec.js | 269 ++++---- javascript/MaterialXTest/environ.spec.js | 9 +- javascript/MaterialXTest/testHelpers.js | 6 +- javascript/MaterialXTest/traversal.spec.js | 98 +-- javascript/MaterialXTest/types.spec.js | 66 +- javascript/MaterialXTest/value.spec.js | 12 +- javascript/MaterialXTest/xmlIo.spec.js | 84 ++- javascript/MaterialXView/index.ejs | 16 + .../MaterialXView/public/shader_ball.svg | 5 + .../MaterialXView/public/shader_ball2.svg | 8 + .../MaterialXView/source/dropHandling.js | 286 ++++++--- javascript/MaterialXView/source/helper.js | 81 +-- javascript/MaterialXView/source/index.js | 93 ++- javascript/MaterialXView/source/viewer.js | 596 +++++++++++++----- javascript/MaterialXView/webpack.config.js | 98 +-- javascript/README.md | 2 +- javascript/build_javascript_win.bat | 3 + libraries/bxdf/gltf_pbr.mtlx | 2 +- libraries/bxdf/usd_preview_surface.mtlx | 4 +- .../nprlib/genglsl/nprlib_genglsl_impl.mtlx | 2 +- .../nprlib/genmdl/nprlib_genmdl_impl.mtlx | 2 +- .../nprlib/genmsl/nprlib_genmsl_impl.mtlx | 2 +- libraries/nprlib/nprlib_defs.mtlx | 19 + libraries/nprlib/nprlib_ng.mtlx | 47 ++ .../genglsl/mx_fractal3d_fa_vector2.glsl | 7 - .../genglsl/mx_fractal3d_fa_vector3.glsl | 7 - .../genglsl/mx_fractal3d_fa_vector4.glsl | 7 - .../stdlib/genglsl/mx_noise2d_fa_vector2.glsl | 7 - .../stdlib/genglsl/mx_noise2d_fa_vector3.glsl | 7 - .../stdlib/genglsl/mx_noise2d_fa_vector4.glsl | 8 - .../stdlib/genglsl/mx_noise3d_fa_vector2.glsl | 7 - .../stdlib/genglsl/mx_noise3d_fa_vector3.glsl | 7 - .../stdlib/genglsl/mx_noise3d_fa_vector4.glsl | 8 - libraries/stdlib/genglsl/mx_normalmap.glsl | 7 +- .../stdlib/genglsl/mx_smoothstep_vec2FA.glsl | 7 - .../stdlib/genglsl/mx_smoothstep_vec3FA.glsl | 8 - .../stdlib/genglsl/mx_smoothstep_vec4FA.glsl | 9 - ...p_vec2.glsl => mx_smoothstep_vector2.glsl} | 2 +- ...p_vec3.glsl => mx_smoothstep_vector3.glsl} | 2 +- ...p_vec4.glsl => mx_smoothstep_vector4.glsl} | 2 +- .../stdlib/genglsl/stdlib_genglsl_impl.mtlx | 38 +- .../stdlib/genmdl/stdlib_genmdl_impl.mtlx | 31 +- libraries/stdlib/genmsl/mx_normalmap.metal | 7 +- .../stdlib/genmsl/mx_smoothstep_vec2FA.metal | 8 - .../stdlib/genmsl/mx_smoothstep_vec3FA.metal | 9 - .../stdlib/genmsl/mx_smoothstep_vec4FA.metal | 10 - ...vec2.metal => mx_smoothstep_vector2.metal} | 2 +- ...vec3.metal => mx_smoothstep_vector3.metal} | 2 +- ...vec4.metal => mx_smoothstep_vector4.metal} | 2 +- .../stdlib/genmsl/stdlib_genmsl_impl.mtlx | 43 +- libraries/stdlib/genosl/mx_creatematrix.osl | 6 +- .../stdlib/genosl/mx_fractal3d_color3.osl | 5 - .../stdlib/genosl/mx_fractal3d_color4.osl | 5 - .../stdlib/genosl/mx_fractal3d_fa_color3.osl | 5 - .../stdlib/genosl/mx_fractal3d_fa_color4.osl | 5 - .../stdlib/genosl/mx_fractal3d_fa_vector2.osl | 5 - .../stdlib/genosl/mx_fractal3d_fa_vector3.osl | 5 - .../stdlib/genosl/mx_fractal3d_fa_vector4.osl | 5 - libraries/stdlib/genosl/mx_noise2d_color3.osl | 5 - libraries/stdlib/genosl/mx_noise2d_color4.osl | 5 - .../stdlib/genosl/mx_noise2d_fa_color3.osl | 5 - .../stdlib/genosl/mx_noise2d_fa_color4.osl | 5 - .../stdlib/genosl/mx_noise2d_fa_vector2.osl | 5 - .../stdlib/genosl/mx_noise2d_fa_vector3.osl | 5 - .../stdlib/genosl/mx_noise2d_fa_vector4.osl | 5 - libraries/stdlib/genosl/mx_noise3d_color3.osl | 5 - libraries/stdlib/genosl/mx_noise3d_color4.osl | 5 - .../stdlib/genosl/mx_noise3d_fa_color3.osl | 5 - .../stdlib/genosl/mx_noise3d_fa_color4.osl | 5 - .../stdlib/genosl/mx_noise3d_fa_vector2.osl | 5 - .../stdlib/genosl/mx_noise3d_fa_vector3.osl | 5 - .../stdlib/genosl/mx_noise3d_fa_vector4.osl | 5 - libraries/stdlib/genosl/mx_normalmap.osl | 9 +- .../stdlib/genosl/stdlib_genosl_impl.mtlx | 37 +- libraries/stdlib/stdlib_defs.mtlx | 8 + libraries/stdlib/stdlib_ng.mtlx | 281 ++++++++- resources/Materials/TestSuite/_options.mtlx | 2 +- .../TestSuite/nprlib/edge_brighten.mtlx | 24 +- .../normalmapped_surfaceshader.mtlx | 25 + .../stdlib/adjustment/smoothstep.mtlx | 60 +- .../TestSuite/stdlib/noise/noise.mtlx | 329 ++++------ .../stdlib/procedural/tiledshape.mtlx | 2 +- .../TestSuite/stdlib/texture/noise.mtlx | 228 ------- .../TestSuite/stdlib/upgrade/syntax_1_37.mtlx | 2 +- source/JsMaterialX/JsMaterialXCore/JsNode.cpp | 1 + source/MaterialXFormat/XmlIo.cpp | 2 +- source/MaterialXFormat/XmlIo.h | 2 +- .../GlslResourceBindingContext.cpp | 6 +- .../MaterialXGenGlsl/GlslShaderGenerator.cpp | 60 +- source/MaterialXGenGlsl/GlslShaderGenerator.h | 19 +- source/MaterialXGenGlsl/GlslSyntax.cpp | 2 +- .../Nodes/BitangentNodeGlsl.cpp | 135 ---- .../MaterialXGenGlsl/Nodes/FrameNodeGlsl.cpp | 35 - .../Nodes/GeomColorNodeGlsl.cpp | 4 +- .../Nodes/HeightToNormalNodeGlsl.cpp | 2 +- .../Nodes/PositionNodeGlsl.cpp | 87 --- .../Nodes/SurfaceNodeGlsl.cpp | 4 +- .../Nodes/SurfaceShaderNodeGlsl.cpp | 4 +- .../MaterialXGenGlsl/Nodes/TimeNodeGlsl.cpp | 38 -- source/MaterialXGenGlsl/Nodes/TimeNodeGlsl.h | 26 - .../Nodes/ViewDirectionNodeGlsl.cpp | 55 -- .../Nodes/ViewDirectionNodeGlsl.h | 26 - .../VkResourceBindingContext.cpp | 8 +- source/MaterialXGenMdl/MdlShaderGenerator.cpp | 4 +- source/MaterialXGenMdl/MdlSyntax.cpp | 6 +- .../Nodes/ClosureLayerNodeMdl.cpp | 2 +- .../MaterialXGenMdl/Nodes/CombineNodeMdl.cpp | 4 +- .../MaterialXGenMdl/Nodes/CompoundNodeMdl.cpp | 2 +- .../Nodes/HeightToNormalNodeMdl.cpp | 2 +- .../MaterialXGenMdl/Nodes/SurfaceNodeMdl.cpp | 2 +- .../MaterialXGenMdl/mdl/materialx/stdlib.mdl | 23 +- .../MslResourceBindingContext.cpp | 4 +- source/MaterialXGenMsl/MslShaderGenerator.cpp | 62 +- source/MaterialXGenMsl/MslShaderGenerator.h | 19 +- source/MaterialXGenMsl/MslSyntax.cpp | 2 +- .../MaterialXGenMsl/Nodes/BitangentNodeMsl.h | 26 - .../Nodes/GeomColorNodeMsl.cpp | 4 +- .../Nodes/HeightToNormalNodeMsl.cpp | 2 +- .../MaterialXGenMsl/Nodes/NormalNodeMsl.cpp | 88 --- source/MaterialXGenMsl/Nodes/NormalNodeMsl.h | 26 - .../MaterialXGenMsl/Nodes/PositionNodeMsl.h | 26 - .../MaterialXGenMsl/Nodes/SurfaceNodeMsl.cpp | 4 +- .../Nodes/SurfaceShaderNodeMsl.cpp | 4 +- .../MaterialXGenMsl/Nodes/TangentNodeMsl.cpp | 88 --- source/MaterialXGenMsl/Nodes/TangentNodeMsl.h | 26 - source/MaterialXGenMsl/Nodes/TimeNodeMsl.h | 26 - .../Nodes/ViewDirectionNodeMsl.h | 26 - .../Nodes/ClosureLayerNodeOsl.cpp | 2 +- source/MaterialXGenOsl/OslShaderGenerator.cpp | 14 +- .../MaterialXGenShader/HwShaderGenerator.cpp | 25 +- source/MaterialXGenShader/HwShaderGenerator.h | 25 + source/MaterialXGenShader/Nodes/BlurNode.cpp | 2 +- .../Nodes/ClosureAddNode.cpp | 4 +- .../Nodes/ClosureCompoundNode.cpp | 2 +- .../Nodes/ClosureLayerNode.cpp | 2 +- .../Nodes/ClosureMixNode.cpp | 4 +- .../Nodes/ClosureMultiplyNode.cpp | 4 +- .../Nodes/ClosureSourceCodeNode.cpp | 2 +- .../MaterialXGenShader/Nodes/CombineNode.cpp | 6 +- .../Nodes/ConvolutionNode.cpp | 4 +- .../Nodes/HwBitangentNode.cpp} | 12 +- .../Nodes/HwBitangentNode.h} | 10 +- .../Nodes/HwFrameNode.cpp} | 10 +- .../Nodes/HwFrameNode.h} | 10 +- .../Nodes/HwNormalNode.cpp} | 12 +- .../Nodes/HwNormalNode.h} | 10 +- .../Nodes/HwPositionNode.cpp} | 12 +- .../Nodes/HwPositionNode.h} | 10 +- .../Nodes/HwTangentNode.cpp} | 12 +- .../Nodes/HwTangentNode.h} | 10 +- .../Nodes/HwTexCoordNode.cpp | 4 +- .../Nodes/HwTimeNode.cpp} | 10 +- .../Nodes/HwTimeNode.h} | 10 +- .../Nodes/HwViewDirectionNode.cpp} | 12 +- .../Nodes/HwViewDirectionNode.h | 26 + source/MaterialXGenShader/ShaderGraph.cpp | 12 +- source/MaterialXGenShader/ShaderNode.cpp | 16 +- source/MaterialXGenShader/Syntax.cpp | 16 +- source/MaterialXGenShader/TypeDesc.cpp | 10 + source/MaterialXGenShader/TypeDesc.h | 6 + source/MaterialXGenShader/Util.cpp | 2 +- source/MaterialXGraphEditor/CMakeLists.txt | 3 + source/MaterialXGraphEditor/Graph.cpp | 101 +-- source/MaterialXGraphEditor/Graph.h | 9 +- source/MaterialXRender/LightHandler.cpp | 2 +- source/MaterialXRenderGlsl/GlslProgram.cpp | 12 +- source/MaterialXView/Viewer.cpp | 4 +- .../PyGlslShaderGenerator.cpp | 2 - .../PyMdlShaderGenerator.cpp | 3 - .../PyMslShaderGenerator.cpp | 2 - .../PyOslShaderGenerator.cpp | 2 - .../PyHwShaderGenerator.cpp | 2 - 180 files changed, 2183 insertions(+), 2632 deletions(-) create mode 100644 javascript/MaterialXView/public/shader_ball.svg create mode 100644 javascript/MaterialXView/public/shader_ball2.svg create mode 100644 libraries/nprlib/nprlib_ng.mtlx delete mode 100644 libraries/stdlib/genglsl/mx_fractal3d_fa_vector2.glsl delete mode 100644 libraries/stdlib/genglsl/mx_fractal3d_fa_vector3.glsl delete mode 100644 libraries/stdlib/genglsl/mx_fractal3d_fa_vector4.glsl delete mode 100644 libraries/stdlib/genglsl/mx_noise2d_fa_vector2.glsl delete mode 100644 libraries/stdlib/genglsl/mx_noise2d_fa_vector3.glsl delete mode 100644 libraries/stdlib/genglsl/mx_noise2d_fa_vector4.glsl delete mode 100644 libraries/stdlib/genglsl/mx_noise3d_fa_vector2.glsl delete mode 100644 libraries/stdlib/genglsl/mx_noise3d_fa_vector3.glsl delete mode 100644 libraries/stdlib/genglsl/mx_noise3d_fa_vector4.glsl delete mode 100644 libraries/stdlib/genglsl/mx_smoothstep_vec2FA.glsl delete mode 100644 libraries/stdlib/genglsl/mx_smoothstep_vec3FA.glsl delete mode 100644 libraries/stdlib/genglsl/mx_smoothstep_vec4FA.glsl rename libraries/stdlib/genglsl/{mx_smoothstep_vec2.glsl => mx_smoothstep_vector2.glsl} (67%) rename libraries/stdlib/genglsl/{mx_smoothstep_vec3.glsl => mx_smoothstep_vector3.glsl} (73%) rename libraries/stdlib/genglsl/{mx_smoothstep_vec4.glsl => mx_smoothstep_vector4.glsl} (78%) delete mode 100644 libraries/stdlib/genmsl/mx_smoothstep_vec2FA.metal delete mode 100644 libraries/stdlib/genmsl/mx_smoothstep_vec3FA.metal delete mode 100644 libraries/stdlib/genmsl/mx_smoothstep_vec4FA.metal rename libraries/stdlib/genmsl/{mx_smoothstep_vec2.metal => mx_smoothstep_vector2.metal} (70%) rename libraries/stdlib/genmsl/{mx_smoothstep_vec3.metal => mx_smoothstep_vector3.metal} (77%) rename libraries/stdlib/genmsl/{mx_smoothstep_vec4.metal => mx_smoothstep_vector4.metal} (80%) delete mode 100644 libraries/stdlib/genosl/mx_fractal3d_color3.osl delete mode 100644 libraries/stdlib/genosl/mx_fractal3d_color4.osl delete mode 100644 libraries/stdlib/genosl/mx_fractal3d_fa_color3.osl delete mode 100644 libraries/stdlib/genosl/mx_fractal3d_fa_color4.osl delete mode 100644 libraries/stdlib/genosl/mx_fractal3d_fa_vector2.osl delete mode 100644 libraries/stdlib/genosl/mx_fractal3d_fa_vector3.osl delete mode 100644 libraries/stdlib/genosl/mx_fractal3d_fa_vector4.osl delete mode 100644 libraries/stdlib/genosl/mx_noise2d_color3.osl delete mode 100644 libraries/stdlib/genosl/mx_noise2d_color4.osl delete mode 100644 libraries/stdlib/genosl/mx_noise2d_fa_color3.osl delete mode 100644 libraries/stdlib/genosl/mx_noise2d_fa_color4.osl delete mode 100644 libraries/stdlib/genosl/mx_noise2d_fa_vector2.osl delete mode 100644 libraries/stdlib/genosl/mx_noise2d_fa_vector3.osl delete mode 100644 libraries/stdlib/genosl/mx_noise2d_fa_vector4.osl delete mode 100644 libraries/stdlib/genosl/mx_noise3d_color3.osl delete mode 100644 libraries/stdlib/genosl/mx_noise3d_color4.osl delete mode 100644 libraries/stdlib/genosl/mx_noise3d_fa_color3.osl delete mode 100644 libraries/stdlib/genosl/mx_noise3d_fa_color4.osl delete mode 100644 libraries/stdlib/genosl/mx_noise3d_fa_vector2.osl delete mode 100644 libraries/stdlib/genosl/mx_noise3d_fa_vector3.osl delete mode 100644 libraries/stdlib/genosl/mx_noise3d_fa_vector4.osl delete mode 100644 resources/Materials/TestSuite/stdlib/texture/noise.mtlx delete mode 100644 source/MaterialXGenGlsl/Nodes/BitangentNodeGlsl.cpp delete mode 100644 source/MaterialXGenGlsl/Nodes/FrameNodeGlsl.cpp delete mode 100644 source/MaterialXGenGlsl/Nodes/PositionNodeGlsl.cpp delete mode 100644 source/MaterialXGenGlsl/Nodes/TimeNodeGlsl.cpp delete mode 100644 source/MaterialXGenGlsl/Nodes/TimeNodeGlsl.h delete mode 100644 source/MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.cpp delete mode 100644 source/MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.h delete mode 100644 source/MaterialXGenMsl/Nodes/BitangentNodeMsl.h delete mode 100644 source/MaterialXGenMsl/Nodes/NormalNodeMsl.cpp delete mode 100644 source/MaterialXGenMsl/Nodes/NormalNodeMsl.h delete mode 100644 source/MaterialXGenMsl/Nodes/PositionNodeMsl.h delete mode 100644 source/MaterialXGenMsl/Nodes/TangentNodeMsl.cpp delete mode 100644 source/MaterialXGenMsl/Nodes/TangentNodeMsl.h delete mode 100644 source/MaterialXGenMsl/Nodes/TimeNodeMsl.h delete mode 100644 source/MaterialXGenMsl/Nodes/ViewDirectionNodeMsl.h rename source/{MaterialXGenMsl/Nodes/BitangentNodeMsl.cpp => MaterialXGenShader/Nodes/HwBitangentNode.cpp} (91%) rename source/{MaterialXGenGlsl/Nodes/NormalNodeGlsl.h => MaterialXGenShader/Nodes/HwBitangentNode.h} (63%) rename source/{MaterialXGenMsl/Nodes/FrameNodeMsl.cpp => MaterialXGenShader/Nodes/HwFrameNode.cpp} (67%) rename source/{MaterialXGenGlsl/Nodes/TangentNodeGlsl.h => MaterialXGenShader/Nodes/HwFrameNode.h} (65%) rename source/{MaterialXGenGlsl/Nodes/NormalNodeGlsl.cpp => MaterialXGenShader/Nodes/HwNormalNode.cpp} (85%) rename source/{MaterialXGenGlsl/Nodes/PositionNodeGlsl.h => MaterialXGenShader/Nodes/HwNormalNode.h} (64%) rename source/{MaterialXGenMsl/Nodes/PositionNodeMsl.cpp => MaterialXGenShader/Nodes/HwPositionNode.cpp} (84%) rename source/{MaterialXGenGlsl/Nodes/FrameNodeGlsl.h => MaterialXGenShader/Nodes/HwPositionNode.h} (63%) rename source/{MaterialXGenGlsl/Nodes/TangentNodeGlsl.cpp => MaterialXGenShader/Nodes/HwTangentNode.cpp} (85%) rename source/{MaterialXGenGlsl/Nodes/BitangentNodeGlsl.h => MaterialXGenShader/Nodes/HwTangentNode.h} (64%) rename source/{MaterialXGenMsl/Nodes/TimeNodeMsl.cpp => MaterialXGenShader/Nodes/HwTimeNode.cpp} (72%) rename source/{MaterialXGenMsl/Nodes/FrameNodeMsl.h => MaterialXGenShader/Nodes/HwTimeNode.h} (65%) rename source/{MaterialXGenMsl/Nodes/ViewDirectionNodeMsl.cpp => MaterialXGenShader/Nodes/HwViewDirectionNode.cpp} (76%) create mode 100644 source/MaterialXGenShader/Nodes/HwViewDirectionNode.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 47b1bfe8b8..bd414573ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,42 @@ ## [1.38.9] - Development +### Added + +- Added a [non-photorealistic rendering](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1631) data library to MaterialX, initially supporting the 'viewdirection' and 'facingratio' nodes. +- Added support for the generation of [pre-filtered environment maps](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1420) in MaterialX GLSL and MSL. +- Added support for the [creatematrix node](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1553) in shader generation. +- Added [floating popups](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1565) for hovered pins in the MaterialX Graph Editor. +- Added support for [UI attributes](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1623) and [enumerated values](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1632) in the MaterialX Web Viewer. +- Added [UI ranges](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1646) to the 'useSpecularWorkflow' and 'normal' inputs of the UsdPreviewSurface shading model. +- Added [versioning rules](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1664) for the MaterialX API and data libraries to the developer guide. +- Added initial C++ [fuzz tests](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1605) and [coverage tests](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1548) to GitHub Actions CI. +- Added [GCC 13, Clang 15](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1602), and [Python 3.12](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1588) builds to GitHub Actions CI. + +### Changed + +- Improved the logic for [connecting pins](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1569) in the MaterialX Graph Editor. +- Improved the robustness of [type pointer comparisons](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1665) in shader generation. +- Improved the handling of [filename inputs](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1547) in OSL shader generation. +- Reduced the size of the MaterialX data libraries, improving the use of [graph definitions](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1653) and merging [duplicate implementations](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1642). +- Updated the MaterialX Web Viewer to [three.js r152](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1615). +- Switched to a more efficient representation of [HDR images](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1616) in the MaterialX Web Viewer. +- Raised the minimum CMake version to [CMake 3.16](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1607). +- Updated the C++ unit test library to [Catch 2.13.10](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1566). + +### Fixed + +- Fixed the attenuation of [coated emission](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1534) in the Standard Surface shading model. +- Fixed the implementation of the [overlay node](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1539) in shader generation. +- Fixed an edge case for [transform nodes](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1560) in GLSL and MSL shader generation. +- Fixed the implementation of [mx_hsvtorgb](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1584) in MDL shader generation. +- Fixed [scroll wheel interactions](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1578) across windows of the MaterialX Graph Editor. +- Fixed the generation of unused [imgui.ini files](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1570) in the MaterialX Graph Editor. +- Fixed a dependency on [module import order](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1595) in MaterialX Python. +- Fixed an [off-by-one index check](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1582) in Element::setChildIndex. +- Fixed a [missing null check](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1601) in Graph::propertyEditor. +- Fixed cases where [absolute paths](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1603) were stored in MaterialXConfig.cmake. + ## [1.38.8] - 2023-09-08 ### Added diff --git a/documents/DeveloperGuide/MainPage.md b/documents/DeveloperGuide/MainPage.md index d6c098a23d..68bd57ce5a 100644 --- a/documents/DeveloperGuide/MainPage.md +++ b/documents/DeveloperGuide/MainPage.md @@ -58,9 +58,24 @@ Building the `install` target of your project will install the MaterialX C++ and ### MaterialX Versioning -The MaterialX codebase uses a modified semantic versioning system where the *major* and *minor* versions match that of the corresponding MaterialX [specification](https://www.materialx.org/Specification.html), and the *build* version represents engineering advances within that specification version. MaterialX documents are similarly marked with the specification version they were authored in, and they are valid to load into any MaterialX codebase with an equal or higher specification version. +The MaterialX codebase uses a modified semantic versioning system where the *major* and *minor* versions match that of the corresponding MaterialX [specification](https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/documents/Specification/MaterialX.Specification.md), and the *build* version represents engineering advances within that specification version. MaterialX documents are similarly marked with the specification version they were authored in, and they are valid to load into any MaterialX codebase with an equal or higher specification version. -Upgrading of MaterialX documents from earlier versions is handled at import time by the Document::upgradeVersion method, which applies the syntax and node interface upgrades that have occurred in previous specification revisions. This allows the syntax conventions of MaterialX and the names and interfaces of nodes to evolve over time, without invalidating documents from earlier versions. +Upgrading of MaterialX documents from earlier versions is handled at import time by the `Document::upgradeVersion` method, which applies the syntax and node interface upgrades that have occurred in previous specification revisions. This allows the syntax conventions of MaterialX and the names and interfaces of nodes to evolve over time, without invalidating documents from earlier versions. + +#### MaterialX API Changes + +The following rules describe the categories of changes to the [MaterialX API](https://materialx.org/docs/api/classes.html) that are allowed in version upgrades: + +- In *build* version upgrades, only non-breaking changes to the MaterialX API are allowed. For any API call that is modified in a build version upgrade, backwards compatibility should be maintained using deprecated C++ and Python wrappers for the original API call. +- In *minor* and *major* version upgrades, breaking changes to the MaterialX API are allowed, though their benefit should be carefully weighed against their cost. Any breaking changes to API calls should be highlighted in the release notes for the new version. + +#### MaterialX Data Library Changes + +The following rules describe the categories of changes to the [MaterialX Data Libraries](https://github.com/AcademySoftwareFoundation/MaterialX/tree/main/libraries) that are allowed in version upgrades: + +- In *build* version upgrades, only additive changes and fixes to the MaterialX data libraries are allowed. Additive changes are allowed to introduce new nodes, node versions, and node inputs with backwards-compatible default values. Data library fixes are allowed to update a node implementation to improve its alignment with the specification, without making any changes to its name or interface. +- In *minor* version upgrades, changes to the names and interfaces of MaterialX nodes are allowed, with the requirement that version upgrade logic be used to maintain the validity and visual interpretation of documents from earlier versions. +- In *major* version upgrades, changes to the syntax rules of MaterialX documents are allowed, with the requirement that version upgrade logic be used to maintain the validity and visual interpretation of documents from earlier versions. These changes usually require synchronized updates to both the MaterialX API and data libraries. ### Additional Links diff --git a/documents/Specification/MaterialX.Specification.md b/documents/Specification/MaterialX.Specification.md index 895b4756c5..42b6cbbcaf 100644 --- a/documents/Specification/MaterialX.Specification.md +++ b/documents/Specification/MaterialX.Specification.md @@ -1084,6 +1084,12 @@ Math nodes have one or two spatially-varying inputs, and are used to perform a m * `in1` (float or colorN or vectorN): the value or nodename for the primary input * `in2` (same type as `in1` or float): the modulo value or nodename to divide by, cannot be 0 in any channel; default is 1.0 in all channels, which effectively returns the fractional part of a float value + + +* **`invert`**: subtract the incoming float/color/vector from "amount" in all channels, outputting: `amount - in`. + * `in` (float or colorN or vectorN): the value or nodename for the primary input + * `amount` (same type as `in` or float): the value or nodename to subtract from; default is 1.0 in all channels + * **`absval`**: the per-channel absolute value of the incoming float/color/vector. diff --git a/javascript/MaterialXTest/browser/esslShaderGenerator.spec.js b/javascript/MaterialXTest/browser/esslShaderGenerator.spec.js index 657310aeeb..dceba112e0 100644 --- a/javascript/MaterialXTest/browser/esslShaderGenerator.spec.js +++ b/javascript/MaterialXTest/browser/esslShaderGenerator.spec.js @@ -1,6 +1,6 @@ // MaterialX is served through a script tag in the test setup. -function createStandardSurfaceMaterial(mx) +function createStandardSurfaceMaterial(mx) { const doc = mx.createDocument(); const ssName = 'SR_default'; @@ -15,19 +15,21 @@ function createStandardSurfaceMaterial(mx) return doc; } -describe('Generate ESSL Shaders', function () +describe('Generate ESSL Shaders', function () { let mx; const canvas = document.createElement('canvas'); const gl = canvas.getContext('webgl2'); - + this.timeout(60000); - before(async function () { + before(async function () + { mx = await MaterialX(); }); - it('Compile Shaders', () => { + it('Compile Shaders', () => + { const doc = createStandardSurfaceMaterial(mx); const gen = new mx.EsslShaderGenerator(); @@ -37,7 +39,7 @@ describe('Generate ESSL Shaders', function () doc.importLibrary(stdlib); const elem = mx.findRenderableElement(doc); - try + try { const mxShader = gen.generate(elem.getNamePath(), elem, genContext); @@ -47,7 +49,7 @@ describe('Generate ESSL Shaders', function () const glVertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(glVertexShader, vShader); gl.compileShader(glVertexShader); - if (!gl.getShaderParameter(glVertexShader, gl.COMPILE_STATUS)) + if (!gl.getShaderParameter(glVertexShader, gl.COMPILE_STATUS)) { console.error("-------- VERTEX SHADER FAILED TO COMPILE: ----------------"); console.error("--- VERTEX SHADER LOG ---"); @@ -61,7 +63,7 @@ describe('Generate ESSL Shaders', function () const glPixelShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(glPixelShader, fShader); gl.compileShader(glPixelShader); - if (!gl.getShaderParameter(glPixelShader, gl.COMPILE_STATUS)) + if (!gl.getShaderParameter(glPixelShader, gl.COMPILE_STATUS)) { console.error("-------- PIXEL SHADER FAILED TO COMPILE: ----------------"); console.error("--- PIXEL SHADER LOG ---"); @@ -75,7 +77,7 @@ describe('Generate ESSL Shaders', function () catch (errPtr) { console.error("-------- Failed code generation: ----------------"); - console.error(mx.getExceptionMessage(errPtr)); + console.error(mx.getExceptionMessage(errPtr)); } }); }); diff --git a/javascript/MaterialXTest/browser/karma.conf.js b/javascript/MaterialXTest/browser/karma.conf.js index aec860e8b5..6dd8051319 100644 --- a/javascript/MaterialXTest/browser/karma.conf.js +++ b/javascript/MaterialXTest/browser/karma.conf.js @@ -1,10 +1,11 @@ -module.exports = function(config) { +module.exports = function (config) +{ config.set({ basePath: '../', // base is the javascript folder files: [ { pattern: '_build/JsMaterialXGenShader.js', watched: false, included: true, served: true }, { pattern: '_build/JsMaterialXGenShader.wasm', watched: false, included: false, served: true }, - {pattern: '_build/JsMaterialXGenShader.data', watched: false, included: false, served: true, nocache: true }, + { pattern: '_build/JsMaterialXGenShader.data', watched: false, included: false, served: true, nocache: true }, { pattern: 'browser/*.spec.js', watched: true, included: true, served: true }, ], mime: { diff --git a/javascript/MaterialXTest/codeExamples.spec.js b/javascript/MaterialXTest/codeExamples.spec.js index 17f2559b49..8cff44c3fe 100644 --- a/javascript/MaterialXTest/codeExamples.spec.js +++ b/javascript/MaterialXTest/codeExamples.spec.js @@ -2,8 +2,10 @@ import { expect } from 'chai'; import Module from './_build/JsMaterialXCore.js'; import { getMtlxStrings } from './testHelpers'; -describe('Code Examples', () => { - it('Building a MaterialX Document', async () => { +describe('Code Examples', () => +{ + it('Building a MaterialX Document', async () => + { const mx = await Module(); // Create a document. const doc = mx.createDocument(); @@ -76,7 +78,8 @@ describe('Code Examples', () => { // expect(roughness.getBoundValue(material).getValueString()).to.equal('0.5'); }); - it('Traversing a Document Tree', async () => { + it('Traversing a Document Tree', async () => + { const xmlStr = getMtlxStrings( ['standard_surface_greysphere_calibration.mtlx'], '../../resources/Materials/Examples/StandardSurface' @@ -92,13 +95,16 @@ describe('Code Examples', () => { let elementCount = 0; let nodeCount = 0; let fileCount = 0; - for(let elem of elements) { + for (let elem of elements) + { elementCount++; // Display the filename of each image node. - if (elem.isANode('image')) { + if (elem.isANode('image')) + { nodeCount++; const input = elem.getInput('file'); - if (input) { + if (input) + { fileCount++; const filename = input.getValueString(); expect(elem.getName()).to.equal('image1'); @@ -111,7 +117,8 @@ describe('Code Examples', () => { expect(fileCount).to.equal(1); }); - it('Building a MaterialX Document', async () => { + it('Building a MaterialX Document', async () => + { const xmlStr = getMtlxStrings(['standard_surface_marble_solid.mtlx'], '../../resources/Materials/Examples/StandardSurface')[0]; const mx = await Module(); diff --git a/javascript/MaterialXTest/customBindings.spec.js b/javascript/MaterialXTest/customBindings.spec.js index e44cc7e85e..740189f0ef 100644 --- a/javascript/MaterialXTest/customBindings.spec.js +++ b/javascript/MaterialXTest/customBindings.spec.js @@ -2,15 +2,18 @@ import { expect } from 'chai'; import Module from './_build/JsMaterialXCore.js'; import { getMtlxStrings } from './testHelpers'; -describe('Custom Bindings', () => { +describe('Custom Bindings', () => +{ const examplesPath = '../../resources/Materials/Examples/StandardSurface'; - let mx; - before(async () => { + let mx; + before(async () => + { mx = await Module(); }); - it('Optional parameters work as expected', () => { + it('Optional parameters work as expected', () => + { const doc = mx.createDocument(); // Call a method without optional argument const nodeGraph = doc.addNodeGraph(); @@ -29,7 +32,8 @@ describe('Custom Bindings', () => { expect(() => { nodeGraph.addNode(); }).to.throw; }); - it('Vector <-> Array conversion', () => { + it('Vector <-> Array conversion', () => + { // Functions that return vectors in C++ should return an array in JS const doc = mx.createDocument(); const nodeGraph = doc.addNodeGraph(); @@ -66,7 +70,8 @@ describe('Custom Bindings', () => { expect(nodes[2].getName()).to.equal('anotherNode'); // Name set explicitly at creation time }); - it('C++ exception handling', () => { + it('C++ exception handling', () => + { // Exceptions that are thrown and caught in C++ shouldn't bubble up to JS const doc = mx.createDocument(); const nodeGraph1 = doc.addNodeGraph(); @@ -79,15 +84,18 @@ describe('Custom Bindings', () => { // Exceptions that are not caught in C++ should throw with an exception pointer nodeGraph1.addNode('node', 'node1'); expect(() => { nodeGraph1.addNode('node', 'node1'); }).to.throw; - try { + try + { nodeGraph1.addNode('node', 'node1'); - } catch (errPtr) { + } catch (errPtr) + { expect(errPtr).to.be.a('number'); expect(mx.getExceptionMessage(errPtr)).to.be.a('string'); } }); - it('getReferencedSourceUris', async () => { + it('getReferencedSourceUris', async () => + { const doc = mx.createDocument(); const filename = 'standard_surface_look_brass_tiled.mtlx'; await mx.readFromXmlFile(doc, filename, examplesPath); @@ -98,7 +106,8 @@ describe('Custom Bindings', () => { expect(sourceUris.includes('standard_surface_brass_tiled.mtlx')).to.be.true; }); - it('Should invoke correct instance of \'validate\'', () => { + it('Should invoke correct instance of \'validate\'', () => + { // We check whether the correct function is called by provoking an error message that is specific to the // function that we expect to be called. const message = {}; @@ -126,7 +135,8 @@ describe('Custom Bindings', () => { expect(message.message).to.include('Unit type definition does not exist in document') }); - it('StringResolver name substitution getters', () => { + it('StringResolver name substitution getters', () => + { const fnTestData = { fnKey: 'fnValue', fnKey1: 'fnValue1' @@ -156,7 +166,8 @@ describe('Custom Bindings', () => { expect(gnSubs).to.deep.equal(gnTestData); }); - it('getShaderNodes', async () => { + it('getShaderNodes', async () => + { const doc = mx.createDocument(); const fileNames = ['standard_surface_marble_solid.mtlx']; const mtlxStrs = getMtlxStrings(fileNames, examplesPath); @@ -175,14 +186,16 @@ describe('Custom Bindings', () => { expect(shaderNodes.length).to.equal(0); }); - it('createValidName', () => { + it('createValidName', () => + { const testString = '_Note_:Please,turn.this+-into*1#valid\nname for_me'; const replaceRegex = /[^a-zA-Z0-9_:]/g expect(mx.createValidName(testString)).to.equal(testString.replace(replaceRegex, '_')); expect(mx.createValidName(testString, '-')).to.equal(testString.replace(replaceRegex, '-')); }); - it('getVersionIntegers', () => { + it('getVersionIntegers', () => + { const versionStringArr = mx.getVersionString().split('.').map((value) => parseInt(value, 10)); // Global getVersionIntegers diff --git a/javascript/MaterialXTest/document.spec.js b/javascript/MaterialXTest/document.spec.js index 01dc828f3f..ac2adba9ff 100644 --- a/javascript/MaterialXTest/document.spec.js +++ b/javascript/MaterialXTest/document.spec.js @@ -1,30 +1,37 @@ import { expect } from 'chai'; import Module from './_build/JsMaterialXCore.js'; -describe('Document', () => { +describe('Document', () => +{ let mx, doc; - before(async () => { + before(async () => + { mx = await Module(); // Create a document. doc = mx.createDocument(); }); - function expectError(type, cb) { - try { + function expectError(type, cb) + { + try + { cb(); throw new Error('Expected function to throw!'); - } catch (exceptionPtr) { + } catch (exceptionPtr) + { const message = mx.getExceptionMessage(exceptionPtr); expect(message.indexOf(type) !== -1).to.be.true; } } let nodeGraph; - it('Build document', () => { + it('Build document', () => + { // Create a node graph with constant and image sources. nodeGraph = doc.addNodeGraph(); expect(nodeGraph).to.exist; - expectError('Child name is not unique: nodegraph1', () => { + expectError('Child name is not unique: nodegraph1', () => + { doc.addNodeGraph(nodeGraph.getName()); }); const constant = nodeGraph.addNode('constant'); diff --git a/javascript/MaterialXTest/element.spec.js b/javascript/MaterialXTest/element.spec.js index e22c374851..cbb672c5c2 100644 --- a/javascript/MaterialXTest/element.spec.js +++ b/javascript/MaterialXTest/element.spec.js @@ -1,145 +1,166 @@ import { expect } from 'chai'; import Module from './_build/JsMaterialXCore.js'; -describe('Element', () => { - let mx, doc, valueTypes; +describe('Element', () => +{ + let mx, doc, valueTypes; - const primitiveValueTypes = { - Integer: 10, - Boolean: true, - String: 'test', - Float: 15, - IntegerArray: [1,2,3,4,5], - FloatArray: [12, 14], // Not using actual floats to avoid precision problems - StringArray: ['first', 'second'], - BooleanArray:[true, true, false], - } + const primitiveValueTypes = { + Integer: 10, + Boolean: true, + String: 'test', + Float: 15, + IntegerArray: [1, 2, 3, 4, 5], + FloatArray: [12, 14], // Not using actual floats to avoid precision problems + StringArray: ['first', 'second'], + BooleanArray: [true, true, false], + } - before(async () => { - mx = await Module(); - doc = mx.createDocument(); - valueTypes = { - Color3: new mx.Color3(1, 0, 0.5), - Color4: new mx.Color4(0, 1, 0.5, 1), - Vector2: new mx.Vector2(0, 1), - Vector3: new mx.Vector3(0, 1, 2), - Vector4: new mx.Vector4(0, 1, 2, 1), - Matrix33: new mx.Matrix33(0, 1, 2, 3, 4, 5, 6, 7, 8), - Matrix44: new mx.Matrix44(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), - }; - }); + before(async () => + { + mx = await Module(); + doc = mx.createDocument(); + valueTypes = { + Color3: new mx.Color3(1, 0, 0.5), + Color4: new mx.Color4(0, 1, 0.5, 1), + Vector2: new mx.Vector2(0, 1), + Vector3: new mx.Vector3(0, 1, 2), + Vector4: new mx.Vector4(0, 1, 2, 1), + Matrix33: new mx.Matrix33(0, 1, 2, 3, 4, 5, 6, 7, 8), + Matrix44: new mx.Matrix44(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), + }; + }); - describe('value setters', () => { - const checkValue = (types, assertionCallback) => { - const elem = doc.addChildOfCategory('geomprop'); - Object.keys(types).forEach((typeName) => { - const setFn = `setValue${typeName}`; - elem[setFn](types[typeName]); - assertionCallback(elem.getValue().getData(), typeName); - }); - }; + describe('value setters', () => + { + const checkValue = (types, assertionCallback) => + { + const elem = doc.addChildOfCategory('geomprop'); + Object.keys(types).forEach((typeName) => + { + const setFn = `setValue${typeName}`; + elem[setFn](types[typeName]); + assertionCallback(elem.getValue().getData(), typeName); + }); + }; - it('should work with expected type', () => { - checkValue(valueTypes, (returnedValue, typeName) => { - expect(returnedValue).to.be.an.instanceof(mx[`${typeName}`]); - expect(returnedValue.equals(valueTypes[typeName])).to.equal(true); - }); - }); + it('should work with expected type', () => + { + checkValue(valueTypes, (returnedValue, typeName) => + { + expect(returnedValue).to.be.an.instanceof(mx[`${typeName}`]); + expect(returnedValue.equals(valueTypes[typeName])).to.equal(true); + }); + }); - it('should work with expected primitive type', () => { - checkValue(primitiveValueTypes, (returnedValue, typeName) => { - expect(returnedValue).to.eql(primitiveValueTypes[typeName]); - }); - }); + it('should work with expected primitive type', () => + { + checkValue(primitiveValueTypes, (returnedValue, typeName) => + { + expect(returnedValue).to.eql(primitiveValueTypes[typeName]); + }); + }); - it('should fail for incorrect type', () => { - const elem = doc.addChildOfCategory('geomprop'); - expect(()=>elem.Matrix33(true)).to.throw(); + it('should fail for incorrect type', () => + { + const elem = doc.addChildOfCategory('geomprop'); + expect(() => elem.Matrix33(true)).to.throw(); + }); }); - }); - describe('typed value setters', () => { - const checkTypes = (types, assertionCallback) => { - const elem = doc.addChildOfCategory('geomprop'); - Object.keys(types).forEach((typeName) => { - const setFn = `setTypedAttribute${typeName}`; - const getFn = `getTypedAttribute${typeName}`; - elem[setFn](typeName, types[typeName]); - assertionCallback(elem[getFn](typeName), types[typeName]); - }); - }; + describe('typed value setters', () => + { + const checkTypes = (types, assertionCallback) => + { + const elem = doc.addChildOfCategory('geomprop'); + Object.keys(types).forEach((typeName) => + { + const setFn = `setTypedAttribute${typeName}`; + const getFn = `getTypedAttribute${typeName}`; + elem[setFn](typeName, types[typeName]); + assertionCallback(elem[getFn](typeName), types[typeName]); + }); + }; - it('should work with expected custom type', () => { - checkTypes(valueTypes, (returnedValue, originalValue) => { - expect(returnedValue.equals(originalValue)).to.equal(true); - }); - }); + it('should work with expected custom type', () => + { + checkTypes(valueTypes, (returnedValue, originalValue) => + { + expect(returnedValue.equals(originalValue)).to.equal(true); + }); + }); - it('should work with expected primitive type', () => { - checkTypes(primitiveValueTypes, (returnedValue, originalValue) => { - expect(returnedValue).to.eql(originalValue); - }); - }); + it('should work with expected primitive type', () => + { + checkTypes(primitiveValueTypes, (returnedValue, originalValue) => + { + expect(returnedValue).to.eql(originalValue); + }); + }); - it('should fail for incorrect type', () => { - const elem = doc.addChildOfCategory('geomprop'); - expect(()=>elem.setTypedAttributeColor3('wrongType', true)).to.throw(); + it('should fail for incorrect type', () => + { + const elem = doc.addChildOfCategory('geomprop'); + expect(() => elem.setTypedAttributeColor3('wrongType', true)).to.throw(); + }); }); - }); - it('factory invocation should match specialized functions', () => { - // List based in source/MaterialXCore/Element.cpp - const elemtypeArr = [ - 'Backdrop', - 'Collection', - 'GeomInfo', - 'MaterialAssign', - 'PropertySetAssign', - 'Visibility', - 'GeomPropDef', - 'Look', - 'LookGroup', - 'PropertySet', - 'TypeDef', - 'AttributeDef', - 'NodeGraph', - 'Implementation', - 'Node', - 'NodeDef', - 'Variant', - 'Member', - 'TargetDef', - 'GeomProp', - 'Input', - 'Output', - 'Property', - 'PropertyAssign', - 'Unit', - 'UnitDef', - 'UnitTypeDef', - 'VariantAssign', - 'VariantSet', - ]; + it('factory invocation should match specialized functions', () => + { + // List based in source/MaterialXCore/Element.cpp + const elemtypeArr = [ + 'Backdrop', + 'Collection', + 'GeomInfo', + 'MaterialAssign', + 'PropertySetAssign', + 'Visibility', + 'GeomPropDef', + 'Look', + 'LookGroup', + 'PropertySet', + 'TypeDef', + 'AttributeDef', + 'NodeGraph', + 'Implementation', + 'Node', + 'NodeDef', + 'Variant', + 'Member', + 'TargetDef', + 'GeomProp', + 'Input', + 'Output', + 'Property', + 'PropertyAssign', + 'Unit', + 'UnitDef', + 'UnitTypeDef', + 'VariantAssign', + 'VariantSet', + ]; - elemtypeArr.forEach((typeName) => { - const specializedFn = `addChild${typeName}`; - const factoryName = typeName.toLowerCase(); - const type = mx[typeName]; - expect(doc[specializedFn]()).to.be.an.instanceof(type); - expect(doc.addChildOfCategory(factoryName)).to.be.an.instanceof(type); - }); + elemtypeArr.forEach((typeName) => + { + const specializedFn = `addChild${typeName}`; + const factoryName = typeName.toLowerCase(); + const type = mx[typeName]; + expect(doc[specializedFn]()).to.be.an.instanceof(type); + expect(doc.addChildOfCategory(factoryName)).to.be.an.instanceof(type); + }); - const specialElemType = { - 'MaterialX': mx.Document, - 'Comment': mx.CommentElement, - 'Generic': mx.GenericElement, - }; + const specialElemType = { + 'MaterialX': mx.Document, + 'Comment': mx.CommentElement, + 'Generic': mx.GenericElement, + }; - Object.keys(specialElemType).forEach((typeName) => { - const specializedFn = `addChild${typeName}`; - const factoryName = typeName.toLowerCase(); - expect(doc[specializedFn]()).to.be.an.instanceof(specialElemType[typeName]); - expect(doc.addChildOfCategory(factoryName)).to.be.an.instanceof(specialElemType[typeName]); + Object.keys(specialElemType).forEach((typeName) => + { + const specializedFn = `addChild${typeName}`; + const factoryName = typeName.toLowerCase(); + expect(doc[specializedFn]()).to.be.an.instanceof(specialElemType[typeName]); + expect(doc.addChildOfCategory(factoryName)).to.be.an.instanceof(specialElemType[typeName]); + }); }); - }); }); diff --git a/javascript/MaterialXTest/environ.spec.js b/javascript/MaterialXTest/environ.spec.js index 2ac71dc044..2277e0b259 100644 --- a/javascript/MaterialXTest/environ.spec.js +++ b/javascript/MaterialXTest/environ.spec.js @@ -1,13 +1,16 @@ import { expect } from 'chai';; import Module from './_build/JsMaterialXCore.js'; -describe('Environ', () => { +describe('Environ', () => +{ let mx; - before(async () => { + before(async () => + { mx = await Module(); }); - it('Environment variables', () => { + it('Environment variables', () => + { expect(mx.getEnviron(mx.MATERIALX_SEARCH_PATH_ENV_VAR)).to.equal(''); mx.setEnviron(mx.MATERIALX_SEARCH_PATH_ENV_VAR, 'test'); expect(mx.getEnviron(mx.MATERIALX_SEARCH_PATH_ENV_VAR)).to.equal('test'); diff --git a/javascript/MaterialXTest/testHelpers.js b/javascript/MaterialXTest/testHelpers.js index c434400c6a..a75c2e6144 100644 --- a/javascript/MaterialXTest/testHelpers.js +++ b/javascript/MaterialXTest/testHelpers.js @@ -1,9 +1,11 @@ var fs = require('fs'); var path = require('path'); -export function getMtlxStrings(fileNames, subPath) { +export function getMtlxStrings(fileNames, subPath) +{ const mtlxStrs = []; - for (let i = 0; i < fileNames.length; i++) { + for (let i = 0; i < fileNames.length; i++) + { const p = path.resolve(subPath, fileNames[parseInt(i, 10)]); const t = fs.readFileSync(p, 'utf8'); mtlxStrs.push(t); diff --git a/javascript/MaterialXTest/traversal.spec.js b/javascript/MaterialXTest/traversal.spec.js index 4f422bb5cc..62a895f852 100644 --- a/javascript/MaterialXTest/traversal.spec.js +++ b/javascript/MaterialXTest/traversal.spec.js @@ -1,13 +1,16 @@ import { expect } from 'chai'; import Module from './_build/JsMaterialXCore.js'; -describe('Traversal', () => { +describe('Traversal', () => +{ let mx; - before(async () => { + before(async () => + { mx = await Module(); }); - it('Traverse Graph', () => { + it('Traverse Graph', () => + { // Create a document. const doc = mx.createDocument(); // Create a node graph with the following structure: @@ -36,67 +39,79 @@ describe('Traversal', () => { mix.setConnectedNode('bg', contrast); mix.setConnectedNode('mask', noise3d); output.setConnectedNode(mix); - + expect(doc.validate()).to.be.true; - + // Traverse the document tree (implicit iterator). let nodeCount = 0; - for (let elem of doc.traverseTree()) { - if (elem instanceof mx.Node) { + for (let elem of doc.traverseTree()) + { + if (elem instanceof mx.Node) + { nodeCount++; } } expect(nodeCount).to.equal(7); - + // Traverse the document tree (explicit iterator) let treeIter = doc.traverseTree(); nodeCount = 0; let maxElementDepth = 0; - for (let elem of treeIter) { - if (elem instanceof mx.Node) { + for (let elem of treeIter) + { + if (elem instanceof mx.Node) + { nodeCount++; } maxElementDepth = Math.max(maxElementDepth, treeIter.getElementDepth()); } expect(nodeCount).to.equal(7); expect(maxElementDepth).to.equal(3); - + // Traverse the document tree (prune subtree). nodeCount = 0; treeIter = doc.traverseTree(); - for (let elem of treeIter) { - if (elem instanceof mx.Node) { + for (let elem of treeIter) + { + if (elem instanceof mx.Node) + { nodeCount++; } - if (elem instanceof mx.NodeGraph) { + if (elem instanceof mx.NodeGraph) + { treeIter.setPruneSubtree(true); } } expect(nodeCount).to.equal(0); - + // Traverse upstream from the graph output (implicit iterator) nodeCount = 0; - for (let edge of output.traverseGraph()) { + for (let edge of output.traverseGraph()) + { const upstreamElem = edge.getUpstreamElement(); const connectingElem = edge.getConnectingElement(); const downstreamElem = edge.getDownstreamElement(); - if (upstreamElem instanceof mx.Node) { + if (upstreamElem instanceof mx.Node) + { nodeCount++; - if (downstreamElem instanceof mx.Node) { + if (downstreamElem instanceof mx.Node) + { expect(connectingElem instanceof mx.Input).to.be.true; } } } expect(nodeCount).to.equal(7); - + // Traverse upstream from the graph output (explicit iterator) nodeCount = 0; maxElementDepth = 0; let maxNodeDepth = 0; let graphIter = output.traverseGraph(); - for (let edge of graphIter) { + for (let edge of graphIter) + { const upstreamElem = edge.getUpstreamElement(); - if (upstreamElem instanceof mx.Node) { + if (upstreamElem instanceof mx.Node) + { nodeCount++; } maxElementDepth = Math.max(maxElementDepth, graphIter.getElementDepth()); @@ -105,22 +120,25 @@ describe('Traversal', () => { expect(nodeCount).to.equal(7); expect(maxElementDepth).to.equal(3); expect(maxNodeDepth).to.equal(3); - + // Traverse upstream from the graph output (prune subgraph) nodeCount = 0; graphIter = output.traverseGraph(); - for (let edge of graphIter) { + for (let edge of graphIter) + { const upstreamElem = edge.getUpstreamElement(); expect(upstreamElem.getSelf()).to.be.an.instanceof(mx.Element); - if (upstreamElem instanceof mx.Node) { + if (upstreamElem instanceof mx.Node) + { nodeCount++; } - if (upstreamElem.getCategory() === 'multiply') { + if (upstreamElem.getCategory() === 'multiply') + { graphIter.setPruneSubgraph(true); } } expect(nodeCount).to.equal(5); - + // Create and detect a cycle multiply.setConnectedNode('in2', mix); expect(output.hasUpstreamCycle()).to.be.true; @@ -128,7 +146,7 @@ describe('Traversal', () => { multiply.setConnectedNode('in2', constant); expect(output.hasUpstreamCycle()).to.be.false; expect(doc.validate()).to.be.true; - + // Create and detect a loop contrast.setConnectedNode('in', contrast); expect(output.hasUpstreamCycle()).to.be.true; @@ -137,10 +155,12 @@ describe('Traversal', () => { expect(output.hasUpstreamCycle()).to.be.false; expect(doc.validate()).to.be.true; }); - - describe("Traverse inheritance", () => { + + describe("Traverse inheritance", () => + { let nodeDefInheritanceLevel2, nodeDefInheritanceLevel1, nodeDefParent; - beforeEach(() => { + beforeEach(() => + { const doc = mx.createDocument(); nodeDefParent = doc.addNodeDef(); nodeDefParent.setName('BaseClass'); @@ -152,23 +172,29 @@ describe('Traversal', () => { nodeDefInheritanceLevel1.setInheritsFrom(nodeDefParent); }); - it('for of loop', () => { + it('for of loop', () => + { const inheritanceIterator = nodeDefInheritanceLevel2.traverseInheritance(); let inheritanceChainLength = 0; - for(const elem of inheritanceIterator) { - if (elem instanceof mx.NodeDef) { + for (const elem of inheritanceIterator) + { + if (elem instanceof mx.NodeDef) + { inheritanceChainLength++; } } expect(inheritanceChainLength).to.equal(2);; }); - it('while loop', () => { + it('while loop', () => + { const inheritanceIterator = nodeDefInheritanceLevel2.traverseInheritance(); let inheritanceChainLength = 0; let elem = inheritanceIterator.next(); - while (!elem.done) { - if (elem.value instanceof mx.NodeDef) { + while (!elem.done) + { + if (elem.value instanceof mx.NodeDef) + { inheritanceChainLength++; } elem = inheritanceIterator.next(); diff --git a/javascript/MaterialXTest/types.spec.js b/javascript/MaterialXTest/types.spec.js index 7fae8b30c7..fc909c8c94 100644 --- a/javascript/MaterialXTest/types.spec.js +++ b/javascript/MaterialXTest/types.spec.js @@ -1,13 +1,16 @@ import { expect } from 'chai';; import Module from './_build/JsMaterialXCore.js'; -describe('Types', () => { +describe('Types', () => +{ let mx; - before(async () => { + before(async () => + { mx = await Module(); }); - it('Vectors', () => { + it('Vectors', () => + { const v1 = new mx.Vector3(1, 2, 3); let v2 = new mx.Vector3(2, 4, 6); @@ -59,10 +62,13 @@ describe('Types', () => { expect(v4.notEquals(v2)).to.be.true; }); - function multiplyMatrix(matrix, val) { + function multiplyMatrix(matrix, val) + { const clonedMatrix = matrix.copy(); - for (let i = 0; i < clonedMatrix.numRows(); ++i) { - for (let k = 0; k < clonedMatrix.numColumns(); ++k) { + for (let i = 0; i < clonedMatrix.numRows(); ++i) + { + for (let k = 0; k < clonedMatrix.numColumns(); ++k) + { const v = clonedMatrix.getItem(i, k); clonedMatrix.setItem(i, k, v * val); } @@ -70,10 +76,13 @@ describe('Types', () => { return clonedMatrix; } - function divideMatrix(matrix, val) { + function divideMatrix(matrix, val) + { const clonedMatrix = matrix.copy(); - for (let i = 0; i < clonedMatrix.numRows(); ++i) { - for (let k = 0; k < clonedMatrix.numColumns(); ++k) { + for (let i = 0; i < clonedMatrix.numRows(); ++i) + { + for (let k = 0; k < clonedMatrix.numColumns(); ++k) + { const v = clonedMatrix.getItem(i, k); clonedMatrix.setItem(i, k, v / val); } @@ -81,18 +90,19 @@ describe('Types', () => { return clonedMatrix; } - it('Matrices', () => { + it('Matrices', () => + { // Translation and scale const trans = mx.Matrix44.createTranslation(new mx.Vector3(1, 2, 3)); const scale = mx.Matrix44.createScale(new mx.Vector3(2, 2, 2)); expect(trans.equals(new mx.Matrix44(1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 1, 2, 3, 1))); + 0, 1, 0, 0, + 0, 0, 1, 0, + 1, 2, 3, 1))); expect(scale.equals(new mx.Matrix44(2, 0, 0, 0, - 0, 2, 0, 0, - 0, 0, 2, 0, - 0, 0, 0, 1))); + 0, 2, 0, 0, + 0, 0, 2, 0, + 0, 0, 0, 1))); // Indexing operators expect(trans.getItem(3, 2)).to.equal(3); @@ -103,9 +113,9 @@ describe('Types', () => { // Matrix methods expect(trans.getTranspose().equals( new mx.Matrix44(1, 0, 0, 1, - 0, 1, 0, 2, - 0, 0, 1, 3, - 0, 0, 0, 1) + 0, 1, 0, 2, + 0, 0, 1, 3, + 0, 0, 0, 1) )).to.be.true; expect(scale.getTranspose().equals(scale)).to.be.true; expect(trans.getDeterminant()).to.equal(1); @@ -120,17 +130,17 @@ describe('Types', () => { let prod4 = trans; prod4 = prod4.multiply(scale); expect(prod1.equals(new mx.Matrix44(2, 0, 0, 0, - 0, 2, 0, 0, - 0, 0, 2, 0, - 2, 4, 6, 1))); + 0, 2, 0, 0, + 0, 0, 2, 0, + 2, 4, 6, 1))); expect(prod2.equals(new mx.Matrix44(2, 0, 0, 0, - 0, 2, 0, 0, - 0, 0, 2, 0, - 1, 2, 3, 1))); + 0, 2, 0, 0, + 0, 0, 2, 0, + 1, 2, 3, 1))); expect(prod3.equals(new mx.Matrix44(2, 0, 0, 0, - 0, 2, 0, 0, - 0, 0, 2, 0, - 2, 4, 6, 2))); + 0, 2, 0, 0, + 0, 0, 2, 0, + 2, 4, 6, 2))); expect(prod4.equals(prod1)); // Matrix division diff --git a/javascript/MaterialXTest/value.spec.js b/javascript/MaterialXTest/value.spec.js index 1b06d3f59b..6a9091ce47 100644 --- a/javascript/MaterialXTest/value.spec.js +++ b/javascript/MaterialXTest/value.spec.js @@ -1,13 +1,16 @@ import { expect } from 'chai';; import Module from './_build/JsMaterialXCore.js'; -describe('Value', () => { +describe('Value', () => +{ let mx; - before(async () => { + before(async () => + { mx = await Module(); }); - it('Create values of different types', () => { + it('Create values of different types', () => + { const testValues = { integer: '1', boolean: 'true', @@ -26,7 +29,8 @@ describe('Value', () => { stringarray: "'one', 'two', 'three'", }; - for (let type in testValues) { + for (let type in testValues) + { const value = testValues[String(type)]; const newValue = mx.Value.createValueFromStrings(value, type); const typeString = newValue.getTypeString(); diff --git a/javascript/MaterialXTest/xmlIo.spec.js b/javascript/MaterialXTest/xmlIo.spec.js index e569b9be76..670b0df43d 100644 --- a/javascript/MaterialXTest/xmlIo.spec.js +++ b/javascript/MaterialXTest/xmlIo.spec.js @@ -4,7 +4,8 @@ import { getMtlxStrings } from './testHelpers'; const TIMEOUT = 60000; -describe('XmlIo', () => { +describe('XmlIo', () => +{ let mx; // These should be relative to cwd @@ -24,18 +25,23 @@ describe('XmlIo', () => { 'UsdPreviewSurface/usd_preview_surface_plastic.mtlx', ]; - async function readStdLibrary(asString = false) { + async function readStdLibrary(asString = false) + { const libs = []; let iterable = libraryFilenames; - if (asString) { + if (asString) + { const libraryMtlxStrings = getMtlxStrings(libraryFilenames, libraryPath); iterable = libraryMtlxStrings; } - for (let file of iterable) { + for (let file of iterable) + { const lib = mx.createDocument(); - if (asString) { + if (asString) + { await mx.readFromXmlString(lib, file, libraryPath); - } else { + } else + { await mx.readFromXmlFile(lib, file, libraryPath); } libs.push(lib); @@ -43,12 +49,15 @@ describe('XmlIo', () => { return libs; } - async function readAndValidateExamples(examples, libraries, readFunc, searchPath = undefined) { - for (let file of examples) { + async function readAndValidateExamples(examples, libraries, readFunc, searchPath = undefined) + { + for (let file of examples) + { const doc = mx.createDocument(); await readFunc(doc, file, searchPath); // Import stdlib into the current document and validate it. - for (let lib of libraries) { + for (let lib of libraries) + { doc.importLibrary(lib); } expect(doc.validate()).to.be.true; @@ -56,8 +65,10 @@ describe('XmlIo', () => { // Make sure the document does actually contain something. let valueElementCount = 0; const treeIter = doc.traverseTree(); - for(const elem of treeIter) { - if (elem instanceof mx.ValueElement) { + for (const elem of treeIter) + { + if (elem instanceof mx.ValueElement) + { valueElementCount++; } } @@ -65,17 +76,20 @@ describe('XmlIo', () => { }; } - before(async () => { + before(async () => + { mx = await Module(); }); - it('Read XML from file', async () => { + it('Read XML from file', async () => + { // Read the standard library const libs = await readStdLibrary(false); // Read and validate the example documents. await readAndValidateExamples(exampleFilenames, libs, - async (document, file, sp) => { + async (document, file, sp) => + { await mx.readFromXmlFile(document, file, sp); }, examplesPath); @@ -90,14 +104,16 @@ describe('XmlIo', () => { expect(copy.equals(doc)).to.be.true; }).timeout(TIMEOUT); - it('Read XML from string', async () => { + it('Read XML from string', async () => + { // Read the standard library const libs = await readStdLibrary(true); // Read and validate each example document. const examplesStrings = getMtlxStrings(exampleFilenames, examplesPath); await readAndValidateExamples(examplesStrings, libs, - async (document, file) => { + async (document, file) => + { await mx.readFromXmlString(document, file); }); @@ -112,14 +128,16 @@ describe('XmlIo', () => { expect(copy.equals(doc)).to.be.true; }).timeout(TIMEOUT); - it('Read XML with recursive includes', async () => { + it('Read XML with recursive includes', async () => + { const doc = mx.createDocument(); await mx.readFromXmlFile(doc, includeTestPath + '/root.mtlx'); expect(doc.getChild('paint_semigloss')).to.exist; expect(doc.validate()).to.be.true; }); - it('Locate XML includes via search path', async () => { + it('Locate XML includes via search path', async () => + { const searchPath = includeTestPath + ';' + includeTestPath + '/folder'; const filename = 'non_relative_includes.mtlx'; const doc = mx.createDocument(); @@ -137,7 +155,8 @@ describe('XmlIo', () => { expect(doc2.equals(doc)).to.be.true; }); - it('Locate XML includes via environment variable', async () => { + it('Locate XML includes via environment variable', async () => + { const searchPath = includeTestPath + ';' + includeTestPath + '/folder'; const filename = 'non_relative_includes.mtlx'; @@ -160,13 +179,16 @@ describe('XmlIo', () => { expect(doc2.equals(doc)).to.be.true; }); - it('Locate XML includes via absolute search paths', async () => { + it('Locate XML includes via absolute search paths', async () => + { let absolutePath; - if (typeof window === 'object') { + if (typeof window === 'object') + { // We're in the browser const cwd = window.location.origin + window.location.pathname; absolutePath = cwd + '/' + includeTestPath; - } else if (typeof process === 'object') { + } else if (typeof process === 'object') + { // We're in Node const nodePath = require('path'); absolutePath = nodePath.resolve(includeTestPath); @@ -175,22 +197,26 @@ describe('XmlIo', () => { await mx.readFromXmlFile(doc, 'root.mtlx', absolutePath); }); - it('Detect XML include cycles', async () => { + it('Detect XML include cycles', async () => + { const doc = mx.createDocument(); expect(async () => await mx.readFromXmlFile(doc, includeTestPath + '/cycle.mtlx')).to.throw; }); - it('Disabling XML includes', async () => { + it('Disabling XML includes', async () => + { const doc = mx.createDocument(); const readOptions = new mx.XmlReadOptions(); readOptions.readXIncludes = false; expect(async () => await mx.readFromXmlFile(doc, includeTestPath + '/cycle.mtlx', readOptions)).to.not.throw; }); - it('Write to XML string', async () => { + it('Write to XML string', async () => + { // Read all example documents and write them to an XML string const searchPath = libraryPath + ';' + examplesPath; - for (let filename of exampleFilenames) { + for (let filename of exampleFilenames) + { const doc = mx.createDocument(); await mx.readFromXmlFile(doc, filename, searchPath); @@ -206,7 +232,8 @@ describe('XmlIo', () => { }; }); - it('Prepend include tag', () => { + it('Prepend include tag', () => + { const doc = mx.createDocument(); const includePath = "SomePath"; const writeOptions = new mx.XmlWriteOptions(); @@ -216,7 +243,8 @@ describe('XmlIo', () => { }); // Node only, because we cannot read from a downloaded file in the browser - it('Write XML to file', async () => { + it('Write XML to file', async () => + { const filename = '_build/testFile.mtlx'; const includeRegex = //g; const doc = mx.createDocument(); diff --git a/javascript/MaterialXView/index.ejs b/javascript/MaterialXView/index.ejs index d832f03e42..8f278051af 100644 --- a/javascript/MaterialXView/index.ejs +++ b/javascript/MaterialXView/index.ejs @@ -10,6 +10,22 @@ margin: 0; font-family: Arial } + + /* Property editor item color */ + .peditoritem { + background-color: #334444; + } + /* Property editor folder color */ + .peditorfolder { + background-color: #333333; + } + + .peditor_material_assigned { + background-color: #006cb8; + } + .peditor_material_assigned:hover { + background-color: #32adff; + } diff --git a/javascript/MaterialXView/public/shader_ball.svg b/javascript/MaterialXView/public/shader_ball.svg new file mode 100644 index 0000000000..2b51705a42 --- /dev/null +++ b/javascript/MaterialXView/public/shader_ball.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/javascript/MaterialXView/public/shader_ball2.svg b/javascript/MaterialXView/public/shader_ball2.svg new file mode 100644 index 0000000000..62907b5df8 --- /dev/null +++ b/javascript/MaterialXView/public/shader_ball2.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/javascript/MaterialXView/source/dropHandling.js b/javascript/MaterialXView/source/dropHandling.js index adcbef2ca1..f54b77115c 100644 --- a/javascript/MaterialXView/source/dropHandling.js +++ b/javascript/MaterialXView/source/dropHandling.js @@ -2,13 +2,21 @@ import * as THREE from 'three'; import * as fflate from 'three/examples/jsm/libs/fflate.module.js'; const debugFileHandling = false; -let loadingCallback; +let loadingCallback = null; +let sceneLoadingCallback = null; -export function setLoadingCallback(cb) { +export function setLoadingCallback(cb) +{ loadingCallback = cb; } -export function dropHandler(ev) { +export function setSceneLoadingCallback(cb) +{ + sceneLoadingCallback = cb; +} + +export function dropHandler(ev) +{ if (debugFileHandling) console.log('File(s) dropped', ev.dataTransfer.items, ev.dataTransfer.files); // Prevent default behavior (Prevent file from being opened) @@ -20,14 +28,15 @@ export function dropHandler(ev) { let haveGetAsEntry = false; if (ev.dataTransfer.items.length > 0) - haveGetAsEntry = - ("getAsEntry" in ev.dataTransfer.items[0]) || - ("webkitGetAsEntry" in ev.dataTransfer.items[0]); + haveGetAsEntry = + ("getAsEntry" in ev.dataTransfer.items[0]) || + ("webkitGetAsEntry" in ev.dataTransfer.items[0]); // Useful for debugging file handling on platforms that don't support newer file system APIs // haveGetAsEntry = false; - if (haveGetAsEntry) { + if (haveGetAsEntry) + { for (var i = 0; i < ev.dataTransfer.items.length; i++) { let item = ev.dataTransfer.items[i]; @@ -41,7 +50,7 @@ export function dropHandler(ev) { for (var i = 0; i < ev.dataTransfer.items.length; i++) { let item = ev.dataTransfer.items[i]; - + // API when there's no "getAsEntry" support console.log(item.kind, item); if (item.kind === 'file') @@ -53,32 +62,40 @@ export function dropHandler(ev) { else if (item.kind === 'directory') { var dirReader = item.createReader(); - dirReader.readEntries(function(entries) { - for (var i = 0; i < entries.length; i++) { - console.log(entries[i].name); - var entry = entries[i]; - if (entry.isFile) { - entry.file(function(file) { - testAndLoadFile(file); - }); + dirReader.readEntries(function (entries) + { + for (var i = 0; i < entries.length; i++) + { + console.log(entries[i].name); + var entry = entries[i]; + if (entry.isFile) + { + entry.file(function (file) + { + testAndLoadFile(file); + }); + } } - } }); } } - } else { - for (var i = 0; i < ev.dataTransfer.files.length; i++) { + } else + { + for (var i = 0; i < ev.dataTransfer.files.length; i++) + { let file = ev.dataTransfer.files[i]; testAndLoadFile(file); } } } -export function dragOverHandler(ev) { +export function dragOverHandler(ev) +{ ev.preventDefault(); } -async function getBufferFromFile(fileEntry) { +async function getBufferFromFile(fileEntry) +{ if (fileEntry instanceof ArrayBuffer) return fileEntry; if (fileEntry instanceof String) return fileEntry; @@ -90,90 +107,120 @@ async function getBufferFromFile(fileEntry) { if (debugFileHandling) console.log("reading ", fileEntry, "as text?", readAsText); if (debugFileHandling) console.log("getBufferFromFile", fileEntry); - const buffer = await new Promise((resolve, reject) => { - function readFile(file) { + const buffer = await new Promise((resolve, reject) => + { + function readFile(file) + { var reader = new FileReader(); - reader.onloadend = function(e) { + reader.onloadend = function (e) + { if (debugFileHandling) console.log("loaded", "should be text?", readAsText, this.result); resolve(this.result); }; - + if (readAsText) reader.readAsText(file); else reader.readAsArrayBuffer(file); } - if ("file" in fileEntry) { - fileEntry.file(function(file) { + if ("file" in fileEntry) + { + fileEntry.file(function (file) + { readFile(file); - }, (e) => { + }, (e) => + { console.error("Error reading file ", e); }); } - else { + else + { readFile(fileEntry); } }); return buffer; } -async function handleFilesystemEntries(entries) { +async function handleFilesystemEntries(entries) +{ const allFiles = []; const fileIgnoreList = [ - '.gitignore', - 'README.md', - '.DS_Store', + '.gitignore', + 'README.md', + '.DS_Store', ] const dirIgnoreList = [ - '.git', - 'node_modules', + '.git', + 'node_modules', ] - for (let entry of entries) { - if (debugFileHandling) console.log("file entry", entry) - if (entry.isFile) { - if (debugFileHandling) console.log("single file", entry); - if (fileIgnoreList.includes(entry.name)) { - continue; - } - allFiles.push(entry); - } - else if (entry.isDirectory) { - if (dirIgnoreList.includes(entry.name)) { - continue; + let isGLB = false; + let haveMtlx = false; + for (let entry of entries) + { + if (debugFileHandling) console.log("file entry", entry) + if (entry.isFile) + { + if (debugFileHandling) + console.log("single file", entry); + if (fileIgnoreList.includes(entry.name)) + { + continue; + } + allFiles.push(entry); + + if (entry.name.endsWith('glb')) + { + isGLB = true; + break; + } } - const files = await readDirectory(entry); - if (debugFileHandling) console.log("all files", files); - for (const file of files) { - if (fileIgnoreList.includes(file.name)) { - continue; - } - allFiles.push(file); + else if (entry.isDirectory) + { + if (dirIgnoreList.includes(entry.name)) + { + continue; + } + const files = await readDirectory(entry); + if (debugFileHandling) console.log("all files", files); + for (const file of files) + { + if (fileIgnoreList.includes(file.name)) + { + continue; + } + allFiles.push(file); + } } - } } const imageLoader = new THREE.ImageLoader(); // unpack zip files first - for (const fileEntry of allFiles) { + for (const fileEntry of allFiles) + { // special case: zip archives - if (fileEntry.fullPath.toLowerCase().endsWith('.zip')) { - await new Promise(async (resolve, reject) => { + if (fileEntry.fullPath.toLowerCase().endsWith('.zip')) + { + await new Promise(async (resolve, reject) => + { const arrayBuffer = await getBufferFromFile(fileEntry); // use fflate to unpack them and add the files to the cache - fflate.unzip(new Uint8Array(arrayBuffer), (error, unzipped) => { + fflate.unzip(new Uint8Array(arrayBuffer), (error, unzipped) => + { // push these files into allFiles - for (const [filePath, buffer] of Object.entries(unzipped)) { + for (const [filePath, buffer] of Object.entries(unzipped)) + { // mock FileEntry for easier usage downstream const blob = new Blob([buffer]); const newFileEntry = { fullPath: "/" + filePath, name: filePath.split('/').pop(), - file: (callback) => { + file: (callback) => + { callback(blob); }, isFile: true, @@ -188,27 +235,54 @@ async function handleFilesystemEntries(entries) { } // sort so mtlx files come first - allFiles.sort((a, b) => { - if (a.name.endsWith('.mtlx') && !b.name.endsWith('.mtlx')) { + allFiles.sort((a, b) => + { + if (a.name.endsWith('.mtlx') && !b.name.endsWith('.mtlx')) + { return -1; } - if (!a.name.endsWith('.mtlx') && b.name.endsWith('.mtlx')) { + if (!a.name.endsWith('.mtlx') && b.name.endsWith('.mtlx')) + { return 1; } return 0; }); - if (debugFileHandling) console.log("all files", allFiles); + if (isGLB) + { + console.log("Load GLB file", allFiles[0]); + + const rootFile = allFiles[0]; + THREE.Cache.add(rootFile.fullPath, await getBufferFromFile(rootFile)); + + if (debugFileHandling) console.log("CACHE", THREE.Cache.files); + + sceneLoadingCallback(rootFile); + return; + } + + if (!allFiles[0].name.endsWith('mtlx')) + { + console.log("No MaterialX files dropped. Skipping content."); + return; + } + + if (debugFileHandling) + { + console.log("- All files", allFiles); + } // put all files in three' Cache - for (const fileEntry of allFiles) { + for (const fileEntry of allFiles) + { const allowedFileTypes = [ 'png', 'jpg', 'jpeg' ]; const ext = fileEntry.fullPath.split('.').pop(); - if (!allowedFileTypes.includes(ext)) { + if (!allowedFileTypes.includes(ext)) + { // console.log("skipping file", fileEntry.fullPath); continue; } @@ -222,45 +296,64 @@ async function handleFilesystemEntries(entries) { // TODO we could also allow dropping of multiple MaterialX files (or folders with them inside) // and seed the dropdown from that. // At that point, actually reading files and textures into memory should be deferred until they are actually used. - const rootFile = allFiles[0]; - THREE.Cache.add(rootFile.fullPath, await getBufferFromFile(rootFile)); + if (allFiles.length > 0) + { + const rootFile = allFiles[0]; + THREE.Cache.add(rootFile.fullPath, await getBufferFromFile(rootFile)); - if (debugFileHandling) console.log("CACHE", THREE.Cache.files); + if (debugFileHandling) console.log("CACHE", THREE.Cache.files); - loadingCallback(rootFile); + loadingCallback(rootFile); + } + else + { + console.log('No files to add cache.') + } } -async function readDirectory(directory) { +async function readDirectory(directory) +{ let entries = []; - let getEntries = async (directory) => { + let getEntries = async (directory) => + { let dirReader = directory.createReader(); - await new Promise((resolve, reject) => { - dirReader.readEntries( - async (results) => { - if (results.length) { - // entries = entries.concat(results); - for (let entry of results) { - if (entry.isDirectory) { - await getEntries(entry); - } - else { - entries.push(entry); - } - } - } - resolve(); - }, - (error) => { - /* handle error — error is a FileError object */ - }, - )} - )}; + await new Promise((resolve, reject) => + { + dirReader.readEntries( + async (results) => + { + if (results.length) + { + // entries = entries.concat(results); + for (let entry of results) + { + if (entry.isDirectory) + { + await getEntries(entry); + } + else + { + entries.push(entry); + } + } + } + resolve(); + }, + (error) => + { + /* handle error — error is a FileError object */ + }, + ) + } + ) + }; await getEntries(directory); return entries; } -async function testAndLoadFile(file) { +async function testAndLoadFile(file) +{ let ext = file.name.split('.').pop(); if (debugFileHandling) console.log(file.name + ", " + file.size + ", " + ext); @@ -272,7 +365,8 @@ async function testAndLoadFile(file) { fullPath: "/" + file.name, name: file.name.split('/').pop(), isFile: true, - file: (callback) => { + file: (callback) => + { callback(file); } }; diff --git a/javascript/MaterialXView/source/helper.js b/javascript/MaterialXView/source/helper.js index 98441a605f..2b7f0f7d5b 100644 --- a/javascript/MaterialXView/source/helper.js +++ b/javascript/MaterialXView/source/helper.js @@ -45,8 +45,8 @@ function fromVector(value, dimension) } else { - outValue = []; - for(let i = 0; i < dimension; ++i) + outValue = []; + for (let i = 0; i < dimension; ++i) outValue.push(0.0); } @@ -69,13 +69,13 @@ function fromMatrix(matrix, dimension) { vec.push(matrix.getItem(i, k)); } - } + } } else { for (let i = 0; i < dimension; ++i) vec.push(0.0); } - + return vec; } @@ -89,7 +89,7 @@ function fromMatrix(matrix, dimension) */ function toThreeUniform(type, value, name, uniforms, textureLoader, searchPath, flipY) { - let outValue; + let outValue; switch (type) { case 'float': @@ -97,7 +97,7 @@ function toThreeUniform(type, value, name, uniforms, textureLoader, searchPath, case 'boolean': outValue = value; break; - case 'vector2': + case 'vector2': outValue = fromVector(value, 2); break; case 'vector3': @@ -123,11 +123,11 @@ function toThreeUniform(type, value, name, uniforms, textureLoader, searchPath, if (texture) setTextureParameters(texture, name, uniforms, flipY); outValue = texture; - } + } break; case 'samplerCube': case 'string': - break; + break; default: // struct outValue = toThreeUniform(value); @@ -184,33 +184,33 @@ function getMinFilter(type, generateMipmaps) * @param {mx.Uniforms} uniforms * @param {mx.TextureFilter.generateMipmaps} generateMipmaps */ - function setTextureParameters(texture, name, uniforms, flipY = true, generateMipmaps = true) - { - const idx = name.lastIndexOf(IMAGE_PROPERTY_SEPARATOR); - const base = name.substring(0, idx) || name; - - texture.generateMipmaps = generateMipmaps; - texture.wrapS = THREE.RepeatWrapping; - texture.wrapT = THREE.RepeatWrapping; - texture.magFilter = THREE.LinearFilter; - texture.flipY = flipY; - - if (uniforms.find(base + UADDRESS_MODE_SUFFIX)) - { - const uaddressmode = uniforms.find(base + UADDRESS_MODE_SUFFIX).getValue().getData(); - texture.wrapS = getWrapping(uaddressmode); - } - - if (uniforms.find(base + VADDRESS_MODE_SUFFIX)) - { - const vaddressmode = uniforms.find(base + VADDRESS_MODE_SUFFIX).getValue().getData(); - texture.wrapT = getWrapping(vaddressmode); - } - - const filterType = uniforms.find(base + FILTER_TYPE_SUFFIX) ? uniforms.get(base + FILTER_TYPE_SUFFIX).value : -1; - texture.minFilter = getMinFilter(filterType, generateMipmaps); - } - +function setTextureParameters(texture, name, uniforms, flipY = true, generateMipmaps = true) +{ + const idx = name.lastIndexOf(IMAGE_PROPERTY_SEPARATOR); + const base = name.substring(0, idx) || name; + + texture.generateMipmaps = generateMipmaps; + texture.wrapS = THREE.RepeatWrapping; + texture.wrapT = THREE.RepeatWrapping; + texture.magFilter = THREE.LinearFilter; + texture.flipY = flipY; + + if (uniforms.find(base + UADDRESS_MODE_SUFFIX)) + { + const uaddressmode = uniforms.find(base + UADDRESS_MODE_SUFFIX).getValue().getData(); + texture.wrapS = getWrapping(uaddressmode); + } + + if (uniforms.find(base + VADDRESS_MODE_SUFFIX)) + { + const vaddressmode = uniforms.find(base + VADDRESS_MODE_SUFFIX).getValue().getData(); + texture.wrapT = getWrapping(vaddressmode); + } + + const filterType = uniforms.find(base + FILTER_TYPE_SUFFIX) ? uniforms.get(base + FILTER_TYPE_SUFFIX).value : -1; + texture.minFilter = getMinFilter(filterType, generateMipmaps); +} + /** * Return the global light rotation matrix */ @@ -269,7 +269,7 @@ export function registerLights(mx, lights, genContext) lightData.push({ type: lightTypesBound[nodeName], direction: rotatedLightDirection, - color: new THREE.Vector3(...lightColor), + color: new THREE.Vector3(...lightColor), intensity: lightIntensity }); } @@ -290,16 +290,17 @@ export function getUniformValues(shaderStage, textureLoader, searchPath, flipY) let threeUniforms = {}; const uniformBlocks = Object.values(shaderStage.getUniformBlocks()); - uniformBlocks.forEach(uniforms => { + uniformBlocks.forEach(uniforms => + { if (!uniforms.empty()) { for (let i = 0; i < uniforms.size(); ++i) { - const variable = uniforms.get(i); + const variable = uniforms.get(i); const value = variable.getValue()?.getData(); const name = variable.getVariable(); - threeUniforms[name] = new THREE.Uniform(toThreeUniform(variable.getType().getName(), value, name, uniforms, - textureLoader, searchPath, flipY)); + threeUniforms[name] = new THREE.Uniform(toThreeUniform(variable.getType().getName(), value, name, uniforms, + textureLoader, searchPath, flipY)); } } }); diff --git a/javascript/MaterialXView/source/index.js b/javascript/MaterialXView/source/index.js index ddd1ec8ffc..026653ca60 100644 --- a/javascript/MaterialXView/source/index.js +++ b/javascript/MaterialXView/source/index.js @@ -12,7 +12,7 @@ import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js'; import { GammaCorrectionShader } from 'three/examples/jsm/shaders/GammaCorrectionShader.js'; import { Viewer } from './viewer.js' -import { dropHandler, dragOverHandler, setLoadingCallback } from './dropHandling.js'; +import { dropHandler, dragOverHandler, setLoadingCallback, setSceneLoadingCallback } from './dropHandling.js'; let renderer, composer, orbitControls; @@ -21,9 +21,12 @@ let turntableEnabled = false; let turntableSteps = 360; let turntableStep = 0; +let captureRequested = false; + // Get URL options. Fallback to defaults if not specified. let materialFilename = new URLSearchParams(document.location.search).get("file"); -if (!materialFilename) { +if (!materialFilename) +{ materialFilename = 'Materials/Examples/StandardSurface/standard_surface_default.mtlx'; } @@ -31,7 +34,19 @@ let viewer = Viewer.create(); init(); viewer.getEditor().updateProperties(0.9); -function init() +// Capture the current frame and save an image file. +function captureFrame() +{ + let canvas = document.getElementById('webglcanvas'); + var url = canvas.toDataURL(); + var link = document.createElement('a'); + link.setAttribute('href', url); + link.setAttribute('target', '_blank'); + link.setAttribute('download', 'screenshot.png'); + link.click(); +} + +function init() { let canvas = document.getElementById('webglcanvas'); let context = canvas.getContext('webgl2'); @@ -39,7 +54,8 @@ function init() // Handle material selection changes let materialsSelect = document.getElementById('materials'); materialsSelect.value = materialFilename; - materialsSelect.addEventListener('change', (e) => { + materialsSelect.addEventListener('change', (e) => + { materialFilename = e.target.value; viewer.getEditor().initialize(); viewer.getMaterial().loadMaterials(viewer, materialFilename); @@ -51,7 +67,9 @@ function init() const scene = viewer.getScene(); let geometrySelect = document.getElementById('geometry'); geometrySelect.value = scene.getGeometryURL(); - geometrySelect.addEventListener('change', (e) => { + geometrySelect.addEventListener('change', (e) => + { + console.log('Change geometry to:', e.target.value); scene.setGeometryURL(e.target.value); scene.loadGeometry(viewer, orbitControls); }); @@ -62,6 +80,13 @@ function init() // Set up renderer renderer = new THREE.WebGLRenderer({ canvas, context }); renderer.setSize(window.innerWidth, window.innerHeight); + // Disable introspection for shader debugging for deployment. + // - The code associated with getting program information can be very slow when + // dealing with shaders with lots of input uniforms (such as standard surface, openpbr shading models) + // as each call is blocking. + // - Adding this avoids the chess set scene from "hanging" the Chrome browser on Windows to a few second load. + // - Documentation for this flag: https://threejs.org/docs/index.html#api/en/renderers/WebGLRenderer.debug + renderer.debug.checkShaderErrors = false; composer = new EffectComposer(renderer); const renderPass = new RenderPass(scene.getScene(), scene.getCamera()); @@ -73,11 +98,20 @@ function init() // Set up controls orbitControls = new OrbitControls(scene.getCamera(), renderer.domElement); - orbitControls.addEventListener('change', () => { + orbitControls.addEventListener('change', () => + { viewer.getScene().setUpdateTransforms(); - }) + }) - // Load model and shaders + // Add hotkey 'f' to capture the current frame and save an image file. + // See check inside the render loop when a capture can be performed. + document.addEventListener('keydown', (event) => + { + if (event.key === 'f') + { + captureRequested = true; + } + }); // Initialize editor viewer.getEditor().initialize(); @@ -88,12 +122,14 @@ function init() new Promise(resolve => hdrLoader.load('Lights/san_giuseppe_bridge_split.hdr', resolve)), new Promise(resolve => hdrLoader.load('Lights/irradiance/san_giuseppe_bridge_split.hdr', resolve)), new Promise(resolve => fileLoader.load('Lights/san_giuseppe_bridge_split.mtlx', resolve)), - new Promise(function (resolve) { - MaterialX().then((module) => { + new Promise(function (resolve) + { + MaterialX().then((module) => + { resolve(module); }); - }) - ]).then(async ([radianceTexture, irradianceTexture, lightRigXml, mxIn]) => + }) + ]).then(async ([radianceTexture, irradianceTexture, lightRigXml, mxIn]) => { // Initialize viewer + lighting await viewer.initialize(mxIn, renderer, radianceTexture, irradianceTexture, lightRigXml); @@ -109,10 +145,12 @@ function init() viewer.getMaterial().updateMaterialAssignments(viewer); canvas.addEventListener("keydown", handleKeyEvents, true); - - }).then(() => { + + }).then(() => + { animate(); - }).catch(err => { + }).catch(err => + { console.error(Number.isInteger(err) ? this.getMx().getExceptionMessage(err) : err); }) @@ -120,7 +158,8 @@ function init() document.addEventListener('drop', dropHandler, false); document.addEventListener('dragover', dragOverHandler, false); - setLoadingCallback(file => { + setLoadingCallback(file => + { materialFilename = file.fullPath || file.name; viewer.getEditor().initialize(); viewer.getMaterial().loadMaterials(viewer, materialFilename); @@ -128,18 +167,26 @@ function init() viewer.getScene().setUpdateTransforms(); }); + setSceneLoadingCallback(file => + { + let glbFileName = file.fullPath || file.name; + console.log('Drop geometry to:', glbFileName); + scene.setGeometryURL(glbFileName); + scene.loadGeometry(viewer, orbitControls); + }); + // enable three.js Cache so that dropped files can reference each other THREE.Cache.enabled = true; } -function onWindowResize() +function onWindowResize() { viewer.getScene().updateCamera(); - viewer.getScene().setUpdateTransforms(); + viewer.getScene().setUpdateTransforms(); renderer.setSize(window.innerWidth, window.innerHeight); } -function animate() +function animate() { requestAnimationFrame(animate); @@ -147,12 +194,18 @@ function animate() { turntableStep = (turntableStep + 1) % 360; var turntableAngle = turntableStep * (360.0 / turntableSteps) / 180.0 * Math.PI; - viewer.getScene()._scene.rotation.y = turntableAngle ; + viewer.getScene()._scene.rotation.y = turntableAngle; viewer.getScene().setUpdateTransforms(); } composer.render(); viewer.getScene().updateTransforms(); + + if (captureRequested) + { + captureFrame(); + captureRequested = false; + } } function handleKeyEvents(event) diff --git a/javascript/MaterialXView/source/viewer.js b/javascript/MaterialXView/source/viewer.js index 3eff576be3..06236fdac9 100644 --- a/javascript/MaterialXView/source/viewer.js +++ b/javascript/MaterialXView/source/viewer.js @@ -9,7 +9,7 @@ import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js'; import { prepareEnvTexture, getLightRotation, findLights, registerLights, getUniformValues } from './helper.js' import { Group } from 'three'; -import GUI from 'lil-gui'; +import GUI from 'lil-gui'; const ALL_GEOMETRY_SPECIFIER = "*"; const NO_GEOMETRY_SPECIFIER = ""; @@ -21,18 +21,18 @@ var logDetailedTime = false; /* Scene management */ -export class Scene +export class Scene { - constructor() + constructor() { this._geometryURL = new URLSearchParams(document.location.search).get("geom"); if (!this._geometryURL) { - this._geometryURL = 'Geometry/shaderball.glb'; + this._geometryURL = 'Geometry/shaderball.glb'; } } - initialize() + initialize() { this._scene = new THREE.Scene(); this._scene.background = new THREE.Color(this.#_backgroundColor); @@ -64,9 +64,10 @@ export class Scene } // Utility to perform geometry file load - loadGeometryFile(geometryFilename, loader) + loadGeometryFile(geometryFilename, loader) { - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => + { loader.load(geometryFilename, data => resolve(data), null, reject); }); } @@ -82,8 +83,9 @@ export class Scene const gltfData = await this.loadGeometryFile(this.getGeometryURL(), this.#_gltfLoader); - const scene = this.getScene(); - while (scene.children.length > 0) { + const scene = this.getScene(); + while (scene.children.length > 0) + { scene.remove(scene.children[0]); } @@ -100,7 +102,7 @@ export class Scene else { this.#_rootNode = model; - } + } scene.add(model); console.log("- Scene load time: ", performance.now() - geomLoadTime, "ms"); @@ -111,7 +113,8 @@ export class Scene console.log("Total geometry load time: ", performance.now() - startTime, " ms."); - viewer.getMaterial().updateMaterialAssignments(viewer); + viewer.getMaterial().clearSoloMaterialUI(); + viewer.getMaterial().updateMaterialAssignments(viewer, ""); this.setUpdateTransforms(); } @@ -122,7 +125,7 @@ export class Scene { var startUpdateSceneTime = performance.now(); var uvTime = 0; - var normalTime = 0 ; + var normalTime = 0; var tangentTime = 0; var streamTime = 0; var bboxTime = 0; @@ -135,41 +138,47 @@ export class Scene let theScene = viewer.getScene(); let flipV = theScene.getFlipGeometryV(); - - this._scene.traverse((child) => { - if (child.isMesh) { + + this._scene.traverse((child) => + { + if (child.isMesh) + { var startUVTime = performance.now(); - if (!child.geometry.attributes.uv) { + if (!child.geometry.attributes.uv) + { const posCount = child.geometry.attributes.position.count; const uvs = []; const pos = child.geometry.attributes.position.array; - - for (let i = 0; i < posCount; i++) { + + for (let i = 0; i < posCount; i++) + { uvs.push((pos[i * 3] - bsphere.center.x) / bsphere.radius); uvs.push((pos[i * 3 + 1] - bsphere.center.y) / bsphere.radius); } - + child.geometry.setAttribute('uv', new THREE.BufferAttribute(new Float32Array(uvs), 2)); } else if (flipV) { const uvCount = child.geometry.attributes.position.count; const uvs = child.geometry.attributes.uv.array; - for (let i = 0; i < uvCount; i++) { - let v = 1.0-(uvs[i*2 +1]); - uvs[i*2+1] = v; + for (let i = 0; i < uvCount; i++) + { + let v = 1.0 - (uvs[i * 2 + 1]); + uvs[i * 2 + 1] = v; } } uvTime += performance.now() - startUVTime; - - if (!child.geometry.attributes.normal) { + + if (!child.geometry.attributes.normal) + { var startNormalTime = performance.new(); child.geometry.computeVertexNormals(); normalTime += performance.now() - startNormalTime; } - - if (child.geometry.getIndex()) + + if (child.geometry.getIndex()) { if (!child.geometry.attributes.tangent) { @@ -178,7 +187,7 @@ export class Scene tangentTime += performance.now() - startTangentTime; } } - + // Use default MaterialX naming convention. var startStreamTime = performance.now(); child.geometry.attributes.i_position = child.geometry.attributes.position; @@ -198,7 +207,7 @@ export class Scene console.log(' - Stream Update time: ', streamTime); console.log(' - Bounds compute time: ', bboxTime); } - + // Update the background this._scene.background = this.getBackground(); @@ -207,10 +216,10 @@ export class Scene camera.position.y = bsphere.center.y; camera.position.z = bsphere.radius * 2.0; camera.updateProjectionMatrix(); - + orbitControls.target = bsphere.center; orbitControls.update(); - } + } setUpdateTransforms() { @@ -230,10 +239,13 @@ export class Scene const scene = this.getScene(); const camera = this.getCamera(); - scene.traverse((child) => { - if (child.isMesh) { + scene.traverse((child) => + { + if (child.isMesh) + { const uniforms = child.material.uniforms; - if (uniforms) { + if (uniforms) + { uniforms.u_worldMatrix.value = child.matrixWorld; uniforms.u_viewProjectionMatrix.value = this.#_viewProjMat.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse); @@ -241,8 +253,8 @@ export class Scene uniforms.u_viewPosition.value = camera.getWorldPosition(this.#_worldViewPos); if (uniforms.u_worldInverseTransposeMatrix) - uniforms.u_worldInverseTransposeMatrix.value = - new THREE.Matrix4().setFromMatrix3(this.#_normalMat.getNormalMatrix(child.matrixWorld)); + uniforms.u_worldInverseTransposeMatrix.value = + new THREE.Matrix4().setFromMatrix3(this.#_normalMat.getNormalMatrix(child.matrixWorld)); } } }); @@ -282,9 +294,9 @@ export class Scene const scene = this.getScene(); const camera = this.getCamera(); - scene.traverse((child) => + scene.traverse((child) => { - if (child.isMesh) + if (child.isMesh) { const dagPath = this.getDagPath(child).join('/'); @@ -303,13 +315,16 @@ export class Scene } else { - const paths = geometry.split(','); - for (let path of paths) + if (geometry != NO_GEOMETRY_SPECIFIER) { - if (dagPath.match(path)) + const paths = geometry.split(','); + for (let path of paths) { - matches = true; - break; + if (dagPath.match(path)) + { + matches = true; + break; + } } } } @@ -332,19 +347,23 @@ export class Scene camera.updateProjectionMatrix(); } - getScene() { + getScene() + { return this._scene; } - getCamera() { + getCamera() + { return this._camera; } - getGeometryURL() { + getGeometryURL() + { return this._geometryURL; } - setGeometryURL(url) { + setGeometryURL(url) + { this._geometryURL = url; } @@ -363,7 +382,7 @@ export class Scene this.#_showBackgroundTexture = enable; } - getBackground() + getBackground() { if (this.#_backgroundTexture && this.#_showBackgroundTexture) { @@ -420,31 +439,34 @@ export class Editor initialize() { Array.from(document.getElementsByClassName('lil-gui')).forEach( - function (element, index, array) { - if (element.className) { + function (element, index, array) + { + if (element.className) + { element.remove(); } } ); - this._gui = new GUI( { title: "Property Editor" } ); + this._gui = new GUI({ title: "Property Editor" }); this._gui.close(); } // Update ui properties // - Hide close button // - Update transparency so scene shows through if overlapping - updateProperties(targetOpacity = 1) + updateProperties(targetOpacity = 1) { // Set opacity Array.from(document.getElementsByClassName('dg')).forEach( - function (element, index, array) { + function (element, index, array) + { element.style.opacity = targetOpacity; } ); } - getGUI() + getGUI() { return this._gui; } @@ -460,6 +482,17 @@ class MaterialAssign this._geometry = geometry; this._collection = collection; this._shader = null; + this._materialUI = null; + } + + setMaterialUI(value) + { + this._materialUI = value; + } + + getMaterialUI() + { + return this._materialUI; } setShader(shader) @@ -476,12 +509,17 @@ class MaterialAssign { return this._material; } - + getGeometry() { return this._geometry; } + setGeometry(value) + { + this._geometry = value; + } + getCollection() { return this._collection; @@ -506,24 +544,50 @@ export class Material { this._materials = []; this._defaultMaterial = null; + this._soloMaterial = ""; + } + + clearMaterials() + { + this._materials.length = 0; + this._defaultMaterial = null; + this._soloMaterial = ""; + } + + setSoloMaterial(value) + { + this._soloMaterial = value; + } + + getSoloMaterial() + { + return this._soloMaterial; } // If no material file is selected, we programmatically create a default material as a fallback - static createFallbackMaterial(doc) + static createFallbackMaterial(doc) { - const ssName = 'SR_default'; - const ssNode = doc.addChildOfCategory('standard_surface', ssName); + let ssNode = doc.getChild('Generated_Default_Shader'); + if (ssNode) + { + return ssNode; + } + const ssName = 'Generated_Default_Shader'; + ssNode = doc.addChildOfCategory('standard_surface', ssName); ssNode.setType('surfaceshader'); const smNode = doc.addChildOfCategory('surfacematerial', 'Default'); smNode.setType('material'); const shaderElement = smNode.addInput('surfaceshader'); shaderElement.setType('surfaceshader'); shaderElement.setNodeName(ssName); + + return ssNode; } async loadMaterialFile(loader, materialFilename) { - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => + { loader.load(materialFilename, data => resolve(data), null, reject); }); } @@ -540,7 +604,7 @@ export class Material doc.importLibrary(viewer.getLibrary()); viewer.setDocument(doc); - const fileloader = viewer.getFileLoader(); + const fileloader = viewer.getFileLoader(); let mtlxMaterial = await viewer.getMaterial().loadMaterialFile(fileloader, materialFilename); @@ -553,7 +617,7 @@ export class Material // location. if (!materialFilename) materialFilename = "/"; const paths = materialFilename.split('/'); - paths.pop(); + paths.pop(); const searchPath = paths.join('/'); // Load material @@ -565,22 +629,21 @@ export class Material // Check if there are any looks defined in the document // If so then traverse the looks for all material assignments. // Generate code and compile for any associated surface shader - // and assign to the associatged geometry. If there are no looks + // and assign to the associated geometry. If there are no looks // then the first material is found and assignment to all the - // geometry. - this._materials.length = 0; - this._defaultMaterial = null; + // geometry. + this.clearMaterials(); var looks = doc.getLooks(); if (looks.length) { for (let look of looks) { const materialAssigns = look.getMaterialAssigns(); - for (let materialAssign of materialAssigns) + for (let materialAssign of materialAssigns) { let matName = materialAssign.getMaterial(); if (matName) - { + { let mat = doc.getChild(matName); var shader; if (mat) @@ -610,7 +673,7 @@ export class Material } else { - newAssignment = new MaterialAssign(shader, NO_GEOMETRY_SPECIFIER); + newAssignment = new MaterialAssign(shader, NO_GEOMETRY_SPECIFIER, null); } if (newAssignment) @@ -623,35 +686,133 @@ export class Material } else { - // Search for any surface shader. It + // Search for any surface shaders. The first found // is assumed to be assigned to the entire scene // The identifier used is "*" to mean the entire scene. - let elem = mx.findRenderableElement(doc); - if (elem) + const materialNodes = doc.getMaterialNodes(); + let shaderList = []; + let foundRenderable = false; + for (let i = 0; i < materialNodes.length; ++i) { - this._materials.push(new MaterialAssign(elem, ALL_GEOMETRY_SPECIFIER)); + let materialNode = materialNodes[i]; + if (materialNode) + { + console.log('Scan material: ', materialNode.getNamePath()); + let shaderNodes = mx.getShaderNodes(materialNode) + if (shaderNodes.length > 0) + { + let shaderNodePath = shaderNodes[0].getNamePath() + if (!shaderList.includes(shaderNodePath)) + { + let assignment = NO_GEOMETRY_SPECIFIER; + if (foundRenderable == false) + { + assignment = ALL_GEOMETRY_SPECIFIER; + foundRenderable = true; + } + console.log('-- add shader: ', shaderNodePath); + shaderList.push(shaderNodePath); + this._materials.push(new MaterialAssign(shaderNodes[0], assignment)); + } + } + } } + const nodeGraphs = doc.getNodeGraphs(); + for (let i = 0; i < nodeGraphs.length; ++i) + { + let nodeGraph = nodeGraphs[i]; + if (nodeGraph) + { + if (nodeGraph.hasAttribute('nodedef') || nodeGraph.hasSourceUri()) + { + continue; + } + // Skip any nodegraph that is connected to something downstream + if (nodeGraph.getDownstreamPorts().length > 0) + { + continue + } + let outputs = nodeGraph.getOutputs(); + for (let j = 0; j < outputs.length; ++j) + { + let output = outputs[j]; + { + let assignment = NO_GEOMETRY_SPECIFIER; + if (foundRenderable == false) + { + assignment = ALL_GEOMETRY_SPECIFIER; + foundRenderable = true; + } + let newMat = new MaterialAssign(output, assignment, null); + this._materials.push(newMat); + } + } + } + } + const outputs = doc.getOutputs(); + for (let i = 0; i < outputs.length; ++i) + { + let output = outputs[i]; + if (output) + { + let assignment = NO_GEOMETRY_SPECIFIER; + if (foundRenderable == false) + { + assignment = ALL_GEOMETRY_SPECIFIER; + foundRenderable = true; + } + this._materials.push(new MaterialAssign(output, assignment)); + } + } + + const shaderNodes = []; + for (let i = 0; i < shaderNodes.length; ++i) + { + let shaderNode = shaderNodes[i]; + let shaderNodePath = shaderNode.getNamePath() + if (!shaderList.includes(shaderNodePath)) + { + let assignment = NO_GEOMETRY_SPECIFIER; + if (foundRenderable == false) + { + assignment = ALL_GEOMETRY_SPECIFIER; + foundRenderable = true; + } + shaderList.push(shaderNodePath); + this._materials.push(new MaterialAssign(shaderNode, assignment)); + } + } + } + + // Assign to default material if none found + if (this._materials.length == 0) + { + const defaultNode = Material.createFallbackMaterial(doc); + this._materials.push(new MaterialAssign(defaultNode, ALL_GEOMETRY_SPECIFIER)); } - + // Create a new shader for each material node. // Only create the shader once even if assigned more than once. var startGenTime = performance.now(); let shaderMap = new Map(); + let closeUI = false; for (let matassign of this._materials) { - let materialName = matassign.getMaterial().getName(); + // Need to use path vs name to get a unique key. + let materialName = matassign.getMaterial().getNamePath(); let shader = shaderMap[materialName]; if (!shader) { - shader = viewer.getMaterial().generateMaterial(matassign.getMaterial(), viewer, searchPath); + shader = viewer.getMaterial().generateMaterial(matassign, viewer, searchPath, closeUI); shaderMap[materialName] = shader; } matassign.setShader(shader); + closeUI = true; } - console.log("- Generate (", this._materials.length, ") shader(s) time: ", performance.now() - startGenTime, " ms.", ); + console.log("- Generate (", this._materials.length, ") shader(s) time: ", performance.now() - startGenTime, " ms.",); // Update scene shader assignments - this.updateMaterialAssignments(viewer); + this.updateMaterialAssignments(viewer, ""); // Mark transform update viewer.getScene().setUpdateTransforms(); @@ -666,16 +827,33 @@ export class Material // in the scene, then the first material assignment shader is assigned // to the entire scene. // - async updateMaterialAssignments(viewer) + async updateMaterialAssignments(viewer, soloMaterial) { + console.log("Update material assignments. Solo=", soloMaterial); var startTime = performance.now(); let assigned = 0; + let assignedSolo = false; for (let matassign of this._materials) { if (matassign.getShader()) { - assigned += viewer.getScene().updateMaterial(matassign); + if (soloMaterial.length) + { + if (matassign.getMaterial().getNamePath() == soloMaterial) + { + let temp = matassign.getGeometry(); + matassign.setGeometry(ALL_GEOMETRY_SPECIFIER); + assigned += viewer.getScene().updateMaterial(matassign); + matassign.setGeometry(temp); + assignedSolo = true; + break + } + } + else + { + assigned += viewer.getScene().updateMaterial(matassign); + } } } if (assigned == 0 && this._materials.length) @@ -694,8 +872,10 @@ export class Material // // Generate a new material for a given element // - generateMaterial(elem, viewer, searchPath) + generateMaterial(matassign, viewer, searchPath, closeUI) { + var elem = matassign.getMaterial(); + var startGenerateMat = performance.now(); const mx = viewer.getMx(); @@ -718,10 +898,10 @@ export class Material genContext.getOptions().shaderInterfaceType = mx.ShaderInterfaceType.SHADER_INTERFACE_COMPLETE; if (logDetailedTime) - console.log(" - Transparency check time: ", performance.now() - startTranspCheckTime, "ms"); + console.log(" - Transparency check time: ", performance.now() - startTranspCheckTime, "ms"); // Generate GLES code - var startMTLXGenTime = performance.now(); + var startMTLXGenTime = performance.now(); let shader = gen.generate(elem.getNamePath(), elem, genContext); if (logDetailedTime) console.log(" - MaterialX gen time: ", performance.now() - startMTLXGenTime, "ms"); @@ -751,7 +931,7 @@ export class Material }); // Create Three JS Material - let newMaterial = new THREE.RawShaderMaterial({ + let newMaterial = new THREE.RawShaderMaterial({ uniforms: uniforms, vertexShader: vShader, fragmentShader: fShader, @@ -767,7 +947,7 @@ export class Material // Update property editor const gui = viewer.getEditor().getGUI(); - this.updateEditor(elem, shader, newMaterial, gui, viewer); + this.updateEditor(matassign, shader, newMaterial, gui, closeUI, viewer); if (logDetailedTime) console.log("- Per material generate time: ", performance.now() - startGenerateMat, "ms"); @@ -775,19 +955,100 @@ export class Material return newMaterial; } + clearSoloMaterialUI() + { + for (let i = 0; i < this._materials.length; ++i) + { + let matassign = this._materials[i]; + let matUI = matassign.getMaterialUI(); + if (matUI) + { + let matTitle = matUI.domElement.getElementsByClassName('title')[0]; + matTitle.classList.remove('peditor_material_assigned'); + let img = matTitle.getElementsByTagName('img')[0]; + img.src = 'public/shader_ball.svg'; + //matTitle.classList.remove('peditor_material_unassigned'); + } + } + } + + static updateSoloMaterial(viewer, elemPath, materials, event) + { + // Prevent the event from being passed to parent folder + event.stopPropagation(); + + for (let i = 0; i < materials.length; ++i) + { + let matassign = materials[i]; + // Need to use path vs name to get a unique key. + let materialName = matassign.getMaterial().getNamePath(); + var matUI = matassign.getMaterialUI(); + let matTitle = matUI.domElement.getElementsByClassName('title')[0]; + let img = matTitle.getElementsByTagName('img')[0]; + if (materialName == elemPath) + { + if (this._soloMaterial == elemPath) + { + img.src = 'public/shader_ball.svg'; + matTitle.classList.remove('peditor_material_assigned'); + this._soloMaterial = ""; + } + else + { + img.src = 'public/shader_ball2.svg'; + matTitle.classList.add('peditor_material_assigned'); + this._soloMaterial = elemPath; + } + } + else + { + img.src = 'public/shader_ball.svg'; + matTitle.classList.remove('peditor_material_assigned'); + } + } + viewer.getMaterial().updateMaterialAssignments(viewer, this._soloMaterial); + viewer.getScene().setUpdateTransforms(); + } + // // Update property editor for a given MaterialX element, it's shader, and // Three material // - updateEditor(elem, shader, material, gui) + updateEditor(matassign, shader, material, gui, closeUI, viewer) { + var elem = matassign.getMaterial(); + var materials = this._materials; + const DEFAULT_MIN = 0; const DEFAULT_MAX = 100; var startTime = performance.now(); const elemPath = elem.getNamePath(); - var matUI = gui.addFolder(elemPath + ' Properties'); + + // Create and cache associated UI + var matUI = gui.addFolder(elemPath); + matassign.setMaterialUI(matUI); + + let matTitle = matUI.domElement.getElementsByClassName('title')[0]; + // Add a icon to the title to allow for assigning the material to geometry + // Clicking on the icon will "solo" the material to the geometry. + // Clicking on the title will open/close the material folder. + matTitle.innerHTML = "" + elem.getNamePath(); + let img = matTitle.getElementsByTagName('img')[0]; + if (img) + { + // Add event listener to icon to call updateSoloMaterial function + img.addEventListener('click', function (event) + { + Material.updateSoloMaterial(viewer, elemPath, materials, event); + }); + } + + if (closeUI) + { + matUI.close(); + } const uniformBlocks = Object.values(shader.getStage('pixel').getUniformBlocks()); var uniformToUpdate; const ignoreList = ['u_envRadianceMips', 'u_envRadianceSamples', 'u_alphaThreshold']; @@ -795,65 +1056,75 @@ export class Material var folderList = new Map(); folderList[elemPath] = matUI; - uniformBlocks.forEach(uniforms => + uniformBlocks.forEach(uniforms => { - if (!uniforms.empty()) + if (!uniforms.empty()) { - for (let i = 0; i < uniforms.size(); ++i) + for (let i = 0; i < uniforms.size(); ++i) { const variable = uniforms.get(i); const value = variable.getValue()?.getData(); let name = variable.getVariable(); - if (ignoreList.includes(name)) { + if (ignoreList.includes(name)) + { continue; } let currentFolder = matUI; let currentElemPath = variable.getPath(); - if (!currentElemPath || currentElemPath.length == 0) { + if (!currentElemPath || currentElemPath.length == 0) + { continue; } let currentElem = elem.getDocument().getDescendant(currentElemPath); - if (!currentElem) { + if (!currentElem) + { continue; } let currentNode = null; if (currentElem.getParent() && currentElem.getParent().getNamePath() != "") - { + { currentNode = currentElem.getParent(); } let uiname = ""; let nodeDefInput = null; - if (currentNode) { + if (currentNode) + { let currentNodePath = currentNode.getNamePath(); var pathSplit = currentNodePath.split('/'); - if (pathSplit.length) { + if (pathSplit.length) + { currentNodePath = pathSplit[0]; } currentFolder = folderList[currentNodePath]; - if (!currentFolder) { + if (!currentFolder) + { currentFolder = matUI.addFolder(currentNodePath); folderList[currentNodePath] = currentFolder; } // Check for ui attributes var nodeDef = currentNode.getNodeDef(); - if (nodeDef) { + if (nodeDef) + { // Remove node name from shader uniform name for non root nodes let lookup_name = name.replace(currentNode.getName() + '_', ''); nodeDefInput = nodeDef.getActiveInput(lookup_name); - if (nodeDefInput) + if (nodeDefInput) { uiname = nodeDefInput.getAttribute('uiname'); let uifolderName = nodeDefInput.getAttribute('uifolder'); - if (uifolderName && uifolderName.length) { + if (uifolderName && uifolderName.length) + { let newFolderName = currentNodePath + '/' + uifolderName; currentFolder = folderList[newFolderName]; - if (!currentFolder) { + if (!currentFolder) + { currentFolder = matUI.addFolder(uifolderName); + currentFolder.domElement.classList.add('peditorfolder'); folderList[newFolderName] = currentFolder; } } @@ -864,17 +1135,21 @@ export class Material // Determine UI name to use let path = name; let interfaceName = currentElem.getAttribute("interfacename"); - if (interfaceName && interfaceName.length) { + if (interfaceName && interfaceName.length) + { const graph = currentNode.getParent(); if (graph) { const graphInput = graph.getInput(interfaceName); - if (graphInput) { + if (graphInput) + { let uiname = graphInput.getAttribute('uiname'); - if (uiname.length) { + if (uiname.length) + { path = uiname; } - else { + else + { path = graphInput.getName(); } } @@ -884,11 +1159,14 @@ export class Material path = interfaceName; } } - else { - if (!uiname) { + else + { + if (!uiname) + { uiname = currentElem.getAttribute('uiname'); } - if (uiname && uiname.length) { + if (uiname && uiname.length) + { path = uiname; } } @@ -929,7 +1207,8 @@ export class Material { step = (maxValue - minValue) / 1000.0; } - currentFolder.add(material.uniforms[name], 'value', minValue, maxValue, step).name(path); + const w = currentFolder.add(material.uniforms[name], 'value', minValue, maxValue, step).name(path); + w.domElement.classList.add('peditoritem'); } break; @@ -991,34 +1270,38 @@ export class Material } if (enumList.length == 0) { - currentFolder.add(material.uniforms[name], 'value', minValue, maxValue, step).name(path); - } + let w = currentFolder.add(material.uniforms[name], 'value', minValue, maxValue, step).name(path); + w.domElement.classList.add('peditoritem'); + } else { // Map enumList strings to values // Map to 0..N if no values are specified via enumvalues attribute if (enumValues.length == 0) - { + { for (let i = 0; i < enumList.length; ++i) { enumValues.push(i); } } const enumeration = {}; - enumList.forEach((str, index) => { + enumList.forEach((str, index) => + { enumeration[str] = enumValues[index]; }); - + // Function to handle enum drop-down - function handleDropdownChange(value) { + function handleDropdownChange(value) + { if (material.uniforms[name]) { material.uniforms[name].value = value; - } - } + } + } const defaultOption = enumList[value]; // Set the default selected option - const dropdownController = gui.add(enumeration, defaultOption, enumeration).name(path); - dropdownController.onChange(handleDropdownChange); + const dropdownController = currentFolder.add(enumeration, defaultOption, enumeration).name(path); + dropdownController.onChange(handleDropdownChange); + dropdownController.domElement.classList.add('peditoritem'); } } break; @@ -1027,7 +1310,8 @@ export class Material uniformToUpdate = material.uniforms[name]; if (uniformToUpdate && value != null) { - currentFolder.add(material.uniforms[name], 'value').name(path); + let w = currentFolder.add(material.uniforms[name], 'value').name(path); + w.domElement.classList.add('peditoritem'); } break; @@ -1041,7 +1325,7 @@ export class Material var maxValue = [DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX]; var step = [0, 0, 0, 0]; - if (nodeDefInput) + if (nodeDefInput) { if (nodeDefInput.hasAttribute('uisoftmin')) minValue = nodeDefInput.getAttribute('uisoftmin').split(',').map(Number); @@ -1054,7 +1338,7 @@ export class Material maxValue = nodeDefInput.getAttribute('uimax').split(',').map(Number); if (nodeDefInput.hasAttribute('uistep')) - step = nodeDefInput.getAttribute('uistep').split(',').map(Number); + step = nodeDefInput.getAttribute('uistep').split(',').map(Number); } for (let i = 0; i < 4; ++i) { @@ -1066,9 +1350,11 @@ export class Material const keyString = ["x", "y", "z", "w"]; let vecFolder = currentFolder.addFolder(path); - Object.keys(material.uniforms[name].value).forEach((key) => { - let w = vecFolder.add(material.uniforms[name].value, + Object.keys(material.uniforms[name].value).forEach((key) => + { + let w = vecFolder.add(material.uniforms[name].value, key, minValue[key], maxValue[key], step[key]).name(keyString[key]); + w.domElement.classList.add('peditoritem'); }) } break; @@ -1085,11 +1371,13 @@ export class Material const color3 = new THREE.Color(dummy.color); color3.fromArray(material.uniforms[name].value); dummy.color = color3.getHex(); - currentFolder.addColor(dummy, 'color').name(path) - .onChange(function (value) { + let w = currentFolder.addColor(dummy, 'color').name(path) + .onChange(function (value) + { const color3 = new THREE.Color(value); material.uniforms[name].value.set(color3.toArray()); }); + w.domElement.classList.add('peditoritem'); } break; @@ -1102,11 +1390,17 @@ export class Material case 'filename': break; case 'string': - uniformToUpdate = material.uniforms[name]; - if (uniformToUpdate && value != null) { - item = currentFolder.add(material.uniforms[name], 'value'); + console.log('String: ', name); + if (value != null) + { + var dummy = + { + thevalue: value + } + let item = currentFolder.add(dummy, 'thevalue'); item.name(path); - item.readonly(true); + item.disable(true); + item.domElement.classList.add('peditoritem'); } break; default: @@ -1135,7 +1429,7 @@ export class Material Keeps track of local scene, and property editor as well as current MaterialX document and assocaited material, shader and lighting information. */ -export class Viewer +export class Viewer { static create() { @@ -1149,7 +1443,7 @@ export class Viewer this.materials.push(new Material()); this.fileLoader = new THREE.FileLoader(); - this.hdrLoader = new RGBELoader(); + this.hdrLoader = new RGBELoader(); } // @@ -1194,15 +1488,18 @@ export class Viewer this.irradianceTexture = prepareEnvTexture(irradianceTexture, renderer.capabilities); } - getEditor() { + getEditor() + { return this.editor; } - getScene() { + getScene() + { return this.scene; } - getMaterial() { + getMaterial() + { return this.materials[0]; } @@ -1216,46 +1513,57 @@ export class Viewer return this.hdrLoader; } - setDocument(doc) { + setDocument(doc) + { this.doc = doc; } - getDocument() { + getDocument() + { return this.doc; } - getLibrary() { + getLibrary() + { return this.stdlib; } - getLightRig() { + getLightRig() + { return this.lightRigDoc; } - getMx() { + getMx() + { return this.mx; } - getGenerator() { + getGenerator() + { return this.generator; } - getGenContext() { + getGenContext() + { return this.genContext; } - getLights() { + getLights() + { return this.lights; } - getLightData() { + getLightData() + { return this.lightData; } - getRadianceTexture() { + getRadianceTexture() + { return this.radianceTexture; } - getIrradianceTexture() { + getIrradianceTexture() + { return this.irradianceTexture; } diff --git a/javascript/MaterialXView/webpack.config.js b/javascript/MaterialXView/webpack.config.js index bf6673284a..cd33a443f2 100644 --- a/javascript/MaterialXView/webpack.config.js +++ b/javascript/MaterialXView/webpack.config.js @@ -6,75 +6,75 @@ const HtmlWebpackPlugin = require('html-webpack-plugin') const stdSurfaceMaterials = "../../resources/Materials/Examples/StandardSurface"; const stdSurfaceMaterialsBaseURL = "Materials/Examples/StandardSurface"; let dirent = fs.readdirSync(stdSurfaceMaterials).filter( - function (file) { if (file.lastIndexOf(".mtlx") > -1) return file; } + function (file) { if (file.lastIndexOf(".mtlx") > -1) return file; } ) let materials = dirent - .map((fileName) => ({name: fileName, value: `${stdSurfaceMaterialsBaseURL}/${fileName}`})); + .map((fileName) => ({ name: fileName, value: `${stdSurfaceMaterialsBaseURL}/${fileName}` })); const usdSurfaceMaterials = "../../resources/Materials/Examples/UsdPreviewSurface"; const usdSurfaceMaterialsBaseURL = "Materials/Examples/UsdPreviewSurface"; dirent = fs.readdirSync(usdSurfaceMaterials).filter( - function (file) { if (file.lastIndexOf(".mtlx") > -1) return file; } + function (file) { if (file.lastIndexOf(".mtlx") > -1) return file; } ) let usdMaterials = dirent - .map((fileName) => ({name: fileName, value: `${usdSurfaceMaterialsBaseURL}/${fileName}`})); + .map((fileName) => ({ name: fileName, value: `${usdSurfaceMaterialsBaseURL}/${fileName}` })); const gltfSurfaceMaterials = "../../resources/Materials/Examples/GltfPbr"; const gltfSurfaceMaterialsBaseURL = "Materials/Examples/GltfPbr"; dirent = fs.readdirSync(gltfSurfaceMaterials).filter( - function (file) { if (file.lastIndexOf(".mtlx") > -1) return file; } + function (file) { if (file.lastIndexOf(".mtlx") > -1) return file; } ) let gltfMaterials = dirent - .map((fileName) => ({name: fileName, value: `${gltfSurfaceMaterialsBaseURL}/${fileName}`})); + .map((fileName) => ({ name: fileName, value: `${gltfSurfaceMaterialsBaseURL}/${fileName}` })); -materials = materials.concat( usdMaterials ); -materials = materials.concat( gltfMaterials ); +materials = materials.concat(usdMaterials); +materials = materials.concat(gltfMaterials); const geometryFiles = "../../resources/Geometry"; const geometryFilesURL = "Geometry"; dirent = fs.readdirSync(geometryFiles).filter( - function (file) { if (file.lastIndexOf(".glb") > -1) return file; } + function (file) { if (file.lastIndexOf(".glb") > -1) return file; } ) let geometry = dirent - .map((fileName) => ({name: fileName, value: `${geometryFilesURL}/${fileName}`})); - + .map((fileName) => ({ name: fileName, value: `${geometryFilesURL}/${fileName}` })); + module.exports = { - entry: './source/index.js', - output: { - filename: 'main.js', - path: path.resolve(__dirname, 'dist') - }, - mode: "development", - plugins: [ - new HtmlWebpackPlugin({ - templateParameters: { - materials, - geometry - }, - template: 'index.ejs' - }), - new CopyPlugin({ - patterns: [ - { - context: "../../resources/Images", - from: "*.*", - to: "Images", - }, - { - context: "../../resources/Geometry/", - from: "*.glb", - to: "Geometry", - }, - { from: "./public", to: 'public' }, - { context: "../../resources/Lights", from: "*.*", to: "Lights" }, - { context: "../../resources/Lights/irradiance", from: "*.*", to: "Lights/irradiance" }, - { from: stdSurfaceMaterials, to: stdSurfaceMaterialsBaseURL }, - { from: usdSurfaceMaterials, to: usdSurfaceMaterialsBaseURL }, - { from: gltfSurfaceMaterials, to: gltfSurfaceMaterialsBaseURL }, - { from: "../build/bin/JsMaterialXGenShader.wasm" }, - { from: "../build/bin/JsMaterialXGenShader.js" }, - { from: "../build/bin/JsMaterialXGenShader.data" }, - ], - }), - ] + entry: './source/index.js', + output: { + filename: 'main.js', + path: path.resolve(__dirname, 'dist') + }, + mode: "development", + plugins: [ + new HtmlWebpackPlugin({ + templateParameters: { + materials, + geometry + }, + template: 'index.ejs' + }), + new CopyPlugin({ + patterns: [ + { + context: "../../resources/Images", + from: "*.*", + to: "Images", + }, + { + context: "../../resources/Geometry/", + from: "*.glb", + to: "Geometry", + }, + { from: "./public", to: 'public' }, + { context: "../../resources/Lights", from: "*.*", to: "Lights" }, + { context: "../../resources/Lights/irradiance", from: "*.*", to: "Lights/irradiance" }, + { from: stdSurfaceMaterials, to: stdSurfaceMaterialsBaseURL }, + { from: usdSurfaceMaterials, to: usdSurfaceMaterialsBaseURL }, + { from: gltfSurfaceMaterials, to: gltfSurfaceMaterialsBaseURL }, + { from: "../build/bin/JsMaterialXGenShader.wasm" }, + { from: "../build/bin/JsMaterialXGenShader.js" }, + { from: "../build/bin/JsMaterialXGenShader.data" }, + ], + }), + ] }; diff --git a/javascript/README.md b/javascript/README.md index 38d1734392..bed7e0bcda 100644 --- a/javascript/README.md +++ b/javascript/README.md @@ -34,7 +34,7 @@ mkdir ./javascript/build cd ./javascript/build ``` -If you are using the emsdk directly on Windows, note that the emscripten SDK doesn't work with Microsoft's Visual Studio build tools. You need to use an alternative CMake generator like [MinGW](http://mingw-w64.org/doku.php) Makefiles or [Ninja](https://ninja-build.org/). We recommend to use Ninja (unless you already have MinGW installed), since it's pretty lightweight and a pure build system, instead of a full compiler suite. +If you are using the emsdk directly on Windows, note that the emscripten SDK doesn't work with Microsoft's Visual Studio build tools. You need to use an alternative CMake generator like [MinGW](http://mingw-w64.org/doku.php) Makefiles or [Ninja](https://ninja-build.org/). We recommend to use Ninja (unless you already have MinGW installed), since it's pretty lightweight and a pure build system, instead of a full compiler suite. Download Ninja for Windows and unzip the ninja.exe file to some suitable directory in your path (use the command "echo $PATH" or similar to view your PATH variable). Generate the build files with CMake. When building the JavaScript bindings, you can optionally specify the emsdk path with the `MATERIALX_EMSDK_PATH` option. This option can be omitted if the `emsdk/emsdk_env.sh` script was run beforehand. ```sh diff --git a/javascript/build_javascript_win.bat b/javascript/build_javascript_win.bat index 8b08c26600..d62f05f84a 100644 --- a/javascript/build_javascript_win.bat +++ b/javascript/build_javascript_win.bat @@ -1,5 +1,8 @@ +@rem This script builds MaterialX JavaScript on Windows. The final command starts a local server, allowing you to +@rem run the MaterialX Web Viewer locally by entering 'http://localhost:8080' in the search bar of your browser. @echo --------------------- Setup Emscripten --------------------- @echo on +@rem Edit the following paths to match your local locations for the Emscripten and MaterialX projects. set EMSDK_LOCATION=C:/GitHub/emsdk set MATERIALX_LOCATION=C:/GitHub/MaterialX call %EMSDK_LOCATION%/emsdk.bat install latest diff --git a/libraries/bxdf/gltf_pbr.mtlx b/libraries/bxdf/gltf_pbr.mtlx index 6654e63454..b42054a185 100644 --- a/libraries/bxdf/gltf_pbr.mtlx +++ b/libraries/bxdf/gltf_pbr.mtlx @@ -359,7 +359,7 @@ - + diff --git a/libraries/bxdf/usd_preview_surface.mtlx b/libraries/bxdf/usd_preview_surface.mtlx index 984bad0326..6efb288184 100644 --- a/libraries/bxdf/usd_preview_surface.mtlx +++ b/libraries/bxdf/usd_preview_surface.mtlx @@ -9,7 +9,7 @@ - + @@ -18,7 +18,7 @@ - + diff --git a/libraries/nprlib/genglsl/nprlib_genglsl_impl.mtlx b/libraries/nprlib/genglsl/nprlib_genglsl_impl.mtlx index 7ddc4cee83..1a96f315e5 100644 --- a/libraries/nprlib/genglsl/nprlib_genglsl_impl.mtlx +++ b/libraries/nprlib/genglsl/nprlib_genglsl_impl.mtlx @@ -12,6 +12,6 @@ - + diff --git a/libraries/nprlib/genmdl/nprlib_genmdl_impl.mtlx b/libraries/nprlib/genmdl/nprlib_genmdl_impl.mtlx index b6472e0c51..73a9d22945 100644 --- a/libraries/nprlib/genmdl/nprlib_genmdl_impl.mtlx +++ b/libraries/nprlib/genmdl/nprlib_genmdl_impl.mtlx @@ -12,6 +12,6 @@ - + diff --git a/libraries/nprlib/genmsl/nprlib_genmsl_impl.mtlx b/libraries/nprlib/genmsl/nprlib_genmsl_impl.mtlx index b8f9a4e3aa..615e9d8ce0 100644 --- a/libraries/nprlib/genmsl/nprlib_genmsl_impl.mtlx +++ b/libraries/nprlib/genmsl/nprlib_genmsl_impl.mtlx @@ -12,6 +12,6 @@ - + diff --git a/libraries/nprlib/nprlib_defs.mtlx b/libraries/nprlib/nprlib_defs.mtlx index e724658ae5..dfbaa5b5f6 100644 --- a/libraries/nprlib/nprlib_defs.mtlx +++ b/libraries/nprlib/nprlib_defs.mtlx @@ -7,6 +7,12 @@ Declarations of standard data types and nodes included in the MaterialX specification. --> + + + + + + @@ -20,4 +26,17 @@ + + + + + + + + + diff --git a/libraries/nprlib/nprlib_ng.mtlx b/libraries/nprlib/nprlib_ng.mtlx new file mode 100644 index 0000000000..0bd7e334e5 --- /dev/null +++ b/libraries/nprlib/nprlib_ng.mtlx @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libraries/stdlib/genglsl/mx_fractal3d_fa_vector2.glsl b/libraries/stdlib/genglsl/mx_fractal3d_fa_vector2.glsl deleted file mode 100644 index 59dbbee127..0000000000 --- a/libraries/stdlib/genglsl/mx_fractal3d_fa_vector2.glsl +++ /dev/null @@ -1,7 +0,0 @@ -#include "lib/mx_noise.glsl" - -void mx_fractal3d_fa_vector2(float amplitude, int octaves, float lacunarity, float diminish, vec3 position, out vec2 result) -{ - vec2 value = mx_fractal_noise_vec2(position, octaves, lacunarity, diminish); - result = value * amplitude; -} diff --git a/libraries/stdlib/genglsl/mx_fractal3d_fa_vector3.glsl b/libraries/stdlib/genglsl/mx_fractal3d_fa_vector3.glsl deleted file mode 100644 index d0f30defd4..0000000000 --- a/libraries/stdlib/genglsl/mx_fractal3d_fa_vector3.glsl +++ /dev/null @@ -1,7 +0,0 @@ -#include "lib/mx_noise.glsl" - -void mx_fractal3d_fa_vector3(float amplitude, int octaves, float lacunarity, float diminish, vec3 position, out vec3 result) -{ - vec3 value = mx_fractal_noise_vec3(position, octaves, lacunarity, diminish); - result = value * amplitude; -} diff --git a/libraries/stdlib/genglsl/mx_fractal3d_fa_vector4.glsl b/libraries/stdlib/genglsl/mx_fractal3d_fa_vector4.glsl deleted file mode 100644 index b9c66c4465..0000000000 --- a/libraries/stdlib/genglsl/mx_fractal3d_fa_vector4.glsl +++ /dev/null @@ -1,7 +0,0 @@ -#include "lib/mx_noise.glsl" - -void mx_fractal3d_fa_vector4(float amplitude, int octaves, float lacunarity, float diminish, vec3 position, out vec4 result) -{ - vec4 value = mx_fractal_noise_vec4(position, octaves, lacunarity, diminish); - result = value * amplitude; -} diff --git a/libraries/stdlib/genglsl/mx_noise2d_fa_vector2.glsl b/libraries/stdlib/genglsl/mx_noise2d_fa_vector2.glsl deleted file mode 100644 index f5a81565d7..0000000000 --- a/libraries/stdlib/genglsl/mx_noise2d_fa_vector2.glsl +++ /dev/null @@ -1,7 +0,0 @@ -#include "lib/mx_noise.glsl" - -void mx_noise2d_fa_vector2(float amplitude, float pivot, vec2 texcoord, out vec2 result) -{ - vec3 value = mx_perlin_noise_vec3(texcoord); - result = value.xy * amplitude + pivot; -} diff --git a/libraries/stdlib/genglsl/mx_noise2d_fa_vector3.glsl b/libraries/stdlib/genglsl/mx_noise2d_fa_vector3.glsl deleted file mode 100644 index 0735965ca0..0000000000 --- a/libraries/stdlib/genglsl/mx_noise2d_fa_vector3.glsl +++ /dev/null @@ -1,7 +0,0 @@ -#include "lib/mx_noise.glsl" - -void mx_noise2d_fa_vector3(float amplitude, float pivot, vec2 texcoord, out vec3 result) -{ - vec3 value = mx_perlin_noise_vec3(texcoord); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genglsl/mx_noise2d_fa_vector4.glsl b/libraries/stdlib/genglsl/mx_noise2d_fa_vector4.glsl deleted file mode 100644 index 6d51a59e4a..0000000000 --- a/libraries/stdlib/genglsl/mx_noise2d_fa_vector4.glsl +++ /dev/null @@ -1,8 +0,0 @@ -#include "lib/mx_noise.glsl" - -void mx_noise2d_fa_vector4(float amplitude, float pivot, vec2 texcoord, out vec4 result) -{ - vec3 xyz = mx_perlin_noise_vec3(texcoord); - float w = mx_perlin_noise_float(texcoord + vec2(19, 73)); - result = vec4(xyz, w) * amplitude + pivot; -} diff --git a/libraries/stdlib/genglsl/mx_noise3d_fa_vector2.glsl b/libraries/stdlib/genglsl/mx_noise3d_fa_vector2.glsl deleted file mode 100644 index 06d91f9135..0000000000 --- a/libraries/stdlib/genglsl/mx_noise3d_fa_vector2.glsl +++ /dev/null @@ -1,7 +0,0 @@ -#include "lib/mx_noise.glsl" - -void mx_noise3d_fa_vector2(float amplitude, float pivot, vec3 position, out vec2 result) -{ - vec3 value = mx_perlin_noise_vec3(position); - result = value.xy * amplitude + pivot; -} diff --git a/libraries/stdlib/genglsl/mx_noise3d_fa_vector3.glsl b/libraries/stdlib/genglsl/mx_noise3d_fa_vector3.glsl deleted file mode 100644 index 168bf572f1..0000000000 --- a/libraries/stdlib/genglsl/mx_noise3d_fa_vector3.glsl +++ /dev/null @@ -1,7 +0,0 @@ -#include "lib/mx_noise.glsl" - -void mx_noise3d_fa_vector3(float amplitude, float pivot, vec3 position, out vec3 result) -{ - vec3 value = mx_perlin_noise_vec3(position); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genglsl/mx_noise3d_fa_vector4.glsl b/libraries/stdlib/genglsl/mx_noise3d_fa_vector4.glsl deleted file mode 100644 index 680410f9d3..0000000000 --- a/libraries/stdlib/genglsl/mx_noise3d_fa_vector4.glsl +++ /dev/null @@ -1,8 +0,0 @@ -#include "lib/mx_noise.glsl" - -void mx_noise3d_fa_vector4(float amplitude, float pivot, vec3 position, out vec4 result) -{ - vec3 xyz = mx_perlin_noise_vec3(position); - float w = mx_perlin_noise_float(position + vec3(19, 73, 29)); - result = vec4(xyz, w) * amplitude + pivot; -} diff --git a/libraries/stdlib/genglsl/mx_normalmap.glsl b/libraries/stdlib/genglsl/mx_normalmap.glsl index 86d5610fea..19e0797c4f 100644 --- a/libraries/stdlib/genglsl/mx_normalmap.glsl +++ b/libraries/stdlib/genglsl/mx_normalmap.glsl @@ -1,4 +1,4 @@ -void mx_normalmap(vec3 value, int map_space, float normal_scale, vec3 N, vec3 T, out vec3 result) +void mx_normalmap_vector2(vec3 value, int map_space, vec2 normal_scale, vec3 N, vec3 T, out vec3 result) { // Decode the normal map. value = (value == vec3(0.0f)) ? vec3(0.0, 0.0, 1.0) : value * 2.0 - 1.0; @@ -14,3 +14,8 @@ void mx_normalmap(vec3 value, int map_space, float normal_scale, vec3 N, vec3 T, // Normalize the result. result = normalize(value); } + +void mx_normalmap_float(vec3 value, int map_space, float normal_scale, vec3 N, vec3 T, out vec3 result) +{ + mx_normalmap_vector2(value, map_space, vec2(normal_scale), N, T, result); +} diff --git a/libraries/stdlib/genglsl/mx_smoothstep_vec2FA.glsl b/libraries/stdlib/genglsl/mx_smoothstep_vec2FA.glsl deleted file mode 100644 index 0b16d99e19..0000000000 --- a/libraries/stdlib/genglsl/mx_smoothstep_vec2FA.glsl +++ /dev/null @@ -1,7 +0,0 @@ -#include "mx_smoothstep_float.glsl" - -void mx_smoothstep_vec2FA(vec2 val, float low, float high, out vec2 result) -{ - mx_smoothstep_float(val.x, low, high, result.x); - mx_smoothstep_float(val.y, low, high, result.y); -} diff --git a/libraries/stdlib/genglsl/mx_smoothstep_vec3FA.glsl b/libraries/stdlib/genglsl/mx_smoothstep_vec3FA.glsl deleted file mode 100644 index ffc913e682..0000000000 --- a/libraries/stdlib/genglsl/mx_smoothstep_vec3FA.glsl +++ /dev/null @@ -1,8 +0,0 @@ -#include "mx_smoothstep_float.glsl" - -void mx_smoothstep_vec3FA(vec3 val, float low, float high, out vec3 result) -{ - mx_smoothstep_float(val.x, low, high, result.x); - mx_smoothstep_float(val.y, low, high, result.y); - mx_smoothstep_float(val.z, low, high, result.z); -} diff --git a/libraries/stdlib/genglsl/mx_smoothstep_vec4FA.glsl b/libraries/stdlib/genglsl/mx_smoothstep_vec4FA.glsl deleted file mode 100644 index e001efd86a..0000000000 --- a/libraries/stdlib/genglsl/mx_smoothstep_vec4FA.glsl +++ /dev/null @@ -1,9 +0,0 @@ -#include "mx_smoothstep_float.glsl" - -void mx_smoothstep_vec4FA(vec4 val, float low, float high, out vec4 result) -{ - mx_smoothstep_float(val.x, low, high, result.x); - mx_smoothstep_float(val.y, low, high, result.y); - mx_smoothstep_float(val.z, low, high, result.z); - mx_smoothstep_float(val.w, low, high, result.w); -} diff --git a/libraries/stdlib/genglsl/mx_smoothstep_vec2.glsl b/libraries/stdlib/genglsl/mx_smoothstep_vector2.glsl similarity index 67% rename from libraries/stdlib/genglsl/mx_smoothstep_vec2.glsl rename to libraries/stdlib/genglsl/mx_smoothstep_vector2.glsl index c46152e3fd..f0e630af20 100644 --- a/libraries/stdlib/genglsl/mx_smoothstep_vec2.glsl +++ b/libraries/stdlib/genglsl/mx_smoothstep_vector2.glsl @@ -1,6 +1,6 @@ #include "mx_smoothstep_float.glsl" -void mx_smoothstep_vec2(vec2 val, vec2 low, vec2 high, out vec2 result) +void mx_smoothstep_vector2(vec2 val, vec2 low, vec2 high, out vec2 result) { mx_smoothstep_float(val.x, low.x, high.x, result.x); mx_smoothstep_float(val.y, low.y, high.y, result.y); diff --git a/libraries/stdlib/genglsl/mx_smoothstep_vec3.glsl b/libraries/stdlib/genglsl/mx_smoothstep_vector3.glsl similarity index 73% rename from libraries/stdlib/genglsl/mx_smoothstep_vec3.glsl rename to libraries/stdlib/genglsl/mx_smoothstep_vector3.glsl index ce15fcddfd..b6094785a8 100644 --- a/libraries/stdlib/genglsl/mx_smoothstep_vec3.glsl +++ b/libraries/stdlib/genglsl/mx_smoothstep_vector3.glsl @@ -1,6 +1,6 @@ #include "mx_smoothstep_float.glsl" -void mx_smoothstep_vec3(vec3 val, vec3 low, vec3 high, out vec3 result) +void mx_smoothstep_vector3(vec3 val, vec3 low, vec3 high, out vec3 result) { mx_smoothstep_float(val.x, low.x, high.x, result.x); mx_smoothstep_float(val.y, low.y, high.y, result.y); diff --git a/libraries/stdlib/genglsl/mx_smoothstep_vec4.glsl b/libraries/stdlib/genglsl/mx_smoothstep_vector4.glsl similarity index 78% rename from libraries/stdlib/genglsl/mx_smoothstep_vec4.glsl rename to libraries/stdlib/genglsl/mx_smoothstep_vector4.glsl index 04609b6073..1a2d4a986b 100644 --- a/libraries/stdlib/genglsl/mx_smoothstep_vec4.glsl +++ b/libraries/stdlib/genglsl/mx_smoothstep_vector4.glsl @@ -1,6 +1,6 @@ #include "mx_smoothstep_float.glsl" -void mx_smoothstep_vec4(vec4 val, vec4 low, vec4 high, out vec4 result) +void mx_smoothstep_vector4(vec4 val, vec4 low, vec4 high, out vec4 result) { mx_smoothstep_float(val.x, low.x, high.x, result.x); mx_smoothstep_float(val.y, low.y, high.y, result.y); diff --git a/libraries/stdlib/genglsl/stdlib_genglsl_impl.mtlx b/libraries/stdlib/genglsl/stdlib_genglsl_impl.mtlx index 6f67b21d33..70d7674981 100644 --- a/libraries/stdlib/genglsl/stdlib_genglsl_impl.mtlx +++ b/libraries/stdlib/genglsl/stdlib_genglsl_impl.mtlx @@ -42,7 +42,9 @@ - + + + @@ -96,42 +98,21 @@ - - - - - - - - - - - - - - - - - - - - - @@ -497,16 +478,9 @@ - - - - - - - - - - + + + diff --git a/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx b/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx index 6c550c92db..80f3aa3509 100644 --- a/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx +++ b/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx @@ -44,7 +44,8 @@ - + + @@ -98,42 +99,21 @@ - - - - - - - - - - - - - - - - - - - - - @@ -503,16 +483,9 @@ - - - - - - - diff --git a/libraries/stdlib/genmsl/mx_normalmap.metal b/libraries/stdlib/genmsl/mx_normalmap.metal index c9c7bd5546..a3ffedaad5 100644 --- a/libraries/stdlib/genmsl/mx_normalmap.metal +++ b/libraries/stdlib/genmsl/mx_normalmap.metal @@ -1,4 +1,4 @@ -void mx_normalmap(vec3 value, int map_space, float normal_scale, vec3 N, vec3 T, out vec3 result) +void mx_normalmap_vector2(vec3 value, int map_space, vec2 normal_scale, vec3 N, vec3 T, out vec3 result) { // Decode the normal map. value = all(value == vec3(0.0f)) ? vec3(0.0, 0.0, 1.0) : value * 2.0 - 1.0; @@ -14,3 +14,8 @@ void mx_normalmap(vec3 value, int map_space, float normal_scale, vec3 N, vec3 T, // Normalize the result. result = normalize(value); } + +void mx_normalmap_float(vec3 value, int map_space, float normal_scale, vec3 N, vec3 T, out vec3 result) +{ + mx_normalmap_vector2(value, map_space, vec2(normal_scale), N, T, result); +} diff --git a/libraries/stdlib/genmsl/mx_smoothstep_vec2FA.metal b/libraries/stdlib/genmsl/mx_smoothstep_vec2FA.metal deleted file mode 100644 index a05a10d746..0000000000 --- a/libraries/stdlib/genmsl/mx_smoothstep_vec2FA.metal +++ /dev/null @@ -1,8 +0,0 @@ -#include "mx_smoothstep_float.metal" - -void mx_smoothstep_vec2FA(vec2 val, float low, float high, out vec2 result) -{ - float f; - mx_smoothstep_float(val.x, low, high, f); result.x = f; - mx_smoothstep_float(val.y, low, high, f); result.y = f; -} diff --git a/libraries/stdlib/genmsl/mx_smoothstep_vec3FA.metal b/libraries/stdlib/genmsl/mx_smoothstep_vec3FA.metal deleted file mode 100644 index 4a1922d5af..0000000000 --- a/libraries/stdlib/genmsl/mx_smoothstep_vec3FA.metal +++ /dev/null @@ -1,9 +0,0 @@ -#include "mx_smoothstep_float.metal" - -void mx_smoothstep_vec3FA(vec3 val, float low, float high, out vec3 result) -{ - float f; - mx_smoothstep_float(val.x, low, high, f); result.x = f; - mx_smoothstep_float(val.y, low, high, f); result.y = f; - mx_smoothstep_float(val.z, low, high, f); result.z = f; -} diff --git a/libraries/stdlib/genmsl/mx_smoothstep_vec4FA.metal b/libraries/stdlib/genmsl/mx_smoothstep_vec4FA.metal deleted file mode 100644 index a7c27cb0e6..0000000000 --- a/libraries/stdlib/genmsl/mx_smoothstep_vec4FA.metal +++ /dev/null @@ -1,10 +0,0 @@ -#include "mx_smoothstep_float.metal" - -void mx_smoothstep_vec4FA(vec4 val, float low, float high, out vec4 result) -{ - float f; - mx_smoothstep_float(val.x, low, high, f); result.x = f; - mx_smoothstep_float(val.y, low, high, f); result.y = f; - mx_smoothstep_float(val.z, low, high, f); result.z = f; - mx_smoothstep_float(val.w, low, high, f); result.w = f; -} diff --git a/libraries/stdlib/genmsl/mx_smoothstep_vec2.metal b/libraries/stdlib/genmsl/mx_smoothstep_vector2.metal similarity index 70% rename from libraries/stdlib/genmsl/mx_smoothstep_vec2.metal rename to libraries/stdlib/genmsl/mx_smoothstep_vector2.metal index 0baa763137..34fec594ee 100644 --- a/libraries/stdlib/genmsl/mx_smoothstep_vec2.metal +++ b/libraries/stdlib/genmsl/mx_smoothstep_vector2.metal @@ -1,6 +1,6 @@ #include "mx_smoothstep_float.metal" -void mx_smoothstep_vec2(vec2 val, vec2 low, vec2 high, out vec2 result) +void mx_smoothstep_vector2(vec2 val, vec2 low, vec2 high, out vec2 result) { float f; mx_smoothstep_float(val.x, low.x, high.x, f); result.x = f; diff --git a/libraries/stdlib/genmsl/mx_smoothstep_vec3.metal b/libraries/stdlib/genmsl/mx_smoothstep_vector3.metal similarity index 77% rename from libraries/stdlib/genmsl/mx_smoothstep_vec3.metal rename to libraries/stdlib/genmsl/mx_smoothstep_vector3.metal index b0f969751b..5b0a9b62cf 100644 --- a/libraries/stdlib/genmsl/mx_smoothstep_vec3.metal +++ b/libraries/stdlib/genmsl/mx_smoothstep_vector3.metal @@ -1,6 +1,6 @@ #include "mx_smoothstep_float.metal" -void mx_smoothstep_vec3(vec3 val, vec3 low, vec3 high, thread vec3& result) +void mx_smoothstep_vector3(vec3 val, vec3 low, vec3 high, thread vec3& result) { float f; mx_smoothstep_float(val.x, low.x, high.x, f); result.x = f; diff --git a/libraries/stdlib/genmsl/mx_smoothstep_vec4.metal b/libraries/stdlib/genmsl/mx_smoothstep_vector4.metal similarity index 80% rename from libraries/stdlib/genmsl/mx_smoothstep_vec4.metal rename to libraries/stdlib/genmsl/mx_smoothstep_vector4.metal index 8bf2f3d025..04dc755149 100644 --- a/libraries/stdlib/genmsl/mx_smoothstep_vec4.metal +++ b/libraries/stdlib/genmsl/mx_smoothstep_vector4.metal @@ -1,6 +1,6 @@ #include "mx_smoothstep_float.metal" -void mx_smoothstep_vec4(vec4 val, vec4 low, vec4 high, out vec4 result) +void mx_smoothstep_vector4(vec4 val, vec4 low, vec4 high, out vec4 result) { float f; mx_smoothstep_float(val.x, low.x, high.x, f); result.x = f; diff --git a/libraries/stdlib/genmsl/stdlib_genmsl_impl.mtlx b/libraries/stdlib/genmsl/stdlib_genmsl_impl.mtlx index 40be6f8c46..2a17cc06fd 100644 --- a/libraries/stdlib/genmsl/stdlib_genmsl_impl.mtlx +++ b/libraries/stdlib/genmsl/stdlib_genmsl_impl.mtlx @@ -42,7 +42,8 @@ - + + @@ -96,42 +97,21 @@ - - - - - - - - - - - - - - - - - - - - - @@ -498,16 +478,9 @@ - - - - - - - - - - + + + @@ -749,9 +722,9 @@ - - - + + + diff --git a/libraries/stdlib/genosl/mx_creatematrix.osl b/libraries/stdlib/genosl/mx_creatematrix.osl index 933dce00ba..3e567d3b5b 100644 --- a/libraries/stdlib/genosl/mx_creatematrix.osl +++ b/libraries/stdlib/genosl/mx_creatematrix.osl @@ -1,4 +1,4 @@ -void mx_creatematrix_vector3_matrix33(vector in1, vector in2, vector in3, out matrix result) +void mx_creatematrix_vector3_matrix33(vector in1, vector in2, vector in3, output matrix result) { result = matrix(in1.x, in1.y, in1.z, 0.0, in2.x, in2.y, in2.z, 0.0, @@ -6,7 +6,7 @@ void mx_creatematrix_vector3_matrix33(vector in1, vector in2, vector in3, out ma 0.0, 0.0, 0.0, 1.0); } -void mx_creatematrix_vector3_matrix44(vector3 in1, vector3 in2, vector3 in3, vector3 in4, out matrix result) +void mx_creatematrix_vector3_matrix44(vector in1, vector in2, vector in3, vector in4, output matrix result) { result = matrix(in1.x, in1.y, in1.z, 0.0, in2.x, in2.y, in2.z, 0.0, @@ -14,7 +14,7 @@ void mx_creatematrix_vector3_matrix44(vector3 in1, vector3 in2, vector3 in3, vec in4.x, in4.y, in4.z, 1.0); } -void mx_creatematrix_vector4_matrix44(vector4 in1, vector4 in2, vector4 in3, vector4 in4, out matrix result) +void mx_creatematrix_vector4_matrix44(vector4 in1, vector4 in2, vector4 in3, vector4 in4, output matrix result) { result = matrix(in1.x, in1.y, in1.z, in1.w, in2.x, in2.y, in2.z, in2.w, diff --git a/libraries/stdlib/genosl/mx_fractal3d_color3.osl b/libraries/stdlib/genosl/mx_fractal3d_color3.osl deleted file mode 100644 index bf1744890b..0000000000 --- a/libraries/stdlib/genosl/mx_fractal3d_color3.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_fractal3d_color3(vector amplitude, int octaves, float lacunarity, float diminish, vector position, output color result) -{ - color f = mx_fbm(position, octaves, lacunarity, diminish, "snoise"); - result = f * amplitude; -} diff --git a/libraries/stdlib/genosl/mx_fractal3d_color4.osl b/libraries/stdlib/genosl/mx_fractal3d_color4.osl deleted file mode 100644 index 9943a92dfd..0000000000 --- a/libraries/stdlib/genosl/mx_fractal3d_color4.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_fractal3d_color4(vector4 amplitude, int octaves, float lacunarity, float diminish, vector position, output color4 result) -{ - color4 f = mx_fbm(position, octaves, lacunarity, diminish, "snoise"); - result = f * color4(color(amplitude.x, amplitude.y, amplitude.z), amplitude.w); -} diff --git a/libraries/stdlib/genosl/mx_fractal3d_fa_color3.osl b/libraries/stdlib/genosl/mx_fractal3d_fa_color3.osl deleted file mode 100644 index 889848c692..0000000000 --- a/libraries/stdlib/genosl/mx_fractal3d_fa_color3.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_fractal3d_fa_color3(float amplitude, int octaves, float lacunarity, float diminish, vector position, output color result) -{ - color f = mx_fbm(position, octaves, lacunarity, diminish, "snoise"); - result = f * amplitude; -} diff --git a/libraries/stdlib/genosl/mx_fractal3d_fa_color4.osl b/libraries/stdlib/genosl/mx_fractal3d_fa_color4.osl deleted file mode 100644 index d2a8f49291..0000000000 --- a/libraries/stdlib/genosl/mx_fractal3d_fa_color4.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_fractal3d_fa_color4(float amplitude, int octaves, float lacunarity, float diminish, vector position, output color4 result) -{ - color4 f = mx_fbm(position, octaves, lacunarity, diminish, "snoise"); - result = f * amplitude; -} diff --git a/libraries/stdlib/genosl/mx_fractal3d_fa_vector2.osl b/libraries/stdlib/genosl/mx_fractal3d_fa_vector2.osl deleted file mode 100644 index c1266d473c..0000000000 --- a/libraries/stdlib/genosl/mx_fractal3d_fa_vector2.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_fractal3d_fa_vector2(float amplitude, int octaves, float lacunarity, float diminish, vector position, output vector2 result) -{ - vector2 f = mx_fbm(position, octaves, lacunarity, diminish, "snoise"); - result = f * amplitude; -} diff --git a/libraries/stdlib/genosl/mx_fractal3d_fa_vector3.osl b/libraries/stdlib/genosl/mx_fractal3d_fa_vector3.osl deleted file mode 100644 index 34f6515ca8..0000000000 --- a/libraries/stdlib/genosl/mx_fractal3d_fa_vector3.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_fractal3d_fa_vector3(float amplitude, int octaves, float lacunarity, float diminish, vector position, output vector result) -{ - vector f = mx_fbm(position, octaves, lacunarity, diminish, "snoise"); - result = f * amplitude; -} diff --git a/libraries/stdlib/genosl/mx_fractal3d_fa_vector4.osl b/libraries/stdlib/genosl/mx_fractal3d_fa_vector4.osl deleted file mode 100644 index fb5a8c73d6..0000000000 --- a/libraries/stdlib/genosl/mx_fractal3d_fa_vector4.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_fractal3d_fa_vector4(float amplitude, int octaves, float lacunarity, float diminish, vector position, output vector4 result) -{ - vector4 f = mx_fbm(position, octaves, lacunarity, diminish, "snoise"); - result = f * amplitude; -} diff --git a/libraries/stdlib/genosl/mx_noise2d_color3.osl b/libraries/stdlib/genosl/mx_noise2d_color3.osl deleted file mode 100644 index 37421ee810..0000000000 --- a/libraries/stdlib/genosl/mx_noise2d_color3.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise2d_color3(vector amplitude, float pivot, vector2 texcoord, output color result) -{ - color value = noise("snoise", texcoord.x, texcoord.y); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise2d_color4.osl b/libraries/stdlib/genosl/mx_noise2d_color4.osl deleted file mode 100644 index ec8064c577..0000000000 --- a/libraries/stdlib/genosl/mx_noise2d_color4.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise2d_color4(vector4 amplitude, float pivot, vector2 texcoord, output color4 result) -{ - color4 value = mx_noise("snoise", texcoord.x, texcoord.y); - result = value * color4(color(amplitude.x, amplitude.y, amplitude.z), amplitude.w) + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise2d_fa_color3.osl b/libraries/stdlib/genosl/mx_noise2d_fa_color3.osl deleted file mode 100644 index 29c09c1ae2..0000000000 --- a/libraries/stdlib/genosl/mx_noise2d_fa_color3.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise2d_fa_color3(float amplitude, float pivot, vector2 texcoord, output color result) -{ - color value = noise("snoise", texcoord.x, texcoord.y); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise2d_fa_color4.osl b/libraries/stdlib/genosl/mx_noise2d_fa_color4.osl deleted file mode 100644 index 35d3463ff7..0000000000 --- a/libraries/stdlib/genosl/mx_noise2d_fa_color4.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise2d_fa_color4(float amplitude, float pivot, vector2 texcoord, output color4 result) -{ - color4 value = mx_noise("snoise", texcoord.x, texcoord.y); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise2d_fa_vector2.osl b/libraries/stdlib/genosl/mx_noise2d_fa_vector2.osl deleted file mode 100644 index b64dc6de7a..0000000000 --- a/libraries/stdlib/genosl/mx_noise2d_fa_vector2.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise2d_fa_vector2(float amplitude, float pivot, vector2 texcoord, output vector2 result) -{ - vector2 value = mx_noise("snoise", texcoord.x, texcoord.y); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise2d_fa_vector3.osl b/libraries/stdlib/genosl/mx_noise2d_fa_vector3.osl deleted file mode 100644 index c1f060a265..0000000000 --- a/libraries/stdlib/genosl/mx_noise2d_fa_vector3.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise2d_fa_vector3(float amplitude, float pivot, vector2 texcoord, output vector result) -{ - vector value = noise("snoise", texcoord.x, texcoord.y); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise2d_fa_vector4.osl b/libraries/stdlib/genosl/mx_noise2d_fa_vector4.osl deleted file mode 100644 index 9cb9f57c7c..0000000000 --- a/libraries/stdlib/genosl/mx_noise2d_fa_vector4.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise2d_fa_vector4(float amplitude, float pivot, vector2 texcoord, output vector4 result) -{ - vector4 value = mx_noise("snoise", texcoord.x, texcoord.y); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise3d_color3.osl b/libraries/stdlib/genosl/mx_noise3d_color3.osl deleted file mode 100644 index f4649a598a..0000000000 --- a/libraries/stdlib/genosl/mx_noise3d_color3.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise3d_color3(vector amplitude, float pivot, vector position, output color result) -{ - color value = noise("snoise", position); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise3d_color4.osl b/libraries/stdlib/genosl/mx_noise3d_color4.osl deleted file mode 100644 index c522f81493..0000000000 --- a/libraries/stdlib/genosl/mx_noise3d_color4.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise3d_color4(vector4 amplitude, float pivot, vector position, output color4 result) -{ - color4 value = mx_noise("snoise", position); - result = value * color4(color(amplitude.x, amplitude.y, amplitude.z), amplitude.w) + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise3d_fa_color3.osl b/libraries/stdlib/genosl/mx_noise3d_fa_color3.osl deleted file mode 100644 index 83b777b2f2..0000000000 --- a/libraries/stdlib/genosl/mx_noise3d_fa_color3.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise3d_fa_color3(float amplitude, float pivot, vector position, output color result) -{ - color value = noise("snoise", position); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise3d_fa_color4.osl b/libraries/stdlib/genosl/mx_noise3d_fa_color4.osl deleted file mode 100644 index ee1a48ea0c..0000000000 --- a/libraries/stdlib/genosl/mx_noise3d_fa_color4.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise3d_fa_color4(float amplitude, float pivot, vector position, output color4 result) -{ - color4 value = mx_noise("snoise", position); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise3d_fa_vector2.osl b/libraries/stdlib/genosl/mx_noise3d_fa_vector2.osl deleted file mode 100644 index 9317d8933b..0000000000 --- a/libraries/stdlib/genosl/mx_noise3d_fa_vector2.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise3d_fa_vector2(float amplitude, float pivot, vector position, output vector2 result) -{ - vector2 value = mx_noise("snoise", position); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise3d_fa_vector3.osl b/libraries/stdlib/genosl/mx_noise3d_fa_vector3.osl deleted file mode 100644 index 4e235febce..0000000000 --- a/libraries/stdlib/genosl/mx_noise3d_fa_vector3.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise3d_fa_vector3(float amplitude, float pivot, vector position, output vector result) -{ - vector value = noise("snoise", position); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genosl/mx_noise3d_fa_vector4.osl b/libraries/stdlib/genosl/mx_noise3d_fa_vector4.osl deleted file mode 100644 index 177fc3f286..0000000000 --- a/libraries/stdlib/genosl/mx_noise3d_fa_vector4.osl +++ /dev/null @@ -1,5 +0,0 @@ -void mx_noise3d_fa_vector4(float amplitude, float pivot, vector position, output vector4 result) -{ - vector4 value = mx_noise("snoise", position); - result = value * amplitude + pivot; -} diff --git a/libraries/stdlib/genosl/mx_normalmap.osl b/libraries/stdlib/genosl/mx_normalmap.osl index a1f276faf1..79b31df69d 100644 --- a/libraries/stdlib/genosl/mx_normalmap.osl +++ b/libraries/stdlib/genosl/mx_normalmap.osl @@ -1,4 +1,4 @@ -void mx_normalmap(vector value, string map_space, float normal_scale, vector N, vector U, output vector result) +void mx_normalmap_vector2(vector value, string map_space, vector2 normal_scale, vector N, vector U, output vector result) { // Tangent space if (map_space == "tangent") @@ -6,7 +6,7 @@ void mx_normalmap(vector value, string map_space, float normal_scale, vector N, vector v = value * 2.0 - 1.0; vector T = normalize(U - dot(U, N) * N); vector B = normalize(cross(N, T)); - result = normalize(T * v[0] * normal_scale + B * v[1] * normal_scale + N * v[2]); + result = normalize(T * v[0] * normal_scale.x + B * v[1] * normal_scale.y + N * v[2]); } // Object space else @@ -15,3 +15,8 @@ void mx_normalmap(vector value, string map_space, float normal_scale, vector N, result = normalize(n); } } + +void mx_normalmap_float(vector value, string map_space, float normal_scale, vector N, vector U, output vector result) +{ + mx_normalmap_vector2(value, map_space, vector2(normal_scale, normal_scale), N, U, result); +} diff --git a/libraries/stdlib/genosl/stdlib_genosl_impl.mtlx b/libraries/stdlib/genosl/stdlib_genosl_impl.mtlx index a984d912b8..177b28cfab 100644 --- a/libraries/stdlib/genosl/stdlib_genosl_impl.mtlx +++ b/libraries/stdlib/genosl/stdlib_genosl_impl.mtlx @@ -44,7 +44,8 @@ - + + @@ -98,42 +99,21 @@ - - - - - - - - - - - - - - - - - - - - - @@ -498,16 +478,9 @@ - - - - - - - @@ -752,9 +725,9 @@ - - - + + + diff --git a/libraries/stdlib/stdlib_defs.mtlx b/libraries/stdlib/stdlib_defs.mtlx index 90ccb57a98..051891cf83 100644 --- a/libraries/stdlib/stdlib_defs.mtlx +++ b/libraries/stdlib/stdlib_defs.mtlx @@ -2505,6 +2505,14 @@ + + + + + + + + - + @@ -196,7 +196,7 @@ @@ -1309,6 +1309,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1576,7 +1770,7 @@ @@ -1669,7 +1863,7 @@ - + @@ -2361,11 +2555,14 @@ - + + @@ -2479,7 +2676,7 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Materials/TestSuite/_options.mtlx b/resources/Materials/TestSuite/_options.mtlx index 1da00394e6..74bfe1eb35 100644 --- a/resources/Materials/TestSuite/_options.mtlx +++ b/resources/Materials/TestSuite/_options.mtlx @@ -91,7 +91,7 @@ - + diff --git a/resources/Materials/TestSuite/nprlib/edge_brighten.mtlx b/resources/Materials/TestSuite/nprlib/edge_brighten.mtlx index 7e9aca7f22..8ce3affd40 100644 --- a/resources/Materials/TestSuite/nprlib/edge_brighten.mtlx +++ b/resources/Materials/TestSuite/nprlib/edge_brighten.mtlx @@ -1,26 +1,16 @@ - - - - - - - - - - - - - + + + - - + + - - + + diff --git a/resources/Materials/TestSuite/pbrlib/surfaceshader/normalmapped_surfaceshader.mtlx b/resources/Materials/TestSuite/pbrlib/surfaceshader/normalmapped_surfaceshader.mtlx index 8a92848783..460f8a8998 100644 --- a/resources/Materials/TestSuite/pbrlib/surfaceshader/normalmapped_surfaceshader.mtlx +++ b/resources/Materials/TestSuite/pbrlib/surfaceshader/normalmapped_surfaceshader.mtlx @@ -25,4 +25,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Materials/TestSuite/stdlib/adjustment/smoothstep.mtlx b/resources/Materials/TestSuite/stdlib/adjustment/smoothstep.mtlx index 90510df2f1..e1fb76113b 100644 --- a/resources/Materials/TestSuite/stdlib/adjustment/smoothstep.mtlx +++ b/resources/Materials/TestSuite/stdlib/adjustment/smoothstep.mtlx @@ -1,8 +1,8 @@ @@ -20,38 +20,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -60,14 +28,6 @@ - - - - - - - - @@ -76,14 +36,6 @@ - - - - - - - - @@ -92,12 +44,4 @@ - - - - - - - - diff --git a/resources/Materials/TestSuite/stdlib/noise/noise.mtlx b/resources/Materials/TestSuite/stdlib/noise/noise.mtlx index 14ab1b9702..9a43223c60 100644 --- a/resources/Materials/TestSuite/stdlib/noise/noise.mtlx +++ b/resources/Materials/TestSuite/stdlib/noise/noise.mtlx @@ -1,208 +1,127 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Materials/TestSuite/stdlib/procedural/tiledshape.mtlx b/resources/Materials/TestSuite/stdlib/procedural/tiledshape.mtlx index 69fd225f2c..fe6e414535 100644 --- a/resources/Materials/TestSuite/stdlib/procedural/tiledshape.mtlx +++ b/resources/Materials/TestSuite/stdlib/procedural/tiledshape.mtlx @@ -24,7 +24,7 @@ - + diff --git a/resources/Materials/TestSuite/stdlib/texture/noise.mtlx b/resources/Materials/TestSuite/stdlib/texture/noise.mtlx deleted file mode 100644 index 760e508896..0000000000 --- a/resources/Materials/TestSuite/stdlib/texture/noise.mtlx +++ /dev/null @@ -1,228 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_37.mtlx b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_37.mtlx index 66dc69f668..7404b75575 100644 --- a/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_37.mtlx +++ b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_37.mtlx @@ -58,7 +58,7 @@ - + diff --git a/source/JsMaterialX/JsMaterialXCore/JsNode.cpp b/source/JsMaterialX/JsMaterialXCore/JsNode.cpp index 8878a219f5..fae1bcba5d 100644 --- a/source/JsMaterialX/JsMaterialXCore/JsNode.cpp +++ b/source/JsMaterialX/JsMaterialXCore/JsNode.cpp @@ -57,6 +57,7 @@ EMSCRIPTEN_BINDINGS(node) .function("setNodeDef", &mx::NodeGraph::setNodeDef) .function("getNodeDef", &mx::NodeGraph::getNodeDef) .function("getImplementation", &mx::NodeGraph::getImplementation) + .function("getDownstreamPorts", &mx::NodeGraph::getDownstreamPorts) .function("addInterfaceName", &mx::NodeGraph::addInterfaceName) .function("removeInterfaceName", &mx::NodeGraph::removeInterfaceName) .function("modifyInterfaceName", &mx::NodeGraph::modifyInterfaceName) diff --git a/source/MaterialXFormat/XmlIo.cpp b/source/MaterialXFormat/XmlIo.cpp index 67d41225a4..2bc0908008 100644 --- a/source/MaterialXFormat/XmlIo.cpp +++ b/source/MaterialXFormat/XmlIo.cpp @@ -353,7 +353,7 @@ void readFromXmlFile(DocumentPtr doc, FilePath filename, FileSearchPath searchPa documentFromXml(doc, xmlDoc, searchPath, readOptions); } -void readFromXmlString(DocumentPtr doc, const string& str, FileSearchPath searchPath, const XmlReadOptions* readOptions) +void readFromXmlString(DocumentPtr doc, const string& str, const FileSearchPath& searchPath, const XmlReadOptions* readOptions) { std::istringstream stream(str); readFromXmlStream(doc, stream, searchPath, readOptions); diff --git a/source/MaterialXFormat/XmlIo.h b/source/MaterialXFormat/XmlIo.h index b098c0fb3a..3aa8d41ed5 100644 --- a/source/MaterialXFormat/XmlIo.h +++ b/source/MaterialXFormat/XmlIo.h @@ -146,7 +146,7 @@ MX_FORMAT_API void readFromXmlFile(DocumentPtr doc, /// If provided, then the given options will affect the behavior of the /// read function. Defaults to a null pointer. /// @throws ExceptionParseError if the document cannot be parsed. -MX_FORMAT_API void readFromXmlString(DocumentPtr doc, const string& str, FileSearchPath searchPath = FileSearchPath(), const XmlReadOptions* readOptions = nullptr); +MX_FORMAT_API void readFromXmlString(DocumentPtr doc, const string& str, const FileSearchPath& searchPath = FileSearchPath(), const XmlReadOptions* readOptions = nullptr); /// @} /// @name Write Functions diff --git a/source/MaterialXGenGlsl/GlslResourceBindingContext.cpp b/source/MaterialXGenGlsl/GlslResourceBindingContext.cpp index 3aad355d60..d4496bf154 100644 --- a/source/MaterialXGenGlsl/GlslResourceBindingContext.cpp +++ b/source/MaterialXGenGlsl/GlslResourceBindingContext.cpp @@ -58,7 +58,7 @@ void GlslResourceBindingContext::emitDirectives(GenContext& context, ShaderStage void GlslResourceBindingContext::emitResourceBindings(GenContext& context, const VariableBlock& uniforms, ShaderStage& stage) { - ShaderGenerator& generator = context.getShaderGenerator(); + const ShaderGenerator& generator = context.getShaderGenerator(); const Syntax& syntax = generator.getSyntax(); // First, emit all value uniforms in a block with single layout binding @@ -93,7 +93,7 @@ void GlslResourceBindingContext::emitResourceBindings(GenContext& context, const // Second, emit all sampler uniforms as separate uniforms with separate layout bindings for (auto uniform : uniforms.getVariableOrder()) { - if (uniform->getType() == Type::FILENAME) + if (*uniform->getType() == *Type::FILENAME) { generator.emitString("layout (binding=" + std::to_string(_separateBindingLocation ? _hwUniformBindLocation++ : _hwSamplerBindLocation++) + ") " + syntax.getUniformQualifier() + " ", stage); generator.emitVariableDeclaration(uniform, EMPTY_STRING, context, stage, false); @@ -108,7 +108,7 @@ void GlslResourceBindingContext::emitStructuredResourceBindings(GenContext& cont ShaderStage& stage, const std::string& structInstanceName, const std::string& arraySuffix) { - ShaderGenerator& generator = context.getShaderGenerator(); + const ShaderGenerator& generator = context.getShaderGenerator(); const Syntax& syntax = generator.getSyntax(); // Glsl structures need to be aligned. We make a best effort to base align struct members and add diff --git a/source/MaterialXGenGlsl/GlslShaderGenerator.cpp b/source/MaterialXGenGlsl/GlslShaderGenerator.cpp index 5b20ee1b03..f8ed1a4892 100644 --- a/source/MaterialXGenGlsl/GlslShaderGenerator.cpp +++ b/source/MaterialXGenGlsl/GlslShaderGenerator.cpp @@ -6,15 +6,8 @@ #include #include -#include -#include -#include -#include #include #include -#include -#include -#include #include #include #include @@ -33,6 +26,13 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -165,13 +165,13 @@ GlslShaderGenerator::GlslShaderGenerator() : registerImplementation(elementNames, CombineNode::create); // - registerImplementation("IM_position_vector3_" + GlslShaderGenerator::TARGET, PositionNodeGlsl::create); + registerImplementation("IM_position_vector3_" + GlslShaderGenerator::TARGET, HwPositionNode::create); // - registerImplementation("IM_normal_vector3_" + GlslShaderGenerator::TARGET, NormalNodeGlsl::create); + registerImplementation("IM_normal_vector3_" + GlslShaderGenerator::TARGET, HwNormalNode::create); // - registerImplementation("IM_tangent_vector3_" + GlslShaderGenerator::TARGET, TangentNodeGlsl::create); + registerImplementation("IM_tangent_vector3_" + GlslShaderGenerator::TARGET, HwTangentNode::create); // - registerImplementation("IM_bitangent_vector3_" + GlslShaderGenerator::TARGET, BitangentNodeGlsl::create); + registerImplementation("IM_bitangent_vector3_" + GlslShaderGenerator::TARGET, HwBitangentNode::create); // registerImplementation("IM_texcoord_vector2_" + GlslShaderGenerator::TARGET, HwTexCoordNode::create); registerImplementation("IM_texcoord_vector3_" + GlslShaderGenerator::TARGET, HwTexCoordNode::create); @@ -194,11 +194,11 @@ GlslShaderGenerator::GlslShaderGenerator() : registerImplementation("IM_geompropvalue_string_" + GlslShaderGenerator::TARGET, GeomPropValueNodeGlslAsUniform::create); // - registerImplementation("IM_frame_float_" + GlslShaderGenerator::TARGET, FrameNodeGlsl::create); + registerImplementation("IM_frame_float_" + GlslShaderGenerator::TARGET, HwFrameNode::create); // - registerImplementation("IM_time_float_" + GlslShaderGenerator::TARGET, TimeNodeGlsl::create); + registerImplementation("IM_time_float_" + GlslShaderGenerator::TARGET, HwTimeNode::create); // - registerImplementation("IM_viewdirection_vector3_" + GlslShaderGenerator::TARGET, ViewDirectionNodeGlsl::create); + registerImplementation("IM_viewdirection_vector3_" + GlslShaderGenerator::TARGET, HwViewDirectionNode::create); // registerImplementation("IM_surface_" + GlslShaderGenerator::TARGET, SurfaceNodeGlsl::create); @@ -782,11 +782,11 @@ void GlslShaderGenerator::toVec4(const TypeDesc* type, string& variable) { variable = "vec4(" + variable + ", 0.0, 1.0)"; } - else if (type == Type::FLOAT || type == Type::INTEGER) + else if (*type == *Type::FLOAT || *type == *Type::INTEGER) { variable = "vec4(" + variable + ", " + variable + ", " + variable + ", 1.0)"; } - else if (type == Type::BSDF || type == Type::EDF) + else if (*type == *Type::BSDF || *type == *Type::EDF) { variable = "vec4(" + variable + ", 1.0)"; } @@ -802,7 +802,7 @@ void GlslShaderGenerator::emitVariableDeclaration(const ShaderPort* variable, co bool assignValue) const { // A file texture input needs special handling on GLSL - if (variable->getType() == Type::FILENAME) + if (*variable->getType() == *Type::FILENAME) { // Samplers must always be uniforms string str = qualifier.empty() ? EMPTY_STRING : qualifier + " "; @@ -813,7 +813,7 @@ void GlslShaderGenerator::emitVariableDeclaration(const ShaderPort* variable, co string str = qualifier.empty() ? EMPTY_STRING : qualifier + " "; // Varying parameters of type int must be flat qualified on output from vertex stage and // input to pixel stage. The only way to get these is with geompropvalue_integer nodes. - if (qualifier.empty() && variable->getType() == Type::INTEGER && !assignValue && variable->getName().rfind(HW::T_IN_GEOMPROP, 0) == 0) + if (qualifier.empty() && *variable->getType() == *Type::INTEGER && !assignValue && variable->getName().rfind(HW::T_IN_GEOMPROP, 0) == 0) { str += GlslSyntax::FLAT_QUALIFIER + " "; } @@ -870,7 +870,7 @@ ShaderNodeImplPtr GlslShaderGenerator::getImplementation(const NodeDef& nodedef, if (implElement->isA()) { // Use a compound implementation. - if (outputType == Type::LIGHTSHADER) + if (*outputType == *Type::LIGHTSHADER) { impl = LightCompoundNodeGlsl::create(); } @@ -913,31 +913,9 @@ ShaderNodeImplPtr GlslShaderGenerator::getImplementation(const NodeDef& nodedef, return impl; } -const string GlslImplementation::SPACE = "space"; -const string GlslImplementation::INDEX = "index"; -const string GlslImplementation::GEOMPROP = "geomprop"; - -namespace -{ - -// List name of inputs that are not to be editable and -// published as shader uniforms in GLSL. -const std::set IMMUTABLE_INPUTS = -{ - // Geometric node inputs are immutable since a shader needs regeneration if they change. - "index", "space", "attrname" -}; - -} // anonymous namespace - const string& GlslImplementation::getTarget() const { return GlslShaderGenerator::TARGET; } -bool GlslImplementation::isEditable(const ShaderInput& input) const -{ - return IMMUTABLE_INPUTS.count(input.getName()) == 0; -} - MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenGlsl/GlslShaderGenerator.h b/source/MaterialXGenGlsl/GlslShaderGenerator.h index acc8b0d6ee..aafd665140 100644 --- a/source/MaterialXGenGlsl/GlslShaderGenerator.h +++ b/source/MaterialXGenGlsl/GlslShaderGenerator.h @@ -88,30 +88,13 @@ class MX_GENGLSL_API GlslShaderGenerator : public HwShaderGenerator }; /// Base class for common GLSL node implementations -class MX_GENGLSL_API GlslImplementation : public ShaderNodeImpl +class MX_GENGLSL_API GlslImplementation : public HwImplementation { public: const string& getTarget() const override; - bool isEditable(const ShaderInput& input) const override; - protected: GlslImplementation() { } - - // Integer identifiers for coordinate spaces. - // The order must match the order given for - // the space enum string in stdlib. - enum Space - { - MODEL_SPACE = 0, - OBJECT_SPACE = 1, - WORLD_SPACE = 2 - }; - - /// Internal string constants - static const string SPACE; - static const string INDEX; - static const string GEOMPROP; }; MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenGlsl/GlslSyntax.cpp b/source/MaterialXGenGlsl/GlslSyntax.cpp index afd6f033dc..2f82250394 100644 --- a/source/MaterialXGenGlsl/GlslSyntax.cpp +++ b/source/MaterialXGenGlsl/GlslSyntax.cpp @@ -364,7 +364,7 @@ bool GlslSyntax::remapEnumeration(const string& value, const TypeDesc* type, con // Don't convert already supported types // or filenames and arrays. if (typeSupported(type) || - type == Type::FILENAME || (type && type->isArray())) + *type == *Type::FILENAME || (type && type->isArray())) { return false; } diff --git a/source/MaterialXGenGlsl/Nodes/BitangentNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/BitangentNodeGlsl.cpp deleted file mode 100644 index 6f515824e7..0000000000 --- a/source/MaterialXGenGlsl/Nodes/BitangentNodeGlsl.cpp +++ /dev/null @@ -1,135 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr BitangentNodeGlsl::create() -{ - return std::make_shared(); -} - -void BitangentNodeGlsl::createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const -{ - const GenOptions& options = context.getOptions(); - - ShaderStage& vs = shader.getStage(Stage::VERTEX); - ShaderStage& ps = shader.getStage(Stage::PIXEL); - - if (options.hwImplicitBitangents) - { - addStageInput(HW::VERTEX_INPUTS, Type::VECTOR3, HW::T_IN_NORMAL, vs); - addStageInput(HW::VERTEX_INPUTS, Type::VECTOR3, HW::T_IN_TANGENT, vs); - } - else - { - addStageInput(HW::VERTEX_INPUTS, Type::VECTOR3, HW::T_IN_BITANGENT, vs); - } - - const ShaderInput* spaceInput = node.getInput(SPACE); - const int space = spaceInput ? spaceInput->getValue()->asA() : OBJECT_SPACE; - if (space == WORLD_SPACE) - { - addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_BITANGENT_WORLD, vs, ps); - addStageUniform(HW::PRIVATE_UNIFORMS, Type::MATRIX44, HW::T_WORLD_MATRIX, vs); - - if (options.hwImplicitBitangents) - { - addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_NORMAL_WORLD, vs, ps); - addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_TANGENT_WORLD, vs, ps); - addStageUniform(HW::PRIVATE_UNIFORMS, Type::MATRIX44, HW::T_WORLD_INVERSE_TRANSPOSE_MATRIX, vs); - } - } - else - { - addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_BITANGENT_OBJECT, vs, ps); - } -} - -void BitangentNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - const GlslShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); - const GenOptions& options = context.getOptions(); - - const ShaderInput* spaceInput = node.getInput(SPACE); - const int space = spaceInput ? spaceInput->getValue()->asA() : OBJECT_SPACE; - - DEFINE_SHADER_STAGE(stage, Stage::VERTEX) - { - VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - if (space == WORLD_SPACE) - { - ShaderPort* bitangent = vertexData[HW::T_BITANGENT_WORLD]; - - if (!bitangent->isEmitted()) - { - bitangent->setEmitted(); - - if (options.hwImplicitBitangents) - { - ShaderPort* normal = vertexData[HW::T_NORMAL_WORLD]; - if (!normal->isEmitted()) - { - normal->setEmitted(); - shadergen.emitLine(prefix + normal->getVariable() + " = normalize((" + HW::T_WORLD_INVERSE_TRANSPOSE_MATRIX + " * vec4(" + HW::T_IN_NORMAL + ", 0.0)).xyz)", stage); - } - ShaderPort* tangent = vertexData[HW::T_TANGENT_WORLD]; - if (!tangent->isEmitted()) - { - tangent->setEmitted(); - shadergen.emitLine(prefix + tangent->getVariable() + " = normalize((" + HW::T_WORLD_MATRIX + " * vec4(" + HW::T_IN_TANGENT + ", 0.0)).xyz)", stage); - } - shadergen.emitLine(prefix + bitangent->getVariable() + " = cross(" + prefix + normal->getVariable() + ", " + prefix + tangent->getVariable() + ")", stage); - } - else - { - shadergen.emitLine(prefix + bitangent->getVariable() + " = normalize((" + HW::T_WORLD_MATRIX + " * vec4(" + HW::T_IN_BITANGENT + ", 0.0)).xyz)", stage); - } - } - } - else - { - ShaderPort* bitangent = vertexData[HW::T_BITANGENT_OBJECT]; - if (!bitangent->isEmitted()) - { - bitangent->setEmitted(); - - if (options.hwImplicitBitangents) - { - shadergen.emitLine(prefix + bitangent->getVariable() + " = cross(" + HW::T_IN_NORMAL + ", " + HW::T_IN_TANGENT + ")", stage); - } - else - { - shadergen.emitLine(prefix + bitangent->getVariable() + " = " + HW::T_IN_BITANGENT, stage); - } - } - } - } - - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - shadergen.emitLineBegin(stage); - shadergen.emitOutput(node.getOutput(), true, false, context, stage); - if (space == WORLD_SPACE) - { - const ShaderPort* bitangent = vertexData[HW::T_BITANGENT_WORLD]; - shadergen.emitString(" = normalize(" + prefix + bitangent->getVariable() + ")", stage); - } - else - { - const ShaderPort* bitangent = vertexData[HW::T_BITANGENT_OBJECT]; - shadergen.emitString(" = normalize(" + prefix + bitangent->getVariable() + ")", stage); - } - shadergen.emitLineEnd(stage); - } -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenGlsl/Nodes/FrameNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/FrameNodeGlsl.cpp deleted file mode 100644 index b6dbb2002b..0000000000 --- a/source/MaterialXGenGlsl/Nodes/FrameNodeGlsl.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr FrameNodeGlsl::create() -{ - return std::make_shared(); -} - -void FrameNodeGlsl::createVariables(const ShaderNode&, GenContext&, Shader& shader) const -{ - ShaderStage& ps = shader.getStage(Stage::PIXEL); - addStageUniform(HW::PRIVATE_UNIFORMS, Type::FLOAT, HW::T_FRAME, ps); -} - -void FrameNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - const ShaderGenerator& shadergen = context.getShaderGenerator(); - shadergen.emitLineBegin(stage); - shadergen.emitOutput(node.getOutput(), true, false, context, stage); - shadergen.emitString(" = " + HW::T_FRAME, stage); - shadergen.emitLineEnd(stage); - } -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenGlsl/Nodes/GeomColorNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/GeomColorNodeGlsl.cpp index 7e24331f93..bdcb4c0fac 100644 --- a/source/MaterialXGenGlsl/Nodes/GeomColorNodeGlsl.cpp +++ b/source/MaterialXGenGlsl/Nodes/GeomColorNodeGlsl.cpp @@ -49,11 +49,11 @@ void GeomColorNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& con DEFINE_SHADER_STAGE(stage, Stage::PIXEL) { string suffix = ""; - if (output->getType() == Type::FLOAT) + if (*output->getType() == *Type::FLOAT) { suffix = ".r"; } - else if (output->getType() == Type::COLOR3) + else if (*output->getType() == *Type::COLOR3) { suffix = ".rgb"; } diff --git a/source/MaterialXGenGlsl/Nodes/HeightToNormalNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/HeightToNormalNodeGlsl.cpp index e98a4ab75c..14716eee1e 100644 --- a/source/MaterialXGenGlsl/Nodes/HeightToNormalNodeGlsl.cpp +++ b/source/MaterialXGenGlsl/Nodes/HeightToNormalNodeGlsl.cpp @@ -54,7 +54,7 @@ void HeightToNormalNodeGlsl::computeSampleOffsetStrings(const string& sampleSize bool HeightToNormalNodeGlsl::acceptsInputType(const TypeDesc* type) const { // Only support inputs which are float scalar - return (type == Type::FLOAT && type->isScalar()); + return (*type == *Type::FLOAT && type->isScalar()); } void HeightToNormalNodeGlsl::emitFunctionDefinition(const ShaderNode&, GenContext& context, ShaderStage& stage) const diff --git a/source/MaterialXGenGlsl/Nodes/PositionNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/PositionNodeGlsl.cpp deleted file mode 100644 index d37af520b2..0000000000 --- a/source/MaterialXGenGlsl/Nodes/PositionNodeGlsl.cpp +++ /dev/null @@ -1,87 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr PositionNodeGlsl::create() -{ - return std::make_shared(); -} - -void PositionNodeGlsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const -{ - ShaderStage vs = shader.getStage(Stage::VERTEX); - ShaderStage ps = shader.getStage(Stage::PIXEL); - - addStageInput(HW::VERTEX_INPUTS, Type::VECTOR3, HW::T_IN_POSITION, vs); - - const ShaderInput* spaceInput = node.getInput(SPACE); - const int space = spaceInput ? spaceInput->getValue()->asA() : OBJECT_SPACE; - if (space == WORLD_SPACE) - { - addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_POSITION_WORLD, vs, ps); - } - else - { - addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_POSITION_OBJECT, vs, ps); - } -} - -void PositionNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - const GlslShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); - - const ShaderInput* spaceInput = node.getInput(SPACE); - const int space = spaceInput ? spaceInput->getValue()->asA() : OBJECT_SPACE; - - DEFINE_SHADER_STAGE(stage, Stage::VERTEX) - { - VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - if (space == WORLD_SPACE) - { - ShaderPort* position = vertexData[HW::T_POSITION_WORLD]; - if (!position->isEmitted()) - { - position->setEmitted(); - shadergen.emitLine(prefix + position->getVariable() + " = hPositionWorld.xyz", stage); - } - } - else - { - ShaderPort* position = vertexData[HW::T_POSITION_OBJECT]; - if (!position->isEmitted()) - { - position->setEmitted(); - shadergen.emitLine(prefix + position->getVariable() + " = " + HW::T_IN_POSITION, stage); - } - } - } - - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - shadergen.emitLineBegin(stage); - shadergen.emitOutput(node.getOutput(), true, false, context, stage); - if (space == WORLD_SPACE) - { - const ShaderPort* position = vertexData[HW::T_POSITION_WORLD]; - shadergen.emitString(" = " + prefix + position->getVariable(), stage); - } - else - { - const ShaderPort* position = vertexData[HW::T_POSITION_OBJECT]; - shadergen.emitString(" = " + prefix + position->getVariable(), stage); - } - shadergen.emitLineEnd(stage); - } -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenGlsl/Nodes/SurfaceNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/SurfaceNodeGlsl.cpp index c83fbe1d78..2e222f6bcc 100644 --- a/source/MaterialXGenGlsl/Nodes/SurfaceNodeGlsl.cpp +++ b/source/MaterialXGenGlsl/Nodes/SurfaceNodeGlsl.cpp @@ -45,8 +45,8 @@ void SurfaceNodeGlsl::createVariables(const ShaderNode&, GenContext& context, Sh { // TODO: // The surface shader needs position, normal, view position and light sources. We should solve this by adding some - // dependency mechanism so this implementation can be set to depend on the PositionNodeGlsl, NormalNodeGlsl - // ViewDirectionNodeGlsl and LightNodeGlsl nodes instead? This is where the MaterialX attribute "internalgeomprops" + // dependency mechanism so this implementation can be set to depend on the HwPositionNode, HwNormalNode + // HwViewDirectionNode and LightNodeGlsl nodes instead? This is where the MaterialX attribute "internalgeomprops" // is needed. // ShaderStage& vs = shader.getStage(Stage::VERTEX); diff --git a/source/MaterialXGenGlsl/Nodes/SurfaceShaderNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/SurfaceShaderNodeGlsl.cpp index 00362b1cab..5e97b8ffc6 100644 --- a/source/MaterialXGenGlsl/Nodes/SurfaceShaderNodeGlsl.cpp +++ b/source/MaterialXGenGlsl/Nodes/SurfaceShaderNodeGlsl.cpp @@ -24,8 +24,8 @@ void SurfaceShaderNodeGlsl::createVariables(const ShaderNode&, GenContext& conte { // TODO: // The surface shader needs position, view position and light sources. We should solve this by adding some - // dependency mechanism so this implementation can be set to depend on the PositionNodeGlsl, - // ViewDirectionNodeGlsl and LightNodeGlsl nodes instead? This is where the MaterialX attribute "internalgeomprops" + // dependency mechanism so this implementation can be set to depend on the HwPositionNode, + // HwViewDirectionNode and LightNodeGlsl nodes instead? This is where the MaterialX attribute "internalgeomprops" // is needed. // ShaderStage& vs = shader.getStage(Stage::VERTEX); diff --git a/source/MaterialXGenGlsl/Nodes/TimeNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/TimeNodeGlsl.cpp deleted file mode 100644 index e508391141..0000000000 --- a/source/MaterialXGenGlsl/Nodes/TimeNodeGlsl.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr TimeNodeGlsl::create() -{ - return std::make_shared(); -} - -void TimeNodeGlsl::createVariables(const ShaderNode&, GenContext&, Shader& shader) const -{ - ShaderStage& ps = shader.getStage(Stage::PIXEL); - addStageUniform(HW::PRIVATE_UNIFORMS, Type::FLOAT, HW::T_FRAME, ps); -} - -void TimeNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - const ShaderGenerator& shadergen = context.getShaderGenerator(); - shadergen.emitLineBegin(stage); - shadergen.emitOutput(node.getOutput(), true, false, context, stage); - shadergen.emitString(" = " + HW::T_FRAME + " / ", stage); - const ShaderInput* fpsInput = node.getInput("fps"); - const string fps = fpsInput->getValue()->getValueString(); - shadergen.emitString(fps, stage); - shadergen.emitLineEnd(stage); - } -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenGlsl/Nodes/TimeNodeGlsl.h b/source/MaterialXGenGlsl/Nodes/TimeNodeGlsl.h deleted file mode 100644 index c97f6b4741..0000000000 --- a/source/MaterialXGenGlsl/Nodes/TimeNodeGlsl.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_TIMENODEGLSL_H -#define MATERIALX_TIMENODEGLSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// Time node implementation for GLSL -class MX_GENGLSL_API TimeNodeGlsl : public GlslImplementation -{ - public: - static ShaderNodeImplPtr create(); - - void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; - - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.cpp deleted file mode 100644 index f9714b5d33..0000000000 --- a/source/MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.cpp +++ /dev/null @@ -1,55 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr ViewDirectionNodeGlsl::create() -{ - return std::make_shared(); -} - -void ViewDirectionNodeGlsl::createVariables(const ShaderNode&, GenContext&, Shader& shader) const -{ - ShaderStage& vs = shader.getStage(Stage::VERTEX); - ShaderStage& ps = shader.getStage(Stage::PIXEL); - - addStageInput(HW::VERTEX_INPUTS, Type::VECTOR3, HW::T_IN_POSITION, vs); - addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_POSITION_WORLD, vs, ps); - addStageUniform(HW::PRIVATE_UNIFORMS, Type::VECTOR3, HW::T_VIEW_POSITION, ps); -} - -void ViewDirectionNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - const GlslShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); - - DEFINE_SHADER_STAGE(stage, Stage::VERTEX) - { - VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - ShaderPort* position = vertexData[HW::T_POSITION_WORLD]; - if (!position->isEmitted()) - { - position->setEmitted(); - shadergen.emitLine(prefix + position->getVariable() + " = hPositionWorld.xyz", stage); - } - } - - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - ShaderPort* position = vertexData[HW::T_POSITION_WORLD]; - shadergen.emitLineBegin(stage); - shadergen.emitOutput(node.getOutput(), true, false, context, stage); - shadergen.emitString(" = normalize(" + prefix + position->getVariable() + " - " + HW::T_VIEW_POSITION + ")", stage); - shadergen.emitLineEnd(stage); - } -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.h b/source/MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.h deleted file mode 100644 index 24cafe2f1d..0000000000 --- a/source/MaterialXGenGlsl/Nodes/ViewDirectionNodeGlsl.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_VIEWDIRECTIONNODEGLSL_H -#define MATERIALX_VIEWDIRECTIONNODEGLSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// ViewDirection node implementation for GLSL -class MX_GENGLSL_API ViewDirectionNodeGlsl : public GlslImplementation -{ - public: - static ShaderNodeImplPtr create(); - - void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; - - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenGlsl/VkResourceBindingContext.cpp b/source/MaterialXGenGlsl/VkResourceBindingContext.cpp index 38e7186f4a..89e65f9d07 100644 --- a/source/MaterialXGenGlsl/VkResourceBindingContext.cpp +++ b/source/MaterialXGenGlsl/VkResourceBindingContext.cpp @@ -24,7 +24,7 @@ void VkResourceBindingContext::initialize() void VkResourceBindingContext::emitDirectives(GenContext& context, ShaderStage& stage) { - ShaderGenerator& generator = context.getShaderGenerator(); + const ShaderGenerator& generator = context.getShaderGenerator(); // Write shader stage directives for Vulkan compliance std::string shaderStage; @@ -45,7 +45,7 @@ void VkResourceBindingContext::emitDirectives(GenContext& context, ShaderStage& void VkResourceBindingContext::emitResourceBindings(GenContext& context, const VariableBlock& uniforms, ShaderStage& stage) { - ShaderGenerator& generator = context.getShaderGenerator(); + const ShaderGenerator& generator = context.getShaderGenerator(); const Syntax& syntax = generator.getSyntax(); // First, emit all value uniforms in a block with single layout binding @@ -80,7 +80,7 @@ void VkResourceBindingContext::emitResourceBindings(GenContext& context, const V // Second, emit all sampler uniforms as separate uniforms with separate layout bindings for (auto uniform : uniforms.getVariableOrder()) { - if (uniform->getType() == Type::FILENAME) + if (*uniform->getType() == *Type::FILENAME) { generator.emitString("layout (binding=" + std::to_string(_hwUniformBindLocation++) + ") " + syntax.getUniformQualifier() + " ", stage); generator.emitVariableDeclaration(uniform, EMPTY_STRING, context, stage, false); @@ -95,7 +95,7 @@ void VkResourceBindingContext::emitStructuredResourceBindings(GenContext& contex ShaderStage& stage, const std::string& structInstanceName, const std::string& arraySuffix) { - ShaderGenerator& generator = context.getShaderGenerator(); + const ShaderGenerator& generator = context.getShaderGenerator(); const Syntax& syntax = generator.getSyntax(); // Glsl structures need to be aligned. We make a best effort to base align struct members and add diff --git a/source/MaterialXGenMdl/MdlShaderGenerator.cpp b/source/MaterialXGenMdl/MdlShaderGenerator.cpp index af75a2cef4..7d52e9e973 100644 --- a/source/MaterialXGenMdl/MdlShaderGenerator.cpp +++ b/source/MaterialXGenMdl/MdlShaderGenerator.cpp @@ -287,7 +287,7 @@ ShaderPtr MdlShaderGenerator::generate(const string& name, ElementPtr element, G const TypeDesc* outputType = outputSocket->getType(); if (graph.hasClassification(ShaderNode::Classification::TEXTURE)) { - if (outputType == Type::DISPLACEMENTSHADER) + if (*outputType == *Type::DISPLACEMENTSHADER) { emitLine("float3 displacement__ = " + result + ".geometry.displacement", stage); emitLine("color finalOutput__ = mk_color3(" @@ -667,7 +667,7 @@ void MdlShaderGenerator::emitShaderInputs(const VariableBlock& inputs, ShaderSta { const ShaderPort* input = inputs[i]; - const string& qualifier = input->isUniform() || input->getType() == Type::FILENAME ? uniformPrefix : EMPTY_STRING; + const string& qualifier = input->isUniform() || *input->getType() == *Type::FILENAME ? uniformPrefix : EMPTY_STRING; const string& type = _syntax->getTypeName(input->getType()); string value = input->getValue() ? _syntax->getValue(input->getType(), *input->getValue(), true) : EMPTY_STRING; diff --git a/source/MaterialXGenMdl/MdlSyntax.cpp b/source/MaterialXGenMdl/MdlSyntax.cpp index 7560297ce4..f32fe6c60f 100644 --- a/source/MaterialXGenMdl/MdlSyntax.cpp +++ b/source/MaterialXGenMdl/MdlSyntax.cpp @@ -492,7 +492,7 @@ const std::unordered_map CHANNELS_TO_XYZW = string MdlSyntax::getSwizzledVariable(const string& srcName, const TypeDesc* srcType, const string& channels, const TypeDesc* dstType) const { - if (srcType == Type::COLOR3 || srcType == Type::COLOR4) + if (*srcType == *Type::COLOR3 || *srcType == *Type::COLOR4) { const TypeSyntax& srcSyntax = getTypeSyntax(srcType); const TypeSyntax& dstSyntax = getTypeSyntax(dstType); @@ -523,7 +523,7 @@ string MdlSyntax::getSwizzledVariable(const string& srcName, const TypeDesc* src } string variable = srcName; - if (srcType == Type::COLOR3) + if (*srcType == *Type::COLOR3) { variable = "float3(" + srcName + ")"; } @@ -567,7 +567,7 @@ bool MdlSyntax::remapEnumeration(const string& value, const TypeDesc* type, cons } // Don't convert filenames or arrays. - if (type == Type::FILENAME || (type && type->isArray())) + if (*type == *Type::FILENAME || (type && type->isArray())) { return false; } diff --git a/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.cpp b/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.cpp index bff1351142..41dfa54111 100644 --- a/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.cpp +++ b/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.cpp @@ -46,7 +46,7 @@ void ClosureLayerNodeMdl::emitFunctionCall(const ShaderNode& _node, GenContext& // // 1. Handle the BSDF-over-VDF case // - if (baseInput->getType() == Type::VDF) + if (*baseInput->getType() == *Type::VDF) { // Make sure we have a top BSDF connected. if (!topInput->getConnection()) diff --git a/source/MaterialXGenMdl/Nodes/CombineNodeMdl.cpp b/source/MaterialXGenMdl/Nodes/CombineNodeMdl.cpp index 9d6789c94c..83dc755b7a 100644 --- a/source/MaterialXGenMdl/Nodes/CombineNodeMdl.cpp +++ b/source/MaterialXGenMdl/Nodes/CombineNodeMdl.cpp @@ -33,10 +33,10 @@ void CombineNodeMdl::emitFunctionCall(const ShaderNode& node, GenContext& contex throw ExceptionShaderGenError("Node '" + node.getName() + "' is not a valid convert node"); } - if (in1->getType() == Type::COLOR3) + if (*in1->getType() == *Type::COLOR3) { const ShaderInput* in2 = node.getInput(1); - if (!in2 || in2->getType() != Type::FLOAT) + if (!in2 || *in2->getType() != *Type::FLOAT) { throw ExceptionShaderGenError("Node '" + node.getName() + "' is not a valid convert node"); } diff --git a/source/MaterialXGenMdl/Nodes/CompoundNodeMdl.cpp b/source/MaterialXGenMdl/Nodes/CompoundNodeMdl.cpp index 03c8bc172f..b7b81e5d30 100644 --- a/source/MaterialXGenMdl/Nodes/CompoundNodeMdl.cpp +++ b/source/MaterialXGenMdl/Nodes/CompoundNodeMdl.cpp @@ -233,7 +233,7 @@ void CompoundNodeMdl::emitFunctionSignature(const ShaderNode&, GenContext& conte int count = int(_rootGraph->numInputSockets()); for (ShaderGraphInputSocket* input : _rootGraph->getInputSockets()) { - const string& qualifier = input->isUniform() || input->getType() == Type::FILENAME ? uniformPrefix : EMPTY_STRING; + const string& qualifier = input->isUniform() || *input->getType() == *Type::FILENAME ? uniformPrefix : EMPTY_STRING; const string& type = syntax.getTypeName(input->getType()); string value = input->getValue() ? syntax.getValue(input->getType(), *input->getValue(), true) : EMPTY_STRING; diff --git a/source/MaterialXGenMdl/Nodes/HeightToNormalNodeMdl.cpp b/source/MaterialXGenMdl/Nodes/HeightToNormalNodeMdl.cpp index 186c88be88..b52ebc8ab2 100644 --- a/source/MaterialXGenMdl/Nodes/HeightToNormalNodeMdl.cpp +++ b/source/MaterialXGenMdl/Nodes/HeightToNormalNodeMdl.cpp @@ -50,7 +50,7 @@ void HeightToNormalNodeMdl::computeSampleOffsetStrings(const string& sampleSizeN bool HeightToNormalNodeMdl::acceptsInputType(const TypeDesc* type) const { // Only support inputs which are float scalar - return (type == Type::FLOAT && type->isScalar()); + return (*type == *Type::FLOAT && type->isScalar()); } void HeightToNormalNodeMdl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const diff --git a/source/MaterialXGenMdl/Nodes/SurfaceNodeMdl.cpp b/source/MaterialXGenMdl/Nodes/SurfaceNodeMdl.cpp index 8ce4bf0f33..508bba43fc 100644 --- a/source/MaterialXGenMdl/Nodes/SurfaceNodeMdl.cpp +++ b/source/MaterialXGenMdl/Nodes/SurfaceNodeMdl.cpp @@ -38,7 +38,7 @@ const ShaderInput* findTransmissionIOR(const ShaderNode& node) } for (const ShaderInput* input : node.getInputs()) { - if (input->getType() == Type::BSDF && input->getConnection()) + if (*input->getType() == *Type::BSDF && input->getConnection()) { const ShaderInput* ior = findTransmissionIOR(*input->getConnection()->getNode()); if (ior) diff --git a/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl b/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl index 81cd039af6..708ea15603 100644 --- a/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl +++ b/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl @@ -2060,13 +2060,13 @@ export float4 mx_transformmatrix_vector4( return mxp_mat * mxp_in; } -export float3 mx_normalmap( +export float3 mx_normalmap_vector2( float3 mxp_in = float3(0.5, 0.5, 1.0), uniform string mxp_space = string("tangent") [[ anno::description("Enumeration {tangent, object}.") ]], - float mxp_scale = float(1.0), + float2 mxp_scale = float2(1.0, 1.0), float3 mxp_normal = float3(::state::transform_normal(::state::coordinate_internal,::state::coordinate_world,::state::normal())), float3 mxp_tangent = float3(state::transform_vector(::state::coordinate_internal,::state::coordinate_world,::state::texture_tangent_u(0))) ) @@ -2078,7 +2078,7 @@ export float3 mx_normalmap( { float3 v = mxp_in * 2.0 - 1.0; float3 binormal = ::math::normalize(::math::cross(mxp_normal, mxp_tangent)); - return ::math::normalize(mxp_tangent * v.x * mxp_scale + binormal * v.y * mxp_scale + mxp_normal * v.z); + return ::math::normalize(mxp_tangent * v.x * mxp_scale.x + binormal * v.y * mxp_scale.y + mxp_normal * v.z); } else { @@ -2087,6 +2087,23 @@ export float3 mx_normalmap( } } +export float3 mx_normalmap_float( + float3 mxp_in = float3(0.5, 0.5, 1.0), + uniform string mxp_space = string("tangent") + [[ + anno::description("Enumeration {tangent, object}.") + ]], + float mxp_scale = float(1.0), + float3 mxp_normal = float3(::state::transform_normal(::state::coordinate_internal,::state::coordinate_world,::state::normal())), + float3 mxp_tangent = float3(state::transform_vector(::state::coordinate_internal,::state::coordinate_world,::state::texture_tangent_u(0))) +) + [[ + anno::description("Node Group: math") + ]] +{ + return mx_normalmap_vector2(mxp_in, mxp_space, float2(mxp_scale, mxp_scale), mxp_normal, mxp_tangent); +} + export float3x3 mx_transpose_matrix33( float3x3 mxp_in = float3x3(1.0,0.0,0.0, 0.0,1.0,0.0, 0.0,0.0,1.0) ) diff --git a/source/MaterialXGenMsl/MslResourceBindingContext.cpp b/source/MaterialXGenMsl/MslResourceBindingContext.cpp index 7b61f41854..5d6cbab6f9 100644 --- a/source/MaterialXGenMsl/MslResourceBindingContext.cpp +++ b/source/MaterialXGenMsl/MslResourceBindingContext.cpp @@ -32,7 +32,7 @@ void MslResourceBindingContext::emitDirectives(GenContext&, ShaderStage&) void MslResourceBindingContext::emitResourceBindings(GenContext& context, const VariableBlock& uniforms, ShaderStage& stage) { - ShaderGenerator& generator = context.getShaderGenerator(); + const ShaderGenerator& generator = context.getShaderGenerator(); // First, emit all value uniforms in a block with single layout binding bool hasValueUniforms = false; @@ -69,7 +69,7 @@ void MslResourceBindingContext::emitStructuredResourceBindings(GenContext& conte ShaderStage& stage, const std::string& structInstanceName, const std::string& arraySuffix) { - ShaderGenerator& generator = context.getShaderGenerator(); + const ShaderGenerator& generator = context.getShaderGenerator(); const size_t baseAlignment = 16; // Values are adjusted based on diff --git a/source/MaterialXGenMsl/MslShaderGenerator.cpp b/source/MaterialXGenMsl/MslShaderGenerator.cpp index 7a2461a5a8..c6f8ed979f 100644 --- a/source/MaterialXGenMsl/MslShaderGenerator.cpp +++ b/source/MaterialXGenMsl/MslShaderGenerator.cpp @@ -6,15 +6,8 @@ #include #include -#include -#include -#include -#include #include #include -#include -#include -#include #include #include #include @@ -33,6 +26,13 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -169,13 +169,13 @@ MslShaderGenerator::MslShaderGenerator() : registerImplementation(elementNames, CombineNode::create); // - registerImplementation("IM_position_vector3_" + MslShaderGenerator::TARGET, PositionNodeMsl::create); + registerImplementation("IM_position_vector3_" + MslShaderGenerator::TARGET, HwPositionNode::create); // - registerImplementation("IM_normal_vector3_" + MslShaderGenerator::TARGET, NormalNodeMsl::create); + registerImplementation("IM_normal_vector3_" + MslShaderGenerator::TARGET, HwNormalNode::create); // - registerImplementation("IM_tangent_vector3_" + MslShaderGenerator::TARGET, TangentNodeMsl::create); + registerImplementation("IM_tangent_vector3_" + MslShaderGenerator::TARGET, HwTangentNode::create); // - registerImplementation("IM_bitangent_vector3_" + MslShaderGenerator::TARGET, BitangentNodeMsl::create); + registerImplementation("IM_bitangent_vector3_" + MslShaderGenerator::TARGET, HwBitangentNode::create); // registerImplementation("IM_texcoord_vector2_" + MslShaderGenerator::TARGET, HwTexCoordNode::create); registerImplementation("IM_texcoord_vector3_" + MslShaderGenerator::TARGET, HwTexCoordNode::create); @@ -198,11 +198,11 @@ MslShaderGenerator::MslShaderGenerator() : registerImplementation("IM_geompropvalue_string_" + MslShaderGenerator::TARGET, GeomPropValueNodeMslAsUniform::create); // - registerImplementation("IM_frame_float_" + MslShaderGenerator::TARGET, FrameNodeMsl::create); + registerImplementation("IM_frame_float_" + MslShaderGenerator::TARGET, HwFrameNode::create); // - registerImplementation("IM_time_float_" + MslShaderGenerator::TARGET, TimeNodeMsl::create); + registerImplementation("IM_time_float_" + MslShaderGenerator::TARGET, HwTimeNode::create); // - registerImplementation("IM_viewdirection_vector3_" + MslShaderGenerator::TARGET, ViewDirectionNodeMsl::create); + registerImplementation("IM_viewdirection_vector3_" + MslShaderGenerator::TARGET, HwViewDirectionNode::create); // registerImplementation("IM_surface_" + MslShaderGenerator::TARGET, SurfaceNodeMsl::create); @@ -604,7 +604,7 @@ void MslShaderGenerator::emitGlobalVariables(GenContext& context, bool hasUniforms = false; for (const ShaderPort* uniform : uniforms.getVariableOrder()) { - if (uniform->getType() == Type::FILENAME) + if (*uniform->getType() == *Type::FILENAME) { emitString(separator, stage); emitString("texture2d " + TEXTURE_NAME(uniform->getVariable()), stage); @@ -1282,11 +1282,11 @@ void MslShaderGenerator::toVec4(const TypeDesc* type, string& variable) { variable = "float4(" + variable + ", 0.0, 1.0)"; } - else if (type == Type::FLOAT || type == Type::INTEGER) + else if (*type == *Type::FLOAT || *type == *Type::INTEGER) { variable = "float4(" + variable + ", " + variable + ", " + variable + ", 1.0)"; } - else if (type == Type::BSDF || type == Type::EDF) + else if (*type == *Type::BSDF || *type == *Type::EDF) { variable = "float4(" + variable + ", 1.0)"; } @@ -1302,7 +1302,7 @@ void MslShaderGenerator::emitVariableDeclaration(const ShaderPort* variable, con bool assignValue) const { // A file texture input needs special handling on MSL - if (variable->getType() == Type::FILENAME) + if (*variable->getType() == *Type::FILENAME) { // Samplers must always be uniforms string str = qualifier.empty() ? EMPTY_STRING : qualifier + " "; @@ -1327,7 +1327,7 @@ void MslShaderGenerator::emitVariableDeclaration(const ShaderPort* variable, con // Varying parameters of type int must be flat qualified on output from vertex stage and // input to pixel stage. The only way to get these is with geompropvalue_integer nodes. - if (qualifier.empty() && variable->getType() == Type::INTEGER && !assignValue && variable->getName().rfind(HW::T_IN_GEOMPROP, 0) == 0) + if (qualifier.empty() && *variable->getType() == *Type::INTEGER && !assignValue && variable->getName().rfind(HW::T_IN_GEOMPROP, 0) == 0) { str += "[[ " + MslSyntax::FLAT_QUALIFIER + " ]]"; } @@ -1372,7 +1372,7 @@ ShaderNodeImplPtr MslShaderGenerator::getImplementation(const NodeDef& nodedef, if (implElement->isA()) { // Use a compound implementation. - if (outputType == Type::LIGHTSHADER) + if (*outputType == *Type::LIGHTSHADER) { impl = LightCompoundNodeMsl::create(); } @@ -1415,31 +1415,9 @@ ShaderNodeImplPtr MslShaderGenerator::getImplementation(const NodeDef& nodedef, return impl; } -const string MslImplementation::SPACE = "space"; -const string MslImplementation::INDEX = "index"; -const string MslImplementation::GEOMPROP = "geomprop"; - -namespace -{ - -// List name of inputs that are not to be editable and -// published as shader uniforms in MSL. -const std::set IMMUTABLE_INPUTS = -{ - // Geometric node inputs are immutable since a shader needs regeneration if they change. - "index", "space", "attrname" -}; - -} // namespace - const string& MslImplementation::getTarget() const { return MslShaderGenerator::TARGET; } -bool MslImplementation::isEditable(const ShaderInput& input) const -{ - return IMMUTABLE_INPUTS.count(input.getName()) == 0; -} - MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenMsl/MslShaderGenerator.h b/source/MaterialXGenMsl/MslShaderGenerator.h index 21817db735..e9f2981045 100644 --- a/source/MaterialXGenMsl/MslShaderGenerator.h +++ b/source/MaterialXGenMsl/MslShaderGenerator.h @@ -115,30 +115,13 @@ class MX_GENMSL_API MslShaderGenerator : public HwShaderGenerator }; /// Base class for common MSL node implementations -class MX_GENMSL_API MslImplementation : public ShaderNodeImpl +class MX_GENMSL_API MslImplementation : public HwImplementation { public: const string& getTarget() const override; - bool isEditable(const ShaderInput& input) const override; - protected: MslImplementation() { } - - // Integer identifiers for coordinate spaces. - // The order must match the order given for - // the space enum string in stdlib. - enum Space - { - MODEL_SPACE = 0, - OBJECT_SPACE = 1, - WORLD_SPACE = 2 - }; - - /// Internal string constants - static const string SPACE; - static const string INDEX; - static const string GEOMPROP; }; MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenMsl/MslSyntax.cpp b/source/MaterialXGenMsl/MslSyntax.cpp index a1e2d6bb83..a4ec46e0c0 100644 --- a/source/MaterialXGenMsl/MslSyntax.cpp +++ b/source/MaterialXGenMsl/MslSyntax.cpp @@ -352,7 +352,7 @@ bool MslSyntax::remapEnumeration(const string& value, const TypeDesc* type, cons // Don't convert already supported types // or filenames and arrays. if (typeSupported(type) || - type == Type::FILENAME || (type && type->isArray())) + *type == *Type::FILENAME || (type && type->isArray())) { return false; } diff --git a/source/MaterialXGenMsl/Nodes/BitangentNodeMsl.h b/source/MaterialXGenMsl/Nodes/BitangentNodeMsl.h deleted file mode 100644 index 7239bb36d4..0000000000 --- a/source/MaterialXGenMsl/Nodes/BitangentNodeMsl.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_BITANGENTNODEMSL_H -#define MATERIALX_BITANGENTNODEMSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// Bitangent node implementation for MSL -class MX_GENMSL_API BitangentNodeMsl : public MslImplementation -{ - public: - static ShaderNodeImplPtr create(); - - void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; - - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenMsl/Nodes/GeomColorNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/GeomColorNodeMsl.cpp index 3845e2ae76..c540960906 100644 --- a/source/MaterialXGenMsl/Nodes/GeomColorNodeMsl.cpp +++ b/source/MaterialXGenMsl/Nodes/GeomColorNodeMsl.cpp @@ -49,11 +49,11 @@ void GeomColorNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& cont DEFINE_SHADER_STAGE(stage, Stage::PIXEL) { string suffix = ""; - if (output->getType() == Type::FLOAT) + if (*output->getType() == *Type::FLOAT) { suffix = ".r"; } - else if (output->getType() == Type::COLOR3) + else if (*output->getType() == *Type::COLOR3) { suffix = ".rgb"; } diff --git a/source/MaterialXGenMsl/Nodes/HeightToNormalNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/HeightToNormalNodeMsl.cpp index 7282e5e9df..2f07e55dfd 100644 --- a/source/MaterialXGenMsl/Nodes/HeightToNormalNodeMsl.cpp +++ b/source/MaterialXGenMsl/Nodes/HeightToNormalNodeMsl.cpp @@ -54,7 +54,7 @@ void HeightToNormalNodeMsl::computeSampleOffsetStrings(const string& sampleSizeN bool HeightToNormalNodeMsl::acceptsInputType(const TypeDesc* type) const { // Only support inputs which are float scalar - return (type == Type::FLOAT && type->isScalar()); + return (*type == *Type::FLOAT && type->isScalar()); } void HeightToNormalNodeMsl::emitFunctionDefinition(const ShaderNode&, GenContext& context, ShaderStage& stage) const diff --git a/source/MaterialXGenMsl/Nodes/NormalNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/NormalNodeMsl.cpp deleted file mode 100644 index 6250290960..0000000000 --- a/source/MaterialXGenMsl/Nodes/NormalNodeMsl.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr NormalNodeMsl::create() -{ - return std::make_shared(); -} - -void NormalNodeMsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const -{ - ShaderStage& vs = shader.getStage(Stage::VERTEX); - ShaderStage& ps = shader.getStage(Stage::PIXEL); - - addStageInput(HW::VERTEX_INPUTS, Type::VECTOR3, HW::T_IN_NORMAL, vs); - - const ShaderInput* spaceInput = node.getInput(SPACE); - const int space = spaceInput ? spaceInput->getValue()->asA() : OBJECT_SPACE; - if (space == WORLD_SPACE) - { - addStageUniform(HW::PRIVATE_UNIFORMS, Type::MATRIX44, HW::T_WORLD_INVERSE_TRANSPOSE_MATRIX, vs); - addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_NORMAL_WORLD, vs, ps); - } - else - { - addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_NORMAL_OBJECT, vs, ps); - } -} - -void NormalNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - const MslShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); - - const ShaderInput* spaceInput = node.getInput(SPACE); - const int space = spaceInput ? spaceInput->getValue()->asA() : OBJECT_SPACE; - - DEFINE_SHADER_STAGE(stage, Stage::VERTEX) - { - VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - if (space == WORLD_SPACE) - { - ShaderPort* normal = vertexData[HW::T_NORMAL_WORLD]; - if (!normal->isEmitted()) - { - normal->setEmitted(); - shadergen.emitLine(prefix + normal->getVariable() + " = normalize((" + HW::T_WORLD_INVERSE_TRANSPOSE_MATRIX + " * float4(" + HW::T_IN_NORMAL + ", 0.0)).xyz)", stage); - } - } - else - { - ShaderPort* normal = vertexData[HW::T_NORMAL_OBJECT]; - if (!normal->isEmitted()) - { - normal->setEmitted(); - shadergen.emitLine(prefix + normal->getVariable() + " = " + HW::T_IN_NORMAL, stage); - } - } - } - - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - shadergen.emitLineBegin(stage); - shadergen.emitOutput(node.getOutput(), true, false, context, stage); - if (space == WORLD_SPACE) - { - const ShaderPort* normal = vertexData[HW::T_NORMAL_WORLD]; - shadergen.emitString(" = normalize(" + prefix + normal->getVariable() + ")", stage); - } - else - { - const ShaderPort* normal = vertexData[HW::T_NORMAL_OBJECT]; - shadergen.emitString(" = normalize(" + prefix + normal->getVariable() + ")", stage); - } - shadergen.emitLineEnd(stage); - } -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenMsl/Nodes/NormalNodeMsl.h b/source/MaterialXGenMsl/Nodes/NormalNodeMsl.h deleted file mode 100644 index 7248613a74..0000000000 --- a/source/MaterialXGenMsl/Nodes/NormalNodeMsl.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_NORMALNODEMSL_H -#define MATERIALX_NORMALNODEMSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// Normal node implementation for MSL -class MX_GENMSL_API NormalNodeMsl : public MslImplementation -{ - public: - static ShaderNodeImplPtr create(); - - void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; - - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenMsl/Nodes/PositionNodeMsl.h b/source/MaterialXGenMsl/Nodes/PositionNodeMsl.h deleted file mode 100644 index 1dada988be..0000000000 --- a/source/MaterialXGenMsl/Nodes/PositionNodeMsl.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_POSITIONNODEMSL_H -#define MATERIALX_POSITIONNODEMSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// Position node implementation for MSL -class MX_GENMSL_API PositionNodeMsl : public MslImplementation -{ - public: - static ShaderNodeImplPtr create(); - - void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; - - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenMsl/Nodes/SurfaceNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/SurfaceNodeMsl.cpp index c7fb7745b7..bd0cd91fb1 100644 --- a/source/MaterialXGenMsl/Nodes/SurfaceNodeMsl.cpp +++ b/source/MaterialXGenMsl/Nodes/SurfaceNodeMsl.cpp @@ -45,8 +45,8 @@ void SurfaceNodeMsl::createVariables(const ShaderNode&, GenContext& context, Sha { // TODO: // The surface shader needs position, normal, view position and light sources. We should solve this by adding some - // dependency mechanism so this implementation can be set to depend on the PositionNodeMsl, NormalNodeMsl - // ViewDirectionNodeMsl and LightNodeMsl nodes instead? This is where the MaterialX attribute "internalgeomprops" + // dependency mechanism so this implementation can be set to depend on the HwPositionNode, HwNormalNode + // HwViewDirectionNode and LightNodeMsl nodes instead? This is where the MaterialX attribute "internalgeomprops" // is needed. // ShaderStage& vs = shader.getStage(Stage::VERTEX); diff --git a/source/MaterialXGenMsl/Nodes/SurfaceShaderNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/SurfaceShaderNodeMsl.cpp index a579c46f1b..a09796a557 100644 --- a/source/MaterialXGenMsl/Nodes/SurfaceShaderNodeMsl.cpp +++ b/source/MaterialXGenMsl/Nodes/SurfaceShaderNodeMsl.cpp @@ -24,8 +24,8 @@ void SurfaceShaderNodeMsl::createVariables(const ShaderNode&, GenContext& contex { // TODO: // The surface shader needs position, view position and light sources. We should solve this by adding some - // dependency mechanism so this implementation can be set to depend on the PositionNodeMsl, - // ViewDirectionNodeMsl and LightNodeMsl nodes instead? This is where the MaterialX attribute "internalgeomprops" + // dependency mechanism so this implementation can be set to depend on the HwPositionNode, + // HwViewDirectionNode and LightNodeMsl nodes instead? This is where the MaterialX attribute "internalgeomprops" // is needed. // ShaderStage& vs = shader.getStage(Stage::VERTEX); diff --git a/source/MaterialXGenMsl/Nodes/TangentNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/TangentNodeMsl.cpp deleted file mode 100644 index 5e557e4e30..0000000000 --- a/source/MaterialXGenMsl/Nodes/TangentNodeMsl.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#include - -#include - -MATERIALX_NAMESPACE_BEGIN - -ShaderNodeImplPtr TangentNodeMsl::create() -{ - return std::make_shared(); -} - -void TangentNodeMsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const -{ - ShaderStage& vs = shader.getStage(Stage::VERTEX); - ShaderStage& ps = shader.getStage(Stage::PIXEL); - - addStageInput(HW::VERTEX_INPUTS, Type::VECTOR3, HW::T_IN_TANGENT, vs); - - const ShaderInput* spaceInput = node.getInput(SPACE); - const int space = spaceInput ? spaceInput->getValue()->asA() : OBJECT_SPACE; - if (space == WORLD_SPACE) - { - addStageUniform(HW::PRIVATE_UNIFORMS, Type::MATRIX44, HW::T_WORLD_MATRIX, vs); - addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_TANGENT_WORLD, vs, ps); - } - else - { - addStageConnector(HW::VERTEX_DATA, Type::VECTOR3, HW::T_TANGENT_OBJECT, vs, ps); - } -} - -void TangentNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const -{ - const MslShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); - - const ShaderInput* spaceInput = node.getInput(SPACE); - const int space = spaceInput ? spaceInput->getValue()->asA() : OBJECT_SPACE; - - DEFINE_SHADER_STAGE(stage, Stage::VERTEX) - { - VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - if (space == WORLD_SPACE) - { - ShaderPort* tangent = vertexData[HW::T_TANGENT_WORLD]; - if (!tangent->isEmitted()) - { - tangent->setEmitted(); - shadergen.emitLine(prefix + tangent->getVariable() + " = normalize((" + HW::T_WORLD_MATRIX + " * float4(" + HW::T_IN_TANGENT + ", 0.0)).xyz)", stage); - } - } - else - { - ShaderPort* tangent = vertexData[HW::T_TANGENT_OBJECT]; - if (!tangent->isEmitted()) - { - tangent->setEmitted(); - shadergen.emitLine(prefix + tangent->getVariable() + " = " + HW::T_IN_TANGENT, stage); - } - } - } - - DEFINE_SHADER_STAGE(stage, Stage::PIXEL) - { - VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA); - const string prefix = shadergen.getVertexDataPrefix(vertexData); - shadergen.emitLineBegin(stage); - shadergen.emitOutput(node.getOutput(), true, false, context, stage); - if (space == WORLD_SPACE) - { - const ShaderPort* tangent = vertexData[HW::T_TANGENT_WORLD]; - shadergen.emitString(" = normalize(" + prefix + tangent->getVariable() + ")", stage); - } - else - { - const ShaderPort* tangent = vertexData[HW::T_TANGENT_OBJECT]; - shadergen.emitString(" = normalize(" + prefix + tangent->getVariable() + ")", stage); - } - shadergen.emitLineEnd(stage); - } -} - -MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenMsl/Nodes/TangentNodeMsl.h b/source/MaterialXGenMsl/Nodes/TangentNodeMsl.h deleted file mode 100644 index 42e2c7ef7c..0000000000 --- a/source/MaterialXGenMsl/Nodes/TangentNodeMsl.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_TANGENTNODEMSL_H -#define MATERIALX_TANGENTNODEMSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// Tangent node implementation for MSL -class MX_GENMSL_API TangentNodeMsl : public MslImplementation -{ - public: - static ShaderNodeImplPtr create(); - - void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; - - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenMsl/Nodes/TimeNodeMsl.h b/source/MaterialXGenMsl/Nodes/TimeNodeMsl.h deleted file mode 100644 index 07c505a082..0000000000 --- a/source/MaterialXGenMsl/Nodes/TimeNodeMsl.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_TIMENODEMSL_H -#define MATERIALX_TIMENODEMSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// Time node implementation for MSL -class MX_GENMSL_API TimeNodeMsl : public MslImplementation -{ - public: - static ShaderNodeImplPtr create(); - - void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; - - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenMsl/Nodes/ViewDirectionNodeMsl.h b/source/MaterialXGenMsl/Nodes/ViewDirectionNodeMsl.h deleted file mode 100644 index be7a40108a..0000000000 --- a/source/MaterialXGenMsl/Nodes/ViewDirectionNodeMsl.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright Contributors to the MaterialX Project -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MATERIALX_VIEWDIRECTIONNODEMSL_H -#define MATERIALX_VIEWDIRECTIONNODEMSL_H - -#include - -MATERIALX_NAMESPACE_BEGIN - -/// ViewDirection node implementation for MSL -class MX_GENMSL_API ViewDirectionNodeMsl : public MslImplementation -{ - public: - static ShaderNodeImplPtr create(); - - void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; - - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; -}; - -MATERIALX_NAMESPACE_END - -#endif diff --git a/source/MaterialXGenOsl/Nodes/ClosureLayerNodeOsl.cpp b/source/MaterialXGenOsl/Nodes/ClosureLayerNodeOsl.cpp index 7c3f9d460c..31f245e9e6 100644 --- a/source/MaterialXGenOsl/Nodes/ClosureLayerNodeOsl.cpp +++ b/source/MaterialXGenOsl/Nodes/ClosureLayerNodeOsl.cpp @@ -92,7 +92,7 @@ void ClosureLayerNodeOsl::emitFunctionCall(const ShaderNode& _node, GenContext& // Calculate the layering result. emitOutputVariables(node, context, stage); - if (base->getOutput()->getType() == Type::VDF) + if (*base->getOutput()->getType() == *Type::VDF) { // Combining a surface closure with a volumetric closure is simply done with the add operator in OSL. shadergen.emitLine(output->getVariable() + ".response = " + topResult + ".response + " + baseResult, stage); diff --git a/source/MaterialXGenOsl/OslShaderGenerator.cpp b/source/MaterialXGenOsl/OslShaderGenerator.cpp index f16770174b..ff9f5b8a8e 100644 --- a/source/MaterialXGenOsl/OslShaderGenerator.cpp +++ b/source/MaterialXGenOsl/OslShaderGenerator.cpp @@ -196,11 +196,11 @@ ShaderPtr OslShaderGenerator::generate(const string& name, ElementPtr element, G // Emit shader type, determined from the first // output if there are multiple outputs. const ShaderGraphOutputSocket* outputSocket0 = graph.getOutputSocket(0); - if (outputSocket0->getType() == Type::SURFACESHADER) + if (*outputSocket0->getType() == *Type::SURFACESHADER) { emitString("surface ", stage); } - else if (outputSocket0->getType() == Type::VOLUMESHADER) + else if (*outputSocket0->getType() == *Type::VOLUMESHADER) { emitString("volume ", stage); } @@ -250,10 +250,10 @@ ShaderPtr OslShaderGenerator::generate(const string& name, ElementPtr element, G const VariableBlock& outputs = stage.getOutputBlock(OSL::OUTPUTS); const ShaderPort* singleOutput = outputs.size() == 1 ? outputs[0] : NULL; - const bool isSurfaceShaderOutput = singleOutput && singleOutput->getType() == Type::SURFACESHADER; + const bool isSurfaceShaderOutput = singleOutput && *singleOutput->getType() == *Type::SURFACESHADER; #ifdef MATERIALX_OSL_LEGACY_CLOSURES - const bool isBsdfOutput = singleOutput && singleOutput->getType() == Type::BSDF; + const bool isBsdfOutput = singleOutput && *singleOutput->getType() == *Type::BSDF; #endif if (isSurfaceShaderOutput) @@ -301,7 +301,7 @@ ShaderPtr OslShaderGenerator::generate(const string& name, ElementPtr element, G for (size_t i = 0; i < inputs.size(); ++i) { ShaderPort* input = inputs[i]; - if (input->getType() == Type::FILENAME) + if (*input->getType() == *Type::FILENAME) { // Construct the textureresource variable. const string newVariableName = input->getVariable() + "_"; @@ -529,7 +529,7 @@ void OslShaderGenerator::emitShaderInputs(const VariableBlock& inputs, ShaderSta const ShaderPort* input = inputs[i]; const string& type = _syntax->getTypeName(input->getType()); - if (input->getType() == Type::FILENAME) + if (*input->getType() == *Type::FILENAME) { // Shader inputs of type 'filename' (textures) need special handling. // In OSL codegen a 'filename' is translated to the custom type 'textureresource', @@ -651,7 +651,7 @@ void OslShaderGenerator::emitMetadata(const ShaderPort* port, ShaderStage& stage { emitLineEnd(stage, false); emitScopeBegin(stage, Syntax::DOUBLE_SQUARE_BRACKETS); - for (auto line : metadataLines) + for (const auto& line : metadataLines) { emitLine(line, stage, false); } diff --git a/source/MaterialXGenShader/HwShaderGenerator.cpp b/source/MaterialXGenShader/HwShaderGenerator.cpp index 6ba94d1280..693e95da7c 100644 --- a/source/MaterialXGenShader/HwShaderGenerator.cpp +++ b/source/MaterialXGenShader/HwShaderGenerator.cpp @@ -12,6 +12,24 @@ MATERIALX_NAMESPACE_BEGIN +const string HwImplementation::SPACE = "space"; +const string HwImplementation::INDEX = "index"; +const string HwImplementation::GEOMPROP = "geomprop"; + +namespace +{ + +// When node inputs with these names are modified, we assume the +// associated HW shader must be recompiled. +const StringSet IMMUTABLE_INPUTS = +{ + "index", + "space", + "attrname" +}; + +} // anonymous namespace + namespace HW { @@ -439,7 +457,7 @@ ShaderPtr HwShaderGenerator::createShader(const string& name, ElementPtr element { for (ShaderInput* input : node->getInputs()) { - if (!input->getConnection() && input->getType() == Type::FILENAME) + if (!input->getConnection() && *input->getType() == *Type::FILENAME) { // Create the uniform using the filename type to make this uniform into a texture sampler. ShaderPort* filename = psPublicUniforms->add(Type::FILENAME, input->getVariable(), input->getValue()); @@ -619,4 +637,9 @@ void HwShaderGenerator::addStageLightingUniforms(GenContext& context, ShaderStag } } +bool HwImplementation::isEditable(const ShaderInput& input) const +{ + return IMMUTABLE_INPUTS.count(input.getName()) == 0; +} + MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenShader/HwShaderGenerator.h b/source/MaterialXGenShader/HwShaderGenerator.h index f839ac56bd..f93a8983ca 100644 --- a/source/MaterialXGenShader/HwShaderGenerator.h +++ b/source/MaterialXGenShader/HwShaderGenerator.h @@ -340,6 +340,31 @@ class MX_GENSHADER_API HwShaderGenerator : public ShaderGenerator mutable ClosureContext _defEmission; }; +/// @class HwShaderGenerator +/// Base class for HW node implementations. +class MX_GENSHADER_API HwImplementation : public ShaderNodeImpl +{ + public: + bool isEditable(const ShaderInput& input) const override; + + protected: + HwImplementation() { } + + // Integer identifiers for coordinate spaces. + // The order must match the order given for the space enum string in stdlib. + enum Space + { + MODEL_SPACE = 0, + OBJECT_SPACE = 1, + WORLD_SPACE = 2 + }; + + /// Internal string constants + static const string SPACE; + static const string INDEX; + static const string GEOMPROP; +}; + /// @class HwResourceBindingContext /// Class representing a context for resource binding for hardware resources. class MX_GENSHADER_API HwResourceBindingContext : public GenUserData diff --git a/source/MaterialXGenShader/Nodes/BlurNode.cpp b/source/MaterialXGenShader/Nodes/BlurNode.cpp index bd30b40715..56f4de85a9 100644 --- a/source/MaterialXGenShader/Nodes/BlurNode.cpp +++ b/source/MaterialXGenShader/Nodes/BlurNode.cpp @@ -49,7 +49,7 @@ void BlurNode::computeSampleOffsetStrings(const string& sampleSizeName, const st bool BlurNode::acceptsInputType(const TypeDesc* type) const { // Float 1-4 is acceptable as input - return ((type == Type::FLOAT && type->isScalar()) || + return ((*type == *Type::FLOAT && type->isScalar()) || type->isFloat2() || type->isFloat3() || type->isFloat4()); } diff --git a/source/MaterialXGenShader/Nodes/ClosureAddNode.cpp b/source/MaterialXGenShader/Nodes/ClosureAddNode.cpp index 34883c6c36..f401b577d8 100644 --- a/source/MaterialXGenShader/Nodes/ClosureAddNode.cpp +++ b/source/MaterialXGenShader/Nodes/ClosureAddNode.cpp @@ -59,13 +59,13 @@ void ClosureAddNode::emitFunctionCall(const ShaderNode& _node, GenContext& conte const string in2Result = shadergen.getUpstreamResult(in2, context); ShaderOutput* output = node.getOutput(); - if (output->getType() == Type::BSDF) + if (*output->getType() == *Type::BSDF) { emitOutputVariables(node, context, stage); shadergen.emitLine(output->getVariable() + ".response = " + in1Result + ".response + " + in2Result + ".response", stage); shadergen.emitLine(output->getVariable() + ".throughput = " + in1Result + ".throughput * " + in2Result + ".throughput", stage); } - else if (output->getType() == Type::EDF) + else if (*output->getType() == *Type::EDF) { shadergen.emitLine(shadergen.getSyntax().getTypeName(Type::EDF) + " " + output->getVariable() + " = " + in1Result + " + " + in2Result, stage); } diff --git a/source/MaterialXGenShader/Nodes/ClosureCompoundNode.cpp b/source/MaterialXGenShader/Nodes/ClosureCompoundNode.cpp index a5f247926f..1cde95a1a6 100644 --- a/source/MaterialXGenShader/Nodes/ClosureCompoundNode.cpp +++ b/source/MaterialXGenShader/Nodes/ClosureCompoundNode.cpp @@ -171,7 +171,7 @@ void ClosureCompoundNode::emitFunctionCall(const ShaderNode& node, GenContext& c // Check if extra parameters has been added for this node. const ClosureContext::ClosureParams* params = cct->getClosureParams(&node); - if (closureType == Type::BSDF && params) + if (*closureType == *Type::BSDF && params) { // Assign the parameters to the BSDF. for (auto it : *params) diff --git a/source/MaterialXGenShader/Nodes/ClosureLayerNode.cpp b/source/MaterialXGenShader/Nodes/ClosureLayerNode.cpp index a2554365c1..2bcc1377d2 100644 --- a/source/MaterialXGenShader/Nodes/ClosureLayerNode.cpp +++ b/source/MaterialXGenShader/Nodes/ClosureLayerNode.cpp @@ -95,7 +95,7 @@ void ClosureLayerNode::emitFunctionCall(const ShaderNode& _node, GenContext& con // Calculate the layering result. emitOutputVariables(node, context, stage); - if (base->getOutput()->getType() == Type::VDF) + if (*(base->getOutput()->getType()) == *Type::VDF) { shadergen.emitLine(output->getVariable() + ".response = " + topResult + ".response * " + baseResult + ".throughput", stage); shadergen.emitLine(output->getVariable() + ".throughput = " + topResult + ".throughput * " + baseResult + ".throughput", stage); diff --git a/source/MaterialXGenShader/Nodes/ClosureMixNode.cpp b/source/MaterialXGenShader/Nodes/ClosureMixNode.cpp index bd314ac7ed..8e5b737698 100644 --- a/source/MaterialXGenShader/Nodes/ClosureMixNode.cpp +++ b/source/MaterialXGenShader/Nodes/ClosureMixNode.cpp @@ -61,13 +61,13 @@ void ClosureMixNode::emitFunctionCall(const ShaderNode& _node, GenContext& conte const string mixResult = shadergen.getUpstreamResult(mix, context); ShaderOutput* output = node.getOutput(); - if (output->getType() == Type::BSDF) + if (*output->getType() == *Type::BSDF) { emitOutputVariables(node, context, stage); shadergen.emitLine(output->getVariable() + ".response = mix(" + bgResult + ".response, " + fgResult + ".response, " + mixResult + ")", stage); shadergen.emitLine(output->getVariable() + ".throughput = mix(" + bgResult + ".throughput, " + fgResult + ".throughput, " + mixResult + ")", stage); } - else if (output->getType() == Type::EDF) + else if (*output->getType() == *Type::EDF) { shadergen.emitLine(shadergen.getSyntax().getTypeName(Type::EDF) + " " + output->getVariable() + " = mix(" + bgResult + ", " + fgResult + ", " + mixResult + ")", stage); } diff --git a/source/MaterialXGenShader/Nodes/ClosureMultiplyNode.cpp b/source/MaterialXGenShader/Nodes/ClosureMultiplyNode.cpp index ac7906e6bb..d582e19ebf 100644 --- a/source/MaterialXGenShader/Nodes/ClosureMultiplyNode.cpp +++ b/source/MaterialXGenShader/Nodes/ClosureMultiplyNode.cpp @@ -50,7 +50,7 @@ void ClosureMultiplyNode::emitFunctionCall(const ShaderNode& _node, GenContext& const string in2Result = shadergen.getUpstreamResult(in2, context); ShaderOutput* output = node.getOutput(); - if (output->getType() == Type::BSDF) + if (*output->getType() == *Type::BSDF) { const string in2clamped = output->getVariable() + "_in2_clamped"; shadergen.emitLine(syntax.getTypeName(in2->getType()) + " " + in2clamped + " = clamp(" + in2Result + ", 0.0, 1.0)", stage); @@ -59,7 +59,7 @@ void ClosureMultiplyNode::emitFunctionCall(const ShaderNode& _node, GenContext& shadergen.emitLine(output->getVariable() + ".response = " + in1Result + ".response * " + in2clamped, stage); shadergen.emitLine(output->getVariable() + ".throughput = " + in1Result + ".throughput * " + in2clamped, stage); } - else if (output->getType() == Type::EDF) + else if (*output->getType() == *Type::EDF) { shadergen.emitLine(shadergen.getSyntax().getTypeName(Type::EDF) + " " + output->getVariable() + " = " + in1Result + " * " + in2Result, stage); } diff --git a/source/MaterialXGenShader/Nodes/ClosureSourceCodeNode.cpp b/source/MaterialXGenShader/Nodes/ClosureSourceCodeNode.cpp index ec5a9aeabf..a1a53b3bcd 100644 --- a/source/MaterialXGenShader/Nodes/ClosureSourceCodeNode.cpp +++ b/source/MaterialXGenShader/Nodes/ClosureSourceCodeNode.cpp @@ -42,7 +42,7 @@ void ClosureSourceCodeNode::emitFunctionCall(const ShaderNode& node, GenContext& // Check if extra parameters has been added for this node. const TypeDesc* closureType = output->getType(); const ClosureContext::ClosureParams* params = cct->getClosureParams(&node); - if (closureType == Type::BSDF && params) + if (*closureType == *Type::BSDF && params) { // Assign the parameters to the BSDF. for (auto it : *params) diff --git a/source/MaterialXGenShader/Nodes/CombineNode.cpp b/source/MaterialXGenShader/Nodes/CombineNode.cpp index 0237830c52..d7b2eb6e22 100644 --- a/source/MaterialXGenShader/Nodes/CombineNode.cpp +++ b/source/MaterialXGenShader/Nodes/CombineNode.cpp @@ -34,7 +34,7 @@ void CombineNode::emitFunctionCall(const ShaderNode& node, GenContext& context, // components to use for constructing the new value. // StringVec valueComponents; - if (in1->getType() == Type::FLOAT) + if (*in1->getType() == *Type::FLOAT) { // Get the components of the input values. const size_t numInputs = node.numInputs(); @@ -45,7 +45,7 @@ void CombineNode::emitFunctionCall(const ShaderNode& node, GenContext& context, valueComponents[i] = shadergen.getUpstreamResult(input, context); } } - else if (in1->getType() == Type::COLOR3 || in1->getType() == Type::VECTOR3) + else if (*in1->getType() == *Type::COLOR3 || *in1->getType() == *Type::VECTOR3) { const ShaderInput* in2 = node.getInput(1); if (!in2 || in2->getType() != Type::FLOAT) @@ -84,7 +84,7 @@ void CombineNode::emitFunctionCall(const ShaderNode& node, GenContext& context, // Get component from in2 valueComponents[memberSize] = shadergen.getUpstreamResult(in2, context); } - else if (in1->getType() == Type::VECTOR2) + else if (*in1->getType() == *Type::VECTOR2) { const ShaderInput* in2 = node.getInput(1); if (!in2 || (in2->getType() != Type::VECTOR2)) diff --git a/source/MaterialXGenShader/Nodes/ConvolutionNode.cpp b/source/MaterialXGenShader/Nodes/ConvolutionNode.cpp index 45992e013f..892920569e 100644 --- a/source/MaterialXGenShader/Nodes/ConvolutionNode.cpp +++ b/source/MaterialXGenShader/Nodes/ConvolutionNode.cpp @@ -94,12 +94,12 @@ const ShaderInput* ConvolutionNode::getSamplingInput(const ShaderNode& node) con if (node.hasClassification(ShaderNode::Classification::SAMPLE2D)) { const ShaderInput* input = node.getInput(SAMPLE2D_INPUT); - return input->getType() == Type::VECTOR2 ? input : nullptr; + return *input->getType() == *Type::VECTOR2 ? input : nullptr; } else if (node.hasClassification(ShaderNode::Classification::SAMPLE3D)) { const ShaderInput* input = node.getInput(SAMPLE3D_INPUT); - return input->getType() == Type::VECTOR3 ? input : nullptr; + return *input->getType() == *Type::VECTOR3 ? input : nullptr; } return nullptr; } diff --git a/source/MaterialXGenMsl/Nodes/BitangentNodeMsl.cpp b/source/MaterialXGenShader/Nodes/HwBitangentNode.cpp similarity index 91% rename from source/MaterialXGenMsl/Nodes/BitangentNodeMsl.cpp rename to source/MaterialXGenShader/Nodes/HwBitangentNode.cpp index 97ca079d35..83c43a3398 100644 --- a/source/MaterialXGenMsl/Nodes/BitangentNodeMsl.cpp +++ b/source/MaterialXGenShader/Nodes/HwBitangentNode.cpp @@ -3,18 +3,18 @@ // SPDX-License-Identifier: Apache-2.0 // -#include +#include #include MATERIALX_NAMESPACE_BEGIN -ShaderNodeImplPtr BitangentNodeMsl::create() +ShaderNodeImplPtr HwBitangentNode::create() { - return std::make_shared(); + return std::make_shared(); } -void BitangentNodeMsl::createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const +void HwBitangentNode::createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const { const GenOptions& options = context.getOptions(); @@ -51,9 +51,9 @@ void BitangentNodeMsl::createVariables(const ShaderNode& node, GenContext& conte } } -void BitangentNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const +void HwBitangentNode::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const { - const MslShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); + const HwShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); const GenOptions& options = context.getOptions(); const ShaderInput* spaceInput = node.getInput(SPACE); diff --git a/source/MaterialXGenGlsl/Nodes/NormalNodeGlsl.h b/source/MaterialXGenShader/Nodes/HwBitangentNode.h similarity index 63% rename from source/MaterialXGenGlsl/Nodes/NormalNodeGlsl.h rename to source/MaterialXGenShader/Nodes/HwBitangentNode.h index acb4d5085d..a8bfa0bf11 100644 --- a/source/MaterialXGenGlsl/Nodes/NormalNodeGlsl.h +++ b/source/MaterialXGenShader/Nodes/HwBitangentNode.h @@ -3,15 +3,15 @@ // SPDX-License-Identifier: Apache-2.0 // -#ifndef MATERIALX_NORMALNODEGLSL_H -#define MATERIALX_NORMALNODEGLSL_H +#ifndef MATERIALX_HWBITANGENTNODE_H +#define MATERIALX_HWBITANGENTNODE_H -#include +#include MATERIALX_NAMESPACE_BEGIN -/// Normal node implementation for GLSL -class MX_GENGLSL_API NormalNodeGlsl : public GlslImplementation +/// Bitangent node implementation for hardware languages +class MX_GENSHADER_API HwBitangentNode : public HwImplementation { public: static ShaderNodeImplPtr create(); diff --git a/source/MaterialXGenMsl/Nodes/FrameNodeMsl.cpp b/source/MaterialXGenShader/Nodes/HwFrameNode.cpp similarity index 67% rename from source/MaterialXGenMsl/Nodes/FrameNodeMsl.cpp rename to source/MaterialXGenShader/Nodes/HwFrameNode.cpp index faac05027a..cd6a3319a8 100644 --- a/source/MaterialXGenMsl/Nodes/FrameNodeMsl.cpp +++ b/source/MaterialXGenShader/Nodes/HwFrameNode.cpp @@ -3,24 +3,24 @@ // SPDX-License-Identifier: Apache-2.0 // -#include +#include #include MATERIALX_NAMESPACE_BEGIN -ShaderNodeImplPtr FrameNodeMsl::create() +ShaderNodeImplPtr HwFrameNode::create() { - return std::make_shared(); + return std::make_shared(); } -void FrameNodeMsl::createVariables(const ShaderNode&, GenContext&, Shader& shader) const +void HwFrameNode::createVariables(const ShaderNode&, GenContext&, Shader& shader) const { ShaderStage& ps = shader.getStage(Stage::PIXEL); addStageUniform(HW::PRIVATE_UNIFORMS, Type::FLOAT, HW::T_FRAME, ps); } -void FrameNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const +void HwFrameNode::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const { DEFINE_SHADER_STAGE(stage, Stage::PIXEL) { diff --git a/source/MaterialXGenGlsl/Nodes/TangentNodeGlsl.h b/source/MaterialXGenShader/Nodes/HwFrameNode.h similarity index 65% rename from source/MaterialXGenGlsl/Nodes/TangentNodeGlsl.h rename to source/MaterialXGenShader/Nodes/HwFrameNode.h index 90a5b3aaad..4487a6a0b9 100644 --- a/source/MaterialXGenGlsl/Nodes/TangentNodeGlsl.h +++ b/source/MaterialXGenShader/Nodes/HwFrameNode.h @@ -3,15 +3,15 @@ // SPDX-License-Identifier: Apache-2.0 // -#ifndef MATERIALX_TANGENTNODEGLSL_H -#define MATERIALX_TANGENTNODEGLSL_H +#ifndef MATERIALX_HWFRAMENODE_H +#define MATERIALX_HWFRAMENODE_H -#include +#include MATERIALX_NAMESPACE_BEGIN -/// Tangent node implementation for GLSL -class MX_GENGLSL_API TangentNodeGlsl : public GlslImplementation +/// Frame node implementation for hardware languages +class MX_GENSHADER_API HwFrameNode : public HwImplementation { public: static ShaderNodeImplPtr create(); diff --git a/source/MaterialXGenGlsl/Nodes/NormalNodeGlsl.cpp b/source/MaterialXGenShader/Nodes/HwNormalNode.cpp similarity index 85% rename from source/MaterialXGenGlsl/Nodes/NormalNodeGlsl.cpp rename to source/MaterialXGenShader/Nodes/HwNormalNode.cpp index d9e27b87df..01234dcb46 100644 --- a/source/MaterialXGenGlsl/Nodes/NormalNodeGlsl.cpp +++ b/source/MaterialXGenShader/Nodes/HwNormalNode.cpp @@ -3,18 +3,18 @@ // SPDX-License-Identifier: Apache-2.0 // -#include +#include #include MATERIALX_NAMESPACE_BEGIN -ShaderNodeImplPtr NormalNodeGlsl::create() +ShaderNodeImplPtr HwNormalNode::create() { - return std::make_shared(); + return std::make_shared(); } -void NormalNodeGlsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const +void HwNormalNode::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const { ShaderStage& vs = shader.getStage(Stage::VERTEX); ShaderStage& ps = shader.getStage(Stage::PIXEL); @@ -34,9 +34,9 @@ void NormalNodeGlsl::createVariables(const ShaderNode& node, GenContext&, Shader } } -void NormalNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const +void HwNormalNode::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const { - const GlslShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); + const HwShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); const ShaderInput* spaceInput = node.getInput(SPACE); const int space = spaceInput ? spaceInput->getValue()->asA() : OBJECT_SPACE; diff --git a/source/MaterialXGenGlsl/Nodes/PositionNodeGlsl.h b/source/MaterialXGenShader/Nodes/HwNormalNode.h similarity index 64% rename from source/MaterialXGenGlsl/Nodes/PositionNodeGlsl.h rename to source/MaterialXGenShader/Nodes/HwNormalNode.h index 95dddbce8e..fb19050600 100644 --- a/source/MaterialXGenGlsl/Nodes/PositionNodeGlsl.h +++ b/source/MaterialXGenShader/Nodes/HwNormalNode.h @@ -3,15 +3,15 @@ // SPDX-License-Identifier: Apache-2.0 // -#ifndef MATERIALX_POSITIONNODEGLSL_H -#define MATERIALX_POSITIONNODEGLSL_H +#ifndef MATERIALX_HWNORMALNODE_H +#define MATERIALX_HWNORMALNODE_H -#include +#include MATERIALX_NAMESPACE_BEGIN -/// Position node implementation for GLSL -class MX_GENGLSL_API PositionNodeGlsl : public GlslImplementation +/// Normal node implementation for hardware languages +class MX_GENSHADER_API HwNormalNode : public HwImplementation { public: static ShaderNodeImplPtr create(); diff --git a/source/MaterialXGenMsl/Nodes/PositionNodeMsl.cpp b/source/MaterialXGenShader/Nodes/HwPositionNode.cpp similarity index 84% rename from source/MaterialXGenMsl/Nodes/PositionNodeMsl.cpp rename to source/MaterialXGenShader/Nodes/HwPositionNode.cpp index 6f45f4364b..df7c11f4e6 100644 --- a/source/MaterialXGenMsl/Nodes/PositionNodeMsl.cpp +++ b/source/MaterialXGenShader/Nodes/HwPositionNode.cpp @@ -3,18 +3,18 @@ // SPDX-License-Identifier: Apache-2.0 // -#include +#include #include MATERIALX_NAMESPACE_BEGIN -ShaderNodeImplPtr PositionNodeMsl::create() +ShaderNodeImplPtr HwPositionNode::create() { - return std::make_shared(); + return std::make_shared(); } -void PositionNodeMsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const +void HwPositionNode::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const { ShaderStage vs = shader.getStage(Stage::VERTEX); ShaderStage ps = shader.getStage(Stage::PIXEL); @@ -33,9 +33,9 @@ void PositionNodeMsl::createVariables(const ShaderNode& node, GenContext&, Shade } } -void PositionNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const +void HwPositionNode::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const { - const MslShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); + const HwShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); const ShaderInput* spaceInput = node.getInput(SPACE); const int space = spaceInput ? spaceInput->getValue()->asA() : OBJECT_SPACE; diff --git a/source/MaterialXGenGlsl/Nodes/FrameNodeGlsl.h b/source/MaterialXGenShader/Nodes/HwPositionNode.h similarity index 63% rename from source/MaterialXGenGlsl/Nodes/FrameNodeGlsl.h rename to source/MaterialXGenShader/Nodes/HwPositionNode.h index f3a5197eae..ae2ce5c3f5 100644 --- a/source/MaterialXGenGlsl/Nodes/FrameNodeGlsl.h +++ b/source/MaterialXGenShader/Nodes/HwPositionNode.h @@ -3,15 +3,15 @@ // SPDX-License-Identifier: Apache-2.0 // -#ifndef MATERIALX_FRAMENODEGLSL_H -#define MATERIALX_FRAMENODEGLSL_H +#ifndef MATERIALX_HWPOSITIONNODE_H +#define MATERIALX_HWPOSITIONNODE_H -#include +#include MATERIALX_NAMESPACE_BEGIN -/// Frame node implementation for GLSL -class MX_GENGLSL_API FrameNodeGlsl : public GlslImplementation +/// Position node implementation for hardware languages +class MX_GENSHADER_API HwPositionNode : public HwImplementation { public: static ShaderNodeImplPtr create(); diff --git a/source/MaterialXGenGlsl/Nodes/TangentNodeGlsl.cpp b/source/MaterialXGenShader/Nodes/HwTangentNode.cpp similarity index 85% rename from source/MaterialXGenGlsl/Nodes/TangentNodeGlsl.cpp rename to source/MaterialXGenShader/Nodes/HwTangentNode.cpp index daffaf0e2c..6e80537932 100644 --- a/source/MaterialXGenGlsl/Nodes/TangentNodeGlsl.cpp +++ b/source/MaterialXGenShader/Nodes/HwTangentNode.cpp @@ -3,18 +3,18 @@ // SPDX-License-Identifier: Apache-2.0 // -#include +#include #include MATERIALX_NAMESPACE_BEGIN -ShaderNodeImplPtr TangentNodeGlsl::create() +ShaderNodeImplPtr HwTangentNode::create() { - return std::make_shared(); + return std::make_shared(); } -void TangentNodeGlsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const +void HwTangentNode::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const { ShaderStage& vs = shader.getStage(Stage::VERTEX); ShaderStage& ps = shader.getStage(Stage::PIXEL); @@ -34,9 +34,9 @@ void TangentNodeGlsl::createVariables(const ShaderNode& node, GenContext&, Shade } } -void TangentNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const +void HwTangentNode::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const { - const GlslShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); + const HwShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); const ShaderInput* spaceInput = node.getInput(SPACE); const int space = spaceInput ? spaceInput->getValue()->asA() : OBJECT_SPACE; diff --git a/source/MaterialXGenGlsl/Nodes/BitangentNodeGlsl.h b/source/MaterialXGenShader/Nodes/HwTangentNode.h similarity index 64% rename from source/MaterialXGenGlsl/Nodes/BitangentNodeGlsl.h rename to source/MaterialXGenShader/Nodes/HwTangentNode.h index 905b2808e0..b36d7f3c56 100644 --- a/source/MaterialXGenGlsl/Nodes/BitangentNodeGlsl.h +++ b/source/MaterialXGenShader/Nodes/HwTangentNode.h @@ -3,15 +3,15 @@ // SPDX-License-Identifier: Apache-2.0 // -#ifndef MATERIALX_BITANGENTNODEGLSL_H -#define MATERIALX_BITANGENTNODEGLSL_H +#ifndef MATERIALX_HWTANGENTNODE_H +#define MATERIALX_HWTANGENTNODE_H -#include +#include MATERIALX_NAMESPACE_BEGIN -/// Bitangent node implementation for GLSL -class MX_GENGLSL_API BitangentNodeGlsl : public GlslImplementation +/// Tangent node implementation for hardware languages +class MX_GENSHADER_API HwTangentNode : public HwImplementation { public: static ShaderNodeImplPtr create(); diff --git a/source/MaterialXGenShader/Nodes/HwTexCoordNode.cpp b/source/MaterialXGenShader/Nodes/HwTexCoordNode.cpp index 3aa84400df..3e5c5c0a65 100644 --- a/source/MaterialXGenShader/Nodes/HwTexCoordNode.cpp +++ b/source/MaterialXGenShader/Nodes/HwTexCoordNode.cpp @@ -60,11 +60,11 @@ void HwTexCoordNode::emitFunctionCall(const ShaderNode& node, GenContext& contex // larger datatype than the requested number of texture coordinates, if several texture // coordinate nodes with different width coexist). string suffix = EMPTY_STRING; - if (output->getType() == Type::VECTOR2) + if (*output->getType() == *Type::VECTOR2) { suffix = ".xy"; } - else if (output->getType() == Type::VECTOR3) + else if (*output->getType() == *Type::VECTOR3) { suffix = ".xyz"; } diff --git a/source/MaterialXGenMsl/Nodes/TimeNodeMsl.cpp b/source/MaterialXGenShader/Nodes/HwTimeNode.cpp similarity index 72% rename from source/MaterialXGenMsl/Nodes/TimeNodeMsl.cpp rename to source/MaterialXGenShader/Nodes/HwTimeNode.cpp index 0c54861b40..8f802a0764 100644 --- a/source/MaterialXGenMsl/Nodes/TimeNodeMsl.cpp +++ b/source/MaterialXGenShader/Nodes/HwTimeNode.cpp @@ -3,24 +3,24 @@ // SPDX-License-Identifier: Apache-2.0 // -#include +#include #include MATERIALX_NAMESPACE_BEGIN -ShaderNodeImplPtr TimeNodeMsl::create() +ShaderNodeImplPtr HwTimeNode::create() { - return std::make_shared(); + return std::make_shared(); } -void TimeNodeMsl::createVariables(const ShaderNode&, GenContext&, Shader& shader) const +void HwTimeNode::createVariables(const ShaderNode&, GenContext&, Shader& shader) const { ShaderStage& ps = shader.getStage(Stage::PIXEL); addStageUniform(HW::PRIVATE_UNIFORMS, Type::FLOAT, HW::T_FRAME, ps); } -void TimeNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const +void HwTimeNode::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const { DEFINE_SHADER_STAGE(stage, Stage::PIXEL) { diff --git a/source/MaterialXGenMsl/Nodes/FrameNodeMsl.h b/source/MaterialXGenShader/Nodes/HwTimeNode.h similarity index 65% rename from source/MaterialXGenMsl/Nodes/FrameNodeMsl.h rename to source/MaterialXGenShader/Nodes/HwTimeNode.h index 4ad554102b..e5e1a2fcd4 100644 --- a/source/MaterialXGenMsl/Nodes/FrameNodeMsl.h +++ b/source/MaterialXGenShader/Nodes/HwTimeNode.h @@ -3,15 +3,15 @@ // SPDX-License-Identifier: Apache-2.0 // -#ifndef MATERIALX_FRAMENODEMSL_H -#define MATERIALX_FRAMENODEMSL_H +#ifndef MATERIALX_HWTIMENODE_H +#define MATERIALX_HWTIMENODE_H -#include +#include MATERIALX_NAMESPACE_BEGIN -/// Frame node implementation for MSL -class MX_GENMSL_API FrameNodeMsl : public MslImplementation +/// Time node implementation for hardware languages +class MX_GENSHADER_API HwTimeNode : public HwImplementation { public: static ShaderNodeImplPtr create(); diff --git a/source/MaterialXGenMsl/Nodes/ViewDirectionNodeMsl.cpp b/source/MaterialXGenShader/Nodes/HwViewDirectionNode.cpp similarity index 76% rename from source/MaterialXGenMsl/Nodes/ViewDirectionNodeMsl.cpp rename to source/MaterialXGenShader/Nodes/HwViewDirectionNode.cpp index 1443b5c320..819ac93029 100644 --- a/source/MaterialXGenMsl/Nodes/ViewDirectionNodeMsl.cpp +++ b/source/MaterialXGenShader/Nodes/HwViewDirectionNode.cpp @@ -3,18 +3,18 @@ // SPDX-License-Identifier: Apache-2.0 // -#include +#include #include MATERIALX_NAMESPACE_BEGIN -ShaderNodeImplPtr ViewDirectionNodeMsl::create() +ShaderNodeImplPtr HwViewDirectionNode::create() { - return std::make_shared(); + return std::make_shared(); } -void ViewDirectionNodeMsl::createVariables(const ShaderNode&, GenContext&, Shader& shader) const +void HwViewDirectionNode::createVariables(const ShaderNode&, GenContext&, Shader& shader) const { ShaderStage& vs = shader.getStage(Stage::VERTEX); ShaderStage& ps = shader.getStage(Stage::PIXEL); @@ -24,9 +24,9 @@ void ViewDirectionNodeMsl::createVariables(const ShaderNode&, GenContext&, Shade addStageUniform(HW::PRIVATE_UNIFORMS, Type::VECTOR3, HW::T_VIEW_POSITION, ps); } -void ViewDirectionNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const +void HwViewDirectionNode::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const { - const MslShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); + const HwShaderGenerator& shadergen = static_cast(context.getShaderGenerator()); DEFINE_SHADER_STAGE(stage, Stage::VERTEX) { diff --git a/source/MaterialXGenShader/Nodes/HwViewDirectionNode.h b/source/MaterialXGenShader/Nodes/HwViewDirectionNode.h new file mode 100644 index 0000000000..143d89d437 --- /dev/null +++ b/source/MaterialXGenShader/Nodes/HwViewDirectionNode.h @@ -0,0 +1,26 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef MATERIALX_HWVIEWDIRECTIONNODE_H +#define MATERIALX_HWVIEWDIRECTIONNODE_H + +#include + +MATERIALX_NAMESPACE_BEGIN + +/// ViewDirection node implementation for hardware languages +class MX_GENSHADER_API HwViewDirectionNode : public HwImplementation +{ + public: + static ShaderNodeImplPtr create(); + + void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override; + + void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; +}; + +MATERIALX_NAMESPACE_END + +#endif diff --git a/source/MaterialXGenShader/ShaderGraph.cpp b/source/MaterialXGenShader/ShaderGraph.cpp index 8482659b34..41ac0da8e7 100644 --- a/source/MaterialXGenShader/ShaderGraph.cpp +++ b/source/MaterialXGenShader/ShaderGraph.cpp @@ -1029,7 +1029,7 @@ void ShaderGraph::optimize(GenContext& context) { // Filename dot nodes must be elided so they do not create extra samplers. ShaderInput* in = node->getInput("in"); - if (in->getChannels().empty() && in->getType() == Type::FILENAME) + if (in->getChannels().empty() && *in->getType() == *Type::FILENAME) { bypass(context, node, 0); ++numEdits; @@ -1240,7 +1240,7 @@ string ShaderGraph::populateColorTransformMap(ColorManagementSystemPtr colorMana const string& sourceColorSpace = input->getActiveColorSpace(); if (shaderPort && !sourceColorSpace.empty()) { - if (shaderPort->getType() == Type::COLOR3 || shaderPort->getType() == Type::COLOR4) + if (*(shaderPort->getType()) == *Type::COLOR3 || *(shaderPort->getType()) == *Type::COLOR4) { // If we're converting between two identical color spaces than we have no work to do. if (sourceColorSpace != targetColorSpace) @@ -1309,10 +1309,10 @@ void ShaderGraph::populateUnitTransformMap(UnitSystemPtr unitSystem, ShaderPort* // Only support convertion for float and vectors. arrays, matrices are not supported. // TODO: This should be provided by the UnitSystem. - bool supportedType = (shaderPort->getType() == Type::FLOAT || - shaderPort->getType() == Type::VECTOR2 || - shaderPort->getType() == Type::VECTOR3 || - shaderPort->getType() == Type::VECTOR4); + bool supportedType = (*shaderPort->getType() == *Type::FLOAT || + *shaderPort->getType() == *Type::VECTOR2 || + *shaderPort->getType() == *Type::VECTOR3 || + *shaderPort->getType() == *Type::VECTOR4); if (supportedType) { UnitTransform transform(sourceUnitSpace, targetUnitSpace, shaderPort->getType(), unitType); diff --git a/source/MaterialXGenShader/ShaderNode.cpp b/source/MaterialXGenShader/ShaderNode.cpp index 9ef5b0789a..6e951b06e6 100644 --- a/source/MaterialXGenShader/ShaderNode.cpp +++ b/source/MaterialXGenShader/ShaderNode.cpp @@ -229,11 +229,11 @@ ShaderNodePtr ShaderNode::create(const ShaderGraph* parent, const string& name, // First, check for specific output types const ShaderOutput* primaryOutput = newNode->getOutput(); - if (primaryOutput->getType() == Type::MATERIAL) + if (*primaryOutput->getType() == *Type::MATERIAL) { newNode->_classification = Classification::MATERIAL; } - else if (primaryOutput->getType() == Type::SURFACESHADER) + else if (*primaryOutput->getType() == *Type::SURFACESHADER) { if (nodeDefName == "ND_surface_unlit") { @@ -244,11 +244,15 @@ ShaderNodePtr ShaderNode::create(const ShaderGraph* parent, const string& name, newNode->_classification = Classification::SHADER | Classification::SURFACE | Classification::CLOSURE; } } - else if (primaryOutput->getType() == Type::LIGHTSHADER) + else if (*primaryOutput->getType() == *Type::VOLUMESHADER) + { + newNode->_classification = Classification::SHADER | Classification::VOLUME | Classification::CLOSURE; + } + else if (*primaryOutput->getType() == *Type::LIGHTSHADER) { newNode->_classification = Classification::LIGHT | Classification::SHADER | Classification::CLOSURE; } - else if (primaryOutput->getType() == Type::BSDF) + else if (*primaryOutput->getType() == *Type::BSDF) { newNode->_classification = Classification::BSDF | Classification::CLOSURE; @@ -278,11 +282,11 @@ ShaderNodePtr ShaderNode::create(const ShaderGraph* parent, const string& name, newNode->_classification |= Classification::THINFILM; } } - else if (primaryOutput->getType() == Type::EDF) + else if (*primaryOutput->getType() == *Type::EDF) { newNode->_classification = Classification::EDF | Classification::CLOSURE; } - else if (primaryOutput->getType() == Type::VDF) + else if (*primaryOutput->getType() == *Type::VDF) { newNode->_classification = Classification::VDF | Classification::CLOSURE; } diff --git a/source/MaterialXGenShader/Syntax.cpp b/source/MaterialXGenShader/Syntax.cpp index 61deda624e..6e97a56609 100644 --- a/source/MaterialXGenShader/Syntax.cpp +++ b/source/MaterialXGenShader/Syntax.cpp @@ -220,42 +220,42 @@ ValuePtr Syntax::getSwizzledValue(ValuePtr value, const TypeDesc* srcType, const { throw ExceptionShaderGenError("Given channel index: '" + string(1, ch) + "' in channels pattern is incorrect for type '" + srcType->getName() + "'."); } - if (srcType == Type::FLOAT) + if (*srcType == *Type::FLOAT) { float v = value->asA(); ss << std::to_string(v); } - else if (srcType == Type::INTEGER) + else if (*srcType == *Type::INTEGER) { int v = value->asA(); ss << std::to_string(v); } - else if (srcType == Type::BOOLEAN) + else if (*srcType == *Type::BOOLEAN) { bool v = value->asA(); ss << std::to_string(v); } - else if (srcType == Type::COLOR3) + else if (*srcType == *Type::COLOR3) { Color3 v = value->asA(); ss << std::to_string(v[channelIndex]); } - else if (srcType == Type::COLOR4) + else if (*srcType == *Type::COLOR4) { Color4 v = value->asA(); ss << std::to_string(v[channelIndex]); } - else if (srcType == Type::VECTOR2) + else if (*srcType == *Type::VECTOR2) { Vector2 v = value->asA(); ss << std::to_string(v[channelIndex]); } - else if (srcType == Type::VECTOR3) + else if (*srcType == *Type::VECTOR3) { Vector3 v = value->asA(); ss << std::to_string(v[channelIndex]); } - else if (srcType == Type::VECTOR4) + else if (*srcType == *Type::VECTOR4) { Vector4 v = value->asA(); ss << std::to_string(v[channelIndex]); diff --git a/source/MaterialXGenShader/TypeDesc.cpp b/source/MaterialXGenShader/TypeDesc.cpp index 54610d81fe..dbe2504758 100644 --- a/source/MaterialXGenShader/TypeDesc.cpp +++ b/source/MaterialXGenShader/TypeDesc.cpp @@ -39,6 +39,16 @@ TypeDesc::TypeDesc(const string& name, unsigned char basetype, unsigned char sem { } +bool TypeDesc::operator==(const TypeDesc& rhs) const +{ + return (this->_name == rhs._name); +} + +bool TypeDesc::operator!=(const TypeDesc& rhs) const +{ + return !(*this == rhs); +} + const TypeDesc* TypeDesc::registerType(const string& name, unsigned char basetype, unsigned char semantic, size_t size, bool editable, const std::unordered_map& channelMapping) { diff --git a/source/MaterialXGenShader/TypeDesc.h b/source/MaterialXGenShader/TypeDesc.h index 425329c32c..daed87d7e2 100644 --- a/source/MaterialXGenShader/TypeDesc.h +++ b/source/MaterialXGenShader/TypeDesc.h @@ -57,6 +57,12 @@ class MX_GENSHADER_API TypeDesc static const TypeDesc* registerType(const string& name, unsigned char basetype, unsigned char semantic = SEMANTIC_NONE, size_t size = 1, bool editable = true, const ChannelMap& channelMapping = ChannelMap()); + /// Equality operator overload + bool operator==(const TypeDesc& rhs) const; + + /// Inequality operator overload + bool operator!=(const TypeDesc& rhs) const; + /// Get a type descriptor for given name. /// Returns an empty shared pointer if no type with the given name is found. static const TypeDesc* get(const string& name); diff --git a/source/MaterialXGenShader/Util.cpp b/source/MaterialXGenShader/Util.cpp index b37383341c..a9f48b31c4 100644 --- a/source/MaterialXGenShader/Util.cpp +++ b/source/MaterialXGenShader/Util.cpp @@ -210,7 +210,7 @@ bool isTransparentShaderGraph(OutputPtr output, const string& target, NodePtr in if (nodeDef) { const TypeDesc* nodeDefType = TypeDesc::get(nodeDef->getType()); - if (nodeDefType == Type::BSDF) + if (*nodeDefType == *Type::BSDF) { InterfaceElementPtr impl = nodeDef->getImplementation(target); if (impl && impl->isA()) diff --git a/source/MaterialXGraphEditor/CMakeLists.txt b/source/MaterialXGraphEditor/CMakeLists.txt index f5f22be2c5..557b134cff 100644 --- a/source/MaterialXGraphEditor/CMakeLists.txt +++ b/source/MaterialXGraphEditor/CMakeLists.txt @@ -60,6 +60,9 @@ set(GLFW_BUILD_TESTS OFF) set(GLFW_BUILD_DOCS OFF) set(GLFW_INSTALL OFF) +# Explicitly build GLFW with static libraries, independent of the broader build settings. +set(BUILD_SHARED_LIBS OFF) + add_subdirectory(External/Glfw) if(MSVC) diff --git a/source/MaterialXGraphEditor/Graph.cpp b/source/MaterialXGraphEditor/Graph.cpp index f0d1791143..43a94edefb 100644 --- a/source/MaterialXGraphEditor/Graph.cpp +++ b/source/MaterialXGraphEditor/Graph.cpp @@ -200,7 +200,7 @@ void Graph::loadStandardLibraries() } } -mx::DocumentPtr Graph::loadDocument(mx::FilePath filename) +mx::DocumentPtr Graph::loadDocument(const mx::FilePath& filename) { mx::FilePathVec libraryFolders = { "libraries" }; _libraryFolders = libraryFolders; @@ -430,14 +430,8 @@ int Graph::findLinkPosition(int id) bool Graph::checkPosition(UiNodePtr node) { - if (node->getMxElement() != nullptr) - { - if (node->getMxElement()->getAttribute("xpos") != "") - { - return true; - } - } - return false; + return node->getMxElement() && + !node->getMxElement()->getAttribute("xpos").empty(); } // Calculate the total vertical space the node level takes up @@ -710,23 +704,6 @@ void Graph::setPinColor() _pinColor.insert(std::make_pair("stringarray", ImColor(120, 180, 100))); } -void Graph::selectMaterial(UiNodePtr uiNode) -{ - // Find renderable element that corresponds with material UiNode - std::vector elems = mx::findRenderableElements(_graphDoc); - mx::TypedElementPtr typedElem = nullptr; - for (mx::TypedElementPtr elem : elems) - { - mx::TypedElementPtr renderableElem = elem; - mx::NodePtr node = elem->asA(); - if (node == uiNode->getNode()) - { - typedElem = elem; - } - } - _renderer->setMaterial(typedElem); -} - void Graph::setRenderMaterial(UiNodePtr node) { // For now only surface shaders and materials are considered renderable. @@ -2028,7 +2005,7 @@ UiPinPtr Graph::getPin(ed::PinId pinId) return nullPin; } -void Graph::drawPinIcon(std::string type, bool connected, int alpha) +void Graph::drawPinIcon(const std::string& type, bool connected, int alpha) { ax::Drawing::IconType iconType = ax::Drawing::IconType::Flow; ImColor color = ImColor(0, 0, 0, 255); @@ -2105,50 +2082,6 @@ bool Graph::readOnly() return _currGraphElem->getActiveSourceUri() != _graphDoc->getActiveSourceUri(); } -mx::InputPtr Graph::findInput(mx::InputPtr nodeInput, const std::string& name) -{ - if (_isNodeGraph) - { - for (UiNodePtr uiNode : _graphNodes) - { - if (uiNode->getNode()) - { - for (mx::InputPtr input : uiNode->getNode()->getActiveInputs()) - { - if (input->getInterfaceInput()) - { - if (input->getInterfaceInput() == nodeInput) - { - return input; - } - } - } - } - } - } - else - { - if (_currUiNode->getNodeGraph()) - { - for (mx::NodePtr node : _currUiNode->getNodeGraph()->getNodes()) - { - for (mx::InputPtr input : node->getActiveInputs()) - { - if (input->getInterfaceInput()) - { - - if (input->getInterfaceName() == name) - { - return input; - } - } - } - } - } - } - return nullptr; -} - void Graph::drawOutputPins(UiNodePtr node, const std::string& longestInputLabel) { std::string longestLabel = longestInputLabel; @@ -2921,10 +2854,10 @@ void Graph::deleteNode(UiNodePtr node) } } - if (node->outputPins.size() > 0) + for (UiPinPtr outputPin : node->outputPins) { // Update downNode info - for (UiPinPtr pin : node->outputPins.front()->getConnections()) + for (UiPinPtr pin : outputPin.get()->getConnections()) { mx::ValuePtr val; if (pin->_pinNode->getNode()) @@ -2939,6 +2872,13 @@ void Graph::deleteNode(UiNodePtr node) { pin->_input->setConnectedNode(nullptr); } + if (node->getInput()) + { + // Remove interface value in order to set the default of the input + pin->_input->removeAttribute(mx::ValueElement::INTERFACE_NAME_ATTRIBUTE); + setDefaults(pin->_input); + setDefaults(node->getInput()); + } } else if (pin->_pinNode->getNodeGraph()) { @@ -3736,7 +3676,6 @@ void Graph::addNodePopup(bool cursor) } } } - cursor = false; ImGui::EndPopup(); open_AddPopup = false; } @@ -3778,7 +3717,6 @@ void Graph::searchNodePopup(bool cursor) } } } - cursor = false; ImGui::EndPopup(); } } @@ -4349,19 +4287,6 @@ int Graph::findNode(int nodeId) return -1; } -std::vector Graph::findLinkId(int id) -{ - std::vector ids; - for (const Link& link : _currLinks) - { - if (link._startAttr == id || link._endAttr == id) - { - ids.push_back(link.id); - } - } - return ids; -} - bool Graph::edgeExists(UiEdge newEdge) { if (_currEdge.size() > 0) diff --git a/source/MaterialXGraphEditor/Graph.h b/source/MaterialXGraphEditor/Graph.h index 821ecf71fd..965ec519b7 100644 --- a/source/MaterialXGraphEditor/Graph.h +++ b/source/MaterialXGraphEditor/Graph.h @@ -66,7 +66,7 @@ class Graph int viewWidth, int viewHeight); - mx::DocumentPtr loadDocument(mx::FilePath filename); + mx::DocumentPtr loadDocument(const mx::FilePath& filename); void drawGraph(ImVec2 mousePos); RenderViewPtr getRenderer() @@ -106,9 +106,6 @@ class Graph // Find link position in current links vector from link id int findLinkPosition(int id); - // Find link from attribute id - std::vector findLinkId(int attrId); - // Check if link exists in the current link vector bool linkExists(Link newLink); @@ -139,7 +136,7 @@ class Graph void setPinColor(); // Based on the pin icon function in the ImGui Node Editor blueprints-example.cpp - void drawPinIcon(std::string type, bool connected, int alpha); + void drawPinIcon(const std::string& type, bool connected, int alpha); UiPinPtr getPin(ed::PinId id); void drawInputPin(UiPinPtr pin); @@ -189,7 +186,6 @@ class Graph // Add input pointer to node based on input pin void addNodeInput(UiNodePtr node, mx::InputPtr& input); - mx::InputPtr findInput(mx::InputPtr input, const std::string& name); void upNodeGraph(); // Set the value of the selected node constants in the node property editor @@ -222,7 +218,6 @@ class Graph void shaderPopup(); void updateMaterials(mx::InputPtr input = nullptr, mx::ValuePtr value = nullptr); - void selectMaterial(UiNodePtr node); // Allow for camera manipulation of render view window void handleRenderViewInputs(); diff --git a/source/MaterialXRender/LightHandler.cpp b/source/MaterialXRender/LightHandler.cpp index c7d9311005..1daef328dd 100644 --- a/source/MaterialXRender/LightHandler.cpp +++ b/source/MaterialXRender/LightHandler.cpp @@ -42,7 +42,7 @@ void LightHandler::findLights(DocumentPtr doc, vector& lights) for (NodePtr node : doc->getNodes()) { const TypeDesc* type = TypeDesc::get(node->getType()); - if (type == Type::LIGHTSHADER) + if (*type == *Type::LIGHTSHADER) { lights.push_back(node); } diff --git a/source/MaterialXRenderGlsl/GlslProgram.cpp b/source/MaterialXRenderGlsl/GlslProgram.cpp index a0bc3a128d..4b318cb52d 100644 --- a/source/MaterialXRenderGlsl/GlslProgram.cpp +++ b/source/MaterialXRenderGlsl/GlslProgram.cpp @@ -1038,11 +1038,11 @@ const GlslProgram::InputMap& GlslProgram::updateUniformsList() int GlslProgram::mapTypeToOpenGLType(const TypeDesc* type) { - if (type == Type::INTEGER) + if (*type == *Type::INTEGER) return GL_INT; - else if (type == Type::BOOLEAN) + else if (*type == *Type::BOOLEAN) return GL_BOOL; - else if (type == Type::FLOAT) + else if (*type == *Type::FLOAT) return GL_FLOAT; else if (type->isFloat2()) return GL_FLOAT_VEC2; @@ -1050,11 +1050,11 @@ int GlslProgram::mapTypeToOpenGLType(const TypeDesc* type) return GL_FLOAT_VEC3; else if (type->isFloat4()) return GL_FLOAT_VEC4; - else if (type == Type::MATRIX33) + else if (*type == *Type::MATRIX33) return GL_FLOAT_MAT3; - else if (type == Type::MATRIX44) + else if (*type == *Type::MATRIX44) return GL_FLOAT_MAT4; - else if (type == Type::FILENAME) + else if (*type == *Type::FILENAME) { // A "filename" is not indicative of type, so just return a 2d sampler. return GL_SAMPLER_2D; diff --git a/source/MaterialXView/Viewer.cpp b/source/MaterialXView/Viewer.cpp index ca6bdb7683..47f1fcacea 100644 --- a/source/MaterialXView/Viewer.cpp +++ b/source/MaterialXView/Viewer.cpp @@ -387,7 +387,7 @@ void Viewer::loadEnvironmentLight() } // Look for an irradiance map using an expected filename convention. - mx::ImagePtr envIrradianceMap = _imageHandler->getZeroImage(); + mx::ImagePtr envIrradianceMap; if (!_normalizeEnvironment && !_splitDirectLight) { mx::FilePath envIrradiancePath = _envRadianceFilename.getParentPath() / IRRADIANCE_MAP_FOLDER / _envRadianceFilename.getBaseName(); @@ -395,7 +395,7 @@ void Viewer::loadEnvironmentLight() } // If not found, then generate an irradiance map via spherical harmonics. - if (envIrradianceMap == _imageHandler->getZeroImage()) + if (!envIrradianceMap || envIrradianceMap->getWidth() == 1) { if (_generateReferenceIrradiance) { diff --git a/source/PyMaterialX/PyMaterialXGenGlsl/PyGlslShaderGenerator.cpp b/source/PyMaterialX/PyMaterialXGenGlsl/PyGlslShaderGenerator.cpp index ba4a9c981e..f26d4f2aee 100644 --- a/source/PyMaterialX/PyMaterialXGenGlsl/PyGlslShaderGenerator.cpp +++ b/source/PyMaterialX/PyMaterialXGenGlsl/PyGlslShaderGenerator.cpp @@ -12,8 +12,6 @@ #include #include -#include - namespace py = pybind11; namespace mx = MaterialX; diff --git a/source/PyMaterialX/PyMaterialXGenMdl/PyMdlShaderGenerator.cpp b/source/PyMaterialX/PyMaterialXGenMdl/PyMdlShaderGenerator.cpp index d06e6f5ba7..d0702cfff0 100644 --- a/source/PyMaterialX/PyMaterialXGenMdl/PyMdlShaderGenerator.cpp +++ b/source/PyMaterialX/PyMaterialXGenMdl/PyMdlShaderGenerator.cpp @@ -8,12 +8,9 @@ #include #include -#include - namespace py = pybind11; namespace mx = MaterialX; - void bindPyMdlShaderGenerator(py::module& mod) { py::class_(mod, "MdlShaderGenerator") diff --git a/source/PyMaterialX/PyMaterialXGenMsl/PyMslShaderGenerator.cpp b/source/PyMaterialX/PyMaterialXGenMsl/PyMslShaderGenerator.cpp index 870b9bc02c..48259cad07 100644 --- a/source/PyMaterialX/PyMaterialXGenMsl/PyMslShaderGenerator.cpp +++ b/source/PyMaterialX/PyMaterialXGenMsl/PyMslShaderGenerator.cpp @@ -10,8 +10,6 @@ #include #include -#include - namespace py = pybind11; namespace mx = MaterialX; diff --git a/source/PyMaterialX/PyMaterialXGenOsl/PyOslShaderGenerator.cpp b/source/PyMaterialX/PyMaterialXGenOsl/PyOslShaderGenerator.cpp index 39082c28f5..7c53002669 100644 --- a/source/PyMaterialX/PyMaterialXGenOsl/PyOslShaderGenerator.cpp +++ b/source/PyMaterialX/PyMaterialXGenOsl/PyOslShaderGenerator.cpp @@ -9,8 +9,6 @@ #include #include -#include - namespace py = pybind11; namespace mx = MaterialX; diff --git a/source/PyMaterialX/PyMaterialXGenShader/PyHwShaderGenerator.cpp b/source/PyMaterialX/PyMaterialXGenShader/PyHwShaderGenerator.cpp index d13b2ad133..286021cb90 100644 --- a/source/PyMaterialX/PyMaterialXGenShader/PyHwShaderGenerator.cpp +++ b/source/PyMaterialX/PyMaterialXGenShader/PyHwShaderGenerator.cpp @@ -9,8 +9,6 @@ #include #include -#include - namespace py = pybind11; namespace mx = MaterialX; From 14c723ec4af98ff4c0e6b164e732b2e4baaf8fdc Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Thu, 1 Feb 2024 20:07:42 -0800 Subject: [PATCH 12/14] Remove default arguments --- source/MaterialXTest/MaterialXRender/RenderUtil.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/MaterialXTest/MaterialXRender/RenderUtil.cpp b/source/MaterialXTest/MaterialXRender/RenderUtil.cpp index 64cfe00013..0460f9282a 100644 --- a/source/MaterialXTest/MaterialXRender/RenderUtil.cpp +++ b/source/MaterialXTest/MaterialXRender/RenderUtil.cpp @@ -478,7 +478,7 @@ void ShaderRenderTester::addAdditionalTestStreams(mx::MeshPtr mesh) const std::string GEOM_VECTOR2_STREAM_NAME("i_" + mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE + "_geompropvalue_vector2"); mx::MeshFloatBuffer* geomVector2Data = nullptr; - if (!mesh->getStream(GEOM_VECTOR2_STREAM_NAME, false)) + if (!mesh->getStream(GEOM_VECTOR2_STREAM_NAME)) { mx::MeshStreamPtr geomVector2Stream = mx::MeshStream::create(GEOM_VECTOR2_STREAM_NAME, mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE, 1); geomVector2Data = &(geomVector2Stream->getData()); @@ -533,7 +533,7 @@ void ShaderRenderTester::addAdditionalTestStreams(mx::MeshPtr mesh) const std::string GEOM_COLOR4_STREAM_NAME("i_" + mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE + "_geompropvalue_color4"); mx::MeshFloatBuffer* geomColor4Data = nullptr; - if (!mesh->getStream(GEOM_COLOR4_STREAM_NAME, false)) + if (!mesh->getStream(GEOM_COLOR4_STREAM_NAME)) { mx::MeshStreamPtr geomColor4Stream = mx::MeshStream::create(GEOM_COLOR4_STREAM_NAME, mx::MeshStream::GEOMETRY_PROPERTY_ATTRIBUTE, 1); geomColor4Data = &(geomColor4Stream->getData()); From cfaec6de4cecb581642ce931715d4425c607021e Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Thu, 1 Feb 2024 20:22:59 -0800 Subject: [PATCH 13/14] Remove extra newline --- source/MaterialXRender/Mesh.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/source/MaterialXRender/Mesh.cpp b/source/MaterialXRender/Mesh.cpp index a50e554bf4..48d359c002 100644 --- a/source/MaterialXRender/Mesh.cpp +++ b/source/MaterialXRender/Mesh.cpp @@ -402,7 +402,6 @@ MeshStreamPtr Mesh::getStream(const string& name, bool allowFallback) returnStream = tangentStream; } - if (needBiTangents) { MeshStreamPtr bitangentStream = getStream("i_" + MeshStream::BITANGENT_ATTRIBUTE); From c21337d1c225d61d801bf32990b7c66938491a68 Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Thu, 1 Feb 2024 20:29:48 -0800 Subject: [PATCH 14/14] Remove unused temporary --- source/MaterialXRender/Mesh.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/MaterialXRender/Mesh.cpp b/source/MaterialXRender/Mesh.cpp index 48d359c002..cb96796e52 100644 --- a/source/MaterialXRender/Mesh.cpp +++ b/source/MaterialXRender/Mesh.cpp @@ -431,8 +431,7 @@ MeshStreamPtr Mesh::getStream(const string& name, bool allowFallback) MeshStreamPtr Mesh::getStream(const string& type, unsigned int index, bool allowFallback) { const string streamName = "i_" + type + "_" + std::to_string(index); - MeshStreamPtr foundStream = getStream(streamName, allowFallback); - return foundStream; + return getStream(streamName, allowFallback); } MATERIALX_NAMESPACE_END