diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype index 1612bf43b0..47d8a9d9d5 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype @@ -1304,9 +1304,11 @@ "textureProperty": "baseColor.textureMap", "useTextureProperty": "baseColor.useTexture", "dependentProperties": ["baseColor.textureMapUv", "baseColor.textureBlendMode"], - "shaderTags": [ + "shaderTags": [ "ForwardPass", - "ForwardPass_EDS" + "ForwardPass_EDS", + "LowEndForward", + "LowEndForward_EDS" ], "shaderOption": "o_baseColor_useTexture" } @@ -1317,9 +1319,11 @@ "textureProperty": "metallic.textureMap", "useTextureProperty": "metallic.useTexture", "dependentProperties": ["metallic.textureMapUv"], - "shaderTags": [ + "shaderTags": [ "ForwardPass", - "ForwardPass_EDS" + "ForwardPass_EDS", + "LowEndForward", + "LowEndForward_EDS" ], "shaderOption": "o_metallic_useTexture" } @@ -1330,9 +1334,11 @@ "textureProperty": "specularF0.textureMap", "useTextureProperty": "specularF0.useTexture", "dependentProperties": ["specularF0.textureMapUv"], - "shaderTags": [ + "shaderTags": [ "ForwardPass", - "ForwardPass_EDS" + "ForwardPass_EDS", + "LowEndForward", + "LowEndForward_EDS" ], "shaderOption": "o_specularF0_useTexture" } @@ -1343,9 +1349,11 @@ "textureProperty": "normal.textureMap", "useTextureProperty": "normal.useTexture", "dependentProperties": ["normal.textureMapUv", "normal.factor", "normal.flipX", "normal.flipY"], - "shaderTags": [ + "shaderTags": [ "ForwardPass", - "ForwardPass_EDS" + "ForwardPass_EDS", + "LowEndForward", + "LowEndForward_EDS" ], "shaderOption": "o_normal_useTexture" } diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli index 7400005508..721c48835d 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli @@ -18,32 +18,30 @@ #include #include -void ApplyIblDiffuse( +float3 GetIblDiffuse( float3 normal, float3 albedo, - float3 diffuseResponse, - out float3 outDiffuse) + float3 diffuseResponse) { float3 irradianceDir = MultiplyVectorQuaternion(normal, SceneSrg::m_iblOrientation); float3 diffuseSample = SceneSrg::m_diffuseEnvMap.Sample(SceneSrg::m_samplerEnv, GetCubemapCoords(irradianceDir)).rgb; - outDiffuse = diffuseResponse * albedo * diffuseSample; + return diffuseResponse * albedo * diffuseSample; } -void ApplyIblSpecular( +float3 GetIblSpecular( float3 position, float3 normal, float3 specularF0, float roughnessLinear, float3 dirToCamera, - float2 brdf, - out float3 outSpecular) + float2 brdf) { float3 reflectDir = reflect(-dirToCamera, normal); reflectDir = MultiplyVectorQuaternion(reflectDir, SceneSrg::m_iblOrientation); // global - outSpecular = SceneSrg::m_specularEnvMap.SampleLevel(SceneSrg::m_samplerEnv, GetCubemapCoords(reflectDir), GetRoughnessMip(roughnessLinear)).rgb; + float3 outSpecular = SceneSrg::m_specularEnvMap.SampleLevel(SceneSrg::m_samplerEnv, GetCubemapCoords(reflectDir), GetRoughnessMip(roughnessLinear)).rgb; outSpecular *= (specularF0 * brdf.x + brdf.y); // reflection probe @@ -72,86 +70,54 @@ void ApplyIblSpecular( outSpecular = lerp(outSpecular, probeSpecular, blendAmount); } + return outSpecular; } void ApplyIBL(Surface surface, inout LightingData lightingData) { - if (o_opacity_mode == OpacityMode::Blended || o_opacity_mode == OpacityMode::TintedTransparent) +#ifdef FORCE_IBL_IN_FORWARD_PASS + bool useDiffuseIbl = true; + bool useSpecularIbl = true; + bool useIbl = true; +#else + bool useDiffuseIbl = (o_opacity_mode == OpacityMode::Blended || o_opacity_mode == OpacityMode::TintedTransparent); + bool useSpecularIbl = (useDiffuseIbl || o_meshUseForwardPassIBLSpecular || o_materialUseForwardPassIBLSpecular); + bool useIbl = o_enableIBL && (useDiffuseIbl || useSpecularIbl); +#endif + + if(useIbl) { - // transparencies currently require IBL in the forward pass - if (o_enableIBL) + float iblExposureFactor = pow(2.0, SceneSrg::m_iblExposure); + + if(useDiffuseIbl) { - float3 iblDiffuse = 0.0f; - ApplyIblDiffuse( - surface.normal, - surface.albedo, - lightingData.diffuseResponse, - iblDiffuse); - - float3 iblSpecular = 0.0f; - ApplyIblSpecular( - surface.position, - surface.normal, - surface.specularF0, - surface.roughnessLinear, - lightingData.dirToCamera, - lightingData.brdf, - iblSpecular); - - // Adjust IBL lighting by exposure. - float iblExposureFactor = pow(2.0, SceneSrg::m_iblExposure); + float3 iblDiffuse = GetIblDiffuse(surface.normal, surface.albedo, lightingData.diffuseResponse); lightingData.diffuseLighting += (iblDiffuse * iblExposureFactor * lightingData.diffuseAmbientOcclusion); - lightingData.specularLighting += (iblSpecular * iblExposureFactor); } - } - else if (o_meshUseForwardPassIBLSpecular || o_materialUseForwardPassIBLSpecular) - { - if (o_enableIBL) - { - float3 iblSpecular = 0.0f; - ApplyIblSpecular( - surface.position, - surface.normal, - surface.specularF0, - surface.roughnessLinear, - lightingData.dirToCamera, - lightingData.brdf, - iblSpecular); + if(useSpecularIbl) + { + float3 iblSpecular = GetIblSpecular(surface.position, surface.normal, surface.specularF0, surface.roughnessLinear, lightingData.dirToCamera, lightingData.brdf); iblSpecular *= lightingData.multiScatterCompensation; - if (o_clearCoat_feature_enabled) + if (o_clearCoat_feature_enabled && surface.clearCoat.factor > 0.0f) { - if (surface.clearCoat.factor > 0.0f) - { - float clearCoatNdotV = saturate(dot(surface.clearCoat.normal, lightingData.dirToCamera)); - clearCoatNdotV = max(clearCoatNdotV, 0.01f); // [GFX TODO][ATOM-4466] This is a current band-aid for specular noise at grazing angles. - float2 clearCoatBrdf = PassSrg::m_brdfMap.Sample(PassSrg::LinearSampler, GetBRDFTexCoords(surface.clearCoat.roughness, clearCoatNdotV)).rg; + float clearCoatNdotV = saturate(dot(surface.clearCoat.normal, lightingData.dirToCamera)); + clearCoatNdotV = max(clearCoatNdotV, 0.01f); // [GFX TODO][ATOM-4466] This is a current band-aid for specular noise at grazing angles. + float2 clearCoatBrdf = PassSrg::m_brdfMap.Sample(PassSrg::LinearSampler, GetBRDFTexCoords(surface.clearCoat.roughness, clearCoatNdotV)).rg; - // clear coat uses fixed IOR = 1.5 represents polyurethane which is the most common material for gloss clear coat - // coat layer assumed to be dielectric thus don't need multiple scattering compensation - float3 clearCoatSpecularF0 = float3(0.04f, 0.04f, 0.04f); - float3 clearCoatIblSpecular = 0.0f; + // clear coat uses fixed IOR = 1.5 represents polyurethane which is the most common material for gloss clear coat + // coat layer assumed to be dielectric thus don't need multiple scattering compensation + float3 clearCoatSpecularF0 = float3(0.04f, 0.04f, 0.04f); + float3 clearCoatIblSpecular = GetIblSpecular(surface.position, surface.clearCoat.normal, clearCoatSpecularF0, surface.clearCoat.roughness, lightingData.dirToCamera, clearCoatBrdf); - ApplyIblSpecular( - surface.position, - surface.clearCoat.normal, - clearCoatSpecularF0, - surface.clearCoat.roughness, - lightingData.dirToCamera, - clearCoatBrdf, - clearCoatIblSpecular); - - clearCoatIblSpecular *= surface.clearCoat.factor; + clearCoatIblSpecular *= surface.clearCoat.factor; - // attenuate base layer energy - float3 clearCoatResponse = FresnelSchlickWithRoughness(clearCoatNdotV, clearCoatSpecularF0, surface.clearCoat.roughness) * surface.clearCoat.factor; - iblSpecular = iblSpecular * (1.0 - clearCoatResponse) * (1.0 - clearCoatResponse) + clearCoatIblSpecular; - } + // attenuate base layer energy + float3 clearCoatResponse = FresnelSchlickWithRoughness(clearCoatNdotV, clearCoatSpecularF0, surface.clearCoat.roughness) * surface.clearCoat.factor; + iblSpecular = iblSpecular * (1.0 - clearCoatResponse) * (1.0 - clearCoatResponse) + clearCoatIblSpecular; } - - float iblExposureFactor = pow(2.0f, SceneSrg::m_iblExposure); lightingData.specularLighting += (iblSpecular * iblExposureFactor); } } diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/ShaderQualityOptions.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/ShaderQualityOptions.azsli index 907e67ada5..d6fb259548 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/ShaderQualityOptions.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/ShaderQualityOptions.azsli @@ -18,7 +18,8 @@ #ifdef QUALITY_LOW_END -#define UNIFIED_FORWARD_OUTPUT 1 +#define UNIFIED_FORWARD_OUTPUT 1 +#define FORCE_IBL_IN_FORWARD_PASS 1 #endif diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Pass.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Pass.h index b0d6bd4117..1cba71ae7e 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Pass.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Pass.h @@ -381,6 +381,7 @@ namespace AZ uint64_t m_createdByPassRequest : 1; uint64_t m_initialized : 1; uint64_t m_enabled : 1; + uint64_t m_parentEnabled : 1; uint64_t m_alreadyCreated : 1; uint64_t m_alreadyReset : 1; uint64_t m_alreadyPrepared : 1; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp index 9401d1a9e0..f93d661b0f 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp @@ -93,11 +93,12 @@ namespace AZ void Pass::SetEnabled(bool enabled) { m_flags.m_enabled = enabled; + OnHierarchyChange(); } bool Pass::IsEnabled() const { - return m_flags.m_enabled; + return m_flags.m_enabled && (m_flags.m_parentEnabled || m_parent == nullptr); } // --- Error Logging --- @@ -140,6 +141,7 @@ namespace AZ } // Set new tree depth and path + m_flags.m_parentEnabled = m_parent->IsEnabled(); m_treeDepth = m_parent->m_treeDepth + 1; m_path = ConcatPassName(m_parent->m_path, m_name); m_flags.m_partOfHierarchy = m_parent->m_flags.m_partOfHierarchy;