Skip to content

Commit

Permalink
[hdSt] Fix Tangent vector calculation for MaterialX NormalMaps
Browse files Browse the repository at this point in the history
Note that the difference in lighting in the baseline is due to differences in
how UsdPreviewSurface and MaterialX's implementation of PreviewSurface
handles roughness values for direct lights.

Fixes #1585

(Internal change: 2306122)
  • Loading branch information
klucknav authored and pixar-oss committed Nov 28, 2023
1 parent bbd9ece commit c5d244e
Show file tree
Hide file tree
Showing 22 changed files with 692 additions and 51 deletions.
73 changes: 55 additions & 18 deletions pxr/imaging/hdSt/materialXShaderGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,22 @@ namespace mx = MaterialX;
PXR_NAMESPACE_OPEN_SCOPE


static const std::string MxHdTangentString =
static const std::string MxHdWorldSpaceVectors =
R"(
// Calculate a worldspace tangent vector
// Calculate the worldspace position and normal vectors
vec3 positionWorld = vec3(HdGet_worldToViewInverseMatrix() * Peye);
vec3 normalWorld = vec3(HdGet_worldToViewInverseMatrix() * vec4(Neye, 0.0));
// Calculate the worldspace tangent vector
#ifdef HD_HAS_%s
vec3 tangentWorld = ComputeTangentVector(positionWorld, normalWorld, HdGet_%s());
#else
vec3 tangentWorld = cross(normalWorld, vec3(0, 1, 0));
if (length(tangentWorld) < M_FLOAT_EPS) {
tangentWorld = cross(normalWorld, vec3(1, 0, 0));
}
#endif
)";

static const std::string MxHdLightString =
Expand Down Expand Up @@ -147,6 +155,8 @@ HdStMaterialXShaderGen<Base>::_EmitGlslfxHeader(mx::ShaderStage& mxStage) const
Base::emitLineBreak(mxStage);
Base::emitComment("File Generated with HdStMaterialXShaderGen.", mxStage);
Base::emitLineBreak(mxStage);
Base::emitString("#import $TOOLS/hdSt/shaders/surfaceHelpers.glslfx\n", mxStage);
Base::emitLineBreak(mxStage);
Base::emitString(
R"(-- configuration)" "\n"
R"({)" "\n", mxStage);
Expand Down Expand Up @@ -198,7 +208,8 @@ HdStMaterialXShaderGen<Base>::_EmitGlslfxHeader(mx::ShaderStage& mxStage) const
R"( "techniques": {)" "\n"
R"( "default": {)" "\n"
R"( "surfaceShader": { )""\n"
R"( "source": [ "MaterialX.Surface" ])""\n"
R"( "source": [ "SurfaceHelpers.TangentSpace",)""\n"
R"( "MaterialX.Surface" ])""\n"
R"( })""\n"
R"( })""\n"
R"( })""\n"
Expand Down Expand Up @@ -356,6 +367,35 @@ HdStMaterialXShaderGen<Base>::_EmitMxSurfaceShader(
Base::emitLineBreak(mxStage);
}

static std::string
_GetTexcoordName(
mx::VariableBlock const& vertexDataBlock,
std::string const& defaultTexcoordName)
{
// Texcoords could come from either a texcoord or a geomprop value node.
// We prioritize using the texcoord name over the geomprop.

// Cycle through the vertexDataBlock to find the texcoord name.
std::string texcoordName = defaultTexcoordName;
for (size_t i = 0; i < vertexDataBlock.size(); ++i) {
const mx::ShaderPort* variable = vertexDataBlock[i];
const std::string mxVariableName = variable->getVariable();

// If we have a texcoord node, use the default texcoord name.
if (mxVariableName.compare(
0, mx::HW::T_TEXCOORD.size(), mx::HW::T_TEXCOORD) == 0) {
return defaultTexcoordName;
}
// Use the geomprop name if this is a vec2 geomprop value node
if (mxVariableName.compare(
0, mx::HW::T_IN_GEOMPROP.size(), mx::HW::T_IN_GEOMPROP) == 0 &&
variable->getType() == mx::Type::VECTOR2) {
texcoordName = mxVariableName.substr(mx::HW::T_IN_GEOMPROP.size()+1);
}
}
return texcoordName;
}

template<typename Base>
void
HdStMaterialXShaderGen<Base>::_EmitMxInitFunction(
Expand All @@ -372,8 +412,13 @@ HdStMaterialXShaderGen<Base>::_EmitMxInitFunction(
emitLine("u_viewPosition = vec3(HdGet_worldToViewInverseMatrix()"
" * vec4(0.0, 0.0, 0.0, 1.0))", mxStage);

// Calculate the worldspace tangent vector
Base::emitString(MxHdTangentString, mxStage);
// Calculate the worldspace position, normal and tangent vectors
const std::string texcoordName =
_GetTexcoordName(vertexData, _defaultTexcoordName);
Base::emitString(
TfStringPrintf(MxHdWorldSpaceVectors.c_str(),
texcoordName.c_str(), texcoordName.c_str()),
mxStage);

// Add the vd declaration that translates HdVertexData -> MxVertexData
std::string mxVertexDataName = "mx" + vertexData.getName();
Expand Down Expand Up @@ -501,21 +546,13 @@ HdStMaterialXShaderGen<Base>::_EmitMxVertexDataLine(
// making sure to convert the Hd data (viewSpace) to Mx data (worldSpace)
std::string hdVariableDef;
const std::string mxVariableName = variable->getVariable();
if (mxVariableName.compare(mx::HW::T_POSITION_WORLD) == 0) {

// Convert to WorldSpace position
hdVariableDef = "vec3(HdGet_worldToViewInverseMatrix() * Peye)"
+ separator;
}
else if (mxVariableName.compare(mx::HW::T_NORMAL_WORLD) == 0) {

// Convert to WorldSpace normal (calculated in MxHdTangentString)
hdVariableDef = "normalWorld" + separator;
}
else if (mxVariableName.compare(mx::HW::T_TANGENT_WORLD) == 0) {
if (mxVariableName.compare(mx::HW::T_POSITION_WORLD) == 0 ||
mxVariableName.compare(mx::HW::T_NORMAL_WORLD) == 0 ||
mxVariableName.compare(mx::HW::T_TANGENT_WORLD) == 0) {

// Calculated in MxHdTangentString
hdVariableDef = "tangentWorld" + separator;
// Calculated in MxHdWorldSpaceVectors
hdVariableDef = mxVariableName.substr(1) + separator;
}
else if (mxVariableName.compare(mx::HW::T_POSITION_OBJECT) == 0) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

// File Generated with HdStMaterialXShaderGen.

#import $TOOLS/hdSt/shaders/surfaceHelpers.glslfx

-- configuration
{
"metadata": {
Expand All @@ -10,7 +12,8 @@
"techniques": {
"default": {
"surfaceShader": {
"source": [ "MaterialX.Surface" ]
"source": [ "SurfaceHelpers.TangentSpace",
"MaterialX.Surface" ]
}
}
}
Expand Down Expand Up @@ -136,13 +139,21 @@ void mxInit(vec4 Peye, vec3 Neye)
// Convert HdData to MxData
u_viewPosition = vec3(HdGet_worldToViewInverseMatrix() * vec4(0.0, 0.0, 0.0, 1.0));

// Calculate a worldspace tangent vector
// Calculate the worldspace position and normal vectors
vec3 positionWorld = vec3(HdGet_worldToViewInverseMatrix() * Peye);
vec3 normalWorld = vec3(HdGet_worldToViewInverseMatrix() * vec4(Neye, 0.0));

// Calculate the worldspace tangent vector
#ifdef HD_HAS_st
vec3 tangentWorld = ComputeTangentVector(positionWorld, normalWorld, HdGet_st());
#else
vec3 tangentWorld = cross(normalWorld, vec3(0, 1, 0));
if (length(tangentWorld) < M_FLOAT_EPS) {
tangentWorld = cross(normalWorld, vec3(1, 0, 0));
}
vd = mxVertexData(normalWorld,tangentWorld,vec3(HdGet_worldToViewInverseMatrix() * Peye));
#endif

vd = mxVertexData(normalWorld,tangentWorld,positionWorld);

// Initialize Material Parameters
base = HdGet_base();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

// File Generated with HdStMaterialXShaderGen.

#import $TOOLS/hdSt/shaders/surfaceHelpers.glslfx

-- configuration
{
"metadata": {
Expand All @@ -10,7 +12,8 @@
"techniques": {
"default": {
"surfaceShader": {
"source": [ "MaterialX.Surface" ]
"source": [ "SurfaceHelpers.TangentSpace",
"MaterialX.Surface" ]
}
}
}
Expand Down Expand Up @@ -136,13 +139,21 @@ void mxInit(vec4 Peye, vec3 Neye)
// Convert HdData to MxData
u_viewPosition = vec3(HdGet_worldToViewInverseMatrix() * vec4(0.0, 0.0, 0.0, 1.0));

// Calculate a worldspace tangent vector
// Calculate the worldspace position and normal vectors
vec3 positionWorld = vec3(HdGet_worldToViewInverseMatrix() * Peye);
vec3 normalWorld = vec3(HdGet_worldToViewInverseMatrix() * vec4(Neye, 0.0));

// Calculate the worldspace tangent vector
#ifdef HD_HAS_st
vec3 tangentWorld = ComputeTangentVector(positionWorld, normalWorld, HdGet_st());
#else
vec3 tangentWorld = cross(normalWorld, vec3(0, 1, 0));
if (length(tangentWorld) < M_FLOAT_EPS) {
tangentWorld = cross(normalWorld, vec3(1, 0, 0));
}
vd = mxVertexData(normalWorld,tangentWorld,vec3(HdGet_worldToViewInverseMatrix() * Peye));
#endif

vd = mxVertexData(normalWorld,tangentWorld,positionWorld);

// Initialize Material Parameters
base = HdGet_base();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

// File Generated with HdStMaterialXShaderGen.

#import $TOOLS/hdSt/shaders/surfaceHelpers.glslfx

-- configuration
{
"metadata": {
Expand All @@ -10,7 +12,8 @@
"techniques": {
"default": {
"surfaceShader": {
"source": [ "MaterialX.Surface" ]
"source": [ "SurfaceHelpers.TangentSpace",
"MaterialX.Surface" ]
}
}
}
Expand Down Expand Up @@ -149,13 +152,21 @@ void mxInit(vec4 Peye, vec3 Neye)
// Convert HdData to MxData
u_viewPosition = vec3(HdGet_worldToViewInverseMatrix() * vec4(0.0, 0.0, 0.0, 1.0));

// Calculate a worldspace tangent vector
// Calculate the worldspace position and normal vectors
vec3 positionWorld = vec3(HdGet_worldToViewInverseMatrix() * Peye);
vec3 normalWorld = vec3(HdGet_worldToViewInverseMatrix() * vec4(Neye, 0.0));

// Calculate the worldspace tangent vector
#ifdef HD_HAS_st
vec3 tangentWorld = ComputeTangentVector(positionWorld, normalWorld, HdGet_st());
#else
vec3 tangentWorld = cross(normalWorld, vec3(0, 1, 0));
if (length(tangentWorld) < M_FLOAT_EPS) {
tangentWorld = cross(normalWorld, vec3(1, 0, 0));
}
vd = mxVertexData(normalWorld,tangentWorld,HdGet_points(),vec3(HdGet_worldToViewInverseMatrix() * Peye));
#endif

vd = mxVertexData(normalWorld,tangentWorld,HdGet_points(),positionWorld);

// Initialize Material Parameters
base = HdGet_base();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

// File Generated with HdStMaterialXShaderGen.

#import $TOOLS/hdSt/shaders/surfaceHelpers.glslfx

-- configuration
{
"metadata": {
Expand All @@ -21,7 +23,8 @@
"techniques": {
"default": {
"surfaceShader": {
"source": [ "MaterialX.Surface" ]
"source": [ "SurfaceHelpers.TangentSpace",
"MaterialX.Surface" ]
}
}
}
Expand Down Expand Up @@ -167,19 +170,27 @@ void mxInit(vec4 Peye, vec3 Neye)
// Convert HdData to MxData
u_viewPosition = vec3(HdGet_worldToViewInverseMatrix() * vec4(0.0, 0.0, 0.0, 1.0));

// Calculate a worldspace tangent vector
// Calculate the worldspace position and normal vectors
vec3 positionWorld = vec3(HdGet_worldToViewInverseMatrix() * Peye);
vec3 normalWorld = vec3(HdGet_worldToViewInverseMatrix() * vec4(Neye, 0.0));

// Calculate the worldspace tangent vector
#ifdef HD_HAS_uv
vec3 tangentWorld = ComputeTangentVector(positionWorld, normalWorld, HdGet_uv());
#else
vec3 tangentWorld = cross(normalWorld, vec3(0, 1, 0));
if (length(tangentWorld) < M_FLOAT_EPS) {
tangentWorld = cross(normalWorld, vec3(1, 0, 0));
}
#endif

vd = mxVertexData(normalWorld,tangentWorld,
#ifdef HD_HAS_uv
HdGet_uv(),
#else
vec2(0.0),
#endif
vec3(HdGet_worldToViewInverseMatrix() * Peye));
positionWorld);

// Initialize Material Parameters
base = HdGet_base();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

// File Generated with HdStMaterialXShaderGen.

#import $TOOLS/hdSt/shaders/surfaceHelpers.glslfx

-- configuration
{
"metadata": {
Expand All @@ -21,7 +23,8 @@
"techniques": {
"default": {
"surfaceShader": {
"source": [ "MaterialX.Surface" ]
"source": [ "SurfaceHelpers.TangentSpace",
"MaterialX.Surface" ]
}
}
}
Expand Down Expand Up @@ -159,19 +162,27 @@ void mxInit(vec4 Peye, vec3 Neye)
// Convert HdData to MxData
u_viewPosition = vec3(HdGet_worldToViewInverseMatrix() * vec4(0.0, 0.0, 0.0, 1.0));

// Calculate a worldspace tangent vector
// Calculate the worldspace position and normal vectors
vec3 positionWorld = vec3(HdGet_worldToViewInverseMatrix() * Peye);
vec3 normalWorld = vec3(HdGet_worldToViewInverseMatrix() * vec4(Neye, 0.0));

// Calculate the worldspace tangent vector
#ifdef HD_HAS_uv
vec3 tangentWorld = ComputeTangentVector(positionWorld, normalWorld, HdGet_uv());
#else
vec3 tangentWorld = cross(normalWorld, vec3(0, 1, 0));
if (length(tangentWorld) < M_FLOAT_EPS) {
tangentWorld = cross(normalWorld, vec3(1, 0, 0));
}
#endif

vd = mxVertexData(normalWorld,tangentWorld,
#ifdef HD_HAS_uv
HdGet_uv(),
#else
vec2(0.0),
#endif
vec3(HdGet_worldToViewInverseMatrix() * Peye));
positionWorld);

// Initialize Material Parameters
base = HdGet_base();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

// File Generated with HdStMaterialXShaderGen.

#import $TOOLS/hdSt/shaders/surfaceHelpers.glslfx

-- configuration
{
"metadata": {
Expand All @@ -10,7 +12,8 @@
"techniques": {
"default": {
"surfaceShader": {
"source": [ "MaterialX.Surface" ]
"source": [ "SurfaceHelpers.TangentSpace",
"MaterialX.Surface" ]
}
}
}
Expand Down Expand Up @@ -112,13 +115,21 @@ void mxInit(vec4 Peye, vec3 Neye)
// Convert HdData to MxData
u_viewPosition = vec3(HdGet_worldToViewInverseMatrix() * vec4(0.0, 0.0, 0.0, 1.0));

// Calculate a worldspace tangent vector
// Calculate the worldspace position and normal vectors
vec3 positionWorld = vec3(HdGet_worldToViewInverseMatrix() * Peye);
vec3 normalWorld = vec3(HdGet_worldToViewInverseMatrix() * vec4(Neye, 0.0));

// Calculate the worldspace tangent vector
#ifdef HD_HAS_st
vec3 tangentWorld = ComputeTangentVector(positionWorld, normalWorld, HdGet_st());
#else
vec3 tangentWorld = cross(normalWorld, vec3(0, 1, 0));
if (length(tangentWorld) < M_FLOAT_EPS) {
tangentWorld = cross(normalWorld, vec3(1, 0, 0));
}
vd = mxVertexData(tangentWorld,normalWorld,vec3(HdGet_worldToViewInverseMatrix() * Peye));
#endif

vd = mxVertexData(tangentWorld,normalWorld,positionWorld);

// Initialize Material Parameters
diffuseColor = HdGet_diffuseColor();
Expand Down
Loading

0 comments on commit c5d244e

Please sign in to comment.