mirror of
https://github.com/lighttransport/tinyusdz.git
synced 2026-01-18 01:11:17 +01:00
Add Blender v4.5 MaterialX OpenPBR shader support
Implement support for ND_open_pbr_surface_surfaceshader exported by Blender v4.5 when using MaterialX. This enables proper parsing and conversion of OpenPBR materials from Blender-exported USD files. Key changes: - Add MtlxOpenPBRSurface struct with all Blender v4.5 parameters in usdMtlx.hh - Implement ReconstructShader specialization for MtlxOpenPBRSurface in prim-reconstruct.cc - Add MaterialXConfigAPI detection and OpenPBR shader attachment in render-data.cc - Implement DumpOpenPBRSurface for material output in render-scene-dump.cc - Add pretty-print support for MtlxOpenPBRSurface in pprinter.cc When MaterialXConfigAPI is present on a Material, the system now: 1. Attempts to parse outputs:mtlx:surface connection 2. Falls back to searching for child Shader prims with OpenPBR info:id 3. Converts MtlxOpenPBRSurface to OpenPBRSurface for rendering Tested with models/cube-materialx.usda and models/suzanne-materialx.usda 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
174
models/cube-materialx.usda
Executable file
174
models/cube-materialx.usda
Executable file
@@ -0,0 +1,174 @@
|
||||
#usda 1.0
|
||||
(
|
||||
defaultPrim = "root"
|
||||
doc = "Blender v4.5.4 LTS"
|
||||
metersPerUnit = 1
|
||||
upAxis = "Z"
|
||||
)
|
||||
|
||||
def Xform "root" (
|
||||
customData = {
|
||||
dictionary Blender = {
|
||||
bool generated = 1
|
||||
}
|
||||
}
|
||||
)
|
||||
{
|
||||
def Xform "Cube"
|
||||
{
|
||||
custom string userProperties:blender:object_name = "Cube"
|
||||
|
||||
def Mesh "Cube_001" (
|
||||
active = true
|
||||
prepend apiSchemas = ["MaterialBindingAPI"]
|
||||
)
|
||||
{
|
||||
uniform bool doubleSided = 1
|
||||
float3[] extent = [(-1, -1, -1), (1, 1, 1)]
|
||||
int[] faceVertexCounts = [4, 4, 4, 4, 4, 4]
|
||||
int[] faceVertexIndices = [0, 1, 3, 2, 2, 3, 7, 6, 6, 7, 5, 4, 4, 5, 1, 0, 2, 6, 4, 0, 7, 3, 1, 5]
|
||||
rel material:binding = </root/_materials/Material_003>
|
||||
normal3f[] normals = [(-1, 0, 0), (-1, 0, 0), (-1, 0, 0), (-1, 0, 0), (0, 1, 0), (0, 1, 0), (0, 1, 0), (0, 1, 0), (1, 0, 0), (1, 0, 0), (1, 0, 0), (1, 0, 0), (0, -1, 0), (0, -1, 0), (0, -1, 0), (0, -1, 0), (0, 0, -1), (0, 0, -1), (0, 0, -1), (0, 0, -1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1)] (
|
||||
interpolation = "faceVarying"
|
||||
)
|
||||
point3f[] points = [(-1, -1, -1), (-1, -1, 1), (-1, 1, -1), (-1, 1, 1), (1, -1, -1), (1, -1, 1), (1, 1, -1), (1, 1, 1)]
|
||||
texCoord2f[] primvars:st = [(0.375, 0), (0.625, 0), (0.625, 0.25), (0.375, 0.25), (0.375, 0.25), (0.625, 0.25), (0.625, 0.5), (0.375, 0.5), (0.375, 0.5), (0.625, 0.5), (0.625, 0.75), (0.375, 0.75), (0.375, 0.75), (0.625, 0.75), (0.625, 1), (0.375, 1), (0.125, 0.5), (0.375, 0.5), (0.375, 0.75), (0.125, 0.75), (0.625, 0.5), (0.875, 0.5), (0.875, 0.75), (0.625, 0.75)] (
|
||||
interpolation = "faceVarying"
|
||||
)
|
||||
uniform token subdivisionScheme = "none"
|
||||
custom string userProperties:blender:data_name = "Cube.001"
|
||||
}
|
||||
}
|
||||
|
||||
def Scope "_materials"
|
||||
{
|
||||
def Material "Material_003" (
|
||||
prepend apiSchemas = ["MaterialXConfigAPI"]
|
||||
)
|
||||
{
|
||||
string config:mtlx:version = "1.39"
|
||||
token outputs:mtlx:surface.connect = </root/_materials/Material_003/Principled_BSDF_mtlx1.outputs:surface>
|
||||
token outputs:surface.connect = </root/_materials/Material_003/Principled_BSDF.outputs:surface>
|
||||
custom string userProperties:blender:data_name = "Material.003"
|
||||
|
||||
def Shader "Principled_BSDF"
|
||||
{
|
||||
uniform token info:id = "UsdPreviewSurface"
|
||||
float inputs:clearcoat = 0
|
||||
float inputs:clearcoatRoughness = 0.03
|
||||
color3f inputs:diffuseColor = (0.8, 0.8, 0.8)
|
||||
float inputs:ior = 1.5
|
||||
float inputs:metallic = 0
|
||||
float inputs:opacity = 1
|
||||
float inputs:roughness = 0.5
|
||||
float inputs:specular = 0.5
|
||||
token outputs:surface
|
||||
}
|
||||
|
||||
def Shader "Principled_BSDF_mtlx1"
|
||||
{
|
||||
uniform token info:id = "ND_open_pbr_surface_surfaceshader"
|
||||
color3f inputs:base_color = (0.8, 0.8, 0.8)
|
||||
float inputs:base_diffuse_roughness = 0
|
||||
float inputs:base_metalness = 0
|
||||
float inputs:base_weight = 1
|
||||
color3f inputs:coat_color = (1, 1, 1)
|
||||
float inputs:coat_darkening
|
||||
float inputs:coat_ior = 1.5
|
||||
float inputs:coat_roughness = 0.03
|
||||
float inputs:coat_roughness_anisotropy
|
||||
float inputs:coat_weight = 0
|
||||
color3f inputs:emission_color = (1, 1, 1)
|
||||
float inputs:emission_luminance = 0
|
||||
color3f inputs:fuzz_color = (1, 1, 1)
|
||||
float inputs:fuzz_roughness = 0.5
|
||||
float inputs:fuzz_weight = 0
|
||||
float3 inputs:geometry_coat_normal
|
||||
float3 inputs:geometry_coat_tangent
|
||||
float3 inputs:geometry_normal
|
||||
float inputs:geometry_opacity = 1
|
||||
float3 inputs:geometry_tangent.connect = </root/_materials/Material_003/NodeGraphs.outputs:node_003_out>
|
||||
bool inputs:geometry_thin_walled
|
||||
color3f inputs:specular_color = (1, 1, 1)
|
||||
float inputs:specular_ior = 1.5
|
||||
float inputs:specular_roughness = 0.5
|
||||
float inputs:specular_roughness_anisotropy = 0
|
||||
float inputs:specular_weight = 1
|
||||
color3f inputs:subsurface_color = (0.8, 0.8, 0.8)
|
||||
float inputs:subsurface_radius = 0.05
|
||||
color3f inputs:subsurface_radius_scale = (1, 0.2, 0.1)
|
||||
float inputs:subsurface_scatter_anisotropy = 0
|
||||
float inputs:subsurface_weight = 0
|
||||
float inputs:thin_film_ior = 1.33
|
||||
float inputs:thin_film_thickness = 0
|
||||
float inputs:thin_film_weight = 0
|
||||
color3f inputs:transmission_color = (0.8, 0.8, 0.8)
|
||||
float inputs:transmission_depth
|
||||
float inputs:transmission_dispersion_abbe_number
|
||||
float inputs:transmission_dispersion_scale
|
||||
color3f inputs:transmission_scatter
|
||||
float inputs:transmission_scatter_anisotropy
|
||||
float inputs:transmission_weight = 0
|
||||
token outputs:surface
|
||||
}
|
||||
|
||||
def NodeGraph "NodeGraphs"
|
||||
{
|
||||
float3 outputs:node_003_out.connect = </root/_materials/Material_003/NodeGraphs/node_003.outputs:out>
|
||||
|
||||
def Shader "node"
|
||||
{
|
||||
uniform token info:id = "ND_normal_vector3"
|
||||
string inputs:space = "world"
|
||||
float3 outputs:out
|
||||
}
|
||||
|
||||
def Shader "node_001"
|
||||
{
|
||||
uniform token info:id = "ND_normalize_vector3"
|
||||
float3 inputs:in.connect = </root/_materials/Material_003/NodeGraphs/node.outputs:out>
|
||||
float3 outputs:out
|
||||
}
|
||||
|
||||
def Shader "node_002"
|
||||
{
|
||||
uniform token info:id = "ND_tangent_vector3"
|
||||
string inputs:space = "world"
|
||||
float3 outputs:out
|
||||
}
|
||||
|
||||
def Shader "node_003"
|
||||
{
|
||||
uniform token info:id = "ND_normalize_vector3"
|
||||
float3 inputs:in.connect = </root/_materials/Material_003/NodeGraphs/node_002.outputs:out>
|
||||
float3 outputs:out
|
||||
}
|
||||
|
||||
def Shader "node_004"
|
||||
{
|
||||
uniform token info:id = "ND_rotate3d_vector3"
|
||||
float inputs:amount = -90
|
||||
float3 inputs:axis.connect = </root/_materials/Material_003/NodeGraphs/node_001.outputs:out>
|
||||
float3 inputs:in.connect = </root/_materials/Material_003/NodeGraphs/node_003.outputs:out>
|
||||
float3 outputs:out
|
||||
}
|
||||
|
||||
def Shader "node_005"
|
||||
{
|
||||
uniform token info:id = "ND_normalize_vector3"
|
||||
float3 inputs:in.connect = </root/_materials/Material_003/NodeGraphs/node_004.outputs:out>
|
||||
float3 outputs:out
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def DomeLight "env_light"
|
||||
{
|
||||
float inputs:intensity = 1
|
||||
asset inputs:texture:file = @.\textures\color_121212.hdr@
|
||||
float3 xformOp:rotateXYZ = (90, 1.2722219e-14, 90)
|
||||
uniform token[] xformOpOrder = ["xformOp:rotateXYZ"]
|
||||
}
|
||||
}
|
||||
|
||||
174
models/suzanne-materialx.usda
Executable file
174
models/suzanne-materialx.usda
Executable file
File diff suppressed because one or more lines are too long
BIN
models/suzanne-materialx.usdc
Executable file
BIN
models/suzanne-materialx.usdc
Executable file
Binary file not shown.
@@ -14,6 +14,7 @@
|
||||
#include "str-util.hh"
|
||||
#include "tiny-format.hh"
|
||||
#include "usdShade.hh"
|
||||
#include "usdMtlx.hh"
|
||||
#include "value-pprint.hh"
|
||||
#include "timesamples-pprint.hh"
|
||||
//
|
||||
@@ -4108,6 +4109,9 @@ std::string to_string(const Shader &shader, const uint32_t indent,
|
||||
ss << print_shader_params(pvtx2d.value(), indent + 1);
|
||||
} else if (auto pvs = shader.value.get_value<UsdPreviewSurface>()) {
|
||||
ss << print_shader_params(pvs.value(), indent + 1);
|
||||
} else if (auto mtlx_opbr = shader.value.get_value<MtlxOpenPBRSurface>()) {
|
||||
// Blender v4.5 MaterialX OpenPBR Surface
|
||||
ss << print_common_shader_params(mtlx_opbr.value(), indent + 1);
|
||||
} else if (auto pvsn = shader.value.get_value<ShaderNode>()) {
|
||||
// Generic ShaderNode
|
||||
ss << print_common_shader_params(pvsn.value(), indent + 1);
|
||||
|
||||
@@ -5529,6 +5529,153 @@ bool ReconstructShader<MtlxAutodeskStandardSurface>(
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool ReconstructShader<MtlxOpenPBRSurface>(
|
||||
const Specifier &spec,
|
||||
PropertyMap &properties,
|
||||
const ReferenceList &references,
|
||||
MtlxOpenPBRSurface *surface,
|
||||
std::string *warn,
|
||||
std::string *err,
|
||||
const PrimReconstructOptions &options) {
|
||||
(void)spec;
|
||||
(void)references;
|
||||
(void)options;
|
||||
(void)warn;
|
||||
|
||||
std::set<std::string> table;
|
||||
table.insert("info:id"); // `info:id` is already parsed in ReconstructPrim<Shader>
|
||||
|
||||
for (auto &prop : properties) {
|
||||
// Base properties
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:base_weight", MtlxOpenPBRSurface,
|
||||
surface->base_weight)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:base_color", MtlxOpenPBRSurface,
|
||||
surface->base_color)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:base_metalness", MtlxOpenPBRSurface,
|
||||
surface->base_metalness)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:base_diffuse_roughness", MtlxOpenPBRSurface,
|
||||
surface->base_diffuse_roughness)
|
||||
|
||||
// Specular properties
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:specular_weight", MtlxOpenPBRSurface,
|
||||
surface->specular_weight)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:specular_color", MtlxOpenPBRSurface,
|
||||
surface->specular_color)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:specular_roughness", MtlxOpenPBRSurface,
|
||||
surface->specular_roughness)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:specular_ior", MtlxOpenPBRSurface,
|
||||
surface->specular_ior)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:specular_anisotropy", MtlxOpenPBRSurface,
|
||||
surface->specular_anisotropy)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:specular_rotation", MtlxOpenPBRSurface,
|
||||
surface->specular_rotation)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:specular_roughness_anisotropy", MtlxOpenPBRSurface,
|
||||
surface->specular_roughness_anisotropy)
|
||||
|
||||
// Transmission properties
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:transmission_weight", MtlxOpenPBRSurface,
|
||||
surface->transmission_weight)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:transmission_color", MtlxOpenPBRSurface,
|
||||
surface->transmission_color)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:transmission_depth", MtlxOpenPBRSurface,
|
||||
surface->transmission_depth)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:transmission_scatter", MtlxOpenPBRSurface,
|
||||
surface->transmission_scatter)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:transmission_scatter_anisotropy", MtlxOpenPBRSurface,
|
||||
surface->transmission_scatter_anisotropy)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:transmission_dispersion", MtlxOpenPBRSurface,
|
||||
surface->transmission_dispersion)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:transmission_dispersion_abbe_number", MtlxOpenPBRSurface,
|
||||
surface->transmission_dispersion_abbe_number)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:transmission_dispersion_scale", MtlxOpenPBRSurface,
|
||||
surface->transmission_dispersion_scale)
|
||||
|
||||
// Subsurface properties
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:subsurface_weight", MtlxOpenPBRSurface,
|
||||
surface->subsurface_weight)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:subsurface_color", MtlxOpenPBRSurface,
|
||||
surface->subsurface_color)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:subsurface_radius", MtlxOpenPBRSurface,
|
||||
surface->subsurface_radius)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:subsurface_radius_scale", MtlxOpenPBRSurface,
|
||||
surface->subsurface_radius_scale)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:subsurface_scale", MtlxOpenPBRSurface,
|
||||
surface->subsurface_scale)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:subsurface_anisotropy", MtlxOpenPBRSurface,
|
||||
surface->subsurface_anisotropy)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:subsurface_scatter_anisotropy", MtlxOpenPBRSurface,
|
||||
surface->subsurface_scatter_anisotropy)
|
||||
|
||||
// Coat properties
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:coat_weight", MtlxOpenPBRSurface,
|
||||
surface->coat_weight)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:coat_color", MtlxOpenPBRSurface,
|
||||
surface->coat_color)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:coat_roughness", MtlxOpenPBRSurface,
|
||||
surface->coat_roughness)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:coat_anisotropy", MtlxOpenPBRSurface,
|
||||
surface->coat_anisotropy)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:coat_rotation", MtlxOpenPBRSurface,
|
||||
surface->coat_rotation)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:coat_roughness_anisotropy", MtlxOpenPBRSurface,
|
||||
surface->coat_roughness_anisotropy)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:coat_ior", MtlxOpenPBRSurface,
|
||||
surface->coat_ior)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:coat_darkening", MtlxOpenPBRSurface,
|
||||
surface->coat_darkening)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:coat_affect_color", MtlxOpenPBRSurface,
|
||||
surface->coat_affect_color)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:coat_affect_roughness", MtlxOpenPBRSurface,
|
||||
surface->coat_affect_roughness)
|
||||
|
||||
// Fuzz properties
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:fuzz_weight", MtlxOpenPBRSurface,
|
||||
surface->fuzz_weight)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:fuzz_color", MtlxOpenPBRSurface,
|
||||
surface->fuzz_color)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:fuzz_roughness", MtlxOpenPBRSurface,
|
||||
surface->fuzz_roughness)
|
||||
|
||||
// Thin film properties
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:thin_film_thickness", MtlxOpenPBRSurface,
|
||||
surface->thin_film_thickness)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:thin_film_ior", MtlxOpenPBRSurface,
|
||||
surface->thin_film_ior)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:thin_film_weight", MtlxOpenPBRSurface,
|
||||
surface->thin_film_weight)
|
||||
|
||||
// Emission properties
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:emission_luminance", MtlxOpenPBRSurface,
|
||||
surface->emission_luminance)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:emission_color", MtlxOpenPBRSurface,
|
||||
surface->emission_color)
|
||||
|
||||
// Geometry properties
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:geometry_opacity", MtlxOpenPBRSurface,
|
||||
surface->geometry_opacity)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:geometry_thin_walled", MtlxOpenPBRSurface,
|
||||
surface->geometry_thin_walled)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:geometry_normal", MtlxOpenPBRSurface,
|
||||
surface->geometry_normal)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:geometry_tangent", MtlxOpenPBRSurface,
|
||||
surface->geometry_tangent)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:geometry_coat_normal", MtlxOpenPBRSurface,
|
||||
surface->geometry_coat_normal)
|
||||
PARSE_TYPED_ATTRIBUTE(table, prop, "inputs:geometry_coat_tangent", MtlxOpenPBRSurface,
|
||||
surface->geometry_coat_tangent)
|
||||
|
||||
// Output
|
||||
PARSE_SHADER_TERMINAL_ATTRIBUTE(table, prop, "outputs:surface", MtlxOpenPBRSurface,
|
||||
surface->surface)
|
||||
|
||||
ADD_PROPERTY(table, prop, MtlxOpenPBRSurface, surface->props)
|
||||
PARSE_PROPERTY_END_MAKE_WARN(table, prop)
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool ReconstructShader<OpenPBRSurface>(
|
||||
const Specifier &spec,
|
||||
@@ -5848,6 +5995,15 @@ bool ReconstructPrim<Shader>(
|
||||
}
|
||||
shader->info_id = kMtlxAutodeskStandardSurface;
|
||||
shader->value = surface;
|
||||
} else if (shader_type.compare(kNdOpenPbrSurfaceSurfaceshader) == 0) {
|
||||
// Blender v4.5 MaterialX OpenPBR Surface export
|
||||
MtlxOpenPBRSurface surface;
|
||||
if (!ReconstructShader<MtlxOpenPBRSurface>(spec, properties, references,
|
||||
&surface, warn, err, options)) {
|
||||
PUSH_ERROR_AND_RETURN("Failed to Reconstruct " << kNdOpenPbrSurfaceSurfaceshader);
|
||||
}
|
||||
shader->info_id = kNdOpenPbrSurfaceSurfaceshader;
|
||||
shader->value = surface;
|
||||
} else {
|
||||
// Reconstruct as generic ShaderNode
|
||||
ShaderNode surface;
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "tinyusdz.hh"
|
||||
#include "usdGeom.hh"
|
||||
#include "usdShade.hh"
|
||||
#include "usdMtlx.hh"
|
||||
#include "value-pprint.hh"
|
||||
#include "logger.hh"
|
||||
#include "bone-util.hh"
|
||||
@@ -6182,6 +6183,7 @@ bool RenderSceneConverter::ConvertMaterial(const RenderSceneConverterEnv &env,
|
||||
|
||||
//
|
||||
// surface shader
|
||||
// First try outputs:surface (standard USD), then outputs:mtlx:surface (MaterialX)
|
||||
{
|
||||
if (material.surface.authored()) {
|
||||
auto paths = material.surface.get_connections();
|
||||
@@ -6233,10 +6235,11 @@ bool RenderSceneConverter::ConvertMaterial(const RenderSceneConverterEnv &env,
|
||||
shaderPrim->prim_type_name()));
|
||||
}
|
||||
|
||||
// Check for UsdPreviewSurface or OpenPBRSurface
|
||||
// Check for UsdPreviewSurface, OpenPBRSurface, or MtlxOpenPBRSurface (Blender v4.5+ export)
|
||||
const UsdPreviewSurface *psurface = shader->value.as<UsdPreviewSurface>();
|
||||
const OpenPBRSurface *openpbr = shader->value.as<OpenPBRSurface>();
|
||||
|
||||
const MtlxOpenPBRSurface *mtlx_openpbr = shader->value.as<MtlxOpenPBRSurface>();
|
||||
|
||||
// prop part must be `outputs:surface` for now.
|
||||
if (surfacePath.prop_part() != "outputs:surface") {
|
||||
PUSH_ERROR_AND_RETURN(
|
||||
@@ -6244,7 +6247,7 @@ bool RenderSceneConverter::ConvertMaterial(const RenderSceneConverterEnv &env,
|
||||
"`outputs:surface`, but got `{}`",
|
||||
mat_abs_path.full_path_name(), surfacePath.prop_part()));
|
||||
}
|
||||
|
||||
|
||||
if (psurface) {
|
||||
// Convert UsdPreviewSurface
|
||||
PreviewSurfaceShader pss;
|
||||
@@ -6254,7 +6257,7 @@ bool RenderSceneConverter::ConvertMaterial(const RenderSceneConverterEnv &env,
|
||||
}
|
||||
rmat.surfaceShader = pss;
|
||||
}
|
||||
|
||||
|
||||
if (openpbr) {
|
||||
// Convert OpenPBRSurface
|
||||
OpenPBRSurfaceShader openpbr_shader;
|
||||
@@ -6264,14 +6267,278 @@ bool RenderSceneConverter::ConvertMaterial(const RenderSceneConverterEnv &env,
|
||||
}
|
||||
rmat.openPBRShader = openpbr_shader;
|
||||
}
|
||||
|
||||
if (!psurface && !openpbr) {
|
||||
|
||||
if (mtlx_openpbr) {
|
||||
// Convert MtlxOpenPBRSurface (Blender v4.5+ MaterialX export with ND_open_pbr_surface_surfaceshader)
|
||||
// For now, convert it to OpenPBRSurface format by copying compatible parameters
|
||||
OpenPBRSurface converted_openpbr;
|
||||
|
||||
// Copy base layer properties
|
||||
converted_openpbr.base_weight = mtlx_openpbr->base_weight;
|
||||
converted_openpbr.base_color = mtlx_openpbr->base_color;
|
||||
converted_openpbr.base_roughness = mtlx_openpbr->base_diffuse_roughness;
|
||||
converted_openpbr.base_metalness = mtlx_openpbr->base_metalness;
|
||||
|
||||
// Copy specular properties
|
||||
converted_openpbr.specular_weight = mtlx_openpbr->specular_weight;
|
||||
converted_openpbr.specular_color = mtlx_openpbr->specular_color;
|
||||
converted_openpbr.specular_roughness = mtlx_openpbr->specular_roughness;
|
||||
converted_openpbr.specular_ior = mtlx_openpbr->specular_ior;
|
||||
converted_openpbr.specular_anisotropy = mtlx_openpbr->specular_anisotropy;
|
||||
converted_openpbr.specular_rotation = mtlx_openpbr->specular_rotation;
|
||||
|
||||
// Copy transmission properties
|
||||
converted_openpbr.transmission_weight = mtlx_openpbr->transmission_weight;
|
||||
converted_openpbr.transmission_color = mtlx_openpbr->transmission_color;
|
||||
converted_openpbr.transmission_depth = mtlx_openpbr->transmission_depth;
|
||||
converted_openpbr.transmission_scatter = mtlx_openpbr->transmission_scatter;
|
||||
converted_openpbr.transmission_scatter_anisotropy = mtlx_openpbr->transmission_scatter_anisotropy;
|
||||
converted_openpbr.transmission_dispersion = mtlx_openpbr->transmission_dispersion;
|
||||
|
||||
// Copy subsurface properties
|
||||
converted_openpbr.subsurface_weight = mtlx_openpbr->subsurface_weight;
|
||||
converted_openpbr.subsurface_color = mtlx_openpbr->subsurface_color;
|
||||
converted_openpbr.subsurface_scale = mtlx_openpbr->subsurface_scale;
|
||||
converted_openpbr.subsurface_anisotropy = mtlx_openpbr->subsurface_anisotropy;
|
||||
|
||||
// Copy coat properties
|
||||
converted_openpbr.coat_weight = mtlx_openpbr->coat_weight;
|
||||
converted_openpbr.coat_color = mtlx_openpbr->coat_color;
|
||||
converted_openpbr.coat_roughness = mtlx_openpbr->coat_roughness;
|
||||
converted_openpbr.coat_anisotropy = mtlx_openpbr->coat_anisotropy;
|
||||
converted_openpbr.coat_rotation = mtlx_openpbr->coat_rotation;
|
||||
converted_openpbr.coat_ior = mtlx_openpbr->coat_ior;
|
||||
// Note: MtlxOpenPBRSurface has float coat_affect_color, OpenPBRSurface has color3f
|
||||
// Just skip coat_affect_color conversion for now since types don't match easily
|
||||
// TODO: Proper type conversion if needed
|
||||
converted_openpbr.coat_affect_roughness = mtlx_openpbr->coat_affect_roughness;
|
||||
|
||||
// Copy emission properties
|
||||
converted_openpbr.emission_luminance = mtlx_openpbr->emission_luminance;
|
||||
converted_openpbr.emission_color = mtlx_openpbr->emission_color;
|
||||
|
||||
// Copy geometry properties
|
||||
converted_openpbr.opacity = mtlx_openpbr->geometry_opacity;
|
||||
// Copy normal and tangent if they have values (TypedAttribute -> TypedAttributeWithFallback)
|
||||
if (mtlx_openpbr->geometry_normal.has_value()) {
|
||||
auto normal_val = mtlx_openpbr->geometry_normal.get_value();
|
||||
if (normal_val) {
|
||||
converted_openpbr.normal = normal_val.value();
|
||||
}
|
||||
}
|
||||
if (mtlx_openpbr->geometry_tangent.has_value()) {
|
||||
auto tangent_val = mtlx_openpbr->geometry_tangent.get_value();
|
||||
if (tangent_val) {
|
||||
converted_openpbr.tangent = tangent_val.value();
|
||||
}
|
||||
}
|
||||
|
||||
// Convert to OpenPBRSurfaceShader
|
||||
OpenPBRSurfaceShader openpbr_shader;
|
||||
if (!ConvertOpenPBRSurfaceShader(env, surfacePath, converted_openpbr, &openpbr_shader)) {
|
||||
PUSH_ERROR_AND_RETURN(fmt::format(
|
||||
"Failed to convert MtlxOpenPBRSurface : {}", surfacePath.prim_part()));
|
||||
}
|
||||
rmat.openPBRShader = openpbr_shader;
|
||||
}
|
||||
|
||||
if (!psurface && !openpbr && !mtlx_openpbr) {
|
||||
PUSH_ERROR_AND_RETURN(
|
||||
fmt::format("Shader's info:id must be UsdPreviewSurface or OpenPBRSurface, but got {}",
|
||||
fmt::format("Shader's info:id must be UsdPreviewSurface, OpenPBRSurface, or ND_open_pbr_surface_surfaceshader, but got {}",
|
||||
shader->info_id));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Process MaterialX-specific surface shader when MaterialXConfigAPI is present
|
||||
// When MaterialXConfigAPI is authored, we look for MaterialX shaders
|
||||
{
|
||||
// Check if MaterialXConfigAPI is applied (via materialXConfig field)
|
||||
// For now, we only check the materialXConfig field as apiSchemas checking would need
|
||||
// proper MaterialXConfigAPI enum support in APISchemas::APIName
|
||||
bool has_materialx_api = material.materialXConfig.has_value();
|
||||
|
||||
PUSH_WARN(fmt::format("Material {}: materialXConfig.has_value = {}",
|
||||
mat_abs_path.full_path_name(), has_materialx_api));
|
||||
|
||||
if (has_materialx_api) {
|
||||
DCOUT("Material has MaterialXConfigAPI, looking for MaterialX shaders");
|
||||
PUSH_WARN("Material has MaterialXConfigAPI, looking for MaterialX shaders");
|
||||
|
||||
// First try to parse outputs:mtlx:surface connection
|
||||
Path mtlxSurfacePath;
|
||||
bool has_mtlx_surface = false;
|
||||
|
||||
// Try to find the connection in various forms
|
||||
for (const auto& prop_name : {"outputs:mtlx:surface.connect", "outputs:mtlx:surface"}) {
|
||||
auto it = material.props.find(prop_name);
|
||||
if (it != material.props.end()) {
|
||||
if (it->second.is_relationship()) {
|
||||
auto targets = it->second.get_relationTargets();
|
||||
if (!targets.empty()) {
|
||||
mtlxSurfacePath = targets[0];
|
||||
has_mtlx_surface = true;
|
||||
DCOUT("Found MaterialX surface connection via relationship: " << mtlxSurfacePath);
|
||||
break;
|
||||
}
|
||||
} else if (it->second.is_attribute()) {
|
||||
// Try to extract path from attribute
|
||||
auto attr = it->second.get_attribute();
|
||||
if (auto token_val = attr.get_value<value::token>()) {
|
||||
std::string path_str = token_val.value().str();
|
||||
if (!path_str.empty()) {
|
||||
// Remove brackets if present
|
||||
if (path_str.front() == '<' && path_str.back() == '>') {
|
||||
path_str = path_str.substr(1, path_str.size() - 2);
|
||||
}
|
||||
// Parse the path
|
||||
size_t pos = path_str.find(".outputs:");
|
||||
if (pos != std::string::npos) {
|
||||
std::string prim_path = path_str.substr(0, pos);
|
||||
mtlxSurfacePath = Path(prim_path, "");
|
||||
has_mtlx_surface = true;
|
||||
DCOUT("Found MaterialX surface connection via token: " << mtlxSurfacePath);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If direct connection parsing failed, look for child Shader prims with OpenPBR info:id
|
||||
if (!has_mtlx_surface) {
|
||||
DCOUT("Direct connection not found, searching for child shaders with OpenPBR info:id");
|
||||
PUSH_WARN("Direct connection not found, searching for child shaders with OpenPBR info:id");
|
||||
|
||||
// Get the material prim from the stage to access its children
|
||||
const Prim* mat_prim = nullptr;
|
||||
if (env.stage.find_prim_at_path(mat_abs_path, mat_prim, &err)) {
|
||||
if (mat_prim) {
|
||||
// Iterate through children to find OpenPBR shader
|
||||
for (const auto& child : mat_prim->children()) {
|
||||
const Shader* shader = child.as<Shader>();
|
||||
if (shader) {
|
||||
// Check if this is an OpenPBR shader by its info:id
|
||||
if (shader->info_id == kNdOpenPbrSurfaceSurfaceshader ||
|
||||
shader->info_id == "ND_open_pbr_surface_surfaceshader") {
|
||||
Path child_path = mat_abs_path;
|
||||
child_path = child_path.append_element(child.element_name());
|
||||
mtlxSurfacePath = child_path;
|
||||
has_mtlx_surface = true;
|
||||
DCOUT("Found OpenPBR shader child: " << child_path);
|
||||
PUSH_WARN(fmt::format("Found OpenPBR shader child: {}", child_path.full_path_name()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process the found MaterialX shader
|
||||
if (has_mtlx_surface) {
|
||||
const Prim *mtlxShaderPrim{nullptr};
|
||||
if (!env.stage.find_prim_at_path(
|
||||
Path(mtlxSurfacePath.prim_part(), /* prop part */ ""), mtlxShaderPrim,
|
||||
&err)) {
|
||||
PUSH_WARN(fmt::format(
|
||||
"MaterialX shader path {} not found in stage",
|
||||
mtlxSurfacePath.full_path_name()));
|
||||
} else if (mtlxShaderPrim) {
|
||||
const Shader *mtlxShader = mtlxShaderPrim->as<Shader>();
|
||||
|
||||
if (mtlxShader) {
|
||||
// Check if it's an OpenPBR shader
|
||||
const MtlxOpenPBRSurface *mtlx_openpbr = mtlxShader->value.as<MtlxOpenPBRSurface>();
|
||||
|
||||
if (mtlx_openpbr) {
|
||||
DCOUT("Converting MtlxOpenPBRSurface to RenderMaterial");
|
||||
|
||||
// Convert MtlxOpenPBRSurface to OpenPBRSurface
|
||||
OpenPBRSurface converted_openpbr;
|
||||
|
||||
// Copy base layer properties
|
||||
converted_openpbr.base_weight = mtlx_openpbr->base_weight;
|
||||
converted_openpbr.base_color = mtlx_openpbr->base_color;
|
||||
converted_openpbr.base_roughness = mtlx_openpbr->base_diffuse_roughness;
|
||||
converted_openpbr.base_metalness = mtlx_openpbr->base_metalness;
|
||||
|
||||
// Copy specular properties
|
||||
converted_openpbr.specular_weight = mtlx_openpbr->specular_weight;
|
||||
converted_openpbr.specular_color = mtlx_openpbr->specular_color;
|
||||
converted_openpbr.specular_roughness = mtlx_openpbr->specular_roughness;
|
||||
converted_openpbr.specular_ior = mtlx_openpbr->specular_ior;
|
||||
converted_openpbr.specular_anisotropy = mtlx_openpbr->specular_anisotropy;
|
||||
converted_openpbr.specular_rotation = mtlx_openpbr->specular_rotation;
|
||||
|
||||
// Copy transmission properties
|
||||
converted_openpbr.transmission_weight = mtlx_openpbr->transmission_weight;
|
||||
converted_openpbr.transmission_color = mtlx_openpbr->transmission_color;
|
||||
converted_openpbr.transmission_depth = mtlx_openpbr->transmission_depth;
|
||||
converted_openpbr.transmission_scatter = mtlx_openpbr->transmission_scatter;
|
||||
converted_openpbr.transmission_scatter_anisotropy = mtlx_openpbr->transmission_scatter_anisotropy;
|
||||
converted_openpbr.transmission_dispersion = mtlx_openpbr->transmission_dispersion;
|
||||
|
||||
// Copy subsurface properties
|
||||
converted_openpbr.subsurface_weight = mtlx_openpbr->subsurface_weight;
|
||||
converted_openpbr.subsurface_color = mtlx_openpbr->subsurface_color;
|
||||
converted_openpbr.subsurface_scale = mtlx_openpbr->subsurface_scale;
|
||||
converted_openpbr.subsurface_anisotropy = mtlx_openpbr->subsurface_anisotropy;
|
||||
|
||||
// Copy coat properties
|
||||
converted_openpbr.coat_weight = mtlx_openpbr->coat_weight;
|
||||
converted_openpbr.coat_color = mtlx_openpbr->coat_color;
|
||||
converted_openpbr.coat_roughness = mtlx_openpbr->coat_roughness;
|
||||
converted_openpbr.coat_anisotropy = mtlx_openpbr->coat_anisotropy;
|
||||
converted_openpbr.coat_rotation = mtlx_openpbr->coat_rotation;
|
||||
converted_openpbr.coat_ior = mtlx_openpbr->coat_ior;
|
||||
converted_openpbr.coat_affect_roughness = mtlx_openpbr->coat_affect_roughness;
|
||||
|
||||
// Copy emission properties
|
||||
converted_openpbr.emission_luminance = mtlx_openpbr->emission_luminance;
|
||||
converted_openpbr.emission_color = mtlx_openpbr->emission_color;
|
||||
|
||||
// Copy geometry properties
|
||||
converted_openpbr.opacity = mtlx_openpbr->geometry_opacity;
|
||||
// Copy normal and tangent if they have values
|
||||
if (mtlx_openpbr->geometry_normal.has_value()) {
|
||||
auto normal_val = mtlx_openpbr->geometry_normal.get_value();
|
||||
if (normal_val) {
|
||||
converted_openpbr.normal = normal_val.value();
|
||||
}
|
||||
}
|
||||
if (mtlx_openpbr->geometry_tangent.has_value()) {
|
||||
auto tangent_val = mtlx_openpbr->geometry_tangent.get_value();
|
||||
if (tangent_val) {
|
||||
converted_openpbr.tangent = tangent_val.value();
|
||||
}
|
||||
}
|
||||
|
||||
// Convert to OpenPBRSurfaceShader
|
||||
OpenPBRSurfaceShader openpbr_shader;
|
||||
if (!ConvertOpenPBRSurfaceShader(env, mtlxSurfacePath, converted_openpbr, &openpbr_shader)) {
|
||||
PUSH_WARN(fmt::format(
|
||||
"Failed to convert MtlxOpenPBRSurface : {}", mtlxSurfacePath.prim_part()));
|
||||
} else {
|
||||
rmat.openPBRShader = openpbr_shader;
|
||||
DCOUT("Successfully attached MaterialX OpenPBR shader to RenderMaterial");
|
||||
PUSH_WARN(fmt::format("Successfully attached MaterialX OpenPBR shader to RenderMaterial: {}",
|
||||
mtlxSurfacePath.full_path_name()));
|
||||
}
|
||||
} else {
|
||||
PUSH_WARN(fmt::format(
|
||||
"Found shader {} but it's not ND_open_pbr_surface_surfaceshader (got {})",
|
||||
mtlxSurfacePath.prim_part(), mtlxShader->info_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DCOUT("No MaterialX OpenPBR shader found for material with MaterialXConfigAPI");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DCOUT("Converted Material: " << mat_abs_path);
|
||||
|
||||
(*rmat_out) = rmat;
|
||||
|
||||
@@ -437,6 +437,151 @@ std::string DumpCamera(const RenderCamera &camera, uint32_t indent) {
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string DumpOpenPBRSurface(const OpenPBRSurfaceShader &shader,
|
||||
uint32_t indent) {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "OpenPBRSurfaceShader {\n";
|
||||
|
||||
// Base layer
|
||||
ss << pprint::Indent(indent + 1) << "base_weight = ";
|
||||
if (shader.base_weight.is_texture()) {
|
||||
ss << "texture_id[" << shader.base_weight.texture_id << "]";
|
||||
} else {
|
||||
ss << shader.base_weight.value;
|
||||
}
|
||||
ss << "\n";
|
||||
|
||||
ss << pprint::Indent(indent + 1) << "base_color = ";
|
||||
if (shader.base_color.is_texture()) {
|
||||
ss << "texture_id[" << shader.base_color.texture_id << "]";
|
||||
} else {
|
||||
ss << shader.base_color.value;
|
||||
}
|
||||
ss << "\n";
|
||||
|
||||
ss << pprint::Indent(indent + 1) << "base_roughness = ";
|
||||
if (shader.base_roughness.is_texture()) {
|
||||
ss << "texture_id[" << shader.base_roughness.texture_id << "]";
|
||||
} else {
|
||||
ss << shader.base_roughness.value;
|
||||
}
|
||||
ss << "\n";
|
||||
|
||||
ss << pprint::Indent(indent + 1) << "base_metalness = ";
|
||||
if (shader.base_metalness.is_texture()) {
|
||||
ss << "texture_id[" << shader.base_metalness.texture_id << "]";
|
||||
} else {
|
||||
ss << shader.base_metalness.value;
|
||||
}
|
||||
ss << "\n";
|
||||
|
||||
// Specular layer
|
||||
ss << pprint::Indent(indent + 1) << "specular_weight = ";
|
||||
if (shader.specular_weight.is_texture()) {
|
||||
ss << "texture_id[" << shader.specular_weight.texture_id << "]";
|
||||
} else {
|
||||
ss << shader.specular_weight.value;
|
||||
}
|
||||
ss << "\n";
|
||||
|
||||
ss << pprint::Indent(indent + 1) << "specular_color = ";
|
||||
if (shader.specular_color.is_texture()) {
|
||||
ss << "texture_id[" << shader.specular_color.texture_id << "]";
|
||||
} else {
|
||||
ss << shader.specular_color.value;
|
||||
}
|
||||
ss << "\n";
|
||||
|
||||
ss << pprint::Indent(indent + 1) << "specular_roughness = ";
|
||||
if (shader.specular_roughness.is_texture()) {
|
||||
ss << "texture_id[" << shader.specular_roughness.texture_id << "]";
|
||||
} else {
|
||||
ss << shader.specular_roughness.value;
|
||||
}
|
||||
ss << "\n";
|
||||
|
||||
ss << pprint::Indent(indent + 1) << "specular_ior = ";
|
||||
if (shader.specular_ior.is_texture()) {
|
||||
ss << "texture_id[" << shader.specular_ior.texture_id << "]";
|
||||
} else {
|
||||
ss << shader.specular_ior.value;
|
||||
}
|
||||
ss << "\n";
|
||||
|
||||
// Coat layer
|
||||
ss << pprint::Indent(indent + 1) << "coat_weight = ";
|
||||
if (shader.coat_weight.is_texture()) {
|
||||
ss << "texture_id[" << shader.coat_weight.texture_id << "]";
|
||||
} else {
|
||||
ss << shader.coat_weight.value;
|
||||
}
|
||||
ss << "\n";
|
||||
|
||||
ss << pprint::Indent(indent + 1) << "coat_color = ";
|
||||
if (shader.coat_color.is_texture()) {
|
||||
ss << "texture_id[" << shader.coat_color.texture_id << "]";
|
||||
} else {
|
||||
ss << shader.coat_color.value;
|
||||
}
|
||||
ss << "\n";
|
||||
|
||||
ss << pprint::Indent(indent + 1) << "coat_roughness = ";
|
||||
if (shader.coat_roughness.is_texture()) {
|
||||
ss << "texture_id[" << shader.coat_roughness.texture_id << "]";
|
||||
} else {
|
||||
ss << shader.coat_roughness.value;
|
||||
}
|
||||
ss << "\n";
|
||||
|
||||
// Emission
|
||||
ss << pprint::Indent(indent + 1) << "emission_luminance = ";
|
||||
if (shader.emission_luminance.is_texture()) {
|
||||
ss << "texture_id[" << shader.emission_luminance.texture_id << "]";
|
||||
} else {
|
||||
ss << shader.emission_luminance.value;
|
||||
}
|
||||
ss << "\n";
|
||||
|
||||
ss << pprint::Indent(indent + 1) << "emission_color = ";
|
||||
if (shader.emission_color.is_texture()) {
|
||||
ss << "texture_id[" << shader.emission_color.texture_id << "]";
|
||||
} else {
|
||||
ss << shader.emission_color.value;
|
||||
}
|
||||
ss << "\n";
|
||||
|
||||
// Transmission
|
||||
ss << pprint::Indent(indent + 1) << "transmission_weight = ";
|
||||
if (shader.transmission_weight.is_texture()) {
|
||||
ss << "texture_id[" << shader.transmission_weight.texture_id << "]";
|
||||
} else {
|
||||
ss << shader.transmission_weight.value;
|
||||
}
|
||||
ss << "\n";
|
||||
|
||||
// Subsurface
|
||||
ss << pprint::Indent(indent + 1) << "subsurface_weight = ";
|
||||
if (shader.subsurface_weight.is_texture()) {
|
||||
ss << "texture_id[" << shader.subsurface_weight.texture_id << "]";
|
||||
} else {
|
||||
ss << shader.subsurface_weight.value;
|
||||
}
|
||||
ss << "\n";
|
||||
|
||||
ss << pprint::Indent(indent + 1) << "subsurface_color = ";
|
||||
if (shader.subsurface_color.is_texture()) {
|
||||
ss << "texture_id[" << shader.subsurface_color.texture_id << "]";
|
||||
} else {
|
||||
ss << shader.subsurface_color.value;
|
||||
}
|
||||
ss << "\n";
|
||||
|
||||
ss << pprint::Indent(indent) << "}";
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string DumpPreviewSurface(const PreviewSurfaceShader &shader,
|
||||
uint32_t indent) {
|
||||
std::stringstream ss;
|
||||
@@ -535,7 +680,7 @@ std::string DumpPreviewSurface(const PreviewSurfaceShader &shader,
|
||||
}
|
||||
ss << "\n";
|
||||
|
||||
ss << pprint::Indent(indent) << "}\n";
|
||||
ss << pprint::Indent(indent) << "}";
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
@@ -559,6 +704,14 @@ std::string DumpMaterial(const RenderMaterial &material, uint32_t indent) {
|
||||
}
|
||||
ss << "\n";
|
||||
|
||||
ss << pprint::Indent(indent + 1) << "openPBRShader = ";
|
||||
if (material.openPBRShader.has_value()) {
|
||||
ss << DumpOpenPBRSurface(*material.openPBRShader, indent + 1);
|
||||
} else {
|
||||
ss << "null";
|
||||
}
|
||||
ss << "\n";
|
||||
|
||||
ss << pprint::Indent(indent) << "}\n";
|
||||
|
||||
return ss.str();
|
||||
|
||||
@@ -29,6 +29,9 @@ constexpr auto kMtlxUsdPreviewSurface = "MtlxUsdPreviewSurface";
|
||||
constexpr auto kMtlxAutodeskStandardSurface = "MtlxAutodeskStandardSurface";
|
||||
constexpr auto kMtlxOpenPBRSurface = "MtlxOpenPBRSurface";
|
||||
|
||||
// MaterialX node definition IDs (as used in info:id attribute)
|
||||
constexpr auto kNdOpenPbrSurfaceSurfaceshader = "ND_open_pbr_surface_surfaceshader";
|
||||
|
||||
|
||||
namespace mtlx {
|
||||
|
||||
@@ -101,6 +104,7 @@ struct MtlxOpenPBRSurface : ShaderNode {
|
||||
TypedAttributeWithFallback<Animatable<float>> specular_ior{1.5f};
|
||||
TypedAttributeWithFallback<Animatable<float>> specular_anisotropy{0.0f};
|
||||
TypedAttributeWithFallback<Animatable<float>> specular_rotation{0.0f};
|
||||
TypedAttributeWithFallback<Animatable<float>> specular_roughness_anisotropy{0.0f};
|
||||
|
||||
// Transmission properties
|
||||
TypedAttributeWithFallback<Animatable<float>> transmission_weight{0.0f};
|
||||
@@ -111,15 +115,19 @@ struct MtlxOpenPBRSurface : ShaderNode {
|
||||
value::color3f{0.0f, 0.0f, 0.0f}};
|
||||
TypedAttributeWithFallback<Animatable<float>> transmission_scatter_anisotropy{0.0f};
|
||||
TypedAttributeWithFallback<Animatable<float>> transmission_dispersion{0.0f};
|
||||
TypedAttributeWithFallback<Animatable<float>> transmission_dispersion_abbe_number{0.0f};
|
||||
TypedAttributeWithFallback<Animatable<float>> transmission_dispersion_scale{0.0f};
|
||||
|
||||
// Subsurface properties
|
||||
TypedAttributeWithFallback<Animatable<float>> subsurface_weight{0.0f};
|
||||
TypedAttributeWithFallback<Animatable<value::color3f>> subsurface_color{
|
||||
value::color3f{0.8f, 0.8f, 0.8f}};
|
||||
TypedAttributeWithFallback<Animatable<value::color3f>> subsurface_radius{
|
||||
value::color3f{1.0f, 1.0f, 1.0f}};
|
||||
TypedAttributeWithFallback<Animatable<float>> subsurface_radius{0.05f}; // Blender uses float, not color3f
|
||||
TypedAttributeWithFallback<Animatable<value::color3f>> subsurface_radius_scale{
|
||||
value::color3f{1.0f, 0.2f, 0.1f}};
|
||||
TypedAttributeWithFallback<Animatable<float>> subsurface_scale{1.0f};
|
||||
TypedAttributeWithFallback<Animatable<float>> subsurface_anisotropy{0.0f};
|
||||
TypedAttributeWithFallback<Animatable<float>> subsurface_scatter_anisotropy{0.0f};
|
||||
|
||||
// Coat properties
|
||||
TypedAttributeWithFallback<Animatable<float>> coat_weight{0.0f};
|
||||
@@ -128,13 +136,22 @@ struct MtlxOpenPBRSurface : ShaderNode {
|
||||
TypedAttributeWithFallback<Animatable<float>> coat_roughness{0.1f};
|
||||
TypedAttributeWithFallback<Animatable<float>> coat_anisotropy{0.0f};
|
||||
TypedAttributeWithFallback<Animatable<float>> coat_rotation{0.0f};
|
||||
TypedAttributeWithFallback<Animatable<float>> coat_roughness_anisotropy{0.0f};
|
||||
TypedAttributeWithFallback<Animatable<float>> coat_ior{1.6f};
|
||||
TypedAttributeWithFallback<Animatable<float>> coat_darkening{0.0f};
|
||||
TypedAttributeWithFallback<Animatable<float>> coat_affect_color{0.0f};
|
||||
TypedAttributeWithFallback<Animatable<float>> coat_affect_roughness{0.0f};
|
||||
|
||||
// Fuzz properties (fabric/cloth layer)
|
||||
TypedAttributeWithFallback<Animatable<float>> fuzz_weight{0.0f};
|
||||
TypedAttributeWithFallback<Animatable<value::color3f>> fuzz_color{
|
||||
value::color3f{1.0f, 1.0f, 1.0f}};
|
||||
TypedAttributeWithFallback<Animatable<float>> fuzz_roughness{0.5f};
|
||||
|
||||
// Thin film properties
|
||||
TypedAttributeWithFallback<Animatable<float>> thin_film_thickness{0.0f};
|
||||
TypedAttributeWithFallback<Animatable<float>> thin_film_ior{1.5f};
|
||||
TypedAttributeWithFallback<Animatable<float>> thin_film_weight{0.0f};
|
||||
|
||||
// Emission properties
|
||||
TypedAttributeWithFallback<Animatable<float>> emission_luminance{0.0f};
|
||||
@@ -148,9 +165,11 @@ struct MtlxOpenPBRSurface : ShaderNode {
|
||||
// Normal and tangent
|
||||
TypedAttribute<Animatable<value::normal3f>> geometry_normal;
|
||||
TypedAttribute<Animatable<value::vector3f>> geometry_tangent;
|
||||
TypedAttribute<Animatable<value::normal3f>> geometry_coat_normal;
|
||||
TypedAttribute<Animatable<value::vector3f>> geometry_coat_tangent;
|
||||
|
||||
// Output
|
||||
TypedTerminalAttribute<value::token> out; // 'out'
|
||||
TypedTerminalAttribute<value::token> surface; // 'outputs:surface'
|
||||
};
|
||||
|
||||
// https://github.com/Autodesk/standard-surface/blob/master/reference/standard_surface.mtlx
|
||||
|
||||
Reference in New Issue
Block a user