diff --git a/cmake/modules/FindMaya.cmake b/cmake/modules/FindMaya.cmake
index 7404899a54..438a8caee7 100644
--- a/cmake/modules/FindMaya.cmake
+++ b/cmake/modules/FindMaya.cmake
@@ -11,6 +11,7 @@
# MAYA_INCLUDE_DIRS Path to the devkit's include directories
# MAYA_API_VERSION Maya version (6-8 digits)
# MAYA_APP_VERSION Maya app version (4 digits)
+# MAYA_LIGHTAPI_VERSION Maya light API version (1 or 2)
#
#=============================================================================
@@ -297,6 +298,40 @@ find_program(MAYA_PY_EXECUTABLE
"Maya's Python executable path"
)
+set(MAYA_LIGHTAPI_VERSION 1)
+if(IS_MACOSX)
+ set(MAYA_DSO_SUFFIX ".dylib")
+ set(MAYA_DSO_PREFIX "lib")
+elseif(IS_WINDOWS)
+ set(MAYA_DSO_SUFFIX ".dll")
+ set(MAYA_DSO_PREFIX "")
+else(IS_LINUX)
+ set(MAYA_DSO_SUFFIX ".so")
+ set(MAYA_DSO_PREFIX "lib")
+endif()
+find_file(MAYA_OGSDEVICES_LIBRARY
+ "${MAYA_DSO_PREFIX}OGSDevices${MAYA_DSO_SUFFIX}"
+ HINTS
+ "${MAYA_LIBRARY_DIR}"
+ "${MAYA_LOCATION}"
+ PATH_SUFFIXES
+ lib/
+ bin/
+ DOC
+ "Maya's ${MAYA_LIB} library path"
+ # NO_CMAKE_SYSTEM_PATH needed to avoid conflicts between
+ # Maya's Foundation library and OSX's framework.
+ NO_CMAKE_SYSTEM_PATH
+)
+message(INFO " Got MAYA_OGSDEVICES_LIBRARY = ${MAYA_OGSDEVICES_LIBRARY}")
+if (MAYA_OGSDEVICES_LIBRARY)
+ file(STRINGS ${MAYA_OGSDEVICES_LIBRARY} HAS_LIGHTAPI_2 REGEX "InitializeLightShader")
+ if (HAS_LIGHTAPI_2)
+ set(MAYA_LIGHTAPI_VERSION 2)
+ endif()
+endif()
+message(INFO " Got MAYA_LIGHTAPI_VERSION = ${MAYA_LIGHTAPI_VERSION}")
+
# handle the QUIETLY and REQUIRED arguments and set MAYA_FOUND to TRUE if
# all listed variables are TRUE
include(FindPackageHandleStandardArgs)
@@ -310,6 +345,7 @@ find_package_handle_standard_args(Maya
MAYA_LIBRARIES
MAYA_API_VERSION
MAYA_APP_VERSION
+ MAYA_LIGHTAPI_VERSION
VERSION_VAR
MAYA_APP_VERSION
)
diff --git a/lib/mayaUsd/CMakeLists.txt b/lib/mayaUsd/CMakeLists.txt
index 7e657ae481..03e831819b 100644
--- a/lib/mayaUsd/CMakeLists.txt
+++ b/lib/mayaUsd/CMakeLists.txt
@@ -75,6 +75,13 @@ if (MAYA_API_VERSION VERSION_GREATER_EQUAL 20230000 AND UFE_VERSION VERSION_GREA
)
endif()
+if (MAYA_LIGHTAPI_VERSION EQUAL 2)
+ target_compile_definitions(${PROJECT_NAME}
+ PRIVATE
+ MAYA_LIGHTAPI_VERSION_2=2
+ )
+endif()
+
# Some of the UFE classes are exporting STL classes which causes this warning.
if(UFE_FOUND AND MSVC)
target_compile_options(${PROJECT_NAME}
diff --git a/lib/mayaUsd/render/vp2ShaderFragments/CMakeLists.txt b/lib/mayaUsd/render/vp2ShaderFragments/CMakeLists.txt
index 3030ef0e7c..ab2550596a 100644
--- a/lib/mayaUsd/render/vp2ShaderFragments/CMakeLists.txt
+++ b/lib/mayaUsd/render/vp2ShaderFragments/CMakeLists.txt
@@ -15,13 +15,15 @@ list(APPEND SHADERFRAGMENTS_XMLS
Float4ToFloatX.xml
Float4ToFloatY.xml
Float4ToFloatZ.xml
- UsdPreviewSurface.xml
+ UsdPreviewSurfaceLightAPI1.xml
+ UsdPreviewSurfaceLightAPI2.xml
lightingContributions.xml
opacityToTransparency.xml
scaledDiffusePassThrough.xml
scaledSpecularPassThrough.xml
usdPreviewSurfaceCombiner.xml
- usdPreviewSurfaceLighting.xml
+ usdPreviewSurfaceLightingAPI1.xml
+ usdPreviewSurfaceLightingAPI2.xml
# New fragments
BasisCurvesCubicColorDomain.xml
BasisCurvesCubicCPVHull.xml
diff --git a/lib/mayaUsd/render/vp2ShaderFragments/UsdPreviewSurface.xml b/lib/mayaUsd/render/vp2ShaderFragments/UsdPreviewSurfaceLightAPI1.xml
similarity index 89%
rename from lib/mayaUsd/render/vp2ShaderFragments/UsdPreviewSurface.xml
rename to lib/mayaUsd/render/vp2ShaderFragments/UsdPreviewSurfaceLightAPI1.xml
index 273bc17bc6..7df571c65c 100644
--- a/lib/mayaUsd/render/vp2ShaderFragments/UsdPreviewSurface.xml
+++ b/lib/mayaUsd/render/vp2ShaderFragments/UsdPreviewSurfaceLightAPI1.xml
@@ -33,7 +33,7 @@ limitations under the License.
and combining them with material properties. -->
-
+
@@ -61,15 +61,15 @@ limitations under the License.
-
-
-
-
+
+
+
+
-
-
-
+
+
+
@@ -82,23 +82,23 @@ limitations under the License.
-
+
-
+
-
+
-
-
+
+
-
-
+
+
@@ -108,8 +108,8 @@ limitations under the License.
-
-
+
+
diff --git a/lib/mayaUsd/render/vp2ShaderFragments/UsdPreviewSurfaceLightAPI2.xml b/lib/mayaUsd/render/vp2ShaderFragments/UsdPreviewSurfaceLightAPI2.xml
new file mode 100644
index 0000000000..fcdf919642
--- /dev/null
+++ b/lib/mayaUsd/render/vp2ShaderFragments/UsdPreviewSurfaceLightAPI2.xml
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/mayaUsd/render/vp2ShaderFragments/shaderFragments.cpp b/lib/mayaUsd/render/vp2ShaderFragments/shaderFragments.cpp
index 48fd39eae7..82dd9fd19c 100644
--- a/lib/mayaUsd/render/vp2ShaderFragments/shaderFragments.cpp
+++ b/lib/mayaUsd/render/vp2ShaderFragments/shaderFragments.cpp
@@ -67,7 +67,8 @@ TF_DEFINE_PRIVATE_TOKENS(
(scaledDiffusePassThrough)
(scaledSpecularPassThrough)
(opacityToTransparency)
- (usdPreviewSurfaceLighting)
+ (usdPreviewSurfaceLightingAPI1)
+ (usdPreviewSurfaceLightingAPI2)
(usdPreviewSurfaceCombiner)
(UsdPrimvarColor)
@@ -80,6 +81,10 @@ TF_DEFINE_PRIVATE_TOKENS(
(UsdPrimvarReader_float3)
(UsdPrimvarReader_float4)
(UsdPrimvarReader_vector)
+
+ // Graph:
+ (UsdPreviewSurfaceLightAPI1)
+ (UsdPreviewSurfaceLightAPI2)
);
// clang-format on
@@ -119,17 +124,14 @@ static const TfTokenVector _FragmentNames = { _tokens->BasisCurvesCubicColorDoma
_tokens->scaledDiffusePassThrough,
_tokens->scaledSpecularPassThrough,
_tokens->opacityToTransparency,
- _tokens->usdPreviewSurfaceLighting,
+ _tokens->usdPreviewSurfaceLightingAPI1,
+ _tokens->usdPreviewSurfaceLightingAPI2,
_tokens->usdPreviewSurfaceCombiner };
static const TfTokenVector _FragmentGraphNames
- = { _tokens->BasisCurvesCubicCPVShader,
- _tokens->BasisCurvesCubicFallbackShader,
- _tokens->BasisCurvesLinearCPVShader,
- _tokens->BasisCurvesLinearFallbackShader,
- _tokens->FallbackCPVShader,
- _tokens->FallbackShader,
- HdVP2ShaderFragmentsTokens->SurfaceFragmentGraphName };
+ = { _tokens->BasisCurvesCubicCPVShader, _tokens->BasisCurvesCubicFallbackShader,
+ _tokens->BasisCurvesLinearCPVShader, _tokens->BasisCurvesLinearFallbackShader,
+ _tokens->FallbackCPVShader, _tokens->FallbackShader };
namespace {
//! Get the file path of the shader fragment.
@@ -300,6 +302,32 @@ MStatus HdVP2ShaderFragments::registerFragments()
}
}
+ // Register a UsdPreviewSurface shader graph:
+ {
+ const MString fragGraphName(HdVP2ShaderFragmentsTokens->SurfaceFragmentGraphName.GetText());
+#ifdef MAYA_LIGHTAPI_VERSION_2
+ const MString fragGraphFileName(_tokens->UsdPreviewSurfaceLightAPI2.GetText());
+#else
+ const MString fragGraphFileName(_tokens->UsdPreviewSurfaceLightAPI1.GetText());
+#endif
+ if (!fragmentManager->hasFragment(fragGraphName)) {
+ const std::string fragGraphXmlFile
+ = TfStringPrintf("%s.xml", fragGraphFileName.asChar());
+ const std::string fragGraphXmlPath = _GetResourcePath(fragGraphXmlFile);
+
+ const MString addedName
+ = fragmentManager->addFragmentGraphFromFile(fragGraphXmlPath.c_str());
+ if (addedName != fragGraphName) {
+ MGlobal::displayError(TfStringPrintf(
+ "Failed to register fragment graph '%s' from file: %s",
+ fragGraphName.asChar(),
+ fragGraphXmlPath.c_str())
+ .c_str());
+ return MS::kFailure;
+ }
+ }
+ }
+
#if MAYA_API_VERSION >= 20210000
// Register automatic shader stage input parameters.
@@ -361,6 +389,13 @@ MStatus HdVP2ShaderFragments::deregisterFragments()
#endif
+ // De-register UsdPreviewsurface graph:
+ if (!fragmentManager->removeFragment(
+ HdVP2ShaderFragmentsTokens->SurfaceFragmentGraphName.GetText())) {
+ MGlobal::displayWarning("Failed to remove fragment graph: UsdPreviewsurface");
+ return MS::kFailure;
+ }
+
// De-register all fragment graphs.
for (const TfToken& fragGraphNameToken : _FragmentGraphNames) {
const MString fragGraphName(fragGraphNameToken.GetText());
diff --git a/lib/mayaUsd/render/vp2ShaderFragments/usdPreviewSurfaceLighting.xml b/lib/mayaUsd/render/vp2ShaderFragments/usdPreviewSurfaceLightingAPI1.xml
similarity index 97%
rename from lib/mayaUsd/render/vp2ShaderFragments/usdPreviewSurfaceLighting.xml
rename to lib/mayaUsd/render/vp2ShaderFragments/usdPreviewSurfaceLightingAPI1.xml
index 368a10b88d..5250c025a5 100644
--- a/lib/mayaUsd/render/vp2ShaderFragments/usdPreviewSurfaceLighting.xml
+++ b/lib/mayaUsd/render/vp2ShaderFragments/usdPreviewSurfaceLightingAPI1.xml
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
========================================================================
-->
-
+
Computes the diffuse and specular lighting contributions for a light.
@@ -69,11 +69,11 @@ limitations under the License.
-
+
-
+
-
+
-
+
-
+
+
+
+ Computes usdPreviewSurface using latest maya lighting functions.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0.0) {
+ vec3 F0 = specularColor;
+ vec3 F90 = vec3(1.0);
+
+ if (!useSpecularWorkflow) {
+ vec3 specColor = mix(vec3(1.0), diffuseColor, metallic);
+ F0 = mix(R * R * specColor, specColor, metallic);
+ F90 = specColor;
+
+ // For metallic workflows, pure metals have no diffuse
+ d *= 1.0 - metallic;
+ }
+
+ s1 = specularAmount * evaluateDirectSpecular(
+ F0, // Specular color 0
+ F90, // Specular color 90
+ specularRoughness, // Roughness
+ fresnel, // Fresnel
+ NdotL, NdotE, NdotH, EdotH); // Dot products needed for lights
+
+ // Adjust the diffuse so glazing angles have less diffuse
+ d *= (1.0 - mix(F0, F90, fresnel));
+ }
+
+ // Evaluate clearcoat
+ vec3 s2 = vec3(0.0);
+ if (clearcoatAmount > 0.0) {
+ s2 = clearcoatAmount * evaluateDirectSpecular(
+ R * R * clearcoatColor, // Clearcoat color 0
+ clearcoatColor, // Clearcoat color 90
+ clearcoatRoughness, // Roughness
+ fresnel, // Fresnel
+ NdotL, NdotE, NdotH, EdotH); // Dot products needed for lights
+ }
+
+ LightingContributions lightingContrib;
+
+ lightingContrib.diffuse =
+ occlusion * NdotL * d * lightDiffuseIrradiance;
+
+ lightingContrib.specular =
+ occlusion * NdotL * (s1 + s2) * lightSpecularIrradiance;
+
+ return lightingContrib;
+}
+
+
+//-- glsl Preview.LightIntegration
+
+vec3
+evaluateIndirectLighting(
+ vec3 diffuseColor,
+ vec3 specularColor,
+ vec3 Neye,
+ vec3 E,
+ float EdotH,
+ float ior,
+ float metallic,
+ float occlusion,
+ float roughness,
+ bool useSpecularWorkflow,
+ float clearcoatAmount,
+ vec3 clearcoatColor,
+ float clearcoatRoughness)
+{
+ vec3 indirect = vec3(0.0);
+
+ vec3 F0 = specularColor;
+ vec3 F90 = vec3(1.0);
+ vec3 d = diffuseColor;
+ const float R = (1.0 - ior) / (1.0 + ior);
+ if (!useSpecularWorkflow) {
+ vec3 specColor = mix(vec3(1.0), diffuseColor, metallic);
+ F0 = mix(R * R * specColor, specColor, metallic);
+ F90 = specColor;
+
+ // For metallic workflows, pure metals have no diffuse
+ d *= 1.0 - metallic;
+ }
+ // Adjust the diffuse so glazing angles have less diffuse
+ float fresnel = SchlickFresnel(EdotH);
+ vec3 F = mix(F0, F90, fresnel);
+ d *= (1.0 - F);
+
+ vec3 diffuse = mayaGetIrradianceEnvironment(Neye);
+
+ // Specular Component
+ float phongExp = mayaRoughnessToPhongExp(roughness);
+ vec3 Li = mayaGetSpecularEnvironment(Neye, E, phongExp);
+ vec3 specular = Li * F;
+
+ // Clearcoat Component
+ vec3 clearcoat = vec3(0.0);
+ if (clearcoatAmount > 0.0) {
+ const vec3 clearcoatF = clearcoatAmount * mix(
+ R * R * clearcoatColor, // Clearcoat F0
+ clearcoatColor, // Clearcoat F90
+ fresnel);
+ phongExp = mayaRoughnessToPhongExp(clearcoatRoughness);
+ Li = mayaGetSpecularEnvironment(Neye, E, phongExp);
+ clearcoat = Li * clearcoatF;
+ }
+
+ // Indirect Lighting
+ indirect = (d * diffuse + specular + clearcoat) * occlusion;
+
+ return indirect;
+}
+
+vec3
+evaluateLights(
+ vec3 emissiveColor,
+ vec3 diffuseColor,
+ bool useSpecularWorkflow,
+ float ior,
+ float metallic,
+ float specularAmount,
+ vec3 specularColor,
+ float specularRoughness,
+ float clearcoatAmount,
+ vec3 clearcoatColor,
+ float clearcoatRoughness,
+ float occlusion,
+ vec3 Peye,
+ vec3 Neye)
+{
+ vec3 n = Neye;
+ vec3 e = normalize(u_viewPosition - Peye);
+ float NdotE = max(0.0, dot(n, e));
+
+ vec3 directLight = vec3(0.0);
+ vec3 indirectLight = vec3(0.0);
+
+ int numLights = mayaGetNumLights();
+ for (int i = 0; i < numLights; ++i) {
+
+ irradiance lightShader = mayaGetLightIrradiance(i, Peye, Neye, e);
+
+ vec3 l = lightShader.Ld;
+ vec3 h = normalize(e + l);
+ float NdotL = max(0.0, dot(n, l));
+ float NdotH = max(0.0, dot(n, h));
+ float EdotH = max(0.0, dot(e, h));
+
+ vec3 lightDiffuseIrradiance = lightShader.diffuseI;
+ vec3 lightSpecularIrradiance = lightShader.specularI;
+
+ LightingContributions lightingContrib = evaluateLight(
+ diffuseColor,
+ useSpecularWorkflow,
+ ior,
+ metallic,
+ specularAmount,
+ specularColor,
+ specularRoughness,
+ clearcoatAmount,
+ clearcoatColor,
+ clearcoatRoughness,
+ occlusion,
+ NdotL,
+ NdotE,
+ NdotH,
+ EdotH,
+ lightDiffuseIrradiance,
+ lightSpecularIrradiance);
+
+ // calculate the indirect light (DomeLight)
+ directLight += (lightingContrib.diffuse + lightingContrib.specular);
+ }
+
+ {
+ // Calculate necessary vector information for lighting
+ vec3 Plight = vec3(0,0,0);
+ vec3 l = normalize(Plight - Peye);
+ vec3 h = normalize(e + l);
+ float EdotH = max(0.0, dot(e, h));
+
+ indirectLight = evaluateIndirectLighting(diffuseColor,
+ specularColor, Neye, e,
+ EdotH, ior, metallic, occlusion,
+ specularRoughness, useSpecularWorkflow,
+ clearcoatAmount, clearcoatColor,
+ clearcoatRoughness);
+ }
+
+ return (emissiveColor + directLight + indirectLight);
+}
+
+
+//-- glsl Preview.Surface
+
+mayaSurfaceShaderOutput
+surfaceShader(vec3 Peye, vec3 Neye,
+ float clearcoatAmount,
+ float clearcoatRoughness,
+ vec3 diffuseColor,
+ vec3 emissiveColor,
+ float ior,
+ float metallic,
+ float occlusion,
+ vec3 transparency,
+ float opacityThreshold,
+ float roughness,
+ vec3 specularColor,
+ bool useSpecularWorkflow,
+ vec3 clearcoatColor,
+ float specularAmount
+)
+{
+ float opacity = 1.0 - transparency.r;
+ if (opacity < opacityThreshold) {
+ discard;
+ }
+
+ mayaSurfaceShaderOutput result;
+
+ // Pre-multiply diffuse color by opacity if not done so already
+ diffuseColor *= opacity;
+
+ // Evaluate all lights.
+ result.outColor = evaluateLights(
+ emissiveColor,
+ diffuseColor,
+ useSpecularWorkflow,
+ ior,
+ metallic,
+ specularAmount,
+ specularColor,
+ roughness,
+ clearcoatAmount,
+ clearcoatColor,
+ clearcoatRoughness,
+ occlusion,
+ Peye,
+ Neye);
+
+ // Transparency
+ result.outTransparency = transparency;
+
+ result.outGlowColor = vec3(0.0, 0.0, 0.0);
+ result.outMatteOpacity = vec3(opacity);
+
+ return result;
+}
+
+
+]]>
+
+
+
+
+
+ 0.0) {
+ vec3 F0 = specularColor;
+ vec3 F90 = vec3(1.0);
+
+ if (!useSpecularWorkflow) {
+ vec3 specColor = mix(vec3(1.0), diffuseColor, metallic);
+ F0 = mix(R * R * specColor, specColor, metallic);
+ F90 = specColor;
+
+ // For metallic workflows, pure metals have no diffuse
+ d *= 1.0 - metallic;
+ }
+
+ s1 = specularAmount * evaluateDirectSpecular(
+ F0, // Specular color 0
+ F90, // Specular color 90
+ specularRoughness, // Roughness
+ fresnel, // Fresnel
+ NdotL, NdotE, NdotH, EdotH); // Dot products needed for lights
+
+ // Adjust the diffuse so glazing angles have less diffuse
+ d *= (1.0 - mix(F0, F90, fresnel));
+ }
+
+ // Evaluate clearcoat
+ vec3 s2 = vec3(0.0);
+ if (clearcoatAmount > 0.0) {
+ s2 = clearcoatAmount * evaluateDirectSpecular(
+ R * R * clearcoatColor, // Clearcoat color 0
+ clearcoatColor, // Clearcoat color 90
+ clearcoatRoughness, // Roughness
+ fresnel, // Fresnel
+ NdotL, NdotE, NdotH, EdotH); // Dot products needed for lights
+ }
+
+ LightingContributions lightingContrib;
+
+ lightingContrib.diffuse =
+ occlusion * NdotL * d * lightDiffuseIrradiance;
+
+ lightingContrib.specular =
+ occlusion * NdotL * (s1 + s2) * lightSpecularIrradiance;
+
+ return lightingContrib;
+}
+
+
+//-- glsl Preview.LightIntegration
+
+vec3
+evaluateIndirectLighting(
+ vec3 diffuseColor,
+ vec3 specularColor,
+ vec3 Neye,
+ vec3 E,
+ float EdotH,
+ float ior,
+ float metallic,
+ float occlusion,
+ float roughness,
+ bool useSpecularWorkflow,
+ float clearcoatAmount,
+ vec3 clearcoatColor,
+ float clearcoatRoughness)
+{
+ vec3 indirect = vec3(0.0);
+
+ vec3 F0 = specularColor;
+ vec3 F90 = vec3(1.0);
+ vec3 d = diffuseColor;
+ const float R = (1.0 - ior) / (1.0 + ior);
+ if (!useSpecularWorkflow) {
+ vec3 specColor = mix(vec3(1.0), diffuseColor, metallic);
+ F0 = mix(R * R * specColor, specColor, metallic);
+ F90 = specColor;
+
+ // For metallic workflows, pure metals have no diffuse
+ d *= 1.0 - metallic;
+ }
+ // Adjust the diffuse so glazing angles have less diffuse
+ float fresnel = SchlickFresnel(EdotH);
+ vec3 F = mix(F0, F90, fresnel);
+ d *= (1.0 - F);
+
+ vec3 diffuse = mayaGetIrradianceEnvironment(Neye);
+
+ // Specular Component
+ float phongExp = mayaRoughnessToPhongExp(roughness);
+ vec3 Li = mayaGetSpecularEnvironment(Neye, E, phongExp);
+ vec3 specular = Li * F;
+
+ // Clearcoat Component
+ vec3 clearcoat = vec3(0.0);
+ if (clearcoatAmount > 0.0) {
+ const vec3 clearcoatF = clearcoatAmount * mix(
+ R * R * clearcoatColor, // Clearcoat F0
+ clearcoatColor, // Clearcoat F90
+ fresnel);
+ phongExp = mayaRoughnessToPhongExp(clearcoatRoughness);
+ Li = mayaGetSpecularEnvironment(Neye, E, phongExp);
+ clearcoat = Li * clearcoatF;
+ }
+
+ // Indirect Lighting
+ indirect = (d * diffuse + specular + clearcoat) * occlusion;
+
+ return indirect;
+}
+
+vec3
+evaluateLights(
+ vec3 emissiveColor,
+ vec3 diffuseColor,
+ bool useSpecularWorkflow,
+ float ior,
+ float metallic,
+ float specularAmount,
+ vec3 specularColor,
+ float specularRoughness,
+ float clearcoatAmount,
+ vec3 clearcoatColor,
+ float clearcoatRoughness,
+ float occlusion,
+ vec3 Peye,
+ vec3 Neye)
+{
+ vec3 n = Neye;
+ vec3 e = normalize(u_viewPosition - Peye);
+ float NdotE = max(0.0, dot(n, e));
+
+ vec3 directLight = vec3(0.0);
+ vec3 indirectLight = vec3(0.0);
+
+ int numLights = mayaGetNumLights();
+ for (int i = 0; i < numLights; ++i) {
+
+ irradiance lightShader = mayaGetLightIrradiance(i, Peye, Neye, e);
+
+ vec3 l = lightShader.Ld;
+ vec3 h = normalize(e + l);
+ float NdotL = max(0.0, dot(n, l));
+ float NdotH = max(0.0, dot(n, h));
+ float EdotH = max(0.0, dot(e, h));
+
+ vec3 lightDiffuseIrradiance = lightShader.diffuseI;
+ vec3 lightSpecularIrradiance = lightShader.specularI;
+
+ LightingContributions lightingContrib = evaluateLight(
+ diffuseColor,
+ useSpecularWorkflow,
+ ior,
+ metallic,
+ specularAmount,
+ specularColor,
+ specularRoughness,
+ clearcoatAmount,
+ clearcoatColor,
+ clearcoatRoughness,
+ occlusion,
+ NdotL,
+ NdotE,
+ NdotH,
+ EdotH,
+ lightDiffuseIrradiance,
+ lightSpecularIrradiance);
+
+ // calculate the indirect light (DomeLight)
+ directLight += (lightingContrib.diffuse + lightingContrib.specular);
+ }
+
+ {
+ // Calculate necessary vector information for lighting
+ vec3 Plight = vec3(0,0,0);
+ vec3 l = normalize(Plight - Peye);
+ vec3 h = normalize(e + l);
+ float EdotH = max(0.0, dot(e, h));
+
+ indirectLight = evaluateIndirectLighting(diffuseColor,
+ specularColor, Neye, e,
+ EdotH, ior, metallic, occlusion,
+ specularRoughness, useSpecularWorkflow,
+ clearcoatAmount, clearcoatColor,
+ clearcoatRoughness);
+ }
+
+ return (emissiveColor + directLight + indirectLight);
+}
+
+
+//-- glsl Preview.Surface
+
+mayaSurfaceShaderOutput
+surfaceShader(vec3 Peye, vec3 Neye,
+ float clearcoatAmount,
+ float clearcoatRoughness,
+ vec3 diffuseColor,
+ vec3 emissiveColor,
+ float ior,
+ float metallic,
+ float occlusion,
+ vec3 transparency,
+ float opacityThreshold,
+ float roughness,
+ vec3 specularColor,
+ bool useSpecularWorkflow,
+ vec3 clearcoatColor,
+ float specularAmount
+)
+{
+ float opacity = 1.0 - transparency.r;
+ if (opacity < opacityThreshold) {
+ discard;
+ }
+
+ mayaSurfaceShaderOutput result;
+
+ // Pre-multiply diffuse color by opacity if not done so already
+ diffuseColor *= opacity;
+
+ // Evaluate all lights.
+ result.outColor = evaluateLights(
+ emissiveColor,
+ diffuseColor,
+ useSpecularWorkflow,
+ ior,
+ metallic,
+ specularAmount,
+ specularColor,
+ roughness,
+ clearcoatAmount,
+ clearcoatColor,
+ clearcoatRoughness,
+ occlusion,
+ Peye,
+ Neye);
+
+ // Transparency
+ result.outTransparency = transparency;
+
+ result.outGlowColor = vec3(0.0, 0.0, 0.0);
+ result.outMatteOpacity = vec3(opacity);
+
+ return result;
+}
+
+
+]]>
+
+
+
+
+
+ 0.0) {
+ float3 F0 = specularColor;
+ float3 F90 = float3(1.0, 1.0, 1.0);
+
+ if (!useSpecularWorkflow) {
+ float3 specColor = lerp(float3(1.0, 1.0, 1.0), diffuseColor, metallic);
+ F0 = lerp(R * R * specColor, specColor, metallic);
+ F90 = specColor;
+
+ // For metallic workflows, pure metals have no diffuse
+ d *= 1.0 - metallic;
+ }
+
+ s1 = specularAmount * evaluateDirectSpecular(
+ F0, // Specular color 0
+ F90, // Specular color 90
+ specularRoughness, // Roughness
+ fresnel, // Fresnel
+ NdotL, NdotE, NdotH, EdotH); // Dot products needed for lights
+
+ // Adjust the diffuse so glazing angles have less diffuse
+ d *= (1.0 - lerp(F0, F90, fresnel));
+ }
+
+ // Evaluate clearcoat
+ float3 s2 = float3(0.0, 0.0, 0.0);
+ if (clearcoatAmount > 0.0) {
+ s2 = clearcoatAmount * evaluateDirectSpecular(
+ R * R * clearcoatColor, // Clearcoat color 0
+ clearcoatColor, // Clearcoat color 90
+ clearcoatRoughness, // Roughness
+ fresnel, // Fresnel
+ NdotL, NdotE, NdotH, EdotH); // Dot products needed for lights
+ }
+
+ LightingContributions lightingContrib;
+
+ lightingContrib.diffuse =
+ occlusion * NdotL * d * lightDiffuseIrradiance;
+
+ lightingContrib.specular =
+ occlusion * NdotL * (s1 + s2) * lightSpecularIrradiance;
+
+ return lightingContrib;
+}
+
+
+//-- glsl Preview.LightIntegration
+
+float3
+evaluateIndirectLighting(
+ float3 diffuseColor,
+ float3 specularColor,
+ float3 Neye,
+ float3 E,
+ float EdotH,
+ float ior,
+ float metallic,
+ float occlusion,
+ float roughness,
+ bool useSpecularWorkflow,
+ float clearcoatAmount,
+ float3 clearcoatColor,
+ float clearcoatRoughness)
+{
+ float3 indirect = float3(0.0, 0.0, 0.0);
+
+ float3 F0 = specularColor;
+ float3 F90 = float3(1.0, 1.0, 1.0);
+ float3 d = diffuseColor;
+ const float R = (1.0 - ior) / (1.0 + ior);
+ if (!useSpecularWorkflow) {
+ float3 specColor = lerp(float3(1.0, 1.0, 1.0), diffuseColor, metallic);
+ F0 = lerp(R * R * specColor, specColor, metallic);
+ F90 = specColor;
+
+ // For metallic workflows, pure metals have no diffuse
+ d *= 1.0 - metallic;
+ }
+ // Adjust the diffuse so glazing angles have less diffuse
+ float fresnel = SchlickFresnel(EdotH);
+ float3 F = lerp(F0, F90, fresnel);
+ d *= (1.0 - F);
+
+ float3 diffuse = mayaGetIrradianceEnvironment(Neye);
+
+ // Specular Component
+ float phongExp = mayaRoughnessToPhongExp(roughness);
+ float3 Li = mayaGetSpecularEnvironment(Neye, E, phongExp);
+ float3 specular = Li * F;
+
+ // Clearcoat Component
+ float3 clearcoat = float3(0.0, 0.0, 0.0);
+ if (clearcoatAmount > 0.0) {
+ const float3 clearcoatF = clearcoatAmount * lerp(
+ R * R * clearcoatColor, // Clearcoat F0
+ clearcoatColor, // Clearcoat F90
+ fresnel);
+ phongExp = mayaRoughnessToPhongExp(clearcoatRoughness);
+ Li = mayaGetSpecularEnvironment(Neye, E, phongExp);
+ clearcoat = Li * clearcoatF;
+ }
+
+ // Indirect Lighting
+ indirect = (d * diffuse + specular + clearcoat) * occlusion;
+
+ return indirect;
+}
+
+float3
+evaluateLights(
+ float3 emissiveColor,
+ float3 diffuseColor,
+ bool useSpecularWorkflow,
+ float ior,
+ float metallic,
+ float specularAmount,
+ float3 specularColor,
+ float specularRoughness,
+ float clearcoatAmount,
+ float3 clearcoatColor,
+ float clearcoatRoughness,
+ float occlusion,
+ float3 Peye,
+ float3 Neye)
+{
+ float3 n = Neye;
+ float3 e = normalize(u_viewPosition - Peye);
+ float NdotE = max(0.0, dot(n, e));
+
+ float3 directLight = float3(0.0, 0.0, 0.0);
+ float3 indirectLight = float3(0.0, 0.0, 0.0);
+
+ int numLights = mayaGetNumLights();
+ for (int i = 0; i < numLights; ++i) {
+
+ irradiance lightShader = mayaGetLightIrradiance(i, Peye, Neye, e);
+
+ float3 l = lightShader.Ld;
+ float3 h = normalize(e + l);
+ float NdotL = max(0.0, dot(n, l));
+ float NdotH = max(0.0, dot(n, h));
+ float EdotH = max(0.0, dot(e, h));
+
+ float3 lightDiffuseIrradiance = lightShader.diffuseI;
+ float3 lightSpecularIrradiance = lightShader.specularI;
+
+ LightingContributions lightingContrib = evaluateLight(
+ diffuseColor,
+ useSpecularWorkflow,
+ ior,
+ metallic,
+ specularAmount,
+ specularColor,
+ specularRoughness,
+ clearcoatAmount,
+ clearcoatColor,
+ clearcoatRoughness,
+ occlusion,
+ NdotL,
+ NdotE,
+ NdotH,
+ EdotH,
+ lightDiffuseIrradiance,
+ lightSpecularIrradiance);
+
+ // calculate the indirect light (DomeLight)
+ directLight += (lightingContrib.diffuse + lightingContrib.specular);
+ }
+
+ {
+ // Calculate necessary vector information for lighting
+ float3 Plight = float3(0,0,0);
+ float3 l = normalize(Plight - Peye);
+ float3 h = normalize(e + l);
+ float EdotH = max(0.0, dot(e, h));
+
+ indirectLight = evaluateIndirectLighting(diffuseColor,
+ specularColor, Neye, e,
+ EdotH, ior, metallic, occlusion,
+ specularRoughness, useSpecularWorkflow,
+ clearcoatAmount, clearcoatColor,
+ clearcoatRoughness);
+ }
+
+ return (emissiveColor + directLight + indirectLight);
+}
+
+
+//-- glsl Preview.Surface
+
+mayaSurfaceShaderOutput
+surfaceShader(float3 Peye, float3 Neye,
+ float clearcoatAmount,
+ float clearcoatRoughness,
+ float3 diffuseColor,
+ float3 emissiveColor,
+ float ior,
+ float metallic,
+ float occlusion,
+ float3 transparency,
+ float opacityThreshold,
+ float roughness,
+ float3 specularColor,
+ bool useSpecularWorkflow,
+ float3 clearcoatColor,
+ float specularAmount
+)
+{
+ float opacity = 1.0 - transparency.r;
+ if (opacity < opacityThreshold) {
+ discard;
+ }
+
+ mayaSurfaceShaderOutput result;
+
+ // Pre-multiply diffuse color by opacity if not done so already
+ diffuseColor *= opacity;
+
+ // Evaluate all lights.
+ result.outColor = evaluateLights(
+ emissiveColor,
+ diffuseColor,
+ useSpecularWorkflow,
+ ior,
+ metallic,
+ specularAmount,
+ specularColor,
+ roughness,
+ clearcoatAmount,
+ clearcoatColor,
+ clearcoatRoughness,
+ occlusion,
+ Peye,
+ Neye);
+
+ // Transparency
+ result.outTransparency = transparency;
+
+ result.outGlowColor = float3(0.0, 0.0, 0.0);
+ result.outMatteOpacity = float3(opacity, opacity, opacity);
+
+ return result;
+}
+
+
+
+]]>
+
+
+
+
\ No newline at end of file
diff --git a/test/lib/mayaUsd/render/vp2RenderDelegate/CMakeLists.txt b/test/lib/mayaUsd/render/vp2RenderDelegate/CMakeLists.txt
index 02e5731cf0..69ee70daeb 100644
--- a/test/lib/mayaUsd/render/vp2RenderDelegate/CMakeLists.txt
+++ b/test/lib/mayaUsd/render/vp2RenderDelegate/CMakeLists.txt
@@ -58,6 +58,7 @@ foreach(script ${TEST_SCRIPT_FILES})
ENV
"MAYA_PLUG_IN_PATH=${CMAKE_INSTALL_PREFIX}/lib/maya"
"LD_LIBRARY_PATH=${ADDITIONAL_LD_LIBRARY_PATH}"
+ "MAYA_LIGHTAPI_VERSION=${MAYA_LIGHTAPI_VERSION}"
# Maya uses a very old version of GLEW, so we need support for
# pre-loading a newer version from elsewhere.
diff --git a/test/lib/mayaUsd/render/vp2RenderDelegate/VP2RenderDelegateUSDPreviewSurface/baseline/testMetallicResponse.png b/test/lib/mayaUsd/render/vp2RenderDelegate/VP2RenderDelegateUSDPreviewSurface/baseline/testMetallicResponseLightAPI1.png
similarity index 100%
rename from test/lib/mayaUsd/render/vp2RenderDelegate/VP2RenderDelegateUSDPreviewSurface/baseline/testMetallicResponse.png
rename to test/lib/mayaUsd/render/vp2RenderDelegate/VP2RenderDelegateUSDPreviewSurface/baseline/testMetallicResponseLightAPI1.png
diff --git a/test/lib/mayaUsd/render/vp2RenderDelegate/VP2RenderDelegateUSDPreviewSurface/baseline/testMetallicResponseLightAPI2.png b/test/lib/mayaUsd/render/vp2RenderDelegate/VP2RenderDelegateUSDPreviewSurface/baseline/testMetallicResponseLightAPI2.png
new file mode 100644
index 0000000000..d4cdb66d40
Binary files /dev/null and b/test/lib/mayaUsd/render/vp2RenderDelegate/VP2RenderDelegateUSDPreviewSurface/baseline/testMetallicResponseLightAPI2.png differ
diff --git a/test/lib/mayaUsd/render/vp2RenderDelegate/testVP2RenderDelegateUSDPreviewSurface.py b/test/lib/mayaUsd/render/vp2RenderDelegate/testVP2RenderDelegateUSDPreviewSurface.py
index c4e3c31797..f6252147da 100644
--- a/test/lib/mayaUsd/render/vp2RenderDelegate/testVP2RenderDelegateUSDPreviewSurface.py
+++ b/test/lib/mayaUsd/render/vp2RenderDelegate/testVP2RenderDelegateUSDPreviewSurface.py
@@ -32,7 +32,6 @@
import os
-
class testVP2RenderDelegateUSDPreviewSurface(imageUtils.ImageDiffingTestCase):
"""
Test various features of the USD Preview Surface implementation.
@@ -104,7 +103,10 @@ def testMetallicResponse(self):
panel = mayaUtils.activeModelPanel()
cmds.modelEditor(panel, edit=True, lights=False, displayLights="all")
- self.assertSnapshotClose("testMetallicResponse.png")
+ if int(os.getenv("MAYA_LIGHTAPI_VERSION")) == 2:
+ self.assertSnapshotClose("testMetallicResponseLightAPI2.png")
+ else:
+ self.assertSnapshotClose("testMetallicResponseLightAPI1.png")
if __name__ == '__main__':
diff --git a/test/testUtils/mayaUtils.py b/test/testUtils/mayaUtils.py
index 8c8b7d15da..9003ffb897 100644
--- a/test/testUtils/mayaUtils.py
+++ b/test/testUtils/mayaUtils.py
@@ -245,6 +245,8 @@ def previewReleaseVersion():
def mayaMajorVersion():
return int(cmds.about(majorVersion=True))
+def mayaMinorVersion():
+ return int(cmds.about(minorVersion=True))
def activeModelPanel():
"""Return the model panel that will be used for playblasting etc..."""