diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index 6298b6fcd1..7847a20f81 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -107,9 +107,11 @@ jobs: - name: Python Tests run: | - python main.py - python genshader.py - working-directory: python/MaterialXTest + python MaterialXTest/main.py + python MaterialXTest/genshader.py + python Scripts/mxvalidate.py ../resources/Materials/Examples/StandardSurface/standard_surface_marble_solid.mtlx --verbose + python Scripts/mxdoc.py ../libraries/pbrlib/pbrlib_defs.mtlx + working-directory: python - name: Render Tests if: matrix.test_render == 'ON' diff --git a/CHANGELOG.md b/CHANGELOG.md index 055df93d15..0ce08b323a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,16 +2,23 @@ ## [1.38] - Development -### v1.38_adsk_development2 : Work-in-progress -- Up-to-date with ILM v1.38 branch @8718c59 -- GPU testing framework setup (in progress) +### v1.38_adsk_development2 : 2021-01-29 +- Up-to-date with LucasFilm v1.38 branch @a2e2633. +- *All documents upgrade to "1.38" as version number. Files must be marked +as "1.37" for upgrade to occur* +- Standard surface default value changes (See https://github.com/Autodesk/standard-surface/blob/master/reference/standard_surface.mtlx) +- UsdPreviewSurface "metallic" input name update. - Deprecation of Language specifier and introduction of TargetDefs - Deprecation of Material and ShaderRef elements. -- Deprecation of Parameter element. -- TextureBaker v1 completion +- Deprecation of Parameter element. Remapped to Input element with optional "uniform" attribute. +- PBR node modifications in. Full deprecated node support upgrade support in progress. +- TextureBaker version "1" completion. +- Nodegraph "version" tag + logic fix (deprecation). +- GPU testing framework setup for Linux. +- Update of MDL support. Passes test verification for v1.6. ### v1.38_adsk_development1 : Major changes since "v1.37.3_parameters_as_inputs" - - Up-to-date with ILM v1.38 branch @3900415. + - Up-to-date with LucasFilm v1.38 branch @3900415. - Finished API support for Material Nodes (from Material Elements) - Baker support for v1.38, CM and units. - Shader Translator support for v1.38, CM and units. diff --git a/libraries/pbrlib/genglsl/lib/mx_environment_fis.glsl b/libraries/pbrlib/genglsl/lib/mx_environment_fis.glsl index 430d4859c3..4f2ed7c621 100644 --- a/libraries/pbrlib/genglsl/lib/mx_environment_fis.glsl +++ b/libraries/pbrlib/genglsl/lib/mx_environment_fis.glsl @@ -15,13 +15,6 @@ float mx_latlong_compute_lod(vec3 dir, float pdf, float maxMipLevel, int envSamp return max(effectiveMaxMipLevel - 0.5 * log2(envSamples * pdf * distortion), 0.0); } -vec3 mx_latlong_map_lookup(vec3 dir, mat4 transform, float lod, sampler2D sampler) -{ - vec3 envDir = normalize((transform * vec4(dir,0.0)).xyz); - vec2 uv = mx_latlong_projection(envDir); - return textureLod(sampler, uv, lod).rgb; -} - vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 roughness, int distribution, FresnelData fd) { vec3 Y = normalize(cross(N, X)); diff --git a/libraries/pbrlib/genglsl/lib/mx_environment_prefilter.glsl b/libraries/pbrlib/genglsl/lib/mx_environment_prefilter.glsl index 5732a3c8c3..ff226d3f53 100644 --- a/libraries/pbrlib/genglsl/lib/mx_environment_prefilter.glsl +++ b/libraries/pbrlib/genglsl/lib/mx_environment_prefilter.glsl @@ -1,32 +1,10 @@ #include "pbrlib/genglsl/lib/mx_microfacet_specular.glsl" -vec3 mx_latlong_map_lookup(vec3 dir, mat4 transform, sampler2D sampler) +float mx_latlong_compute_lod(float roughness) { - vec2 res = textureSize(sampler, 0); - if (res.x > 1) - { - vec3 dir = normalize((transform * vec4(dir,0.0)).xyz); - vec2 uv = mx_latlong_projection(dir); - return texture(sampler, uv).rgb; - } - return vec3(0.0); -} - -vec3 mx_latlong_map_lookup(vec3 dir, mat4 transform, float lodBias, sampler2D sampler) -{ - vec2 res = textureSize(sampler, 0); - if (res.x > 1) - { - // Heuristic for faking a blur by roughness - int levels = 1 + int(floor(log2(max(res.x, res.y)))); - lodBias = lodBias < 0.25 ? sqrt(lodBias) : 0.5*lodBias + 0.375; - float lod = lodBias * levels; - - vec3 dir = normalize((transform * vec4(dir,0.0)).xyz); - vec2 uv = mx_latlong_projection(dir); - return textureLod(sampler, uv, lod).rgb; - } - return vec3(0.0); + // Select a mip level based on input roughness. + float lodBias = roughness < 0.25 ? sqrt(roughness) : 0.5*roughness + 0.375; + return lodBias * $envRadianceMips; } vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 roughness, int distribution, FresnelData fd) @@ -36,15 +14,16 @@ vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 roughness, int distrib float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); - vec3 F = mx_compute_fresnel(NdotV, fd); float avgRoughness = mx_average_roughness(roughness); + vec3 F = mx_compute_fresnel(NdotV, fd); + float G = mx_ggx_smith_G(NdotV, NdotV, avgRoughness); vec3 comp = mx_ggx_energy_compensation(NdotV, avgRoughness, F); - vec3 Li = mx_latlong_map_lookup(L, $envMatrix, avgRoughness, $envRadiance); + vec3 Li = mx_latlong_map_lookup(L, $envMatrix, mx_latlong_compute_lod(avgRoughness), $envRadiance); - return Li * F * comp; + return Li * F * G * comp; } vec3 mx_environment_irradiance(vec3 N) { - return mx_latlong_map_lookup(N, $envMatrix, $envIrradiance); + return mx_latlong_map_lookup(N, $envMatrix, 0.0, $envIrradiance); } diff --git a/libraries/pbrlib/genglsl/lib/mx_math.glsl b/libraries/pbrlib/genglsl/lib/mx_math.glsl index 015d151c5b..8460e665a8 100644 --- a/libraries/pbrlib/genglsl/lib/mx_math.glsl +++ b/libraries/pbrlib/genglsl/lib/mx_math.glsl @@ -63,6 +63,13 @@ vec2 mx_latlong_projection(vec3 dir) return vec2(longitude, latitude); } +vec3 mx_latlong_map_lookup(vec3 dir, mat4 transform, float lod, sampler2D sampler) +{ + vec3 envDir = normalize((transform * vec4(dir,0.0)).xyz); + vec2 uv = mx_latlong_projection(envDir); + return textureLod(sampler, uv, lod).rgb; +} + vec3 mx_forward_facing_normal(vec3 N, vec3 V) { if (dot(N, V) < 0.0) diff --git a/source/MaterialXCore/Document.cpp b/source/MaterialXCore/Document.cpp index f292c6d177..29fc36fbdc 100644 --- a/source/MaterialXCore/Document.cpp +++ b/source/MaterialXCore/Document.cpp @@ -17,17 +17,6 @@ const string Document::CMS_CONFIG_ATTRIBUTE = "cmsconfig"; namespace { -template shared_ptr updateChildSubclass(ElementPtr parent, ElementPtr origChild) -{ - string childName = origChild->getName(); - int childIndex = parent->getChildIndex(childName); - parent->removeChild(childName); - shared_ptr newChild = parent->addChild(childName); - parent->setChildIndex(childName, childIndex); - newChild->copyContentFrom(origChild); - return newChild; -} - NodeDefPtr getShaderNodeDef(ElementPtr shaderRef) { if (shaderRef->hasAttribute(NodeDef::NODE_DEF_ATTRIBUTE)) @@ -389,7 +378,7 @@ void Document::upgradeVersion() } for (ElementPtr child : getChildrenOfType("assign")) { - updateChildSubclass(elem, child); + elem->changeChildCategory(child, "materialassign"); } } minorVersion = 24; @@ -437,11 +426,11 @@ void Document::upgradeVersion() { if (child->getCategory() == "opgraph") { - updateChildSubclass(elem, child); + elem->changeChildCategory(child, "nodegraph"); } else if (child->getCategory() == "shader") { - NodeDefPtr nodeDef = updateChildSubclass(elem, child); + NodeDefPtr nodeDef = elem->changeChildCategory(child, "nodedef")->asA(); if (nodeDef->hasAttribute("shadertype")) { nodeDef->setType(SURFACE_SHADER_TYPE_STRING); @@ -467,7 +456,7 @@ void Document::upgradeVersion() { if (elem->isA()) { - InputPtr input = updateChildSubclass(elem, child); + InputPtr input = elem->changeChildCategory(child, "input")->asA(); input->setNodeName(input->getAttribute("value")); input->removeAttribute("value"); if (input->getConnectedNode()) @@ -541,7 +530,7 @@ void Document::upgradeVersion() { for (ElementPtr child : geomInfo->getChildrenOfType("geomattr")) { - updateChildSubclass(geomInfo, child); + geomInfo->changeChildCategory(child, "geomprop"); } } if (getGeomPropValue("udim") && !getGeomPropValue("udimset")) @@ -706,7 +695,7 @@ void Document::upgradeVersion() { for (ElementPtr child : geomInfo->getChildrenOfType("geomattr")) { - updateChildSubclass(geomInfo, child); + geomInfo->changeChildCategory(child, "geomprop"); } } for (ElementPtr elem : traverseTree()) @@ -762,7 +751,7 @@ void Document::upgradeVersion() ElementPtr cutoff = node->getChild("cutoff"); if (cutoff) { - cutoff = updateChildSubclass(node, cutoff); + cutoff = node->changeChildCategory(cutoff, "input"); cutoff->setName("value2"); } InputPtr in1 = node->getInput("in1"); @@ -1005,7 +994,7 @@ void Document::upgradeVersion() ElementPtr axis = nodedef->getChild(AXIS); if (axis) { - updateChildSubclass(nodedef, axis); + nodedef->changeChildCategory(axis, "input"); } } @@ -1141,7 +1130,7 @@ void Document::upgradeVersion() ElementPtr axis = node->getChild(AXIS); if (axis) { - updateChildSubclass(node, axis); + node->changeChildCategory(axis, "input"); } } else if (nodeCategory == DIELECTRIC_BRDF.first) @@ -1222,7 +1211,7 @@ void Document::upgradeVersion() { node->setCategory(SUBSURFACE_BRDF.second); } - else if(nodeCategory == ARTISTIC_IOR) + else if (nodeCategory == ARTISTIC_IOR) { OutputPtr ior = node->getOutput(IOR); if (ior) @@ -1241,7 +1230,7 @@ void Document::upgradeVersion() // since the outputs of artistic_ior is now color3. // Save the inputs here and insert the conversion nodes below, // since we can't modify the graph while traversing it. - for (auto input : node->getInputs()) + for (InputPtr input : node->getInputs()) { if (input->getOutputString() == IOR && input->getType() == VECTOR3) { @@ -1334,14 +1323,14 @@ void Document::upgradeVersion() const string FRAME_OFFSET_STRING = "frameoffset"; const string INDEX_STRING = "index"; const string DEFAULT_STRING = "default"; - for (ElementPtr elementPtr : traverseTree()) + for (ElementPtr elem : traverseTree()) { - if (elementPtr->isA()) + if (elem->isA()) { - for (ElementPtr param : elementPtr->getChildrenOfType("parameter")) + for (ElementPtr param : elem->getChildrenOfType("parameter")) { - InputPtr input = updateChildSubclass(elementPtr, param); - if (elementPtr->isA()) + InputPtr input = elem->changeChildCategory(param, "input")->asA(); + if (elem->isA()) { // Strings and filename types should always be uniforms. const string& inputType = input->getType(); diff --git a/source/MaterialXCore/Element.cpp b/source/MaterialXCore/Element.cpp index 7e415315e6..09cad27265 100644 --- a/source/MaterialXCore/Element.cpp +++ b/source/MaterialXCore/Element.cpp @@ -298,6 +298,21 @@ ElementPtr Element::addChildOfCategory(const string& category, string name) return child; } +ElementPtr Element::changeChildCategory(ElementPtr child, const string& category) +{ + int childIndex = getChildIndex(child->getName()); + if (childIndex == -1) + { + return nullptr; + } + + removeChild(child->getName()); + ElementPtr newChild = addChildOfCategory(category, child->getName()); + setChildIndex(child->getName(), childIndex); + newChild->copyContentFrom(child); + return newChild; +} + ElementPtr Element::getRoot() { ElementPtr root = _root.lock(); diff --git a/source/MaterialXCore/Element.h b/source/MaterialXCore/Element.h index f62dd3e425..bac72b06bb 100644 --- a/source/MaterialXCore/Element.h +++ b/source/MaterialXCore/Element.h @@ -466,6 +466,13 @@ class Element : public std::enable_shared_from_this /// @return A shared pointer to the new child element. ElementPtr addChildOfCategory(const string& category, string name = EMPTY_STRING); + /// Change the category of the given child element. + /// @param child The child element that will be modified. + /// @param category The new category string for the child element. + /// @return A shared pointer to a new child element, containing the contents + /// of the original child but with a new category and subclass. + ElementPtr changeChildCategory(ElementPtr child, const string& category); + /// Return the child element, if any, with the given name. ElementPtr getChild(const string& name) const { diff --git a/source/MaterialXCore/Util.cpp b/source/MaterialXCore/Util.cpp index c486ba3ca8..58b41e4d03 100644 --- a/source/MaterialXCore/Util.cpp +++ b/source/MaterialXCore/Util.cpp @@ -4,7 +4,6 @@ // #include -#include #include @@ -165,15 +164,4 @@ string parentNamePath(const string& namePath) return EMPTY_STRING; } -ElementPtr changeChildCategory(ElementPtr parent, ElementPtr origChild, const string& category) -{ - string childName = origChild->getName(); - int childIndex = parent->getChildIndex(childName); - parent->removeChild(childName); - ElementPtr newChild = parent->addChildOfCategory(category, childName); - parent->setChildIndex(childName, childIndex); - newChild->copyContentFrom(origChild); - return newChild; -} - } // namespace MaterialX diff --git a/source/MaterialXCore/Util.h b/source/MaterialXCore/Util.h index 5d74758659..310a5a64eb 100644 --- a/source/MaterialXCore/Util.h +++ b/source/MaterialXCore/Util.h @@ -14,9 +14,6 @@ namespace MaterialX { -class Element; -using ElementPtr = shared_ptr; - extern const string EMPTY_STRING; /// Return the version of the MaterialX library as a string. @@ -66,9 +63,6 @@ string createNamePath(const StringVec& nameVec); /// Given a name path, return the parent name path string parentNamePath(const string& namePath); -// Change the category of a child element -ElementPtr changeChildCategory(ElementPtr parent, ElementPtr origChild, const string& category); - } // namespace MaterialX #endif diff --git a/source/MaterialXRender/ImageHandler.h b/source/MaterialXRender/ImageHandler.h index e4471d0c6a..52a4713307 100644 --- a/source/MaterialXRender/ImageHandler.h +++ b/source/MaterialXRender/ImageHandler.h @@ -226,7 +226,8 @@ class ImageHandler return _zeroImage; } - /// Return a reference to the "invalid" image returned when a image cannot be loaded. + /// Return the sentinel invalid image, representing images that cannot be loaded + /// and should be replaced with their declared default value. ImagePtr getInvalidImage() const { return _invalidImage; diff --git a/source/MaterialXRenderGlsl/TextureBaker.cpp b/source/MaterialXRenderGlsl/TextureBaker.cpp index b644dde2a3..dc5fa190ee 100644 --- a/source/MaterialXRenderGlsl/TextureBaker.cpp +++ b/source/MaterialXRenderGlsl/TextureBaker.cpp @@ -162,13 +162,6 @@ void TextureBaker::optimizeBakedTextures(NodePtr shader) return; } - // Early exist if not optimizing - if (!_optimizeConstants) - { - _bakedConstantMap.clear(); - return; - } - // Check for uniform images. for (auto& pair : _bakedImageMap) { diff --git a/source/MaterialXView/Material.cpp b/source/MaterialXView/Material.cpp index 1f1230a52a..59c2bdc7d6 100644 --- a/source/MaterialXView/Material.cpp +++ b/source/MaterialXView/Material.cpp @@ -329,14 +329,11 @@ void Material::bindLights(const mx::GenContext& genContext, mx::LightHandlerPtr } // Bind any associated uniforms. - if (genContext.getOptions().hwSpecularEnvironmentMethod == mx::SPECULAR_ENVIRONMENT_FIS) + if (uniform == mx::HW::ENV_RADIANCE) { - if (uniform == mx::HW::ENV_RADIANCE) + if (_glProgram->hasUniform(mx::HW::ENV_RADIANCE_MIPS)) { - if (_glProgram->hasUniform(mx::HW::ENV_RADIANCE_MIPS)) - { - _glProgram->bindUniform(mx::HW::ENV_RADIANCE_MIPS, mx::Value::createValue((int) image->getMaxMipCount())); - } + _glProgram->bindUniform(mx::HW::ENV_RADIANCE_MIPS, mx::Value::createValue((int) image->getMaxMipCount())); } } } diff --git a/source/MaterialXView/Viewer.cpp b/source/MaterialXView/Viewer.cpp index 24d6bd4d76..54580c0394 100644 --- a/source/MaterialXView/Viewer.cpp +++ b/source/MaterialXView/Viewer.cpp @@ -390,7 +390,7 @@ void Viewer::loadEnvironmentLight() } // Look for an irradiance map using an expected filename convention. - mx::ImagePtr envIrradianceMap = nullptr; + mx::ImagePtr envIrradianceMap; if (!_normalizeEnvironment && !_splitDirectLight) { mx::FilePath envIrradiancePath = _envRadianceFilename.getParentPath() / IRRADIANCE_MAP_FOLDER / _envRadianceFilename.getBaseName(); @@ -398,7 +398,7 @@ void Viewer::loadEnvironmentLight() } // If not found, then generate an irradiance map via spherical harmonics. - if (!envIrradianceMap || envIrradianceMap == _imageHandler->getInvalidImage()) + if (envIrradianceMap == _imageHandler->getInvalidImage()) { if (_generateReferenceIrradiance) { @@ -1266,6 +1266,14 @@ void Viewer::loadDocument(const mx::FilePath& filename, mx::DocumentPtr librarie } } } + catch (mx::ExceptionShaderRenderError& e) + { + for (const std::string& error : e.errorLog()) + { + std::cerr << error << std::endl; + } + new ng::MessageDialog(this, ng::MessageDialog::Type::Warning, "Shader generation error", e.what()); + } catch (std::exception& e) { new ng::MessageDialog(this, ng::MessageDialog::Type::Warning, "Failed to load material", e.what()); @@ -1287,11 +1295,22 @@ void Viewer::reloadShaders() { material->generateShader(_genContext); } + return; + } + catch (mx::ExceptionShaderRenderError& e) + { + for (const std::string& error : e.errorLog()) + { + std::cerr << error << std::endl; + } + new ng::MessageDialog(this, ng::MessageDialog::Type::Warning, "Shader generation error", e.what()); } catch (std::exception& e) { - new ng::MessageDialog(this, ng::MessageDialog::Type::Warning, "Shader Generation Error", e.what()); + new ng::MessageDialog(this, ng::MessageDialog::Type::Warning, "Failed to reload shaders", e.what()); } + + _materials.clear(); } void Viewer::saveShaderSource(mx::GenContext& context) diff --git a/source/PyMaterialX/PyMaterialXCore/PyElement.cpp b/source/PyMaterialX/PyMaterialXCore/PyElement.cpp index f01d7a7b62..bc1dceb089 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyElement.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyElement.cpp @@ -72,6 +72,7 @@ void bindPyElement(py::module& mod) .def("getDocString", &mx::Element::getDocString) .def("addChildOfCategory", &mx::Element::addChildOfCategory, py::arg("category"), py::arg("name") = mx::EMPTY_STRING) + .def("changeChildCategory", &mx::Element::changeChildCategory) .def("_getChild", &mx::Element::getChild) .def("getChildren", &mx::Element::getChildren) .def("setChildIndex", &mx::Element::setChildIndex) diff --git a/source/PyMaterialX/PyMaterialXCore/PyUtil.cpp b/source/PyMaterialX/PyMaterialXCore/PyUtil.cpp index 6dd761c52e..a646a5ecf1 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyUtil.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyUtil.cpp @@ -26,5 +26,4 @@ void bindPyUtil(py::module& mod) mod.def("splitNamePath", &mx::splitNamePath); mod.def("createNamePath", &mx::createNamePath); mod.def("parentNamePath", &mx::parentNamePath); - mod.def("changeChildCategory", &mx::changeChildCategory); }