diff --git a/lib/mayaUsd/render/MaterialXGenOgsXml/CMakeLists.txt b/lib/mayaUsd/render/MaterialXGenOgsXml/CMakeLists.txt index 208dff7d8e..add21cdc73 100644 --- a/lib/mayaUsd/render/MaterialXGenOgsXml/CMakeLists.txt +++ b/lib/mayaUsd/render/MaterialXGenOgsXml/CMakeLists.txt @@ -87,6 +87,17 @@ if(MaterialX_VERSION VERSION_LESS "1.38.4") DESTINATION ${CMAKE_INSTALL_PREFIX}/libraries/pbrlib/genglsl/ogsxml ) endforeach() +elseif(MaterialX_VERSION VERSION_LESS "1.38.8") + MESSAGE(STATUS "Using 1.38.[4-7] libraries with MaterialX ${MaterialX_VERSION}") + install(FILES ${NODE_GLSL_IMPLEMENTATIONS_VERSIONED} + DESTINATION ${CMAKE_INSTALL_PREFIX}/libraries/adsk/maya/genglsl + ) + foreach(MTLX_FILE ${LIGHT_IMPLEMENTATIONS}) + string(REPLACE "libraries/" "libraries/1.38.7/" MTLX_FILE ${MTLX_FILE}) + install(FILES "${MTLX_FILE}" + DESTINATION ${CMAKE_INSTALL_PREFIX}/libraries/pbrlib/genglsl/ogsxml + ) + endforeach() else() MESSAGE(STATUS "Using latest libraries with MaterialX ${MaterialX_VERSION}") install(FILES ${NODE_GLSL_IMPLEMENTATIONS_VERSIONED} diff --git a/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/1.38.7/mx_lighting_maya_none.glsl b/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/1.38.7/mx_lighting_maya_none.glsl new file mode 100644 index 0000000000..fb5a9da055 --- /dev/null +++ b/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/1.38.7/mx_lighting_maya_none.glsl @@ -0,0 +1,19 @@ +// This is the same algorithm as found in libraries\pbrlib\genglsl\lib\mx_environment_prefilter.glsl +// but adjusted for Maya. At this time we will compute a roughness based on the radiance and +// irradiance samples, so materials with small amount of roughness will look wrong. +// +// A more precise roughness computation can be done using Maya samplers, but this requires +// knowing that the Maya sampling functions are there, otherwise compilation will fail unless +// there is an IBL active in the Maya lighting. + +#include "libraries/pbrlib/genglsl/lib/mx_microfacet_specular.glsl" + +vec3 mx_environment_irradiance(vec3 N) +{ + return vec3(0); +} + +vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 alpha, int distribution, FresnelData fd) +{ + return vec3(0); +} diff --git a/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/1.38.7/mx_lighting_maya_v1.glsl b/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/1.38.7/mx_lighting_maya_v1.glsl new file mode 100644 index 0000000000..f69e68e1f2 --- /dev/null +++ b/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/1.38.7/mx_lighting_maya_v1.glsl @@ -0,0 +1,27 @@ +// This is the same algorithm as found in libraries\pbrlib\genglsl\lib\mx_environment_prefilter.glsl +// but adjusted for Maya. At this time we will compute a roughness based on the radiance and +// irradiance samples, so materials with small amount of roughness will look wrong. +// +// A more precise roughness computation can be done using Maya samplers, but this requires +// knowing that the Maya sampling functions are there, otherwise compilation will fail unless +// there is an IBL active in the Maya lighting. + +#include "libraries/pbrlib/genglsl/lib/mx_microfacet_specular.glsl" + +vec3 mx_environment_irradiance(vec3 N) +{ + return g_diffuseI; +} + +vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 alpha, int distribution, FresnelData fd) +{ + N = mx_forward_facing_normal(N, V); + vec3 L = reflect(-V, N); + float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); + float avgAlpha = mx_average_alpha(alpha); + vec3 F = mx_compute_fresnel(NdotV, fd); + float G = mx_ggx_smith_G2(NdotV, NdotV, avgAlpha); + vec3 comp = mx_ggx_energy_compensation(NdotV, avgAlpha, F); + vec3 Li = mix(g_specularI, g_diffuseI, avgAlpha); + return Li * F * G * comp; +} diff --git a/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/1.38.7/mx_lighting_maya_v2.glsl b/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/1.38.7/mx_lighting_maya_v2.glsl new file mode 100644 index 0000000000..9fa439b70d --- /dev/null +++ b/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/1.38.7/mx_lighting_maya_v2.glsl @@ -0,0 +1,27 @@ +// This is the same algorithm as found in libraries\pbrlib\genglsl\lib\mx_environment_prefilter.glsl +// but adjusted for Maya. +// +// Since we are on a more recent versions of Maya, we have external lighting functions that can be +// called to fetch environment samples: + +#include "libraries/pbrlib/genglsl/lib/mx_microfacet_specular.glsl" + +vec3 mx_environment_irradiance(vec3 N) +{ + return mayaGetIrradianceEnvironment(N); +} + +vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 alpha, int distribution, FresnelData fd) +{ + N = mx_forward_facing_normal(N, V); + vec3 L = reflect(-V, N); + float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); + float avgAlpha = mx_average_alpha(alpha); + vec3 F = mx_compute_fresnel(NdotV, fd); + float G = mx_ggx_smith_G2(NdotV, NdotV, avgAlpha); + vec3 comp = mx_ggx_energy_compensation(NdotV, avgAlpha, F); + float phongExp = mayaRoughnessToPhongExp(sqrt(avgAlpha)); + vec3 Li = mayaGetSpecularEnvironment(N, V, phongExp); + + return Li * F * G * comp; +} diff --git a/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/1.38.7/mx_lighting_maya_v3.glsl b/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/1.38.7/mx_lighting_maya_v3.glsl new file mode 100644 index 0000000000..61f705c757 --- /dev/null +++ b/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/1.38.7/mx_lighting_maya_v3.glsl @@ -0,0 +1,82 @@ +// This is the same algorithm as found in libraries\pbrlib\genglsl\lib\mx_environment_fis.glsl +// but adjusted for Maya. +// +// Since we are on a more recent versions of Maya, we have external lighting functions that can be +// called to fetch environment samples: +#include "libraries/pbrlib/genglsl/lib/mx_microfacet_specular.glsl" + +// https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch20.html +// Section 20.4 Equation 13 +float mx_latlong_compute_lod(vec3 dir, float pdf, float maxMipLevel, int envSamples) +{ + const float MIP_LEVEL_OFFSET = 1.5; + float effectiveMaxMipLevel = maxMipLevel - MIP_LEVEL_OFFSET; + float distortion = sqrt(1.0 - mx_square(dir.y)); + return max(effectiveMaxMipLevel - 0.5 * log2(float(envSamples) * pdf * distortion), 0.0); +} + +vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 alpha, int distribution, FresnelData fd) +{ + if (mayaGetSpecularEnvironmentNumLOD() == 0) { + return vec3(0); + } + + // Generate tangent frame. + vec3 Y = normalize(cross(N, X)); + X = cross(Y, N); + mat3 tangentToWorld = mat3(X, Y, N); + + // Transform the view vector to tangent space. + V = vec3(dot(V, X), dot(V, Y), dot(V, N)); + + // Compute derived properties. + float NdotV = clamp(V.z, M_FLOAT_EPS, 1.0); + float avgAlpha = mx_average_alpha(alpha); + + // Integrate outgoing radiance using filtered importance sampling. + // http://cgg.mff.cuni.cz/~jaroslav/papers/2008-egsr-fis/2008-egsr-fis-final-embedded.pdf + vec3 radiance = vec3(0.0); + for (int i = 0; i < MX_NUM_FIS_SAMPLES; i++) + { + vec2 Xi = mx_spherical_fibonacci(i, MX_NUM_FIS_SAMPLES); + + // Compute the half vector and incoming light direction. + vec3 H = mx_ggx_importance_sample_NDF(Xi, alpha); + vec3 L = -reflect(V, H); + + // Compute dot products for this sample. + float NdotH = clamp(H.z, M_FLOAT_EPS, 1.0); + float NdotL = clamp(L.z, M_FLOAT_EPS, 1.0); + float VdotH = clamp(dot(V, H), M_FLOAT_EPS, 1.0); + float LdotH = VdotH; + + // Sample the environment light from the given direction. + vec3 Lw = tangentToWorld * L; + float pdf = mx_ggx_PDF(H, LdotH, alpha); + float lod = mx_latlong_compute_lod(Lw, pdf, float(mayaGetSpecularEnvironmentNumLOD() - 1), MX_NUM_FIS_SAMPLES); + vec3 sampleColor = mayaSampleSpecularEnvironmentAtLOD(Lw, lod); + + // Compute the Fresnel term. + vec3 F = mx_compute_fresnel(VdotH, fd); + + // Compute the geometric term. + float G = mx_ggx_smith_G2(NdotL, NdotV, avgAlpha); + + // Add the radiance contribution of this sample. + // From https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf + // incidentLight = sampleColor * NdotL + // microfacetSpecular = D * F * G / (4 * NdotL * NdotV) + // pdf = D * NdotH / (4 * VdotH) + // radiance = incidentLight * microfacetSpecular / pdf + radiance += sampleColor * F * G * VdotH / (NdotV * NdotH); + } + + // Normalize and return the final radiance. + radiance /= float(MX_NUM_FIS_SAMPLES); + return radiance; +} + +vec3 mx_environment_irradiance(vec3 N) +{ + return mayaGetIrradianceEnvironment(N); +} diff --git a/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/mx_lighting_maya_none.glsl b/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/mx_lighting_maya_none.glsl index fb5a9da055..063babd981 100644 --- a/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/mx_lighting_maya_none.glsl +++ b/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/mx_lighting_maya_none.glsl @@ -10,10 +10,10 @@ vec3 mx_environment_irradiance(vec3 N) { - return vec3(0); + return vec3(0.0); } -vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 alpha, int distribution, FresnelData fd) +vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 roughness, int distribution, FresnelData fd) { - return vec3(0); + return vec3(0.0); } diff --git a/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/mx_lighting_maya_v1.glsl b/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/mx_lighting_maya_v1.glsl index f69e68e1f2..3e54af5658 100644 --- a/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/mx_lighting_maya_v1.glsl +++ b/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/mx_lighting_maya_v1.glsl @@ -16,12 +16,12 @@ vec3 mx_environment_irradiance(vec3 N) vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 alpha, int distribution, FresnelData fd) { N = mx_forward_facing_normal(N, V); - vec3 L = reflect(-V, N); + vec3 L = fd.refraction ? mx_refraction_solid_sphere(-V, N, fd.ior.x) : -reflect(V, N); float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); float avgAlpha = mx_average_alpha(alpha); vec3 F = mx_compute_fresnel(NdotV, fd); float G = mx_ggx_smith_G2(NdotV, NdotV, avgAlpha); - vec3 comp = mx_ggx_energy_compensation(NdotV, avgAlpha, F); + vec3 FG = fd.refraction ? vec3(1.0) - (F * G) : F * G; vec3 Li = mix(g_specularI, g_diffuseI, avgAlpha); - return Li * F * G * comp; + return Li * FG; } diff --git a/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/mx_lighting_maya_v2.glsl b/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/mx_lighting_maya_v2.glsl index 9fa439b70d..1a491a6aa4 100644 --- a/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/mx_lighting_maya_v2.glsl +++ b/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/mx_lighting_maya_v2.glsl @@ -14,14 +14,13 @@ vec3 mx_environment_irradiance(vec3 N) vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 alpha, int distribution, FresnelData fd) { N = mx_forward_facing_normal(N, V); - vec3 L = reflect(-V, N); + vec3 L = fd.refraction ? mx_refraction_solid_sphere(-V, N, fd.ior.x) : -reflect(V, N); float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); float avgAlpha = mx_average_alpha(alpha); vec3 F = mx_compute_fresnel(NdotV, fd); float G = mx_ggx_smith_G2(NdotV, NdotV, avgAlpha); - vec3 comp = mx_ggx_energy_compensation(NdotV, avgAlpha, F); + vec3 FG = fd.refraction ? vec3(1.0) - (F * G) : F * G; float phongExp = mayaRoughnessToPhongExp(sqrt(avgAlpha)); vec3 Li = mayaGetSpecularEnvironment(N, V, phongExp); - - return Li * F * G * comp; + return Li * FG; } diff --git a/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/mx_lighting_maya_v3.glsl b/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/mx_lighting_maya_v3.glsl index 61f705c757..18a4da5be3 100644 --- a/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/mx_lighting_maya_v3.glsl +++ b/lib/mayaUsd/render/MaterialXGenOgsXml/libraries/mx_lighting_maya_v3.glsl @@ -22,8 +22,8 @@ vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 alpha, int distributio } // Generate tangent frame. - vec3 Y = normalize(cross(N, X)); - X = cross(Y, N); + X = normalize(X - dot(X, N) * N); + vec3 Y = cross(N, X); mat3 tangentToWorld = mat3(X, Y, N); // Transform the view vector to tangent space. @@ -32,6 +32,7 @@ vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 alpha, int distributio // Compute derived properties. float NdotV = clamp(V.z, M_FLOAT_EPS, 1.0); float avgAlpha = mx_average_alpha(alpha); + float G1V = mx_ggx_smith_G1(NdotV, avgAlpha); // Integrate outgoing radiance using filtered importance sampling. // http://cgg.mff.cuni.cz/~jaroslav/papers/2008-egsr-fis/2008-egsr-fis-final-embedded.pdf @@ -41,18 +42,16 @@ vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 alpha, int distributio vec2 Xi = mx_spherical_fibonacci(i, MX_NUM_FIS_SAMPLES); // Compute the half vector and incoming light direction. - vec3 H = mx_ggx_importance_sample_NDF(Xi, alpha); - vec3 L = -reflect(V, H); + vec3 H = mx_ggx_importance_sample_VNDF(Xi, V, alpha); + vec3 L = fd.refraction ? mx_refraction_solid_sphere(-V, H, fd.ior.x) : -reflect(V, H); // Compute dot products for this sample. - float NdotH = clamp(H.z, M_FLOAT_EPS, 1.0); float NdotL = clamp(L.z, M_FLOAT_EPS, 1.0); float VdotH = clamp(dot(V, H), M_FLOAT_EPS, 1.0); - float LdotH = VdotH; // Sample the environment light from the given direction. vec3 Lw = tangentToWorld * L; - float pdf = mx_ggx_PDF(H, LdotH, alpha); + float pdf = mx_ggx_NDF(H, alpha) * G1V / (4.0 * NdotV); float lod = mx_latlong_compute_lod(Lw, pdf, float(mayaGetSpecularEnvironmentNumLOD() - 1), MX_NUM_FIS_SAMPLES); vec3 sampleColor = mayaSampleSpecularEnvironmentAtLOD(Lw, lod); @@ -62,17 +61,22 @@ vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 alpha, int distributio // Compute the geometric term. float G = mx_ggx_smith_G2(NdotL, NdotV, avgAlpha); + // Compute the combined FG term, which is inverted for refraction. + vec3 FG = fd.refraction ? vec3(1.0) - (F * G) : F * G; + // Add the radiance contribution of this sample. // From https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf // incidentLight = sampleColor * NdotL // microfacetSpecular = D * F * G / (4 * NdotL * NdotV) - // pdf = D * NdotH / (4 * VdotH) + // pdf = D * G1V / (4 * NdotV); // radiance = incidentLight * microfacetSpecular / pdf - radiance += sampleColor * F * G * VdotH / (NdotV * NdotH); + radiance += sampleColor * FG; } - // Normalize and return the final radiance. - radiance /= float(MX_NUM_FIS_SAMPLES); + // Apply the global component of the geometric term and normalize. + radiance /= G1V * float(MX_NUM_FIS_SAMPLES); + + // Return the final radiance. return radiance; } diff --git a/test/lib/mayaUsd/render/vp2RenderDelegate/VP2RenderDelegateMaterialXTest/baseline/MayaSurfaces_flat_ocio_blended_render.png b/test/lib/mayaUsd/render/vp2RenderDelegate/VP2RenderDelegateMaterialXTest/baseline/MayaSurfaces_flat_ocio_blended_render.png new file mode 100644 index 0000000000..ace576bd30 Binary files /dev/null and b/test/lib/mayaUsd/render/vp2RenderDelegate/VP2RenderDelegateMaterialXTest/baseline/MayaSurfaces_flat_ocio_blended_render.png differ diff --git a/test/lib/mayaUsd/render/vp2RenderDelegate/VP2RenderDelegateMaterialXTest/baseline/MayaSurfaces_ocio_blended_render.png b/test/lib/mayaUsd/render/vp2RenderDelegate/VP2RenderDelegateMaterialXTest/baseline/MayaSurfaces_ocio_blended_render.png new file mode 100644 index 0000000000..0874cc3aae Binary files /dev/null and b/test/lib/mayaUsd/render/vp2RenderDelegate/VP2RenderDelegateMaterialXTest/baseline/MayaSurfaces_ocio_blended_render.png differ diff --git a/test/lib/mayaUsd/render/vp2RenderDelegate/testVP2RenderDelegateMaterialX.py b/test/lib/mayaUsd/render/vp2RenderDelegate/testVP2RenderDelegateMaterialX.py index 854ab07eec..0f4df88b84 100644 --- a/test/lib/mayaUsd/render/vp2RenderDelegate/testVP2RenderDelegateMaterialX.py +++ b/test/lib/mayaUsd/render/vp2RenderDelegate/testVP2RenderDelegateMaterialX.py @@ -94,6 +94,10 @@ def testMayaSurfaces(self): if os.getenv('MAYA_HAS_COLOR_MANAGEMENT_SUPPORT_API', 'FALSE') == 'TRUE': suffix = "_ocio" + # MaterialX 1.38.8 has a new triplanar node with superior blending + if os.getenv('MATERIALX_VERSION', '1.38.0') >= '1.38.8': + suffix += "_blended" + mayaUtils.loadPlugin("mayaUsdPlugin") panel = mayaUtils.activeModelPanel() cmds.modelEditor(panel, edit=True, displayTextures=True)