Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MAYA-121735: Add UV tangents directly in MaterialX #2113

Merged
merged 2 commits into from
Feb 22, 2022
Merged
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
19 changes: 19 additions & 0 deletions lib/mayaUsd/render/MaterialXGenOgsXml/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ list(APPEND LIGHT_IMPLEMENTATIONS
libraries/mx_lighting_maya_v2.glsl
)

list(APPEND NODE_DECLARATIONS
libraries/maya_surfaces.mtlx
libraries/usd_utilities.mtlx
)

list(APPEND NODE_IMPLEMENTATIONS
libraries/usd_utilities_genglsl_impl.mtlx
libraries/mx_texcoordtangents_vector3.glsl
libraries/mx_arbitrarytangents_vector3.glsl
)

# -----------------------------------------------------------------------------
# promote headers
# -----------------------------------------------------------------------------
Expand All @@ -35,3 +46,11 @@ mayaUsd_promoteHeaderList(HEADERS ${HEADERS} SUBDIR render/MaterialXGenOgsXml)
install(FILES ${LIGHT_IMPLEMENTATIONS}
DESTINATION ${CMAKE_INSTALL_PREFIX}/libraries/pbrlib/genglsl/ogsxml
)

install(FILES ${NODE_DECLARATIONS}
DESTINATION ${CMAKE_INSTALL_PREFIX}/libraries/adsk/maya
)

install(FILES ${NODE_IMPLEMENTATIONS}
DESTINATION ${CMAKE_INSTALL_PREFIX}/libraries/adsk/maya/genglsl
)
297 changes: 297 additions & 0 deletions lib/mayaUsd/render/MaterialXGenOgsXml/libraries/maya_surfaces.mtlx
Original file line number Diff line number Diff line change
@@ -0,0 +1,297 @@
<?xml version="1.0"?>
<materialx version="1.38">

<!-- ======================================================================== -->
<!-- Maya surface node definitions -->
<!-- ======================================================================== -->

<!-- Node: Lambert -->
<nodedef name="MayaND_lambert_surfaceshader" node="MayaLambert" nodegroup="npbr" doc="Maya Lambert surface shader" version="1.0" isdefaultversion="true">
<input name="diffuse" type="float" value="0.8" />
<input name="color" type="color3" value="0.5, 0.5, 0.5" />
<input name="transparency" type="color3" value="0.0, 0.0, 0.0" />
<input name="incandescence" type="color3" value="0.0, 0.0, 0.0" />
<input name="normalCamera" type="vector3" defaultgeomprop="Nworld" />
<output name="outColor" type="surfaceshader" />
</nodedef>

<!-- Node: Phong -->
<nodedef name="MayaND_phong_surfaceshader" node="MayaPhong" nodegroup="npbr" doc="Maya Phong surface shader" version="1.0" isdefaultversion="true">
<!-- lambert -->
<input name="diffuse" type="float" value="0.8" />
<input name="color" type="color3" value="0.5, 0.5, 0.5" />
<input name="transparency" type="color3" value="0.0, 0.0, 0.0" />
<input name="incandescence" type="color3" value="0.0, 0.0, 0.0" />
<input name="normalCamera" type="vector3" defaultgeomprop="Nworld" />

<!-- reflect -->
<input name="specularColor" type="color3" value="0.5, 0.5, 0.5" />
<input name="reflectivity" type="float" value="0.5" />
<input name="reflectedColor" type="color3" value="0.0, 0.0, 0.0" />
<input name="tangent" type="vector3" defaultgeomprop="Tworld" />

<!-- phong -->
<input name="cosinePower" type="float" value="20.0" />

<output name="outColor" type="surfaceshader" />
</nodedef>

<!-- Node: Blinn -->
<nodedef name="MayaND_blinn_surfaceshader" node="MayaBlinn" nodegroup="npbr" doc="Maya Blinn surface shader" version="1.0" isdefaultversion="true">
<!-- lambert -->
<input name="diffuse" type="float" value="0.8" />
<input name="color" type="color3" value="0.5, 0.5, 0.5" />
<input name="transparency" type="color3" value="0.0, 0.0, 0.0" />
<input name="incandescence" type="color3" value="0.0, 0.0, 0.0" />
<input name="normalCamera" type="vector3" defaultgeomprop="Nworld" />

<!-- reflect -->
<input name="specularColor" type="color3" value="0.5, 0.5, 0.5" />
<input name="reflectivity" type="float" value="0.5" />
<input name="reflectedColor" type="color3" value="0.0, 0.0, 0.0" />
<input name="tangent" type="vector3" defaultgeomprop="Tworld" />

<!-- blinn -->
<input name="eccentricity" type="float" value="0.3" />
<input name="specularRollOff" type="float" value="0.7" />

<output name="outColor" type="surfaceshader" />
</nodedef>

<!-- ======================================================================== -->
<!-- Maya surface node PBR nodegraph implementations -->
<!-- -->
<!-- These implementations do not try to replicate Maya behavior exactly. -->
<!-- They will use the smallest MaterialX graph that is close enough. -->
<!-- ======================================================================== -->

<!-- Node: Lambert -->
<nodegraph name="MayaIMP_lambert_surfaceshader" nodedef="MayaND_lambert_surfaceshader">
<!-- Diffuse Layer -->
<burley_diffuse_bsdf name="diffuse_bsdf" type="BSDF">
<input name="weight" type="float" interfacename="diffuse" />
<input name="color" type="color3" interfacename="color" />
<input name="roughness" type="float" value="0.0" />
<input name="normal" type="vector3" interfacename="normalCamera" />
</burley_diffuse_bsdf>

<!-- Emission Layer -->
<uniform_edf name="emission_edf" type="EDF">
<input name="color" type="color3" interfacename="incandescence" />
</uniform_edf>

<!-- Node <surface> only supports monochromatic opacity so use the luminance of input opacity color -->
<luminance name="transparency_luminance" type="color3">
<input name="in" type="color3" interfacename="transparency" />
</luminance>
<swizzle name="transparency_luminance_r" type="float">
<input name="in" type="color3" nodename="transparency_luminance" />
<param name="channels" type="string" value="r" />
</swizzle>
<subtract name="cutout_opacity" type="float">
<input name="in1" type="float" value="1.0" />
<input name="in2" type="float" nodename="transparency_luminance_r" />
</subtract>

<!-- Surface Shader Constructor -->
<surface name="surface_constructor" type="surfaceshader">
<input name="bsdf" type="BSDF" nodename="diffuse_bsdf" />
<input name="edf" type="EDF" nodename="emission_edf" />
<input name="opacity" type="float" nodename="cutout_opacity" />
</surface>

<!-- Output -->
<output name="outColor" type="surfaceshader" nodename="surface_constructor" />
</nodegraph>

<!-- Node: Phong -->
<nodegraph name="MayaIMP_phong_surfaceshader" nodedef="MayaND_phong_surfaceshader">
<!-- Diffuse Layer -->
<burley_diffuse_bsdf name="diffuse_bsdf" type="BSDF">
<input name="weight" type="float" interfacename="diffuse" />
<input name="color" type="color3" interfacename="color" />
<input name="roughness" type="float" value="0.0" />
<input name="normal" type="vector3" interfacename="normalCamera" />
</burley_diffuse_bsdf>

<!-- Node <surface> only supports monochromatic opacity so use the luminance of input opacity color -->
<luminance name="transparency_luminance" type="color3">
<input name="in" type="color3" interfacename="transparency" />
</luminance>
<swizzle name="transparency_luminance_r" type="float">
<input name="in" type="color3" nodename="transparency_luminance" />
<param name="channels" type="string" value="r" />
</swizzle>
<subtract name="cutout_opacity" type="float">
<input name="in1" type="float" value="1.0" />
<input name="in2" type="float" nodename="transparency_luminance_r" />
</subtract>

<!-- Transmission Layer. Used to emulate transparency. -->
<dielectric_bsdf name="transmission_bsdf" type="BSDF">
<input name="weight" type="float" value="1" />
<input name="tint" type="color3" value="1, 1, 1" />
<input name="ior" type="float" value="1.5" />
<input name="roughness" type="vector2" value="0.0, 0.0" />
<input name="normal" type="vector3" interfacename="normalCamera" />
<input name="tangent" type="vector3" interfacename="tangent" />
<input name="scatter_mode" type="string" value="T" />
</dielectric_bsdf>
<mix name="transmission_mix" type="BSDF">
<input name="fg" type="BSDF" nodename="diffuse_bsdf" />
<input name="bg" type="BSDF" nodename="transmission_bsdf" />
<input name="mix" type="float" nodename="cutout_opacity" />
</mix>

<!-- roughness = sqrt(1.0 / (0.454 * cosinePower + 3.357)) -->
<multiply name="mul0" type="float">
<input name="in1" type="float" interfacename="cosinePower" />
<input name="in2" type="float" value="0.454" />
</multiply>
<add name="add0" type="float">
<input name="in1" type="float" value="3.357" />
<input name="in2" type="float" nodename="mul0" />
</add>
<divide name="div0" type="float">
<input name="in1" type="float" value="1.0" />
<input name="in2" type="float" nodename="add0" />
</divide>
<sqrt name="roughness" type="float">
<input name="in" type="float" nodename="div0" />
</sqrt>

<!-- Specular Workflow -->
<roughness_anisotropy name="specular_roughness" type="vector2">
<input name="roughness" type="float" nodename="roughness" />
<input name="anisotropy" type="float" value="0" />
</roughness_anisotropy>
<generalized_schlick_bsdf name="specular_bsdf1" type="BSDF">
<input name="weight" type="float" value="1" />
<input name="color0" type="color3" interfacename="specularColor" />
<input name="color90" type="color3" value="1, 1, 1" />
<input name="roughness" type="vector2" nodename="specular_roughness" />
<input name="normal" type="vector3" interfacename="normalCamera" />
<input name="tangent" type="vector3" interfacename="tangent" />
</generalized_schlick_bsdf>
<layer name="specular_workflow_bsdf" type="BSDF">
<input name="top" type="BSDF" nodename="specular_bsdf1" />
<input name="base" type="BSDF" nodename="transmission_mix" />
</layer>

<!-- reflectivity implemented as a coat layer -->
<dielectric_bsdf name="coat_dielectric_bsdf" type="BSDF">
<input name="weight" type="float" interfacename="reflectivity" />
<input name="tint" type="color3" interfacename="reflectedColor" />
<input name="ior" type="float" value="1.5" />
<input name="roughness" type="vector2" value="0.0, 0.0" />
<input name="normal" type="vector3" interfacename="normalCamera" />
<input name="tangent" type="vector3" interfacename="tangent" />
</dielectric_bsdf>
<layer name="coat_bsdf" type="BSDF">
<input name="top" type="BSDF" nodename="coat_dielectric_bsdf" />
<input name="base" type="BSDF" nodename="specular_workflow_bsdf" />
</layer>

<!-- Emission Layer -->
<uniform_edf name="emission_edf" type="EDF">
<input name="color" type="color3" interfacename="incandescence" />
</uniform_edf>

<!-- Surface Shader Constructor -->
<surface name="surface_constructor" type="surfaceshader">
<input name="bsdf" type="BSDF" nodename="coat_bsdf" />
<input name="edf" type="EDF" nodename="emission_edf" />
<input name="opacity" type="float" nodename="cutout_opacity" />
</surface>

<!-- Output -->
<output name="outColor" type="surfaceshader" nodename="surface_constructor" />
</nodegraph>

<!-- Node: Blinn -->
<nodegraph name="MayaIMP_blinn_surfaceshader" nodedef="MayaND_blinn_surfaceshader">
<!-- Diffuse Layer -->
<burley_diffuse_bsdf name="diffuse_bsdf" type="BSDF">
<input name="weight" type="float" interfacename="diffuse" />
<input name="color" type="color3" interfacename="color" />
<input name="roughness" type="float" value="0.0" />
<input name="normal" type="vector3" interfacename="normalCamera" />
</burley_diffuse_bsdf>

<!-- Node <surface> only supports monochromatic opacity so use the luminance of input opacity color -->
<luminance name="transparency_luminance" type="color3">
<input name="in" type="color3" interfacename="transparency" />
</luminance>
<swizzle name="transparency_luminance_r" type="float">
<input name="in" type="color3" nodename="transparency_luminance" />
<param name="channels" type="string" value="r" />
</swizzle>
<subtract name="cutout_opacity" type="float">
<input name="in1" type="float" value="1.0" />
<input name="in2" type="float" nodename="transparency_luminance_r" />
</subtract>

<!-- Transmission Layer. Used to emulate transparency. -->
<dielectric_bsdf name="transmission_bsdf" type="BSDF">
<input name="weight" type="float" value="1" />
<input name="tint" type="color3" value="1, 1, 1" />
<input name="ior" type="float" value="1.5" />
<input name="roughness" type="vector2" value="0.0, 0.0" />
<input name="normal" type="vector3" interfacename="normalCamera" />
<input name="tangent" type="vector3" interfacename="tangent" />
<input name="scatter_mode" type="string" value="T" />
</dielectric_bsdf>
<mix name="transmission_mix" type="BSDF">
<input name="fg" type="BSDF" nodename="diffuse_bsdf" />
<input name="bg" type="BSDF" nodename="transmission_bsdf" />
<input name="mix" type="float" nodename="cutout_opacity" />
</mix>

<!-- Specular Workflow -->
<roughness_anisotropy name="specular_roughness" type="vector2">
<input name="roughness" type="float" interfacename="eccentricity" />
<input name="anisotropy" type="float" value="0" />
</roughness_anisotropy>
<generalized_schlick_bsdf name="specular_bsdf1" type="BSDF">
<input name="weight" type="float" interfacename="specularRollOff" />
<input name="color0" type="color3" interfacename="specularColor" />
<input name="color90" type="color3" value="1, 1, 1" />
<input name="roughness" type="vector2" nodename="specular_roughness" />
<input name="normal" type="vector3" interfacename="normalCamera" />
<input name="tangent" type="vector3" interfacename="tangent" />
</generalized_schlick_bsdf>
<layer name="specular_workflow_bsdf" type="BSDF">
<input name="top" type="BSDF" nodename="specular_bsdf1" />
<input name="base" type="BSDF" nodename="transmission_mix" />
</layer>

<!-- reflectivity implemented as a coat layer -->
<dielectric_bsdf name="coat_dielectric_bsdf" type="BSDF">
<input name="weight" type="float" interfacename="reflectivity" />
<input name="tint" type="color3" interfacename="reflectedColor" />
<input name="ior" type="float" value="1.5" />
<input name="roughness" type="vector2" value="0.0, 0.0" />
<input name="normal" type="vector3" interfacename="normalCamera" />
<input name="tangent" type="vector3" interfacename="tangent" />
</dielectric_bsdf>
<layer name="coat_bsdf" type="BSDF">
<input name="top" type="BSDF" nodename="coat_dielectric_bsdf" />
<input name="base" type="BSDF" nodename="specular_workflow_bsdf" />
</layer>

<!-- Emission Layer -->
<uniform_edf name="emission_edf" type="EDF">
<input name="color" type="color3" interfacename="incandescence" />
</uniform_edf>

<!-- Surface Shader Constructor -->
<surface name="surface_constructor" type="surfaceshader">
<input name="bsdf" type="BSDF" nodename="coat_bsdf" />
<input name="edf" type="EDF" nodename="emission_edf" />
<input name="opacity" type="float" nodename="cutout_opacity" />
</surface>

<!-- Output -->
<output name="outColor" type="surfaceshader" nodename="surface_constructor" />
</nodegraph>
</materialx>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
void mx_arbitrarytangents_vector3(vec3 position, vec3 normal, out vec3 tangent)
{
// Get screen space derivatives of position
vec3 dPdx = dFdx(position);

// Ensure position derivatives are perpendicular to normal
tangent = normalize(dPdx - dot(dPdx, normal) * normal);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
void mx_texcoordtangents_vector3(vec3 position, vec3 normal, vec2 texcoord, out vec3 tangent)
{
// Calculation of TBN matrix and terminology based on "Surface
// Gradient-Based Bump Mapping Framework" (2020)

// Get screen space derivatives of position
vec3 dPdx = dFdx(position);
vec3 dPdy = dFdy(position);

// Ensure position derivatives are perpendicular to normal
vec3 sigmaX = dPdx - dot(dPdx, normal) * normal;
vec3 sigmaY = dPdy - dot(dPdy, normal) * normal;

float flipSign = dot(dPdy, cross(normal, dPdx)) < 0 ? -1 : 1;

// Get screen space derivatives of st
vec2 dSTdx = dFdx(texcoord);
vec2 dSTdy = dFdy(texcoord);

// Get determinant and determinant sign of st matrix
float det = dot(dSTdx, vec2(dSTdy.y, -dSTdy.x));
float signDet = det < 0 ? -1 : 1;

// Get first column of inv st matrix
// Don't divide by det, but scale by its sign
vec2 invC0 = signDet * vec2(dSTdy.y, -dSTdx.y);

vec3 T = sigmaX * invC0.x + sigmaY * invC0.y;

if (abs(det) > 0) {
T = normalize(T);
}

tangent = T;
}
24 changes: 24 additions & 0 deletions lib/mayaUsd/render/MaterialXGenOgsXml/libraries/usd_utilities.mtlx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0"?>
<materialx version="1.38">

<!-- ======================================================================== -->
<!-- Utilities specific to USD handling -->
<!-- ======================================================================== -->

<!-- Node: texcoordtangents: Generate world tangents from derivatives of position
and texcoord -->
<nodedef name="MayaND_texcoordtangents_vector3" node="texcoordtangents" nodegroup="math">
<input name="position" type="vector3" defaultgeomprop="Pworld" />
<input name="normal" type="vector3" defaultgeomprop="Nworld" />
<input name="texcoord" type="vector2" defaultgeomprop="UV0" />
<output name="out" type="vector3" />
</nodedef>

<!-- Node: arbitrarytangents: Completely arbitrary tangent for when there is no
texcoord space available -->
<nodedef name="MayaND_arbitrarytangents_vector3" node="arbitrarytangents" nodegroup="math">
<input name="position" type="vector3" defaultgeomprop="Pworld" />
<input name="normal" type="vector3" defaultgeomprop="Nworld" />
<output name="out" type="vector3" />
</nodedef>
</materialx>
Loading