Skip to content

Commit

Permalink
HYDRA-1329 : Support dome lights in the custom GLSL shader
Browse files Browse the repository at this point in the history
  • Loading branch information
lanierd-adsk committed Dec 11, 2024
1 parent 7082e71 commit c7fedec
Show file tree
Hide file tree
Showing 8 changed files with 248 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,111 @@ BasicLightingCoeffs computeLightingCoefficients(vec3 L, vec3 N, vec3 V, float ex
return coeffs;
}

//To support dome lights
struct LightingContributions
{
vec3 diffuse;
vec3 specular;
};

mat4 GetDomeLightTransform(mat4 worldToLightTransform)
{
// transform from view space to light space
mat4 worldToViewInverse = GetWorldToViewInverseMatrix();
return worldToLightTransform * worldToViewInverse;
}

#define PI 3.1415
vec2 ProjectToLatLong(vec3 sample3D)
{
// project spherical coord onto latitude-longitude map with
// latitude: +y == pi/2 and longitude: +z == 0, +x == pi/2
float x = (atan(sample3D.z, sample3D.x) + 0.5 * PI) / (2.0 * PI);
float y = acos(sample3D.y) / PI;

return vec2(x,y);
}

LightingContributions
evaluateIndirectLighting(
vec3 diffuseColor,
vec3 specularColor,
vec3 Neye,
vec3 Reye,
float NdotE,
float EdotH,
float ior,
float metallic,
float occlusion,
float roughness,
bool useSpecularWorkflow,
float clearcoatAmount,
vec3 clearcoatColor,
float clearcoatRoughness,
mat4 worldToLightTransform)
{
LightingContributions indirect;
indirect.diffuse = vec3(0.0);
indirect.specular = vec3(0.0);

#ifdef HD_HAS_domeLightIrradiance
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 = pow(max(0.0, 1.0 - EdotH), 5.0);//SchlickFresnel
vec3 F = mix(F0, F90, fresnel);
d *= (1.0 - F);

mat4 transformationMatrix = GetDomeLightTransform(worldToLightTransform);

// Diffuse Component
vec3 dir = normalize((transformationMatrix * vec4(Neye,0.0)).xyz);
vec2 coord = ProjectToLatLong(dir);
vec3 diffuse = HdGet_domeLightIrradiance(coord).rgb;

// Specular Component
const float MAX_REFLECTION_LOD =
textureQueryLevels(HdGetSampler_domeLightPrefilter());
float lod = roughness * MAX_REFLECTION_LOD;
vec3 Rdir = normalize((transformationMatrix * vec4(Reye,0.0)).xyz);
vec2 Rcoord = ProjectToLatLong(Rdir);
vec3 prefilter = HdTextureLod_domeLightPrefilter(Rcoord, lod).rgb;

vec2 brdf = HdGet_domeLightBRDF(vec2(NdotE, roughness)).rg;

vec3 specular = prefilter * (F * brdf.x + brdf.y);

// 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);
lod = clearcoatRoughness * MAX_REFLECTION_LOD;
prefilter = HdTextureLod_domeLightPrefilter(Rcoord, lod).rgb;
clearcoat = prefilter * (clearcoatF * brdf.x + brdf.y);
}

// Indirect Lighting
indirect.diffuse = (d * diffuse) * occlusion;
indirect.specular = (specular + clearcoat) * occlusion;

#endif

return indirect;
}

vec4
surfaceShader(vec4 Peye, vec3 Neye, vec4 color, vec4 patchCoord)
{
Expand All @@ -89,34 +194,65 @@ surfaceShader(vec4 Peye, vec3 Neye, vec4 color, vec4 patchCoord)

vec3 n = Neye;
vec3 e = normalize(-Peye.xyz);

vec3 directLight = vec3(0.0);
vec3 indirectLight = vec3(0.0);//For dome light
float glossiness = 30.0;//Hardcoded
float ior = 1.5; //Hardcoded
float metallic = 0.0;//Hardcoded
float occlusion = 1.0;//Hardcoded
bool useSpecularWorkflow = true;//Hardcoded
float clearcoatAmount = 0.0;//Hardcoded
vec3 clearcoatColor = vec3(1.0);//Hardcoded
float clearcoatRoughness = 0.01;//Hardcoded

//Do basic lighting
//Do lighting (with no shadows)
#if NUM_LIGHTS > 0
for (int i = 0; i < NUM_LIGHTS; ++i)
{
LightSource light = GetLightSource(i);
if (!light.isIndirectLight)
{
vec4 Plight = light.position;
vec3 l = (Plight.w == 0.0)
? normalize(Plight.xyz)
: normalize(Plight - Peye).xyz;
LightSource light = GetLightSource(i);
vec4 Plight = light.isIndirectLight //light.isIndirectLight is true for dome light.
? vec4(0,0,0,1)
: light.position;

vec3 l = (Plight.w == 0.0)
? normalize(Plight.xyz)
: normalize(Plight - Peye).xyz;

float atten = lightDistanceAttenuation(Peye, i);
float spot = lightSpotAttenuation(l, i);
float atten = lightDistanceAttenuation(Peye, i);
float spot = lightSpotAttenuation(l, i);

float intensity = 1.0 * atten * spot;
float intensity = 1.0 * atten * spot;

vec3 lightDiffuseIrradiance = intensity * light.diffuse.rgb;
vec3 lightSpecularIrradiance = intensity * light.specular.rgb;
vec3 lightDiffuseIrradiance = intensity * light.diffuse.rgb;
vec3 lightSpecularIrradiance = intensity * light.specular.rgb;

BasicLightingCoeffs coeffs = computeLightingCoefficients(l, n, e, glossiness);
directLight += (light.ambient.rgb *ambientColor + lightDiffuseIrradiance * coeffs.diffuse * diffuseColor + lightSpecularIrradiance * coeffs.specular * specularColor);
BasicLightingCoeffs coeffs = computeLightingCoefficients(l, n, e, glossiness);

if (light.isIndirectLight) {
float NdotE = max(0.0, dot(n, e));
vec3 Reye = reflect(-e, n);

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));
// Calculate the indirect light (DomeLight)
LightingContributions indirectLightContrib =
evaluateIndirectLighting(diffuseColor, specularColor,
Neye, Reye, NdotE, EdotH, ior, metallic, occlusion,
glossiness, useSpecularWorkflow,
clearcoatAmount, clearcoatColor, clearcoatRoughness,
light.worldToLightTransform);
indirectLight += (indirectLightContrib.diffuse * light.diffuse.rgb
+ indirectLightContrib.specular * light.specular.rgb);
}
else {
// All other light sources contribute to the direct lighting
directLight += (light.ambient.rgb *ambientColor + lightDiffuseIrradiance * coeffs.diffuse * diffuseColor + lightSpecularIrradiance * coeffs.specular * specularColor);
}
}
#endif

return vec4(directLight, 1.0);
return vec4(directLight+indirectLight, 1.0);
}
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 9 additions & 1 deletion test/lib/mayaUsd/render/mayaToHydra/testCustomShadersNode.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,15 @@ def test_LoadCustomShaderNode(self):
"testCustomShadersNode",
"testCustomShadersNode.ma")
cmds.refresh()
self.assertSnapshotClose("testCustomShadersNode.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT)
self.assertSnapshotClose("testCustomShadersNodeDefaultLight.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT)

# Switch the lighting mode to use all scene lights.
cmds.modelEditor(mayaUtils.activeModelPanel(), edit=True, displayLights = 'all')
self.assertSnapshotClose("testCustomShadersNodeUseAllLights.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT)

#Remove the direct lighting to check if the dome light works fine
cmds.setAttr("pointLightShape1.intensity", 0);
self.assertSnapshotClose("testCustomShadersNodeDomeLightOnly.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT)

if __name__ == '__main__':
fixturesUtils.runTests(globals())
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
100 changes: 87 additions & 13 deletions test/testSamples/testCustomShadersNode/testCustomShadersNode.ma
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
//Maya ASCII 2025ff01 scene
//Maya ASCII 2025ff02 scene
//Name: testCustomShadersNode.ma
//Last modified: Tue, Dec 10, 2024 02:09:44 PM
//Last modified: Wed, Dec 11, 2024 11:46:10 AM
//Codeset: 1252
requires maya "2025ff01";
requires maya "2025ff02";
requires -nodeType "MhCustomShaders" "mayaHydraCustomShadersNode" "2025.0";
requires -nodeType "aiOptions" -nodeType "aiAOVDriver" -nodeType "aiAOVFilter" -nodeType "aiSkyDomeLight"
-nodeType "aiImagerDenoiserOidn" "mtoa" "5.5.0";
currentUnit -l centimeter -a degree -t film;
fileInfo "application" "maya";
fileInfo "product" "Maya 2025";
fileInfo "version" "Preview Release";
fileInfo "cutIdentifier" "202406201527-000000";
fileInfo "cutIdentifier" "202412031025-000000";
fileInfo "osv" "Windows 10 Enterprise v2009 (Build: 19045)";
fileInfo "UUID" "1CC4C576-45C2-C419-BB7C-C6ADB74EB77E";
fileInfo "UUID" "32399C4F-4798-7197-6C92-ABA4785D13A3";
createNode transform -s -n "persp";
rename -uid "CAC40983-46C8-183E-1AFA-C889DB90A237";
setAttr ".v" no;
setAttr ".t" -type "double3" 1.7032043776282506 1.3442620959436657 1.6628472799166649 ;
setAttr ".r" -type "double3" -32.738352729575475 44.999999999961283 -2.2489917831959524e-15 ;
setAttr ".t" -type "double3" 2.3444946207989208 2.6275868051098961 2.2417681041490223 ;
setAttr ".r" -type "double3" -41.138352729575864 45.799999999961258 -6.8431882242206845e-15 ;
createNode camera -s -n "perspShape" -p "persp";
rename -uid "98B104E6-4BBD-86B0-9523-75B2BDF52ADE";
setAttr -k off ".v" no;
setAttr ".fl" 34.999999999999993;
setAttr ".coi" 2.7290490368539975;
setAttr ".coi" 4.1940870213230212;
setAttr ".imn" -type "string" "persp";
setAttr ".den" -type "string" "persp_depth";
setAttr ".man" -type "string" "persp_mask";
Expand Down Expand Up @@ -78,21 +80,33 @@ createNode MhCustomShaders -n "MhCustomShaders1" -p "transform1";
rename -uid "2588465F-4F45-D5D0-30EE-079DD68236D8";
setAttr -k off ".v";
setAttr ".col" -type "double3" 1 1 1 ;
createNode transform -n "aiSkyDomeLight1";
rename -uid "C5F4165C-4AFD-9433-9888-2892633BBCC7";
createNode aiSkyDomeLight -n "aiSkyDomeLightShape1" -p "aiSkyDomeLight1";
rename -uid "AA09D07E-4E4A-B07D-8CEA-5AA70457B47E";
setAttr -k off ".v";
createNode transform -n "pointLight1";
rename -uid "5AB2DCD7-4F0C-4E42-65A9-E5824FC99182";
setAttr ".t" -type "double3" 0.72655050063505378 0.58409642784605986 0 ;
createNode pointLight -n "pointLightShape1" -p "pointLight1";
rename -uid "61F387C9-49DA-1D37-7F8F-1D80492D0949";
setAttr -k off ".v";
setAttr ".us" no;
createNode lightLinker -s -n "lightLinker1";
rename -uid "17FE1D90-4E82-91F9-865C-769041D175BC";
rename -uid "F9AF3BD0-44AF-9D2E-5E78-A7A859E122BC";
setAttr -s 2 ".lnk";
setAttr -s 2 ".slnk";
createNode shapeEditorManager -n "shapeEditorManager";
rename -uid "8DB5C160-420F-D5BA-683B-0A89E4280978";
rename -uid "08EEB963-4DEE-1A77-BA04-5FBBAEBDBDED";
createNode poseInterpolatorManager -n "poseInterpolatorManager";
rename -uid "D74D9600-4F8B-9358-8CF2-2DBF7BD24F2C";
rename -uid "3DD30F0A-4745-FDB2-C2AA-1C90F62D90E8";
createNode displayLayerManager -n "layerManager";
rename -uid "B164B0DD-4EF2-18A1-6FE0-CFBF493D8E6D";
rename -uid "58745776-4014-38C3-8FAC-AB9D4C406B48";
createNode displayLayer -n "defaultLayer";
rename -uid "E6921E06-44BE-9413-CEDF-B8BE8AAC03F8";
setAttr ".ufem" -type "stringArray" 0 ;
createNode renderLayerManager -n "renderLayerManager";
rename -uid "AA6B9068-483F-5E56-A11F-519EA23FC0CD";
rename -uid "3B89CDF4-4990-B59E-02ED-CB97E5291EDE";
createNode renderLayer -n "defaultRenderLayer";
rename -uid "DD7E50CB-4068-BEFD-F909-1092A320CBAA";
setAttr ".g" yes;
Expand Down Expand Up @@ -144,6 +158,25 @@ createNode script -n "sceneConfigurationScriptNode";
rename -uid "6D6880C9-4A2E-EBCD-99E5-47A4F9F4379A";
setAttr ".b" -type "string" "playbackOptions -min 1 -max 120 -ast 1 -aet 200 ";
setAttr ".st" 6;
createNode aiOptions -s -n "defaultArnoldRenderOptions";
rename -uid "897C0433-427B-A1A7-56FF-7180E45E9460";
setAttr ".version" -type "string" "5.5.0";
createNode aiAOVFilter -s -n "defaultArnoldFilter";
rename -uid "939FC437-435A-5D2D-E989-F6B44FC6D83B";
createNode aiAOVDriver -s -n "defaultArnoldDriver";
rename -uid "FFF5C067-4E9D-AF13-BE0A-57BE613433BF";
createNode aiAOVDriver -s -n "defaultArnoldDisplayDriver";
rename -uid "FAA3D8DB-498D-8F49-E692-9AB5EA825653";
setAttr ".ai_translator" -type "string" "maya";
setAttr ".output_mode" 0;
createNode aiImagerDenoiserOidn -s -n "defaultArnoldDenoiser";
rename -uid "58A6D5FC-429A-C8A7-38B0-92BE87D40FF7";
createNode file -n "file1";
rename -uid "73223ABC-4CB5-EDF7-2134-1ABC6D855D11";
setAttr ".ftn" -type "string" "D:/GIT/maya-hydra-opensource/test/testSamples/testCustomShadersNode/UVChecker.png";
setAttr ".cs" -type "string" "sRGB";
createNode place2dTexture -n "place2dTexture1";
rename -uid "1C593DED-4767-D011-1183-BD90C0A7794B";
select -ne :time1;
setAttr ".o" 1;
setAttr ".unw" 1;
Expand All @@ -161,7 +194,11 @@ select -ne :defaultShaderList1;
setAttr -s 6 ".s";
select -ne :postProcessList1;
setAttr -s 2 ".p";
select -ne :defaultRenderUtilityList1;
select -ne :defaultRenderingList1;
select -ne :lightList1;
setAttr -s 2 ".l";
select -ne :defaultTextureList1;
select -ne :standardSurface1;
setAttr ".bc" -type "float3" 0.40000001 0.40000001 0.40000001 ;
setAttr ".sr" 0.5;
Expand Down Expand Up @@ -203,6 +240,8 @@ select -ne :defaultRenderGlobals;
setAttr ".dss" -type "string" "standardSurface1";
select -ne :defaultResolution;
setAttr ".pa" 1;
select -ne :defaultLightSet;
setAttr -s 2 ".dsm";
select -ne :defaultColorMgtGlobals;
setAttr ".cfe" yes;
setAttr ".cfp" -type "string" "<MAYA_RESOURCES>/OCIO-configs/Maya2022-default/config.ocio";
Expand All @@ -215,11 +254,46 @@ select -ne :defaultColorMgtGlobals;
select -ne :hardwareRenderGlobals;
setAttr ".ctrs" 256;
setAttr ".btrs" 512;
connectAttr "file1.oc" "aiSkyDomeLightShape1.sc";
relationship "link" ":lightLinker1" ":initialShadingGroup.message" ":defaultLightSet.message";
relationship "link" ":lightLinker1" ":initialParticleSE.message" ":defaultLightSet.message";
relationship "shadowLink" ":lightLinker1" ":initialShadingGroup.message" ":defaultLightSet.message";
relationship "shadowLink" ":lightLinker1" ":initialParticleSE.message" ":defaultLightSet.message";
connectAttr "layerManager.dli[0]" "defaultLayer.id";
connectAttr "renderLayerManager.rlmi[0]" "defaultRenderLayer.rlid";
connectAttr ":defaultArnoldDenoiser.msg" ":defaultArnoldRenderOptions.imagers" -na
;
connectAttr ":defaultArnoldDisplayDriver.msg" ":defaultArnoldRenderOptions.drivers"
-na;
connectAttr ":defaultArnoldFilter.msg" ":defaultArnoldRenderOptions.filt";
connectAttr ":defaultArnoldDriver.msg" ":defaultArnoldRenderOptions.drvr";
connectAttr ":defaultColorMgtGlobals.cme" "file1.cme";
connectAttr ":defaultColorMgtGlobals.cfe" "file1.cmcf";
connectAttr ":defaultColorMgtGlobals.cfp" "file1.cmcp";
connectAttr ":defaultColorMgtGlobals.wsn" "file1.ws";
connectAttr "place2dTexture1.c" "file1.c";
connectAttr "place2dTexture1.tf" "file1.tf";
connectAttr "place2dTexture1.rf" "file1.rf";
connectAttr "place2dTexture1.mu" "file1.mu";
connectAttr "place2dTexture1.mv" "file1.mv";
connectAttr "place2dTexture1.s" "file1.s";
connectAttr "place2dTexture1.wu" "file1.wu";
connectAttr "place2dTexture1.wv" "file1.wv";
connectAttr "place2dTexture1.re" "file1.re";
connectAttr "place2dTexture1.of" "file1.of";
connectAttr "place2dTexture1.r" "file1.ro";
connectAttr "place2dTexture1.n" "file1.n";
connectAttr "place2dTexture1.vt1" "file1.vt1";
connectAttr "place2dTexture1.vt2" "file1.vt2";
connectAttr "place2dTexture1.vt3" "file1.vt3";
connectAttr "place2dTexture1.vc1" "file1.vc1";
connectAttr "place2dTexture1.o" "file1.uv";
connectAttr "place2dTexture1.ofs" "file1.fs";
connectAttr "place2dTexture1.msg" ":defaultRenderUtilityList1.u" -na;
connectAttr "defaultRenderLayer.msg" ":defaultRenderingList1.r" -na;
connectAttr "aiSkyDomeLightShape1.ltd" ":lightList1.l" -na;
connectAttr "pointLightShape1.ltd" ":lightList1.l" -na;
connectAttr "file1.msg" ":defaultTextureList1.tx" -na;
connectAttr "aiSkyDomeLight1.iog" ":defaultLightSet.dsm" -na;
connectAttr "pointLight1.iog" ":defaultLightSet.dsm" -na;
// End of testCustomShadersNode.ma

0 comments on commit c7fedec

Please sign in to comment.