From 038c71a660bedf0c3ddde707e913dbcc4d09db19 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Thu, 23 Dec 2021 17:55:27 +0100 Subject: [PATCH] Move mode-specific behavior into GetBackLighting (improvement on https://github.com/o3de/o3de/pull/6428#discussion_r774259781 and https://github.com/o3de/o3de/pull/6428/commits/c700b95c8d4aed5605b28c901a49a7287725e9cb) Signed-off-by: Santi Paprika --- .../Atom/Features/PBR/BackLighting.azsli | 8 +++++- .../PBR/Lights/DirectionalLight.azsli | 25 ++++++++----------- .../Atom/Features/PBR/Lights/DiskLight.azsli | 17 ++++++------- .../Atom/Features/PBR/Lights/PointLight.azsli | 19 ++++++-------- .../Atom/Features/PBR/Lights/QuadLight.azsli | 11 ++++---- 5 files changed, 39 insertions(+), 41 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/BackLighting.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/BackLighting.azsli index b35e17b160..2f4680bc9d 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/BackLighting.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/BackLighting.azsli @@ -64,11 +64,17 @@ float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightI // http://www.iryoku.com/translucency/downloads/Real-Time-Realistic-Skin-Translucency.pdf { + // transmissionDistance < 0.0f means shadows are not enabled --> avoid unnecessary computation + if (transmissionDistance < 0.0f) + { + break; + } + // Irradiance arround surface point. // Increase angle of influence (angle(N,L) -> angle(N,L) + acos(angleOffset)) to smooth transition regions float3 E = surface.albedo * max(lightingData.angleOffset + dot(-surface.normal, dirToLight),0.0); - // Transmission distance modulated by editor-exposed scale parameter + // Transmission distance modulated by hardcoded constant (could be exposed as a weight of scattering distance for transmission) float s = transmissionDistance * 100.0; // Use scattering color to weight thin object transmission color diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DirectionalLight.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DirectionalLight.azsli index da4901cf8e..a34411c332 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DirectionalLight.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DirectionalLight.azsli @@ -20,8 +20,8 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData) float litRatio = 1.0f; float camToSurfDist = distance(ViewSrg::m_worldPosition, surface.position); - // Distance travelled by the light inside the object - float transmissionDistance = 0.0f; + // Distance travelled by the light inside the object. If not redefined, it will take mode-specific null behaviors (see GetBackLighting()) + float transmissionDistance = -1.0f; if (o_enableShadows && shadowIndex < SceneSrg::m_directionalLightCount) { @@ -68,22 +68,19 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData) // [GFX TODO][ATOM-2012] care of multiple directional light // Currently shadow check is done only for index == shadowIndex. float currentLitRatio = 1.0f; + float currentTransmissionDistance = -1.0f; - if (o_enableShadows) + if (o_enableShadows && index == shadowIndex) { - bool activeLight = index == shadowIndex; - // Add contribution only if current directional light is the active one for shadows - currentLitRatio = activeLight ? litRatio : 1.; - if (activeLight) - { - float3 backLighting = GetBackLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight, transmissionDistance); - - // Attenuation applied to hide artifacts due to low-res shadow maps (might need some work in the future) - float attenuation = 1.0 / pow(max(1.0, camToSurfDist/2.0), lightingData.distanceAttenuation + 1.0); - lightingData.translucentBackLighting += backLighting * attenuation; - } + currentLitRatio = litRatio; + currentTransmissionDistance = transmissionDistance; } + + // Transmission contribution with attenuation applied to hide artifacts due to low-res shadow maps (might need some work in the future) + float3 backLighting = GetBackLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight, currentTransmissionDistance); + float attenuation = 1.0 / pow(max(1.0, camToSurfDist/2.0), lightingData.distanceAttenuation + 1.0); + lightingData.translucentBackLighting += backLighting * attenuation; lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight) * currentLitRatio; lightingData.specularLighting += GetSpecularLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight) * currentLitRatio; diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DiskLight.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DiskLight.azsli index 9d4e503df6..cc0e33ff5b 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DiskLight.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DiskLight.azsli @@ -88,6 +88,9 @@ void ApplyDiskLight(ViewSrg::DiskLight light, Surface surface, inout LightingDat lightIntensity *= penumbraMask; } + // Distance travelled by the light inside the object. If not redefined, it will take mode-specific null behaviors (see GetBackLighting()) + float transmissionDistance = -1.0f; + if (o_enableShadows) { litRatio = ProjectedShadow::GetVisibility( @@ -97,8 +100,6 @@ void ApplyDiskLight(ViewSrg::DiskLight light, Surface surface, inout LightingDat -dirToConeTip, surface.vertexNormal); - // Distance travelled by the light inside the object - float transmissionDistance = 0.0f; // o_transmission_mode == NONE is not taken into account because GetBackLighting already ignores this case if (o_transmission_mode == TransmissionMode::ThickObject) @@ -110,18 +111,16 @@ void ApplyDiskLight(ViewSrg::DiskLight light, Surface surface, inout LightingDat transmissionDistance = ProjectedShadow::GetThickness(light.m_shadowIndex, surface.position - lightingData.shrinkFactor * surface.vertexNormal); } - // Attenuation applied to hide artifacts due to low-res shadow maps (might need some work in the future) - float attenuation = 1.0 / pow(max(1.0, sqrt(distanceToLight2)), lightingData.distanceAttenuation + 1.0); - - // Transmission contribution - float3 backLighting = GetBackLighting(surface, lightingData, lightIntensity, posToLightDir, transmissionDistance); - - lightingData.translucentBackLighting += backLighting * attenuation; } // Diffuse contribution lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, lightIntensity, posToLightDir) * litRatio; + // Transmission contribution with attenuation applied to hide artifacts due to low-res shadow maps (might need some work in the future) + float3 backLighting = GetBackLighting(surface, lightingData, lightIntensity, posToLightDir, transmissionDistance); + float attenuation = 1.0 / pow(max(1.0, sqrt(distanceToLight2)), lightingData.distanceAttenuation + 1.0); + lightingData.translucentBackLighting += backLighting * attenuation; + // Adjust the light direction for specular based on disk size // Calculate the reflection off the normal from the view direction diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli index e2297fd3d3..664c3693fb 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli @@ -85,6 +85,9 @@ void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingD // shadow float litRatio = 1.0; + // Distance travelled by the light inside the object. If not redefined, it will take mode-specific null behaviors (see GetBackLighting()) + float transmissionDistance = -1.0f; + if (o_enableShadows) { const float3 lightDir = normalize(light.m_position - surface.position); @@ -95,9 +98,6 @@ void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingD surface.position, lightDir, surface.vertexNormal); - - // Distance travelled by the light inside the object - float transmissionDistance = 0.0f; // o_transmission_mode == NONE is not taken into account because GetBackLighting already ignores this case if (o_transmission_mode == TransmissionMode::ThickObject) @@ -108,19 +108,16 @@ void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingD { transmissionDistance = ProjectedShadow::GetThickness(shadowIndex, surface.position - lightingData.shrinkFactor * surface.vertexNormal); } - - // Transmission contribution - float3 backLighting = GetBackLighting(surface, lightingData, lightIntensity, normalize(posToLight), transmissionDistance); - - // Attenuation applied to hide artifacts due to low-res shadow maps (might need some work in the future) - float attenuation = 1.0 / pow(max(1.0, posToLightDist), lightingData.distanceAttenuation + 1.0); - - lightingData.translucentBackLighting += backLighting * attenuation; } // Diffuse contribution lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, lightIntensity, normalize(posToLight)) * litRatio; + // Transmission contribution with attenuation applied to hide artifacts due to low-res shadow maps (might need some work in the future) + float3 backLighting = GetBackLighting(surface, lightingData, lightIntensity, normalize(posToLight), transmissionDistance); + float attenuation = 1.0 / pow(max(1.0, posToLightDist), lightingData.distanceAttenuation + 1.0); + lightingData.translucentBackLighting += backLighting * attenuation; + // Adjust the light direcion for specular based on bulb size // Calculate the reflection off the normal from the view direction diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/QuadLight.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/QuadLight.azsli index a4ef25572d..b4cdbeb847 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/QuadLight.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/QuadLight.azsli @@ -148,14 +148,13 @@ void ApplyQuadLight(ViewSrg::QuadLight light, Surface surface, inout LightingDat GetDiffuseLighting(surface, lightingData, intensity, dirToLightCenter) ); - float nullTransmissionDistance = (o_transmission_mode == TransmissionMode::ThickObject) ? 0.0f : 9999.0f; lightingData.translucentBackLighting += ( - GetBackLighting(surface, lightingData, intensity, p0, nullTransmissionDistance) + - GetBackLighting(surface, lightingData, intensity, p1, nullTransmissionDistance) + - GetBackLighting(surface, lightingData, intensity, p2, nullTransmissionDistance) + - GetBackLighting(surface, lightingData, intensity, p3, nullTransmissionDistance) + - GetBackLighting(surface, lightingData, intensity, dirToLightCenter, nullTransmissionDistance) + GetBackLighting(surface, lightingData, intensity, p0, -1.0f) + + GetBackLighting(surface, lightingData, intensity, p1, -1.0f) + + GetBackLighting(surface, lightingData, intensity, p2, -1.0f) + + GetBackLighting(surface, lightingData, intensity, p3, -1.0f) + + GetBackLighting(surface, lightingData, intensity, dirToLightCenter, -1.0f) ); // Calculate specular by choosing a single representative point on the light's surface based on the reflection ray