Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
876 changes: 865 additions & 11 deletions libraries/bxdf/open_pbr_surface.mtlx

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0"?>
<materialx version="1.39" colorspace="lin_rec709">
<surfacematerial name="dielectric_haze" type="material">
<input name="surfaceshader" type="surfaceshader" nodename="dielectric_haze_shader" />
</surfacematerial>
<open_pbr_surface name="dielectric_haze_shader" type="surfaceshader">
<input name="specular_roughness" type="float" value="0.1" />
<input name="specular_haze" type="float" value="0.5" />
<input name="specular_haze_spread" type="float" value="0.5" />
</open_pbr_surface>
<surfacematerial name="metallic_haze" type="material">
<input name="surfaceshader" type="surfaceshader" nodename="metallic_haze_shader" />
</surfacematerial>
<open_pbr_surface name="metallic_haze_shader" type="surfaceshader">
<input name="base_metalness" type="float" value="1.0" />
<input name="base_color" type="color3" value="0.9, 0.7, 0.4" />
<input name="specular_roughness" type="float" value="0.15" />
<input name="specular_haze" type="float" value="0.5" />
<input name="specular_haze_spread" type="float" value="0.3" />
</open_pbr_surface>
</materialx>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0"?>
<materialx version="1.39" colorspace="lin_rec709">
<surfacematerial name="open_pbr_v1_1_1_mat" type="material">
<input name="surfaceshader" type="surfaceshader" nodename="open_pbr_v1_1_1_shader" />
</surfacematerial>
<open_pbr_surface name="open_pbr_v1_1_1_shader" type="surfaceshader" version="1.1.1">
<input name="base_color" type="color3" value="0.2, 0.5, 0.8" />
<input name="specular_roughness" type="float" value="0.2" />
<input name="coat_weight" type="float" value="0.5" />
<input name="coat_color" type="color3" value="1, 1, 1" />
<input name="coat_roughness" type="float" value="0.1" />
</open_pbr_surface>
</materialx>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?xml version="1.0"?>
<materialx version="1.39" colorspace="lin_rec709">
<!-- Explicit v1.2 with specular haze -->
<surfacematerial name="open_pbr_v1_2_explicit" type="material">
<input name="surfaceshader" type="surfaceshader" nodename="v1_2_shader" />
</surfacematerial>
<open_pbr_surface name="v1_2_shader" type="surfaceshader" version="1.2">
<input name="base_color" type="color3" value="0.9, 0.1, 0.1" />
<input name="specular_roughness" type="float" value="0.1" />
<input name="specular_haze" type="float" value="0.3" />
<input name="specular_haze_spread" type="float" value="0.4" />
</open_pbr_surface>

<!-- Explicit v1.1.1 without haze params -->
<surfacematerial name="open_pbr_v1_1_1_explicit" type="material">
<input name="surfaceshader" type="surfaceshader" nodename="v1_1_1_shader" />
</surfacematerial>
<open_pbr_surface name="v1_1_1_shader" type="surfaceshader" version="1.1.1">
<input name="base_color" type="color3" value="0.1, 0.9, 0.1" />
<input name="specular_roughness" type="float" value="0.25" />
<input name="coat_weight" type="float" value="0.3" />
</open_pbr_surface>

<!-- Implicit default (should resolve to v1.2) with haze params -->
<surfacematerial name="open_pbr_default_version" type="material">
<input name="surfaceshader" type="surfaceshader" nodename="default_shader" />
</surfacematerial>
<open_pbr_surface name="default_shader" type="surfaceshader">
<input name="base_color" type="color3" value="0.1, 0.1, 0.9" />
<input name="specular_roughness" type="float" value="0.05" />
<input name="specular_haze" type="float" value="0.6" />
<input name="specular_haze_spread" type="float" value="0.2" />
</open_pbr_surface>
</materialx>
69 changes: 67 additions & 2 deletions source/MaterialXCore/Document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

#include <MaterialXCore/Document.h>

#include <algorithm>
#include <map>
#include <mutex>
#include <shared_mutex>

Expand Down Expand Up @@ -265,16 +267,64 @@ void Document::importLibrary(const ConstDocumentPtr& library)
return;
}

// Phase 1: Build a rename map for versioned nodedef conflicts.
// When an incoming nodedef has the same name as an existing one but a
// different version, auto-rename it to <name>_<version> (dots→underscores)
// so both can coexist in the merged document.
std::map<string, string> renames;
for (const auto& child : library->getChildren())
{
ConstNodeDefPtr newNodeDef = child->asA<NodeDef>();
if (!newNodeDef || newNodeDef->getVersionString().empty())
continue;
const string childName = child->getQualifiedName(child->getName());
ConstElementPtr previous = getChild(childName);
if (!previous)
continue;
ConstNodeDefPtr prevNodeDef = previous->asA<NodeDef>();
if (!prevNodeDef)
continue;
if (newNodeDef->getVersionString() != prevNodeDef->getVersionString())
{
string vSuffix = newNodeDef->getVersionString();
std::replace(vSuffix.begin(), vSuffix.end(), '.', '_');
renames[childName] = childName + "_" + vSuffix;
}
}

// Phase 2: Extend renames to nodegraphs that implement a renamed nodedef.
if (!renames.empty())
{
for (const auto& child : library->getChildren())
{
if (!child->asA<NodeGraph>())
continue;
const string ndAttr = child->getAttribute(InterfaceElement::NODE_DEF_ATTRIBUTE);
if (ndAttr.empty())
continue;
const string qualNd = child->getQualifiedName(ndAttr);
auto it = renames.find(qualNd);
if (it == renames.end())
continue;
const string ngName = child->getQualifiedName(child->getName());
const string suffix = it->second.substr(it->first.size());
renames[ngName] = ngName + suffix;
}
}

// Phase 3: Import all children, applying renames and updating references.
for (auto child : library->getChildren())
{
if (child->getCategory().empty())
{
throw Exception("Trying to import child without a category: " + child->getName());
}

const string childName = child->getQualifiedName(child->getName());
const string originalName = child->getQualifiedName(child->getName());
auto renameIt = renames.find(originalName);
const string childName = (renameIt != renames.end()) ? renameIt->second : originalName;

// Check for duplicate elements.
// Check for duplicate elements (after applying any rename).
ConstElementPtr previous = getChild(childName);
if (previous)
{
Expand All @@ -284,6 +334,21 @@ void Document::importLibrary(const ConstDocumentPtr& library)
// Create the imported element.
ElementPtr childCopy = addChildOfCategory(child->getCategory(), childName);
childCopy->copyContentFrom(child);

// If this nodegraph's nodedef reference was renamed, update it.
if (!renames.empty() && child->asA<NodeGraph>())
{
const string ndAttr = childCopy->getAttribute(InterfaceElement::NODE_DEF_ATTRIBUTE);
if (!ndAttr.empty())
{
const string qualNd = child->getQualifiedName(ndAttr);
auto ndRename = renames.find(qualNd);
if (ndRename != renames.end())
childCopy->setAttribute(InterfaceElement::NODE_DEF_ATTRIBUTE, ndRename->second);

}
}

if (!childCopy->hasFilePrefix() && library->hasFilePrefix())
{
childCopy->setFilePrefix(library->getFilePrefix());
Expand Down
55 changes: 53 additions & 2 deletions source/MaterialXFormat/XmlIo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@

#include <MaterialXCore/Types.h>

#include <algorithm>
#include <cstring>
#include <fstream>
#include <map>
#include <sstream>

using namespace pugi;
Expand Down Expand Up @@ -123,6 +125,9 @@ void elementFromXml(const xml_node& xmlNode, ElementPtr elem, const XmlReadOptio
}
}

// Track auto-renames for versioned nodedef conflicts within this element's children.
std::map<string, string> versionedRenames;

// Create child elements and recurse.
for (const xml_node& xmlChild : xmlNode.children())
{
Expand All @@ -133,12 +138,47 @@ void elementFromXml(const xml_node& xmlNode, ElementPtr elem, const XmlReadOptio
continue;
}

// Get child name and skip duplicates.
// Get child name and handle duplicates.
string name = xmlChild.attribute(Element::NAME_ATTRIBUTE.c_str()).value();
ConstElementPtr previous = elem->getChild(name);
if (previous)
{
continue;
// Auto-rename versioned nodedef conflicts instead of skipping.
if (category == NodeDef::CATEGORY)
{
string newVersion = xmlChild.attribute(InterfaceElement::VERSION_ATTRIBUTE.c_str()).value();
ConstNodeDefPtr prevNodeDef = previous->asA<NodeDef>();
if (prevNodeDef && !newVersion.empty() && newVersion != prevNodeDef->getVersionString())
{
string vSuffix = newVersion;
std::replace(vSuffix.begin(), vSuffix.end(), '.', '_');
name = name + "_" + vSuffix;
versionedRenames[xmlChild.attribute(Element::NAME_ATTRIBUTE.c_str()).value()] = name;
}
else
{
continue;
}
}
else if (category == NodeGraph::CATEGORY && !versionedRenames.empty())
{
// Auto-rename nodegraphs that implement a renamed nodedef.
string ndAttr = xmlChild.attribute(InterfaceElement::NODE_DEF_ATTRIBUTE.c_str()).value();
auto it = versionedRenames.find(ndAttr);
if (it != versionedRenames.end())
{
string suffix = it->second.substr(it->first.size());
name = name + suffix;
}
else
{
continue;
}
}
else
{
continue;
}
}

// Enforce maximum tree depth.
Expand All @@ -151,6 +191,17 @@ void elementFromXml(const xml_node& xmlNode, ElementPtr elem, const XmlReadOptio
ElementPtr child = elem->addChildOfCategory(category, name);
elementFromXml(xmlChild, child, readOptions, depth + 1);

// Update nodedef reference on auto-renamed nodegraphs.
if (category == NodeGraph::CATEGORY && !versionedRenames.empty())
{
string ndAttr = child->getAttribute(InterfaceElement::NODE_DEF_ATTRIBUTE);
auto it = versionedRenames.find(ndAttr);
if (it != versionedRenames.end())
{
child->setAttribute(InterfaceElement::NODE_DEF_ATTRIBUTE, it->second);
}
}

// Handle the interpretation of XML comments and newlines.
if (readOptions && category.empty())
{
Expand Down
Loading
Loading