From 9825d6aba3ab83d85c93a9e9c6801944fa2d6494 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Mon, 29 Nov 2021 15:49:15 +0100 Subject: [PATCH 01/39] Thin transmission mode fix for directional lights Signed-off-by: Santi Paprika --- .../Common/Assets/Materials/Types/Skin.azsl | 10 +++++ .../Atom/Features/PBR/BackLighting.azsli | 43 +++++++++++-------- .../Features/PBR/Lighting/LightingData.azsli | 3 ++ .../PBR/Lights/DirectionalLight.azsli | 25 ++++++++--- 4 files changed, 56 insertions(+), 25 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl index 523353f8fa..091e0a5645 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl @@ -92,6 +92,7 @@ struct VSOutput float3 m_bitangent : BITANGENT; float3 m_worldPosition : UV0; float3 m_shadowCoords[ViewSrg::MaxCascadeCount] : UV4; + float3 m_shrinkedShadowCoords[ViewSrg::MaxCascadeCount] : UV9; // Extended fields (only referenced in this azsl file)... float2 m_uv[UvSetCount] : UV1; @@ -137,6 +138,14 @@ VSOutput SkinVS(VSInput IN) VertexHelper(IN, OUT, worldPosition, false); + // Fetch shadow coords for shrinked world position (used in thin transmission materials) + const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight; + DirectionalLightShadow::GetShadowCoords( + shadowIndex, + worldPosition - 0.005 * OUT.m_normal, + OUT.m_normal, + OUT.m_shrinkedShadowCoords); + return OUT; } @@ -336,6 +345,7 @@ PbrLightingOutput SkinPS_Common(VSOutput IN) // Directional light shadow coordinates lightingData.shadowCoords = IN.m_shadowCoords; + lightingData.shrinkedShadowCoords = IN.m_shrinkedShadowCoords; // Diffuse and Specular response (used in IBL calculations) lightingData.specularResponse = FresnelSchlickWithRoughness(lightingData.NdotV, surface.specularF0, surface.roughnessLinear); 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 dfd5522f5c..70f49f0a66 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 @@ -16,24 +16,26 @@ #include // Analytical integation (approximation) of diffusion profile over radius, could be replaced by other pre integrated kernels -// such as sum of Gaussian +// such as sum of Gaussian (see T(s)) float3 TransmissionKernel(float t, float3 s) { float3 exponent = s * t; return 0.25 * (1.0 / exp(exponent) + 3.0 / exp(exponent / 3.0)); } -float ThinObjectFalloff(const float3 surfaceNormal, const float3 dirToLight) +// Analytical integation (approximation) of diffusion profile over radius, could be precomputed in a LUT +float3 T(float s) { - const float ndl = saturate(dot(-surfaceNormal, dirToLight)); - - // ndl works decently well but it can produce a harsh discontinuity in the area just before - // the shadow starts appearing on objects like cylinder and tubes. - // Smoothing out ndl does a decent enough job of removing this artifact. - return smoothstep(0, 1, ndl * ndl); + // dipoles and multipoles are approximated with sums of a small number of Gaussians with variable weights and variances + return float3(0.233, 0.455, 0.649) * exp(-s*s/0.0064) + + float3(0.1, 0.336, 0.344) * exp(-s*s/0.0484) + + float3(0.118, 0.198, 0.0) * exp(-s*s/0.187) + + float3(0.113, 0.007, 0.007) * exp(-s*s/0.567) + + float3(0.358, 0.004, 0.0) * exp(-s*s/1.99) + + float3(0.078, 0.0, 0.0) * exp(-s*s/7.41); } -float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightIntensity, float3 dirToLight, float shadowRatio) +float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightIntensity, float3 dirToLight, float transmissionDistance) { float3 result = float3(0.0, 0.0, 0.0); float thickness = 0.0; @@ -49,7 +51,7 @@ float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightI // https://colinbarrebrisebois.com/2011/03/07/gdc-2011-approximating-translucency-for-a-fast-cheap-and-convincing-subsurface-scattering-look/ { - thickness = max(shadowRatio, surface.transmission.thickness); + thickness = max(transmissionDistance, surface.transmission.thickness); float transmittance = pow( saturate( dot( lightingData.dirToCamera, -normalize( dirToLight + surface.normal * transmissionParams.z ) ) ), transmissionParams.y ) * transmissionParams.w; float lamberAttenuation = exp(-thickness * transmissionParams.x) * saturate(1.0 - thickness); result = transmittance * lamberAttenuation * lightIntensity; @@ -57,18 +59,21 @@ float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightI break; case TransmissionMode::ThinObject: - // Thin object mode, using thin-film assumption proposed by Jimenez J. et al, 2010, "Real-Time Realistic Skin Translucency" + // Thin object mode, based on Jimenez J. et al, 2010, "Real-Time Realistic Skin Translucency" // http://www.iryoku.com/translucency/downloads/Real-Time-Realistic-Skin-Translucency.pdf - - float litRatio = 1.0 - shadowRatio; - if (litRatio) + { - const float thickness = surface.transmission.thickness * transmissionParams.w; - const float3 invScattering = rcp(transmissionParams.xyz); - const float falloff = ThinObjectFalloff(surface.normal, dirToLight); - result = TransmissionKernel(thickness, invScattering) * falloff * lightIntensity * litRatio; - } + // Irradiance arround surface point. + // Begin the transmittance dot product slightly before it would with the regular dot(N,L) + float E = max(0.30 + dot(-surface.normal, dirToLight), 0.0); + // Transmission distance computed from shadowmaps modulated by editor-exposed parameters + float s = transmissionDistance * surface.transmission.thickness * (20 - transmissionParams.w) * 10; + + // Albedo at front (surface point) is used to approximate irradiance at the back of the object + // See observation 4 in [Jimenez J. et al, 2010] + result = T(s) * lightIntensity * surface.albedo * E; + } break; } diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli index 878bed02d4..51bd421418 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli @@ -28,6 +28,9 @@ class LightingData // Direction light shadow coordinates float3 shadowCoords[ViewSrg::MaxCascadeCount]; + // Direction light shadow coordinates for shrinked positions + float3 shrinkedShadowCoords[ViewSrg::MaxCascadeCount]; + // Normalized direction from surface to camera float3 dirToCamera; 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 1eee53a24f..32654e0427 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 @@ -18,7 +18,9 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData) // Shadowed check const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight; float litRatio = 1.0f; + float transmissionDistance = 0.0f; float backShadowRatio = 0.0f; + if (o_enableShadows && shadowIndex < SceneSrg::m_directionalLightCount) { litRatio = DirectionalLightShadow::GetVisibility( @@ -30,6 +32,12 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData) if (o_transmission_mode == TransmissionMode::ThickObject) { backShadowRatio = DirectionalLightShadow::GetThickness(shadowIndex, lightingData.shadowCoords); + } + else if (o_transmission_mode == TransmissionMode::ThinObject) + { + // Use shrinked positions for thin object transmission to ensure they fall onto the object when querying + // the depth from the shadow map + transmissionDistance = DirectionalLightShadow::GetThickness(shadowIndex, lightingData.shrinkedShadowCoords); } } @@ -50,21 +58,26 @@ 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 currentBackShadowRatio = 1.0f; + float currentTransmissionParameter = 1.0f; if (o_enableShadows) { - currentLitRatio = (index == shadowIndex) ? litRatio : 1.; - - currentBackShadowRatio = 1.0 - currentLitRatio; + bool activeLight = index == shadowIndex; + currentLitRatio = activeLight ? litRatio : 1.; if (o_transmission_mode == TransmissionMode::ThickObject) { - currentBackShadowRatio = (index == shadowIndex) ? backShadowRatio : 0.; + // Back shadow ratio (add contribution only if current directional light is the active one for shadows) + currentTransmissionParameter = activeLight ? backShadowRatio : 0.; + } + else if (o_transmission_mode == TransmissionMode::ThinObject) + { + // Transmission distance (add contribution only if current directional light is the active one for shadows) + currentTransmissionParameter = activeLight ? transmissionDistance : 9999.f; } } lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight) * currentLitRatio; lightingData.specularLighting += GetSpecularLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight) * currentLitRatio; - lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight, currentBackShadowRatio); + lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight, currentTransmissionParameter); } // Add debug coloring for directional light shadow From 1417488a2b2939affa14d0494b66c865bef907f9 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Mon, 29 Nov 2021 20:22:31 +0100 Subject: [PATCH 02/39] Increase scale range + expose shrink factor Signed-off-by: Santi Paprika --- .../Feature/Common/Assets/Materials/Types/Skin.azsl | 2 +- .../Common/Assets/Materials/Types/Skin.materialtype | 13 +++++++++++++ .../Common/Assets/Materials/Types/Skin_Common.azsli | 1 + .../ShaderLib/Atom/Features/PBR/BackLighting.azsli | 2 +- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl index 091e0a5645..b672016c00 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl @@ -142,7 +142,7 @@ VSOutput SkinVS(VSInput IN) const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight; DirectionalLightShadow::GetShadowCoords( shadowIndex, - worldPosition - 0.005 * OUT.m_normal, + worldPosition - MaterialSrg::m_shrinkFactor * OUT.m_normal, OUT.m_normal, OUT.m_shrinkedShadowCoords); diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype index e2a05aa916..496d6286cc 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype @@ -637,6 +637,19 @@ "min": 0.0, "softMax": 20.0 }, + { + "name": "shrinkFactor", + "displayName": " Shrink Factor", + "description": "Shrink (absolute) offset towards the normal opposite direction to ensure correct shadow map projection", + "type": "float", + "defaultValue": 0.005, + "min": 0.0, + "softMax": 0.05, + "connection": { + "type": "ShaderInput", + "name": "m_shrinkFactor" + } + }, { "name": "transmissionScale", "displayName": " Scale", diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_Common.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_Common.azsli index a94f203b23..406da8b70c 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_Common.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_Common.azsli @@ -71,6 +71,7 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial float4 m_transmissionTintThickness; Texture2D m_transmissionThicknessMap; uint m_transmissionThicknessMapUvIndex; + float m_shrinkFactor; Texture2D m_wrinkle_baseColor_texture1; Texture2D m_wrinkle_baseColor_texture2; 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 70f49f0a66..559b8cac2e 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 @@ -68,7 +68,7 @@ float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightI float E = max(0.30 + dot(-surface.normal, dirToLight), 0.0); // Transmission distance computed from shadowmaps modulated by editor-exposed parameters - float s = transmissionDistance * surface.transmission.thickness * (20 - transmissionParams.w) * 10; + float s = transmissionDistance * surface.transmission.thickness * (50 - transmissionParams.w) * 10; // Albedo at front (surface point) is used to approximate irradiance at the back of the object // See observation 4 in [Jimenez J. et al, 2010] From 85d206c0c8a86c7bae4df1f818fc3e71aee26ed2 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Tue, 30 Nov 2021 18:19:39 +0100 Subject: [PATCH 03/39] Support directional lights with disabled shadows Signed-off-by: Santi Paprika --- .../Atom/Features/PBR/Lights/DirectionalLight.azsli | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 32654e0427..ccaedcd34a 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 @@ -58,7 +58,7 @@ 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 currentTransmissionParameter = 1.0f; + float currentTransmissionParameter = (o_transmission_mode == TransmissionMode::ThickObject) ? 0.0f : 9999.0f; if (o_enableShadows) { bool activeLight = index == shadowIndex; @@ -66,12 +66,12 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData) if (o_transmission_mode == TransmissionMode::ThickObject) { // Back shadow ratio (add contribution only if current directional light is the active one for shadows) - currentTransmissionParameter = activeLight ? backShadowRatio : 0.; + currentTransmissionParameter = activeLight ? backShadowRatio : 0.0f; } else if (o_transmission_mode == TransmissionMode::ThinObject) { // Transmission distance (add contribution only if current directional light is the active one for shadows) - currentTransmissionParameter = activeLight ? transmissionDistance : 9999.f; + currentTransmissionParameter = activeLight ? transmissionDistance : 9999.0f; } } From 9f8994823bd42636cef98e059bf73ea57ace0b79 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Tue, 30 Nov 2021 18:41:08 +0100 Subject: [PATCH 04/39] Fix naming for transmission distance parameter Signed-off-by: Santi Paprika --- .../Features/PBR/Lights/DirectionalLight.azsli | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) 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 ccaedcd34a..0b0be82d72 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 @@ -19,7 +19,6 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData) const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight; float litRatio = 1.0f; float transmissionDistance = 0.0f; - float backShadowRatio = 0.0f; if (o_enableShadows && shadowIndex < SceneSrg::m_directionalLightCount) { @@ -31,7 +30,7 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData) if (o_transmission_mode == TransmissionMode::ThickObject) { - backShadowRatio = DirectionalLightShadow::GetThickness(shadowIndex, lightingData.shadowCoords); + transmissionDistance = DirectionalLightShadow::GetThickness(shadowIndex, lightingData.shadowCoords); } else if (o_transmission_mode == TransmissionMode::ThinObject) { @@ -58,26 +57,21 @@ 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 currentTransmissionParameter = (o_transmission_mode == TransmissionMode::ThickObject) ? 0.0f : 9999.0f; + float currentTransmissionDistance = (o_transmission_mode == TransmissionMode::ThickObject) ? 0.0f : 9999.0f; if (o_enableShadows) { bool activeLight = index == shadowIndex; currentLitRatio = activeLight ? litRatio : 1.; - if (o_transmission_mode == TransmissionMode::ThickObject) - { - // Back shadow ratio (add contribution only if current directional light is the active one for shadows) - currentTransmissionParameter = activeLight ? backShadowRatio : 0.0f; - } - else if (o_transmission_mode == TransmissionMode::ThinObject) + if (activeLight) { // Transmission distance (add contribution only if current directional light is the active one for shadows) - currentTransmissionParameter = activeLight ? transmissionDistance : 9999.0f; + currentTransmissionDistance = transmissionDistance; } } lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight) * currentLitRatio; lightingData.specularLighting += GetSpecularLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight) * currentLitRatio; - lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight, currentTransmissionParameter); + lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight, currentTransmissionDistance); } // Add debug coloring for directional light shadow From 348c3cc0f62268e74114e27f4cad913b64b2ddfd Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Thu, 2 Dec 2021 13:04:16 +0100 Subject: [PATCH 05/39] Expose angle offset below (N.L) Signed-off-by: Santi Paprika --- .../Common/Assets/Materials/Types/Skin.azsl | 3 +++ .../Assets/Materials/Types/Skin.materialtype | 15 ++++++++++++++- .../Assets/Materials/Types/Skin_Common.azsli | 1 + .../Atom/Features/PBR/BackLighting.azsli | 4 ++-- .../Atom/Features/PBR/Lighting/LightingData.azsli | 5 ++++- 5 files changed, 24 insertions(+), 4 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl index b672016c00..2e861a61bb 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl @@ -351,6 +351,9 @@ PbrLightingOutput SkinPS_Common(VSOutput IN) lightingData.specularResponse = FresnelSchlickWithRoughness(lightingData.NdotV, surface.specularF0, surface.roughnessLinear); lightingData.diffuseResponse = 1.0 - lightingData.specularResponse; + // Angle offset for subsurface scattering through thin objects + lightingData.angleOffset = MaterialSrg::m_angleOffset; + // ------- Occlusion ------- lightingData.diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture); diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype index 496d6286cc..39cbe21a18 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype @@ -650,6 +650,19 @@ "name": "m_shrinkFactor" } }, + { + "name": "angleOffset", + "displayName": " Angle Offset", + "description": "Angle to accept below (N . L = 0) in scattering through thin objects", + "type": "float", + "defaultValue": 0.1, + "min": -1.0, + "softMax": 1.0, + "connection": { + "type": "ShaderInput", + "name": "m_angleOffset" + } + }, { "name": "transmissionScale", "displayName": " Scale", @@ -657,7 +670,7 @@ "type": "float", "defaultValue": 3.0, "min": 0.0, - "softMax": 20.0 + "softMax": 100.0 } ], "wrinkleLayers": [ diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_Common.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_Common.azsli index 406da8b70c..1fa2039c72 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_Common.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_Common.azsli @@ -72,6 +72,7 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial Texture2D m_transmissionThicknessMap; uint m_transmissionThicknessMapUvIndex; float m_shrinkFactor; + float m_angleOffset; Texture2D m_wrinkle_baseColor_texture1; Texture2D m_wrinkle_baseColor_texture2; 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 559b8cac2e..0e39739fcb 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 @@ -65,10 +65,10 @@ float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightI { // Irradiance arround surface point. // Begin the transmittance dot product slightly before it would with the regular dot(N,L) - float E = max(0.30 + dot(-surface.normal, dirToLight), 0.0); + float E = saturate(lightingData.angleOffset + dot(-surface.normal, dirToLight)); // Transmission distance computed from shadowmaps modulated by editor-exposed parameters - float s = transmissionDistance * surface.transmission.thickness * (50 - transmissionParams.w) * 10; + float s = transmissionDistance * surface.transmission.thickness * (100 - transmissionParams.w) * 10; // Albedo at front (surface point) is used to approximate irradiance at the back of the object // See observation 4 in [Jimenez J. et al, 2010] diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli index 51bd421418..7ca8a797a8 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli @@ -28,9 +28,12 @@ class LightingData // Direction light shadow coordinates float3 shadowCoords[ViewSrg::MaxCascadeCount]; - // Direction light shadow coordinates for shrinked positions + // Direction light shadow coordinates for shrinked positions (used in scattering through thin objects) float3 shrinkedShadowCoords[ViewSrg::MaxCascadeCount]; + // Angle to accept below (N . L = 0) in scattering through thin objects + float angleOffset; + // Normalized direction from surface to camera float3 dirToCamera; From 2b99867225fdd21445af244ea6076526ccf6131a Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Thu, 2 Dec 2021 13:32:28 +0100 Subject: [PATCH 06/39] Add informative comments for directional light thin scattering Signed-off-by: Santi Paprika --- .../Atom/Features/PBR/Lights/DirectionalLight.azsli | 5 +++++ 1 file changed, 5 insertions(+) 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 0b0be82d72..82bad459cf 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 @@ -18,6 +18,8 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData) // Shadowed check const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight; float litRatio = 1.0f; + + // Transmission distance inside object float transmissionDistance = 0.0f; if (o_enableShadows && shadowIndex < SceneSrg::m_directionalLightCount) @@ -57,6 +59,9 @@ 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; + + // Transmission distance from current light inside object (default non-influential values) + // o_transmission_mode == NONE is not taken into account because GetBackLighting already ignores this case float currentTransmissionDistance = (o_transmission_mode == TransmissionMode::ThickObject) ? 0.0f : 9999.0f; if (o_enableShadows) { From 97c36a71a26a92b98fa33fe42fa4edacc31cd155 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Thu, 2 Dec 2021 17:49:26 +0100 Subject: [PATCH 07/39] Move directional shadow coordinates computation to PS + Fix clamp values Signed-off-by: Santi Paprika --- .../Common/Assets/Materials/Types/Skin.azsl | 15 +++++---------- .../Atom/Features/PBR/BackLighting.azsli | 2 +- .../Atom/Features/PBR/Lighting/LightingData.azsli | 3 +++ .../Features/PBR/Lights/DirectionalLight.azsli | 8 ++++++++ 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl index 2e861a61bb..4908e736f4 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl @@ -92,7 +92,6 @@ struct VSOutput float3 m_bitangent : BITANGENT; float3 m_worldPosition : UV0; float3 m_shadowCoords[ViewSrg::MaxCascadeCount] : UV4; - float3 m_shrinkedShadowCoords[ViewSrg::MaxCascadeCount] : UV9; // Extended fields (only referenced in this azsl file)... float2 m_uv[UvSetCount] : UV1; @@ -137,14 +136,6 @@ VSOutput SkinVS(VSInput IN) } VertexHelper(IN, OUT, worldPosition, false); - - // Fetch shadow coords for shrinked world position (used in thin transmission materials) - const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight; - DirectionalLightShadow::GetShadowCoords( - shadowIndex, - worldPosition - MaterialSrg::m_shrinkFactor * OUT.m_normal, - OUT.m_normal, - OUT.m_shrinkedShadowCoords); return OUT; } @@ -345,15 +336,19 @@ PbrLightingOutput SkinPS_Common(VSOutput IN) // Directional light shadow coordinates lightingData.shadowCoords = IN.m_shadowCoords; - lightingData.shrinkedShadowCoords = IN.m_shrinkedShadowCoords; // Diffuse and Specular response (used in IBL calculations) lightingData.specularResponse = FresnelSchlickWithRoughness(lightingData.NdotV, surface.specularF0, surface.roughnessLinear); lightingData.diffuseResponse = 1.0 - lightingData.specularResponse; + // ------- Thin Object Light Transmission ------- + // Angle offset for subsurface scattering through thin objects lightingData.angleOffset = MaterialSrg::m_angleOffset; + // Shrink (absolute) offset towards the normal opposite direction to ensure correct shadow map projection + lightingData.shrinkFactor = MaterialSrg::m_shrinkFactor; + // ------- Occlusion ------- lightingData.diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture); 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 0e39739fcb..cd2ce763e4 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 @@ -65,7 +65,7 @@ float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightI { // Irradiance arround surface point. // Begin the transmittance dot product slightly before it would with the regular dot(N,L) - float E = saturate(lightingData.angleOffset + dot(-surface.normal, dirToLight)); + float E = max(lightingData.angleOffset + dot(-surface.normal, dirToLight),0.0); // Transmission distance computed from shadowmaps modulated by editor-exposed parameters float s = transmissionDistance * surface.transmission.thickness * (100 - transmissionParams.w) * 10; diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli index 7ca8a797a8..8f3bca703e 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli @@ -33,6 +33,9 @@ class LightingData // Angle to accept below (N . L = 0) in scattering through thin objects float angleOffset; + + // Shrink (absolute) offset towards the normal opposite direction to ensure correct shadow map projection + float shrinkFactor; // Normalized direction from surface to camera float3 dirToCamera; 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 82bad459cf..d7fa77d701 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 @@ -29,6 +29,14 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData) lightingData.shadowCoords, surface.vertexNormal, debugInfo); + + // Fetch shadow coords for shrinked world position (used in thin transmission materials) + float3 shrinkedShadowCoords[ViewSrg::MaxCascadeCount]; + DirectionalLightShadow::GetShadowCoords( + shadowIndex, + surface.position - lightingData.shrinkFactor * surface.normal, + surface.normal, + lightingData.shrinkedShadowCoords); if (o_transmission_mode == TransmissionMode::ThickObject) { From d1b19a51d5d078eb13f575591d92fdac9cc6b6a3 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Thu, 2 Dec 2021 18:36:55 +0100 Subject: [PATCH 08/39] Add point light thin transmission support Signed-off-by: Santi Paprika --- .../Atom/Features/PBR/Lights/PointLight.azsli | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) 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 92f4065931..7f4cd46749 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 @@ -84,8 +84,9 @@ void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingD // shadow float litRatio = 1.0; - // How much is back face shadowed, it's set to the reverse of litRatio to share the same default value with thickness, which should be 0 if no shadow map available - float backShadowRatio = 0.0; + // Transmission distance from current light inside object (default non-influential values) + // o_transmission_mode == NONE is not taken into account because GetBackLighting already ignores this case + float transmissionDistance = (o_transmission_mode == TransmissionMode::ThickObject) ? 0.0f : 9999.0f; if (o_enableShadows) { const float3 lightDir = normalize(light.m_position - surface.position); @@ -97,13 +98,13 @@ void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingD lightDir, surface.vertexNormal); - // Use backShadowRatio to carry thickness from shadow map for thick mode - backShadowRatio = 1.0 - litRatio; if (o_transmission_mode == TransmissionMode::ThickObject) { - backShadowRatio = ProjectedShadow::GetThickness( - shadowIndex, - surface.position); + transmissionDistance = ProjectedShadow::GetThickness(shadowIndex, surface.position); + } + else if (o_transmission_mode == TransmissionMode::ThinObject) + { + transmissionDistance = ProjectedShadow::GetThickness(shadowIndex, surface.position - lightingData.shrinkFactor * surface.normal); } } @@ -111,7 +112,7 @@ void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingD lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, lightIntensity, normalize(posToLight)) * litRatio; // Transmission contribution - lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, normalize(posToLight), backShadowRatio); + lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, normalize(posToLight), transmissionDistance); // Adjust the light direcion for specular based on bulb size From 1178bc142091a84687ba59e5a9489d82cdb32edf Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Fri, 3 Dec 2021 17:02:02 +0100 Subject: [PATCH 09/39] Add disk light support for thin object translucency Signed-off-by: Santi Paprika --- .../Atom/Features/PBR/Lights/DiskLight.azsli | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) 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 63f671f021..7cc5a34453 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 @@ -77,8 +77,9 @@ void ApplyDiskLight(ViewSrg::DiskLight light, Surface surface, inout LightingDat // shadow float litRatio = 1.0; - // How much is back face shadowed, it's set to the reverse of litRatio to share the same default value with thickness, which should be 0 if no shadow map available - float backShadowRatio = 0.0; + // Transmission distance from current light inside object (default non-influential values) + // o_transmission_mode == NONE is not taken into account because GetBackLighting already ignores this case + float transmissionDistance = (o_transmission_mode == TransmissionMode::ThickObject) ? 0.0f : 9999.0f; if (o_enableShadows) { litRatio = ProjectedShadow::GetVisibility( @@ -88,14 +89,14 @@ void ApplyDiskLight(ViewSrg::DiskLight light, Surface surface, inout LightingDat -dirToConeTip, surface.vertexNormal); - // Use backShadowRatio to carry thickness from shadow map for thick mode - backShadowRatio = 1.0 - litRatio; if (o_transmission_mode == TransmissionMode::ThickObject) { - backShadowRatio = ProjectedShadow::GetThickness( - light.m_shadowIndex, - surface.position); + transmissionDistance = ProjectedShadow::GetThickness(light.m_shadowIndex, surface.position); } + else if (o_transmission_mode == TransmissionMode::ThinObject) + { + transmissionDistance = ProjectedShadow::GetThickness(light.m_shadowIndex, surface.position - lightingData.shrinkFactor * surface.normal); + } } if (useConeAngle && dotWithDirection < light.m_cosInnerConeAngle) // in penumbra @@ -113,7 +114,7 @@ void ApplyDiskLight(ViewSrg::DiskLight light, Surface surface, inout LightingDat lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, lightIntensity, posToLightDir) * litRatio; // Transmission contribution - lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, posToLightDir, backShadowRatio); + lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, posToLightDir, transmissionDistance); // Adjust the light direction for specular based on disk size From d951cd332f80de55d18824e9a82b2efe90a4266a Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Fri, 3 Dec 2021 22:06:29 +0100 Subject: [PATCH 10/39] Consider default thickness value for quadlight fast approx mode Signed-off-by: Santi Paprika --- .../Atom/Features/PBR/Lights/QuadLight.azsli | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) 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 63515339d8..a4ef25572d 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,13 +148,14 @@ 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, 0.0) + - GetBackLighting(surface, lightingData, intensity, p1, 0.0) + - GetBackLighting(surface, lightingData, intensity, p2, 0.0) + - GetBackLighting(surface, lightingData, intensity, p3, 0.0) + - GetBackLighting(surface, lightingData, intensity, dirToLightCenter, 0.0) + 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) ); // Calculate specular by choosing a single representative point on the light's surface based on the reflection ray From 6172bb003442ffb85b446a698d96f290669055b0 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Sat, 4 Dec 2021 09:59:16 +0100 Subject: [PATCH 11/39] Add EnhancedPBR support for thin object transmission Signed-off-by: Santi Paprika --- .../Materials/Types/EnhancedPBR.materialtype | 28 ++++++++++++++++++- .../Materials/Types/EnhancedPBR_Common.azsli | 2 ++ .../Types/EnhancedPBR_ForwardPass.azsl | 8 ++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype index 5de756067a..a83721f0b1 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype @@ -1223,6 +1223,32 @@ "min": 0.0, "softMax": 20.0 }, + { + "name": "shrinkFactor", + "displayName": " Shrink Factor", + "description": "Shrink (absolute) offset towards the normal opposite direction to ensure correct shadow map projection", + "type": "float", + "defaultValue": 0.005, + "min": 0.0, + "softMax": 0.05, + "connection": { + "type": "ShaderInput", + "name": "m_shrinkFactor" + } + }, + { + "name": "angleOffset", + "displayName": " Angle Offset", + "description": "Angle to accept below (N . L = 0) in scattering through thin objects", + "type": "float", + "defaultValue": 0.1, + "min": -1.0, + "softMax": 1.0, + "connection": { + "type": "ShaderInput", + "name": "m_angleOffset" + } + }, { "name": "transmissionScale", "displayName": " Scale", @@ -1230,7 +1256,7 @@ "type": "float", "defaultValue": 3.0, "min": 0.0, - "softMax": 20.0 + "softMax": 100.0 } ], "detailLayerGroup": [ diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Common.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Common.azsli index 3c35ca65be..98f091cb12 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Common.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Common.azsli @@ -100,6 +100,8 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial float4 m_transmissionTintThickness; Texture2D m_transmissionThicknessMap; uint m_transmissionThicknessMapUvIndex; + float m_shrinkFactor; + float m_angleOffset; } // Callback function for ParallaxMapping.azsli diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl index 0f9771e480..bc660979f6 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl @@ -275,6 +275,14 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float lightingData.diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture); lightingData.specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture); + // ------- Thin Object Light Transmission ------- + + // Angle offset for subsurface scattering through thin objects + lightingData.angleOffset = MaterialSrg::m_angleOffset; + + // Shrink (absolute) offset towards the normal opposite direction to ensure correct shadow map projection + lightingData.shrinkFactor = MaterialSrg::m_shrinkFactor; + // ------- Clearcoat ------- // [GFX TODO][ATOM-14603]: Clean up the double uses of these clear coat flags From 7e78c260c1d80103764de83433df5e9c7a467da4 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Mon, 6 Dec 2021 12:38:30 +0100 Subject: [PATCH 12/39] Use generic diffusion profiles instead of skin-specific Signed-off-by: Santi Paprika --- .../ShaderLib/Atom/Features/PBR/BackLighting.azsli | 9 +++++++-- 1 file changed, 7 insertions(+), 2 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 cd2ce763e4..79a5041cf1 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 @@ -23,6 +23,7 @@ float3 TransmissionKernel(float t, float3 s) return 0.25 * (1.0 / exp(exponent) + 3.0 / exp(exponent / 3.0)); } +// [specific profile for SKIN (not used ATM)] // Analytical integation (approximation) of diffusion profile over radius, could be precomputed in a LUT float3 T(float s) { @@ -68,11 +69,15 @@ float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightI float E = max(lightingData.angleOffset + dot(-surface.normal, dirToLight),0.0); // Transmission distance computed from shadowmaps modulated by editor-exposed parameters - float s = transmissionDistance * surface.transmission.thickness * (100 - transmissionParams.w) * 10; + float s = transmissionDistance * surface.transmission.thickness * (100 - transmissionParams.w); + + // Use scattering color to weight thin object transmission color + const float3 invScattering = rcp(transmissionParams.xyz); // Albedo at front (surface point) is used to approximate irradiance at the back of the object // See observation 4 in [Jimenez J. et al, 2010] - result = T(s) * lightIntensity * surface.albedo * E; + result = TransmissionKernel(s, invScattering) * lightIntensity * surface.albedo * E; + // result = T(s) * lightIntensity * surface.albedo * E; } break; } From 4a10b5ac62b999d385b99c755032863223b3cdf4 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Mon, 6 Dec 2021 17:17:17 +0100 Subject: [PATCH 13/39] Update T(s) function explanation (comment) Signed-off-by: Santi Paprika --- .../Assets/ShaderLib/Atom/Features/PBR/BackLighting.azsli | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 79a5041cf1..7c5e4732cd 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 @@ -23,7 +23,7 @@ float3 TransmissionKernel(float t, float3 s) return 0.25 * (1.0 / exp(exponent) + 3.0 / exp(exponent / 3.0)); } -// [specific profile for SKIN (not used ATM)] +// [specific profile for SKIN (not used ATM, replaced by TransmissionKernel)] // Analytical integation (approximation) of diffusion profile over radius, could be precomputed in a LUT float3 T(float s) { From 2e5df3f0181425f5eae7bd43d3cb80eadc69b8f6 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Wed, 8 Dec 2021 16:12:02 +0100 Subject: [PATCH 14/39] Avoid negative thickness values Signed-off-by: Santi Paprika --- .../Atom/Features/Shadow/DirectionalLightShadow.azsli | 5 ++++- .../ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli | 5 +++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli index 59817af701..5405d2e914 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli @@ -154,7 +154,10 @@ float DirectionalLightShadow::GetThickness(uint lightIndex, float3 shadowCoords[ shadowCoord.y >= 0. && shadowCoord.y * size < size - PixelMargin && shadowCoord.z < (1. - DepthMargin)) { const float depthBufferValue = shadowmap.Sample(PassSrg::LinearSampler, float3(shadowCoord.xy, indexOfCascade)).r; - const float deltaDepth = abs(shadowCoord.z - depthBufferValue); + + // Normalized thickness (avoid negative values given by to precission or shrinking offsets) + const float deltaDepth = max(shadowCoord.z - depthBufferValue,0.0); + const float viewSpaceThickness = ViewSrg::m_directionalLightShadows[lightIndex].m_far_minus_near * deltaDepth; return viewSpaceThickness; } diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli index 98ec9ea8bc..5baacf4756 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli @@ -274,8 +274,9 @@ float ProjectedShadow::GetThickness() float3(atlasPosition.xy * invAtlasSize, atlasPosition.z), /*LOD=*/0 ).r; - - const float viewSpaceThickness = abs(UnprojectDepth(m_shadowIndex, m_shadowPosition.z) - UnprojectDepth(m_shadowIndex, depthValue)); + + // Denormalized thickness (avoid negative values given by to precission or shrinking offsets) + const float viewSpaceThickness = max(UnprojectDepth(m_shadowIndex, depthValue) - UnprojectDepth(m_shadowIndex, m_shadowPosition.z), 0.0); return viewSpaceThickness; } From 8de5f8b9383b17483b1a0ce88678f6486c1ac5c7 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Thu, 9 Dec 2021 11:51:47 +0100 Subject: [PATCH 15/39] Use geometry normals instead of altered-by-maps normals Signed-off-by: Santi Paprika --- .../ShaderLib/Atom/Features/PBR/Lights/DirectionalLight.azsli | 2 +- .../Assets/ShaderLib/Atom/Features/PBR/Lights/DiskLight.azsli | 2 +- .../Assets/ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) 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 d7fa77d701..0b48094bbf 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 @@ -34,7 +34,7 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData) float3 shrinkedShadowCoords[ViewSrg::MaxCascadeCount]; DirectionalLightShadow::GetShadowCoords( shadowIndex, - surface.position - lightingData.shrinkFactor * surface.normal, + surface.position - lightingData.shrinkFactor * surface.vertexNormal, surface.normal, lightingData.shrinkedShadowCoords); 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 7cc5a34453..fbef38595d 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 @@ -95,7 +95,7 @@ void ApplyDiskLight(ViewSrg::DiskLight light, Surface surface, inout LightingDat } else if (o_transmission_mode == TransmissionMode::ThinObject) { - transmissionDistance = ProjectedShadow::GetThickness(light.m_shadowIndex, surface.position - lightingData.shrinkFactor * surface.normal); + transmissionDistance = ProjectedShadow::GetThickness(light.m_shadowIndex, surface.position - lightingData.shrinkFactor * surface.vertexNormal); } } 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 7f4cd46749..a7b6b822c9 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 @@ -104,7 +104,7 @@ void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingD } else if (o_transmission_mode == TransmissionMode::ThinObject) { - transmissionDistance = ProjectedShadow::GetThickness(shadowIndex, surface.position - lightingData.shrinkFactor * surface.normal); + transmissionDistance = ProjectedShadow::GetThickness(shadowIndex, surface.position - lightingData.shrinkFactor * surface.vertexNormal); } } From 78aa73e3fd6540ebcb90366dc2c181f757d5c07f Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Thu, 9 Dec 2021 18:44:02 +0100 Subject: [PATCH 16/39] Remove thickness + refactor scale parameter influence Signed-off-by: Santi Paprika --- .../Assets/Materials/Types/EnhancedPBR.materialtype | 4 ++-- .../Common/Assets/Materials/Types/Skin.materialtype | 4 ++-- .../ShaderLib/Atom/Features/PBR/BackLighting.azsli | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype index a83721f0b1..ef1d2539f6 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype @@ -1254,9 +1254,9 @@ "displayName": " Scale", "description": "Strength of transmission", "type": "float", - "defaultValue": 3.0, + "defaultValue": 0.01, "min": 0.0, - "softMax": 100.0 + "softMax": 1.0 } ], "detailLayerGroup": [ diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype index 39cbe21a18..33b07bb86b 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype @@ -668,9 +668,9 @@ "displayName": " Scale", "description": "Strength of transmission", "type": "float", - "defaultValue": 3.0, + "defaultValue": 0.01, "min": 0.0, - "softMax": 100.0 + "softMax": 1.0 } ], "wrinkleLayers": [ 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 7c5e4732cd..a550180f9c 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 @@ -65,18 +65,18 @@ float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightI { // Irradiance arround surface point. - // Begin the transmittance dot product slightly before it would with the regular dot(N,L) - float E = max(lightingData.angleOffset + dot(-surface.normal, dirToLight),0.0); + // Increase angle of influence (angle(N,L) -> angle(N,L) + acos(angleOffset)) to smoothen transition regions + float3 E = surface.albedo * max(lightingData.angleOffset + dot(-surface.normal, dirToLight),0.0); - // Transmission distance computed from shadowmaps modulated by editor-exposed parameters - float s = transmissionDistance * surface.transmission.thickness * (100 - transmissionParams.w); + // Transmission distance modulated by editor-exposed scale parameter + float s = transmissionDistance / (transmissionParams.w * transmissionParams.w); // Use scattering color to weight thin object transmission color const float3 invScattering = rcp(transmissionParams.xyz); // Albedo at front (surface point) is used to approximate irradiance at the back of the object // See observation 4 in [Jimenez J. et al, 2010] - result = TransmissionKernel(s, invScattering) * lightIntensity * surface.albedo * E; + result = TransmissionKernel(s, invScattering) * lightIntensity * E; // result = T(s) * lightIntensity * surface.albedo * E; } break; From 90bf2520be0a0c23d34590593e94f0907349b88c Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Fri, 10 Dec 2021 13:57:04 +0100 Subject: [PATCH 17/39] Add and expose distance attenuation to compensate low-res shadow maps Signed-off-by: Santi Paprika --- .../Materials/Types/EnhancedPBR.materialtype | 15 ++++++++++++++- .../Materials/Types/EnhancedPBR_Common.azsli | 1 + .../Materials/Types/EnhancedPBR_ForwardPass.azsl | 3 +++ .../Common/Assets/Materials/Types/Skin.azsl | 3 +++ .../Assets/Materials/Types/Skin.materialtype | 15 ++++++++++++++- .../Assets/Materials/Types/Skin_Common.azsli | 1 + .../Atom/Features/PBR/Lighting/LightingData.azsli | 3 +++ .../Features/PBR/Lights/DirectionalLight.azsli | 10 ++++++++-- .../Atom/Features/PBR/Lights/DiskLight.azsli | 7 ++++++- .../Atom/Features/PBR/Lights/PointLight.azsli | 8 +++++++- 10 files changed, 60 insertions(+), 6 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype index ef1d2539f6..31f8bd3c32 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype @@ -1239,7 +1239,7 @@ { "name": "angleOffset", "displayName": " Angle Offset", - "description": "Angle to accept below (N . L = 0) in scattering through thin objects", + "description": "cosine of angle to extend below (N . L = 0) in scattering through thin objects", "type": "float", "defaultValue": 0.1, "min": -1.0, @@ -1249,6 +1249,19 @@ "name": "m_angleOffset" } }, + { + "name": "distanceAttenuation", + "displayName": " Distance Attenuation", + "description": "Attenuation applied to hide artifacts due to low-res shadow maps (e.g. objects far to the camera when using directional lights or objects far to the light when using sphere/disk lights", + "type": "float", + "defaultValue": 4.0, + "min": 0.0, + "softMax": 10.0, + "connection": { + "type": "ShaderInput", + "name": "m_distanceAttenuation" + } + }, { "name": "transmissionScale", "displayName": " Scale", diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Common.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Common.azsli index 98f091cb12..7c791e1cd0 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Common.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Common.azsli @@ -102,6 +102,7 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial uint m_transmissionThicknessMapUvIndex; float m_shrinkFactor; float m_angleOffset; + float m_distanceAttenuation; } // Callback function for ParallaxMapping.azsli diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl index bc660979f6..e35941c623 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl @@ -283,6 +283,9 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // Shrink (absolute) offset towards the normal opposite direction to ensure correct shadow map projection lightingData.shrinkFactor = MaterialSrg::m_shrinkFactor; + // Attenuation applied to hide artifacts due to low-res shadow maps + lightingData.distanceAttenuation = MaterialSrg::m_distanceAttenuation; + // ------- Clearcoat ------- // [GFX TODO][ATOM-14603]: Clean up the double uses of these clear coat flags diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl index 4908e736f4..ca02d496c5 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl @@ -349,6 +349,9 @@ PbrLightingOutput SkinPS_Common(VSOutput IN) // Shrink (absolute) offset towards the normal opposite direction to ensure correct shadow map projection lightingData.shrinkFactor = MaterialSrg::m_shrinkFactor; + // Attenuation applied to hide artifacts due to low-res shadow maps + lightingData.distanceAttenuation = MaterialSrg::m_distanceAttenuation; + // ------- Occlusion ------- lightingData.diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture); diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype index 33b07bb86b..fa190657c0 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype @@ -653,7 +653,7 @@ { "name": "angleOffset", "displayName": " Angle Offset", - "description": "Angle to accept below (N . L = 0) in scattering through thin objects", + "description": "cosine of angle to extend below (N . L = 0) in scattering through thin objects", "type": "float", "defaultValue": 0.1, "min": -1.0, @@ -663,6 +663,19 @@ "name": "m_angleOffset" } }, + { + "name": "distanceAttenuation", + "displayName": " Distance Attenuation", + "description": "Attenuation applied to hide artifacts due to low-res shadow maps (e.g. objects far to the camera when using directional lights or objects far to the light when using sphere/disk lights", + "type": "float", + "defaultValue": 4.0, + "min": 0.0, + "softMax": 10.0, + "connection": { + "type": "ShaderInput", + "name": "m_distanceAttenuation" + } + }, { "name": "transmissionScale", "displayName": " Scale", diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_Common.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_Common.azsli index 1fa2039c72..2ec1e6e8dc 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_Common.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_Common.azsli @@ -73,6 +73,7 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial uint m_transmissionThicknessMapUvIndex; float m_shrinkFactor; float m_angleOffset; + float m_distanceAttenuation; Texture2D m_wrinkle_baseColor_texture1; Texture2D m_wrinkle_baseColor_texture2; diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli index 8f3bca703e..cc55c4796e 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli @@ -37,6 +37,9 @@ class LightingData // Shrink (absolute) offset towards the normal opposite direction to ensure correct shadow map projection float shrinkFactor; + // Attenuation applied to hide artifacts due to low-res shadow maps + float distanceAttenuation; + // Normalized direction from surface to camera float3 dirToCamera; 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 0b48094bbf..ffac82232f 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 @@ -18,7 +18,7 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData) // Shadowed check const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight; float litRatio = 1.0f; - + float camToSurfDist = distance(ViewSrg::m_worldPosition, surface.position); // Transmission distance inside object float transmissionDistance = 0.0f; @@ -84,7 +84,13 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData) lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight) * currentLitRatio; lightingData.specularLighting += GetSpecularLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight) * currentLitRatio; - lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight, currentTransmissionDistance); + + float3 backLighting = GetBackLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight, currentTransmissionDistance); + + // 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; } // Add debug coloring for directional light shadow 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 fbef38595d..209a6af823 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 @@ -114,8 +114,13 @@ void ApplyDiskLight(ViewSrg::DiskLight light, Surface surface, inout LightingDat lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, lightIntensity, posToLightDir) * litRatio; // Transmission contribution - lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, posToLightDir, transmissionDistance); + float3 backLighting = GetBackLighting(surface, lightingData, lightIntensity, posToLightDir, 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, 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 a7b6b822c9..2eb815410d 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 @@ -67,6 +67,7 @@ uint ComputeShadowIndex(const ViewSrg::PointLight light, const Surface surface) void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingData lightingData) { float3 posToLight = light.m_position - surface.position; + float posToLightDist = length(posToLight); float d2 = dot(posToLight, posToLight); // light distance squared float falloff = d2 * light.m_invAttenuationRadiusSquared; @@ -112,7 +113,12 @@ void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingD lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, lightIntensity, normalize(posToLight)) * litRatio; // Transmission contribution - lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, normalize(posToLight), transmissionDistance); + 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; // Adjust the light direcion for specular based on bulb size From 84829dd8eed1322cb6cc2570709af1e7d1b140b6 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Mon, 13 Dec 2021 10:47:03 +0100 Subject: [PATCH 18/39] Make scale parameter influence output instead of transmission distance Signed-off-by: Santi Paprika --- .../Assets/ShaderLib/Atom/Features/PBR/BackLighting.azsli | 8 +++++--- 1 file changed, 5 insertions(+), 3 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 a550180f9c..e729fcb363 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 @@ -69,15 +69,17 @@ float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightI float3 E = surface.albedo * max(lightingData.angleOffset + dot(-surface.normal, dirToLight),0.0); // Transmission distance modulated by editor-exposed scale parameter - float s = transmissionDistance / (transmissionParams.w * transmissionParams.w); + float s = transmissionDistance * 100.0; // Use scattering color to weight thin object transmission color const float3 invScattering = rcp(transmissionParams.xyz); // Albedo at front (surface point) is used to approximate irradiance at the back of the object // See observation 4 in [Jimenez J. et al, 2010] - result = TransmissionKernel(s, invScattering) * lightIntensity * E; - // result = T(s) * lightIntensity * surface.albedo * E; + result = TransmissionKernel(s, invScattering) * lightIntensity * E * transmissionParams.w; + + // Alternative specific to skin translucency + // result = T(s) * lightIntensity * surface.albedo * E * transmissionParams.w; } break; } From 2d45ecb616a504d1fa4135dea04e5adfa19775b4 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Thu, 23 Dec 2021 11:33:36 +0100 Subject: [PATCH 19/39] Fix nits (https://github.com/o3de/o3de/pull/6428#discussion_r774251316 , https://github.com/o3de/o3de/pull/6428#discussion_r774252019) Signed-off-by: Santi Paprika --- Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl | 2 +- .../Assets/ShaderLib/Atom/Features/PBR/BackLighting.azsli | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl index ca02d496c5..8a041a93f1 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl @@ -136,7 +136,7 @@ VSOutput SkinVS(VSInput IN) } VertexHelper(IN, OUT, worldPosition, false); - + return OUT; } 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 e729fcb363..b35e17b160 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 @@ -65,7 +65,7 @@ float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightI { // Irradiance arround surface point. - // Increase angle of influence (angle(N,L) -> angle(N,L) + acos(angleOffset)) to smoothen transition regions + // 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 From c700b95c8d4aed5605b28c901a49a7287725e9cb Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Thu, 23 Dec 2021 15:33:00 +0100 Subject: [PATCH 20/39] Avoid mode-specific transmission distance initialization (potential fix for https://github.com/o3de/o3de/pull/6428#discussion_r774259781) Signed-off-by: Santi Paprika --- .../PBR/Lights/DirectionalLight.azsli | 20 ++++----- .../Atom/Features/PBR/Lights/DiskLight.azsli | 45 ++++++++++--------- .../Atom/Features/PBR/Lights/PointLight.azsli | 25 ++++++----- 3 files changed, 45 insertions(+), 45 deletions(-) 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 ffac82232f..d2aeb4b5f8 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 @@ -19,7 +19,8 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData) const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight; float litRatio = 1.0f; float camToSurfDist = distance(ViewSrg::m_worldPosition, surface.position); - // Transmission distance inside object + + // Distance travelled by the light inside the object float transmissionDistance = 0.0f; if (o_enableShadows && shadowIndex < SceneSrg::m_directionalLightCount) @@ -69,28 +70,25 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData) float currentLitRatio = 1.0f; // Transmission distance from current light inside object (default non-influential values) - // o_transmission_mode == NONE is not taken into account because GetBackLighting already ignores this case - float currentTransmissionDistance = (o_transmission_mode == TransmissionMode::ThickObject) ? 0.0f : 9999.0f; if (o_enableShadows) { bool activeLight = index == shadowIndex; + + // Add contribution only if current directional light is the active one for shadows currentLitRatio = activeLight ? litRatio : 1.; if (activeLight) { - // Transmission distance (add contribution only if current directional light is the active one for shadows) - currentTransmissionDistance = transmissionDistance; + 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; } } lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight) * currentLitRatio; lightingData.specularLighting += GetSpecularLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight) * currentLitRatio; - float3 backLighting = GetBackLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight, currentTransmissionDistance); - - // 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; } // Add debug coloring for directional light shadow 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 209a6af823..9d4e503df6 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 @@ -76,10 +76,18 @@ void ApplyDiskLight(ViewSrg::DiskLight light, Surface surface, inout LightingDat // shadow float litRatio = 1.0; - - // Transmission distance from current light inside object (default non-influential values) - // o_transmission_mode == NONE is not taken into account because GetBackLighting already ignores this case - float transmissionDistance = (o_transmission_mode == TransmissionMode::ThickObject) ? 0.0f : 9999.0f; + + if (useConeAngle && dotWithDirection < light.m_cosInnerConeAngle) // in penumbra + { + // Normalize into 0.0 - 1.0 space. + float penumbraMask = (dotWithDirection - light.m_cosOuterConeAngle) / (light.m_cosInnerConeAngle - light.m_cosOuterConeAngle); + + // Apply smoothstep + penumbraMask = penumbraMask * penumbraMask * (3.0 - 2.0 * penumbraMask); + + lightIntensity *= penumbraMask; + } + if (o_enableShadows) { litRatio = ProjectedShadow::GetVisibility( @@ -89,6 +97,10 @@ 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) { transmissionDistance = ProjectedShadow::GetThickness(light.m_shadowIndex, surface.position); @@ -96,31 +108,20 @@ void ApplyDiskLight(ViewSrg::DiskLight light, Surface surface, inout LightingDat else if (o_transmission_mode == TransmissionMode::ThinObject) { transmissionDistance = ProjectedShadow::GetThickness(light.m_shadowIndex, surface.position - lightingData.shrinkFactor * surface.vertexNormal); - } - } + } - if (useConeAngle && dotWithDirection < light.m_cosInnerConeAngle) // in penumbra - { - // Normalize into 0.0 - 1.0 space. - float penumbraMask = (dotWithDirection - light.m_cosOuterConeAngle) / (light.m_cosInnerConeAngle - light.m_cosOuterConeAngle); - - // Apply smoothstep - penumbraMask = penumbraMask * penumbraMask * (3.0 - 2.0 * penumbraMask); + // 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); - lightIntensity *= penumbraMask; + lightingData.translucentBackLighting += backLighting * attenuation; } // Diffuse contribution lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, lightIntensity, posToLightDir) * litRatio; - // Transmission contribution - float3 backLighting = GetBackLighting(surface, lightingData, lightIntensity, posToLightDir, 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, 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 2eb815410d..e2297fd3d3 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,9 +85,6 @@ void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingD // shadow float litRatio = 1.0; - // Transmission distance from current light inside object (default non-influential values) - // o_transmission_mode == NONE is not taken into account because GetBackLighting already ignores this case - float transmissionDistance = (o_transmission_mode == TransmissionMode::ThickObject) ? 0.0f : 9999.0f; if (o_enableShadows) { const float3 lightDir = normalize(light.m_position - surface.position); @@ -99,6 +96,10 @@ void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingD 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) { transmissionDistance = ProjectedShadow::GetThickness(shadowIndex, surface.position); @@ -106,20 +107,20 @@ void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingD else if (o_transmission_mode == TransmissionMode::ThinObject) { 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 - 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; - // Adjust the light direcion for specular based on bulb size // Calculate the reflection off the normal from the view direction From 14683bf3eff17aa5c4eeed09fa5237c616cf45db Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Thu, 23 Dec 2021 15:47:00 +0100 Subject: [PATCH 21/39] Fix nits (remove residual comment) Signed-off-by: Santi Paprika --- .../ShaderLib/Atom/Features/PBR/Lights/DirectionalLight.azsli | 2 -- 1 file changed, 2 deletions(-) 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 d2aeb4b5f8..da4901cf8e 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 @@ -69,7 +69,6 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData) // Currently shadow check is done only for index == shadowIndex. float currentLitRatio = 1.0f; - // Transmission distance from current light inside object (default non-influential values) if (o_enableShadows) { bool activeLight = index == shadowIndex; @@ -88,7 +87,6 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData) lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight) * currentLitRatio; lightingData.specularLighting += GetSpecularLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight) * currentLitRatio; - } // Add debug coloring for directional light shadow From 038c71a660bedf0c3ddde707e913dbcc4d09db19 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Thu, 23 Dec 2021 17:55:27 +0100 Subject: [PATCH 22/39] 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 From 6e3ada487e14ab43dae08161b1099ccb099c338b Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Thu, 23 Dec 2021 18:21:18 +0100 Subject: [PATCH 23/39] Move penumbra computation back to original place. Signed-off-by: Santi Paprika --- .../Atom/Features/PBR/Lights/DiskLight.azsli | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) 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 cc0e33ff5b..3acd74ab03 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 @@ -77,16 +77,6 @@ void ApplyDiskLight(ViewSrg::DiskLight light, Surface surface, inout LightingDat // shadow float litRatio = 1.0; - if (useConeAngle && dotWithDirection < light.m_cosInnerConeAngle) // in penumbra - { - // Normalize into 0.0 - 1.0 space. - float penumbraMask = (dotWithDirection - light.m_cosOuterConeAngle) / (light.m_cosInnerConeAngle - light.m_cosOuterConeAngle); - - // Apply smoothstep - penumbraMask = penumbraMask * penumbraMask * (3.0 - 2.0 * penumbraMask); - - 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; @@ -110,7 +100,17 @@ void ApplyDiskLight(ViewSrg::DiskLight light, Surface surface, inout LightingDat { transmissionDistance = ProjectedShadow::GetThickness(light.m_shadowIndex, surface.position - lightingData.shrinkFactor * surface.vertexNormal); } + } + if (useConeAngle && dotWithDirection < light.m_cosInnerConeAngle) // in penumbra + { + // Normalize into 0.0 - 1.0 space. + float penumbraMask = (dotWithDirection - light.m_cosOuterConeAngle) / (light.m_cosInnerConeAngle - light.m_cosOuterConeAngle); + + // Apply smoothstep + penumbraMask = penumbraMask * penumbraMask * (3.0 - 2.0 * penumbraMask); + + lightIntensity *= penumbraMask; } // Diffuse contribution From eda405f5f1d3ca785f61ea9ae1f4b9fb3ea54c0a Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Thu, 23 Dec 2021 19:49:47 +0100 Subject: [PATCH 24/39] Move attenuation computation into GetBackLighting (https://github.com/o3de/o3de/pull/6428#discussion_r774259148) Signed-off-by: Santi Paprika --- .../ShaderLib/Atom/Features/PBR/BackLighting.azsli | 5 ++++- .../Atom/Features/PBR/Lights/CapsuleLight.azsli | 2 +- .../Atom/Features/PBR/Lights/DirectionalLight.azsli | 6 ++---- .../ShaderLib/Atom/Features/PBR/Lights/DiskLight.azsli | 6 ++---- .../Atom/Features/PBR/Lights/LightTypesCommon.azsli | 2 +- .../Atom/Features/PBR/Lights/PointLight.azsli | 6 ++---- .../ShaderLib/Atom/Features/PBR/Lights/QuadLight.azsli | 10 +++++----- 7 files changed, 17 insertions(+), 20 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 2f4680bc9d..adb2dea927 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 @@ -36,7 +36,7 @@ float3 T(float s) float3(0.078, 0.0, 0.0) * exp(-s*s/7.41); } -float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightIntensity, float3 dirToLight, float transmissionDistance) +float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightIntensity, float3 dirToLight, float transmissionDistance, float attenuationDistance) { float3 result = float3(0.0, 0.0, 0.0); float thickness = 0.0; @@ -86,6 +86,9 @@ float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightI // Alternative specific to skin translucency // result = T(s) * lightIntensity * surface.albedo * E * transmissionParams.w; + + // Distance attenuation applied to hide artifacts due to low-res projected areas onto shadowmaps (might need some work in the future) + result *= 1.0 / pow(max(1.0, sqrt(attenuationDistance)), lightingData.distanceAttenuation + 1.0); } break; } diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/CapsuleLight.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/CapsuleLight.azsli index e6b18df9b5..bb4be45e5a 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/CapsuleLight.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/CapsuleLight.azsli @@ -136,7 +136,7 @@ void ApplyCapsuleLight(ViewSrg::CapsuleLight light, Surface surface, inout Light float3 posToLight = closestIntersectionPoint - surface.position; // Tranmission contribution - lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, normalize(posToLight), 0.0); + lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, normalize(posToLight), -1.0f, 0.0f); // Calculate the offset from the nearest point on the reflection vector to the nearest point on the capsule light float3 posToClosestPointAlongReflection = dot(posToLight, reflectionDir) * reflectionDir; 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 a34411c332..e3f3f1135a 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 @@ -77,10 +77,8 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData) 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; + // Transmission contribution + lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight, currentTransmissionDistance, camToSurfDist/2.0); 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 3acd74ab03..a98b99452b 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 @@ -116,10 +116,8 @@ void ApplyDiskLight(ViewSrg::DiskLight light, Surface surface, inout LightingDat // 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; + // Transmission contribution + lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, posToLightDir, transmissionDistance, distanceToLight2); // Adjust the light direction for specular based on disk size diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/LightTypesCommon.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/LightTypesCommon.azsli index f0169e29b8..dee0d63c79 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/LightTypesCommon.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/LightTypesCommon.azsli @@ -49,6 +49,6 @@ void AddSampleContribution( float3 intensityRgb = float3(intensity, intensity, intensity); diffuseAcc += GetDiffuseLighting(surface, lightingData, intensityRgb, posToLightSampleDir); - translucentAcc += GetBackLighting(surface, lightingData, intensityRgb, posToLightSampleDir, 0.0); + translucentAcc += GetBackLighting(surface, lightingData, intensityRgb, posToLightSampleDir, -1.0f, 0.0f); specularAcc += GetSpecularLighting(surface, lightingData, intensityRgb, posToLightSampleDir); } 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 664c3693fb..ecec0af004 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 @@ -113,10 +113,8 @@ void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingD // 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; + // Transmission contribution + lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, normalize(posToLight), transmissionDistance, posToLightDist); // Adjust the light direcion for specular based on bulb size 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 b4cdbeb847..f5e148f771 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 @@ -150,11 +150,11 @@ void ApplyQuadLight(ViewSrg::QuadLight light, Surface surface, inout LightingDat lightingData.translucentBackLighting += ( - 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) + GetBackLighting(surface, lightingData, intensity, p0, -1.0f, 0.0f) + + GetBackLighting(surface, lightingData, intensity, p1, -1.0f, 0.0f) + + GetBackLighting(surface, lightingData, intensity, p2, -1.0f, 0.0f) + + GetBackLighting(surface, lightingData, intensity, p3, -1.0f, 0.0f) + + GetBackLighting(surface, lightingData, intensity, dirToLightCenter, -1.0f, 0.0f) ); // Calculate specular by choosing a single representative point on the light's surface based on the reflection ray From 46abff309336e54ff19507ef8f32c3a883f2df28 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Thu, 23 Dec 2021 20:29:42 +0100 Subject: [PATCH 25/39] Rename 'angleOffset' to 'transmissionNdLBias' (https://github.com/o3de/o3de/pull/6428#discussion_r774253626) Signed-off-by: Santi Paprika --- .../Common/Assets/Materials/Types/EnhancedPBR.materialtype | 6 +++--- .../Common/Assets/Materials/Types/EnhancedPBR_Common.azsli | 2 +- .../Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl | 2 +- Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl | 2 +- .../Feature/Common/Assets/Materials/Types/Skin.materialtype | 6 +++--- .../Feature/Common/Assets/Materials/Types/Skin_Common.azsli | 2 +- .../Assets/ShaderLib/Atom/Features/PBR/BackLighting.azsli | 4 ++-- .../ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli | 4 ++-- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype index 31f8bd3c32..77caf42834 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype @@ -1237,8 +1237,8 @@ } }, { - "name": "angleOffset", - "displayName": " Angle Offset", + "name": "transmissionAngleBias", + "displayName": " Angle Bias", "description": "cosine of angle to extend below (N . L = 0) in scattering through thin objects", "type": "float", "defaultValue": 0.1, @@ -1246,7 +1246,7 @@ "softMax": 1.0, "connection": { "type": "ShaderInput", - "name": "m_angleOffset" + "name": "m_transmissionNdLBias" } }, { diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Common.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Common.azsli index 7c791e1cd0..c15b49dc7d 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Common.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Common.azsli @@ -101,7 +101,7 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial Texture2D m_transmissionThicknessMap; uint m_transmissionThicknessMapUvIndex; float m_shrinkFactor; - float m_angleOffset; + float m_transmissionNdLBias; float m_distanceAttenuation; } diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl index e35941c623..5e02da679e 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl @@ -278,7 +278,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // ------- Thin Object Light Transmission ------- // Angle offset for subsurface scattering through thin objects - lightingData.angleOffset = MaterialSrg::m_angleOffset; + lightingData.transmissionNdLBias = MaterialSrg::m_transmissionNdLBias; // Shrink (absolute) offset towards the normal opposite direction to ensure correct shadow map projection lightingData.shrinkFactor = MaterialSrg::m_shrinkFactor; diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl index 8a041a93f1..faa16b205a 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl @@ -344,7 +344,7 @@ PbrLightingOutput SkinPS_Common(VSOutput IN) // ------- Thin Object Light Transmission ------- // Angle offset for subsurface scattering through thin objects - lightingData.angleOffset = MaterialSrg::m_angleOffset; + lightingData.transmissionNdLBias = MaterialSrg::m_transmissionNdLBias; // Shrink (absolute) offset towards the normal opposite direction to ensure correct shadow map projection lightingData.shrinkFactor = MaterialSrg::m_shrinkFactor; diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype index fa190657c0..d42f62d0ac 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype @@ -651,8 +651,8 @@ } }, { - "name": "angleOffset", - "displayName": " Angle Offset", + "name": "transmissionAngleBias", + "displayName": " Angle Bias", "description": "cosine of angle to extend below (N . L = 0) in scattering through thin objects", "type": "float", "defaultValue": 0.1, @@ -660,7 +660,7 @@ "softMax": 1.0, "connection": { "type": "ShaderInput", - "name": "m_angleOffset" + "name": "m_transmissionNdLBias" } }, { diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_Common.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_Common.azsli index 2ec1e6e8dc..630291c260 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_Common.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_Common.azsli @@ -72,7 +72,7 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial Texture2D m_transmissionThicknessMap; uint m_transmissionThicknessMapUvIndex; float m_shrinkFactor; - float m_angleOffset; + float m_transmissionNdLBias; float m_distanceAttenuation; Texture2D m_wrinkle_baseColor_texture1; 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 adb2dea927..0506f08db1 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 @@ -71,8 +71,8 @@ float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightI } // 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); + // Increase angle of influence (angle(N,L) -> angle(N,L) + acos(transmissionNdLBias)) to smooth transition regions + float3 E = surface.albedo * max(lightingData.transmissionNdLBias + dot(-surface.normal, dirToLight),0.0); // Transmission distance modulated by hardcoded constant (could be exposed as a weight of scattering distance for transmission) float s = transmissionDistance * 100.0; diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli index cc55c4796e..7e7af6be96 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli @@ -31,8 +31,8 @@ class LightingData // Direction light shadow coordinates for shrinked positions (used in scattering through thin objects) float3 shrinkedShadowCoords[ViewSrg::MaxCascadeCount]; - // Angle to accept below (N . L = 0) in scattering through thin objects - float angleOffset; + // (N . L) to accept below (N . L = 0) in scattering through thin objects + float transmissionNdLBias; // Shrink (absolute) offset towards the normal opposite direction to ensure correct shadow map projection float shrinkFactor; From 6dbb8e1794f763302226dce41ff91e99b3b7e875 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Thu, 23 Dec 2021 21:02:02 +0100 Subject: [PATCH 26/39] Use local shrinked shadow coords (https://github.com/o3de/o3de/pull/6428#discussion_r774255818) Signed-off-by: Santi Paprika --- .../ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli | 3 --- .../ShaderLib/Atom/Features/PBR/Lights/DirectionalLight.azsli | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli index 7e7af6be96..a1278b8126 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli @@ -28,9 +28,6 @@ class LightingData // Direction light shadow coordinates float3 shadowCoords[ViewSrg::MaxCascadeCount]; - // Direction light shadow coordinates for shrinked positions (used in scattering through thin objects) - float3 shrinkedShadowCoords[ViewSrg::MaxCascadeCount]; - // (N . L) to accept below (N . L = 0) in scattering through thin objects float transmissionNdLBias; 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 e3f3f1135a..e6de9e57c3 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 @@ -37,7 +37,7 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData) shadowIndex, surface.position - lightingData.shrinkFactor * surface.vertexNormal, surface.normal, - lightingData.shrinkedShadowCoords); + shrinkedShadowCoords); if (o_transmission_mode == TransmissionMode::ThickObject) { @@ -47,7 +47,7 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData) { // Use shrinked positions for thin object transmission to ensure they fall onto the object when querying // the depth from the shadow map - transmissionDistance = DirectionalLightShadow::GetThickness(shadowIndex, lightingData.shrinkedShadowCoords); + transmissionDistance = DirectionalLightShadow::GetThickness(shadowIndex, shrinkedShadowCoords); } } From 60ec8c3cfb5d9a1110a96977bdc3318739b3f1e0 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Thu, 23 Dec 2021 21:17:17 +0100 Subject: [PATCH 27/39] Alias shadowCoords memory instead of using local variable (https://github.com/o3de/o3de/pull/6428#discussion_r774255818 cont'd) Signed-off-by: Santi Paprika --- .../Features/PBR/Lights/DirectionalLight.azsli | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) 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 e6de9e57c3..507b226682 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 @@ -31,23 +31,21 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData) surface.vertexNormal, debugInfo); - // Fetch shadow coords for shrinked world position (used in thin transmission materials) - float3 shrinkedShadowCoords[ViewSrg::MaxCascadeCount]; - DirectionalLightShadow::GetShadowCoords( - shadowIndex, - surface.position - lightingData.shrinkFactor * surface.vertexNormal, - surface.normal, - shrinkedShadowCoords); - if (o_transmission_mode == TransmissionMode::ThickObject) { transmissionDistance = DirectionalLightShadow::GetThickness(shadowIndex, lightingData.shadowCoords); } else if (o_transmission_mode == TransmissionMode::ThinObject) { - // Use shrinked positions for thin object transmission to ensure they fall onto the object when querying + // Fetch and use shrinked positions for thin object transmission to ensure they fall onto the object when querying + DirectionalLightShadow::GetShadowCoords( + shadowIndex, + surface.position - lightingData.shrinkFactor * surface.vertexNormal, + surface.normal, + lightingData.shadowCoords); + // the depth from the shadow map - transmissionDistance = DirectionalLightShadow::GetThickness(shadowIndex, shrinkedShadowCoords); + transmissionDistance = DirectionalLightShadow::GetThickness(shadowIndex, lightingData.shadowCoords); } } From 7052b99671027ceb36174d95e275d935eeb5be42 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Tue, 4 Jan 2022 09:49:15 +0100 Subject: [PATCH 28/39] Add reference for skin-specific profiles (https://github.com/o3de/o3de/pull/6428/files#r776068153) Signed-off-by: Santi Paprika --- .../Common/Assets/ShaderLib/Atom/Features/PBR/BackLighting.azsli | 1 + 1 file changed, 1 insertion(+) 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 0506f08db1..eec90a1da9 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 @@ -25,6 +25,7 @@ float3 TransmissionKernel(float t, float3 s) // [specific profile for SKIN (not used ATM, replaced by TransmissionKernel)] // Analytical integation (approximation) of diffusion profile over radius, could be precomputed in a LUT +// From d'Eon and Luebke (https://developer.nvidia.com/gpugems/gpugems3/part-iii-rendering/chapter-14-advanced-techniques-realistic-real-time-skin, section 14.4.7) float3 T(float s) { // dipoles and multipoles are approximated with sums of a small number of Gaussians with variable weights and variances From c814be22fd65eacf47ea11d969acc8994780c2eb Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Tue, 4 Jan 2022 10:34:05 +0100 Subject: [PATCH 29/39] Saturate (NdL + bias) to preserve energy (https://github.com/o3de/o3de/pull/6428#discussion_r774253478, https://github.com/o3de/o3de/pull/6428#discussion_r776069110) Signed-off-by: Santi Paprika --- .../Assets/ShaderLib/Atom/Features/PBR/BackLighting.azsli | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 eec90a1da9..dd40b94414 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 @@ -73,7 +73,7 @@ float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightI // Irradiance arround surface point. // Increase angle of influence (angle(N,L) -> angle(N,L) + acos(transmissionNdLBias)) to smooth transition regions - float3 E = surface.albedo * max(lightingData.transmissionNdLBias + dot(-surface.normal, dirToLight),0.0); + float3 E = surface.albedo * saturate(lightingData.transmissionNdLBias + dot(-surface.normal, dirToLight)); // Transmission distance modulated by hardcoded constant (could be exposed as a weight of scattering distance for transmission) float s = transmissionDistance * 100.0; From 69df812941fedec065e23e1965fc646f66a50624 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Tue, 4 Jan 2022 12:23:02 +0100 Subject: [PATCH 30/39] Add explanations for default constant parameters + define as separate const variables (https://github.com/o3de/o3de/pull/6428#discussion_r776073076, https://github.com/o3de/o3de/pull/6428#discussion_r776072881, https://github.com/o3de/o3de/pull/6428#discussion_r776069391) Signed-off-by: Santi Paprika --- .../Atom/Features/PBR/BackLighting.azsli | 5 +++-- .../Features/PBR/Lights/CapsuleLight.azsli | 11 +++++++++-- .../Features/PBR/Lights/DirectionalLight.azsli | 4 +++- .../Atom/Features/PBR/Lights/DiskLight.azsli | 5 +++-- .../Features/PBR/Lights/LightTypesCommon.azsli | 12 +++++++++++- .../Atom/Features/PBR/Lights/PointLight.azsli | 4 +++- .../Atom/Features/PBR/Lights/QuadLight.azsli | 18 +++++++++++++----- 7 files changed, 45 insertions(+), 14 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 dd40b94414..87dd42fd28 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 @@ -75,8 +75,9 @@ float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightI // Increase angle of influence (angle(N,L) -> angle(N,L) + acos(transmissionNdLBias)) to smooth transition regions float3 E = surface.albedo * saturate(lightingData.transmissionNdLBias + dot(-surface.normal, dirToLight)); - // Transmission distance modulated by hardcoded constant (could be exposed as a weight of scattering distance for transmission) - float s = transmissionDistance * 100.0; + // Transmission distance modulated by hardcoded constant C (could be exposed as a weight of scattering distance for transmission) + const float C = 100.0f; + float s = transmissionDistance * C; // Use scattering color to weight thin object transmission color const float3 invScattering = rcp(transmissionParams.xyz); diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/CapsuleLight.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/CapsuleLight.azsli index bb4be45e5a..1921159c03 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/CapsuleLight.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/CapsuleLight.azsli @@ -135,8 +135,15 @@ void ApplyCapsuleLight(ViewSrg::CapsuleLight light, Surface surface, inout Light float3 closestIntersectionPoint = startPoint + closestT * startToEnd; float3 posToLight = closestIntersectionPoint - surface.position; - // Tranmission contribution - lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, normalize(posToLight), -1.0f, 0.0f); + // Transmission contribution + // We cannot compute the actual transmission distance so we want to: + // - If transmission mode is thick object -> use transmission thickness parameter instead + // - If transmission mode is thin object -> ignore back lighting + // To detect and apply this behavior in the GetBackLighting function, we need to use a negative transmissionDistance + const float transmissionDistance = -1.0f; + // If the transmissionDistance is ignored then the attenuation distance (only used on thin objects) does not have any influence + const float attenuationDistance = 0.0f; + lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, normalize(posToLight), transmissionDistance, attenuationDistance); // Calculate the offset from the nearest point on the reflection vector to the nearest point on the capsule light float3 posToClosestPointAlongReflection = dot(posToLight, reflectionDir) * reflectionDir; 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 507b226682..92b90b16ea 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,7 +20,9 @@ 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. If not redefined, it will take mode-specific null behaviors (see GetBackLighting()) + // Distance travelled by the light inside the object. If not redefined to a non-negative value, it will take the following behavior: + // - If transmission mode is thick object -> use transmission thickness parameter instead + // - If transmission mode is thin object -> ignore back lighting float transmissionDistance = -1.0f; if (o_enableShadows && shadowIndex < SceneSrg::m_directionalLightCount) 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 a98b99452b..4f05caa912 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 @@ -77,8 +77,9 @@ void ApplyDiskLight(ViewSrg::DiskLight light, Surface surface, inout LightingDat // 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()) + // Distance travelled by the light inside the object. If not redefined to a non-negative value, it will take the following behavior: + // - If transmission mode is thick object -> use transmission thickness parameter instead + // - If transmission mode is thin object -> ignore back lighting float transmissionDistance = -1.0f; if (o_enableShadows) diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/LightTypesCommon.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/LightTypesCommon.azsli index dee0d63c79..6718c6f385 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/LightTypesCommon.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/LightTypesCommon.azsli @@ -49,6 +49,16 @@ void AddSampleContribution( float3 intensityRgb = float3(intensity, intensity, intensity); diffuseAcc += GetDiffuseLighting(surface, lightingData, intensityRgb, posToLightSampleDir); - translucentAcc += GetBackLighting(surface, lightingData, intensityRgb, posToLightSampleDir, -1.0f, 0.0f); + + // Transmission contribution + // We cannot compute the actual transmission distance so we want to: + // - If transmission mode is thick object -> use transmission thickness parameter instead + // - If transmission mode is thin object -> ignore back lighting + // To detect and apply this behavior in the GetBackLighting function, we need to use a negative transmissionDistance + const float transmissionDistance = -1.0f; + // If the transmissionDistance is ignored then the attenuation distance (only used on thin objects) does not have any influence + const float attenuationDistance = 0.0f; + translucentAcc += GetBackLighting(surface, lightingData, intensityRgb, posToLightSampleDir, transmissionDistance, attenuationDistance); + specularAcc += GetSpecularLighting(surface, lightingData, intensityRgb, posToLightSampleDir); } 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 ecec0af004..02ae82d0f9 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,7 +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()) + // Distance travelled by the light inside the object. If not redefined to a non-negative value, it will take the following behavior: + // - If transmission mode is thick object -> use transmission thickness parameter instead + // - If transmission mode is thin object -> ignore back lighting float transmissionDistance = -1.0f; if (o_enableShadows) 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 f5e148f771..e6ac886fb6 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,13 +148,21 @@ void ApplyQuadLight(ViewSrg::QuadLight light, Surface surface, inout LightingDat GetDiffuseLighting(surface, lightingData, intensity, dirToLightCenter) ); + // Transmission contribution + // We cannot compute the actual transmission distance so we want to: + // - If transmission mode is thick object -> use transmission thickness parameter instead + // - If transmission mode is thin object -> ignore back lighting + // To detect and apply this behavior in the GetBackLighting function, we need to use a negative transmissionDistance + const float transmissionDistance = -1.0f; + // If the transmissionDistance is ignored then the attenuation distance (only used on thin objects) does not have any influence + const float attenuationDistance = 0.0f; lightingData.translucentBackLighting += ( - GetBackLighting(surface, lightingData, intensity, p0, -1.0f, 0.0f) + - GetBackLighting(surface, lightingData, intensity, p1, -1.0f, 0.0f) + - GetBackLighting(surface, lightingData, intensity, p2, -1.0f, 0.0f) + - GetBackLighting(surface, lightingData, intensity, p3, -1.0f, 0.0f) + - GetBackLighting(surface, lightingData, intensity, dirToLightCenter, -1.0f, 0.0f) + GetBackLighting(surface, lightingData, intensity, p0, transmissionDistance, attenuationDistance) + + GetBackLighting(surface, lightingData, intensity, p1, transmissionDistance, attenuationDistance) + + GetBackLighting(surface, lightingData, intensity, p2, transmissionDistance, attenuationDistance) + + GetBackLighting(surface, lightingData, intensity, p3, transmissionDistance, attenuationDistance) + + GetBackLighting(surface, lightingData, intensity, dirToLightCenter, transmissionDistance, attenuationDistance) ); // Calculate specular by choosing a single representative point on the light's surface based on the reflection ray From 41e8e5dc89ccf7ce6ca710e07653074c6c64d39b Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Tue, 4 Jan 2022 12:37:20 +0100 Subject: [PATCH 31/39] Add nit empty space Signed-off-by: Santi Paprika --- .../ShaderLib/Atom/Features/PBR/Lights/DirectionalLight.azsli | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 92b90b16ea..81fd8deb74 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 @@ -32,7 +32,7 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData) lightingData.shadowCoords, surface.vertexNormal, debugInfo); - + if (o_transmission_mode == TransmissionMode::ThickObject) { transmissionDistance = DirectionalLightShadow::GetThickness(shadowIndex, lightingData.shadowCoords); From 0bae6d062fe65390d371d059e843ed9ec47caa99 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Tue, 4 Jan 2022 14:58:49 +0100 Subject: [PATCH 32/39] Remove pows and sqrts from attenuation computation + readjust attenuation parameter bounds (https://github.com/o3de/o3de/pull/6428#discussion_r776071926, https://github.com/o3de/o3de/pull/6428#discussion_r776066792) Signed-off-by: Santi Paprika --- .../Common/Assets/Materials/Types/EnhancedPBR.materialtype | 4 ++-- .../Feature/Common/Assets/Materials/Types/Skin.materialtype | 4 ++-- .../Assets/ShaderLib/Atom/Features/PBR/BackLighting.azsli | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype index 77caf42834..f1d8952bb2 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype @@ -1254,9 +1254,9 @@ "displayName": " Distance Attenuation", "description": "Attenuation applied to hide artifacts due to low-res shadow maps (e.g. objects far to the camera when using directional lights or objects far to the light when using sphere/disk lights", "type": "float", - "defaultValue": 4.0, + "defaultValue": 0.5, "min": 0.0, - "softMax": 10.0, + "softMax": 4.0, "connection": { "type": "ShaderInput", "name": "m_distanceAttenuation" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype index d42f62d0ac..59d8be914e 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype @@ -668,9 +668,9 @@ "displayName": " Distance Attenuation", "description": "Attenuation applied to hide artifacts due to low-res shadow maps (e.g. objects far to the camera when using directional lights or objects far to the light when using sphere/disk lights", "type": "float", - "defaultValue": 4.0, + "defaultValue": 0.5, "min": 0.0, - "softMax": 10.0, + "softMax": 4.0, "connection": { "type": "ShaderInput", "name": "m_distanceAttenuation" 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 87dd42fd28..47ec914815 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 @@ -90,7 +90,7 @@ float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightI // result = T(s) * lightIntensity * surface.albedo * E * transmissionParams.w; // Distance attenuation applied to hide artifacts due to low-res projected areas onto shadowmaps (might need some work in the future) - result *= 1.0 / pow(max(1.0, sqrt(attenuationDistance)), lightingData.distanceAttenuation + 1.0); + result /= max(1.0, attenuationDistance * attenuationDistance * lightingData.distanceAttenuation); } break; } From c580499b6fd5e4a7e5c91390677fe9e656adbe17 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Wed, 5 Jan 2022 09:03:35 +0100 Subject: [PATCH 33/39] Fix nit typo in comment Signed-off-by: Santi Paprika --- .../ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli index 5405d2e914..d6fdc012b4 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli @@ -155,7 +155,7 @@ float DirectionalLightShadow::GetThickness(uint lightIndex, float3 shadowCoords[ { const float depthBufferValue = shadowmap.Sample(PassSrg::LinearSampler, float3(shadowCoord.xy, indexOfCascade)).r; - // Normalized thickness (avoid negative values given by to precission or shrinking offsets) + // Normalized thickness (avoid negative values given by precission errors or shrinking offsets) const float deltaDepth = max(shadowCoord.z - depthBufferValue,0.0); const float viewSpaceThickness = ViewSrg::m_directionalLightShadows[lightIndex].m_far_minus_near * deltaDepth; From 8770118b904f73ad27d0a5ceb71c067e4f5ecb9b Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Wed, 5 Jan 2022 09:06:06 +0100 Subject: [PATCH 34/39] Fix nit typo in comment v2 Signed-off-by: Santi Paprika --- .../ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli index d6fdc012b4..f59b3cf5c8 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli @@ -155,7 +155,7 @@ float DirectionalLightShadow::GetThickness(uint lightIndex, float3 shadowCoords[ { const float depthBufferValue = shadowmap.Sample(PassSrg::LinearSampler, float3(shadowCoord.xy, indexOfCascade)).r; - // Normalized thickness (avoid negative values given by precission errors or shrinking offsets) + // Normalized thickness (avoid negative values given by precision errors or shrinking offsets) const float deltaDepth = max(shadowCoord.z - depthBufferValue,0.0); const float viewSpaceThickness = ViewSrg::m_directionalLightShadows[lightIndex].m_far_minus_near * deltaDepth; From d0bb222ce6115f308f920089e31b15fbcca4df8d Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Mon, 10 Jan 2022 18:19:39 +0100 Subject: [PATCH 35/39] Refactor thin transmission factor variable packing and visibility + use thickness to modulate transmission distance Signed-off-by: Santi Paprika --- .../Materials/Types/EnhancedPBR.materialtype | 29 ++++++----------- .../Materials/Types/EnhancedPBR_Common.azsli | 5 +-- .../Types/EnhancedPBR_ForwardPass.azsl | 11 ++++--- .../Types/EnhancedPBR_SubsurfaceState.lua | 31 +++++++++++++------ .../Common/Assets/Materials/Types/Skin.azsl | 11 ++++--- .../Assets/Materials/Types/Skin.materialtype | 29 ++++++----------- .../Assets/Materials/Types/Skin_Common.azsli | 5 +-- .../Atom/Features/PBR/BackLighting.azsli | 10 +++--- .../Surfaces/TransmissionSurfaceData.azsli | 4 ++- ...SubsurfaceTransmissionParameterFunctor.cpp | 10 +++++- .../SubsurfaceTransmissionParameterFunctor.h | 3 ++ ...TransmissionParameterFunctorSourceData.cpp | 12 ++++++- ...ceTransmissionParameterFunctorSourceData.h | 3 ++ 13 files changed, 89 insertions(+), 74 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype index 3fe3569a50..9186efd385 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype @@ -1154,7 +1154,7 @@ { "name": "thickness", "displayName": " Thickness", - "description": "Normalized global thickness, the maxima between this value (multiplied by thickness map if enabled) and thickness from shadow map (if applicable) will be used as final thickness of pixel", + "description": "In thick transmission mode: Normalized global thickness, the maxima between this value (multiplied by thickness map if enabled) and thickness from shadow map (if applicable) will be used as final thickness of pixel\n\nIn thin transmission mode: This value modulates the distance traversed by light inside an object.", "type": "float", "defaultValue": 0.5, "min": 0.0, @@ -1230,24 +1230,16 @@ "type": "float", "defaultValue": 0.005, "min": 0.0, - "softMax": 0.05, - "connection": { - "type": "ShaderInput", - "name": "m_shrinkFactor" - } + "softMax": 0.05 }, { - "name": "transmissionAngleBias", + "name": "transmissionNdLBias", "displayName": " Angle Bias", "description": "cosine of angle to extend below (N . L = 0) in scattering through thin objects", "type": "float", "defaultValue": 0.1, "min": -1.0, - "softMax": 1.0, - "connection": { - "type": "ShaderInput", - "name": "m_transmissionNdLBias" - } + "softMax": 1.0 }, { "name": "distanceAttenuation", @@ -1256,20 +1248,16 @@ "type": "float", "defaultValue": 0.5, "min": 0.0, - "softMax": 4.0, - "connection": { - "type": "ShaderInput", - "name": "m_distanceAttenuation" - } + "softMax": 4.0 }, { "name": "transmissionScale", "displayName": " Scale", "description": "Strength of transmission", "type": "float", - "defaultValue": 0.01, + "defaultValue": 1.0, "min": 0.0, - "softMax": 1.0 + "softMax": 5.0 } ], "detailLayerGroup": [ @@ -1594,6 +1582,9 @@ "power": "subsurfaceScattering.transmissionPower", "distortion": "subsurfaceScattering.transmissionDistortion", "attenuation": "subsurfaceScattering.transmissionAttenuation", + "shrinkFactor": "subsurfaceScattering.shrinkFactor", + "transmissionNdLBias": "subsurfaceScattering.transmissionNdLBias", + "distanceAttenuation": "subsurfaceScattering.distanceAttenuation", "tintColor": "subsurfaceScattering.transmissionTint", "thickness": "subsurfaceScattering.thickness", "enabled": "subsurfaceScattering.enableSubsurfaceScattering", diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Common.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Common.azsli index c15b49dc7d..786b0db4d7 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Common.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Common.azsli @@ -93,16 +93,13 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial // Elements of m_transmissionParams: // Thick object mode: (attenuation coefficient, power, distortion, scale) - // Thin object mode: (float3 scatter distance, scale) + // Thin object mode: (shrinkFactor, transmissionNdLBias, distanceAttenuation, scale) float4 m_transmissionParams; // (float3 TintColor, thickness) float4 m_transmissionTintThickness; Texture2D m_transmissionThicknessMap; uint m_transmissionThicknessMapUvIndex; - float m_shrinkFactor; - float m_transmissionNdLBias; - float m_distanceAttenuation; } // Callback function for ParallaxMapping.azsli diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl index 5e02da679e..600617aa6f 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl @@ -243,6 +243,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float surface.transmission.tint = transmissionTintThickness.rgb; surface.transmission.thickness = transmissionTintThickness.w; surface.transmission.transmissionParams = MaterialSrg::m_transmissionParams; + surface.transmission.scatterDistance = MaterialSrg::m_scatterDistance; // ------- Anisotropy ------- @@ -277,14 +278,14 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // ------- Thin Object Light Transmission ------- - // Angle offset for subsurface scattering through thin objects - lightingData.transmissionNdLBias = MaterialSrg::m_transmissionNdLBias; - // Shrink (absolute) offset towards the normal opposite direction to ensure correct shadow map projection - lightingData.shrinkFactor = MaterialSrg::m_shrinkFactor; + lightingData.shrinkFactor = surface.transmission.transmissionParams.x; + + // Angle offset for subsurface scattering through thin objects + lightingData.transmissionNdLBias = surface.transmission.transmissionParams.y; // Attenuation applied to hide artifacts due to low-res shadow maps - lightingData.distanceAttenuation = MaterialSrg::m_distanceAttenuation; + lightingData.distanceAttenuation = surface.transmission.transmissionParams.z; // ------- Clearcoat ------- diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_SubsurfaceState.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_SubsurfaceState.lua index e705d7867a..1f1979e3a9 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_SubsurfaceState.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_SubsurfaceState.lua @@ -92,23 +92,34 @@ function ProcessEditor(context) -- Update visibility for transmission... - local transmissionEnabled = TransmissionMode_None ~= context:GetMaterialPropertyValue_enum("subsurfaceScattering.transmissionMode") - - local commonTrasmissionVisibility - if(transmissionEnabled) then + local thickTransmissionEnabled = TransmissionMode_ThickObject == context:GetMaterialPropertyValue_enum("subsurfaceScattering.transmissionMode") + local thinTransmissionEnabled = TransmissionMode_ThinObject == context:GetMaterialPropertyValue_enum("subsurfaceScattering.transmissionMode") + + local commonTrasmissionVisibility = MaterialPropertyVisibility_Hidden + local thickTransmissionVisibility = MaterialPropertyVisibility_Hidden + local thinTransmissionVisibility = MaterialPropertyVisibility_Hidden + if (thickTransmissionEnabled or thinTransmissionEnabled) then commonTrasmissionVisibility = MaterialPropertyVisibility_Enabled - else - commonTrasmissionVisibility = MaterialPropertyVisibility_Hidden + + if(thickTransmissionEnabled) then + thickTransmissionVisibility = MaterialPropertyVisibility_Enabled + else -- thin transmission enabled + thinTransmissionVisibility = MaterialPropertyVisibility_Enabled + end end context:SetMaterialPropertyVisibility("subsurfaceScattering.thickness", commonTrasmissionVisibility) context:SetMaterialPropertyVisibility("subsurfaceScattering.thicknessMap", commonTrasmissionVisibility) context:SetMaterialPropertyVisibility("subsurfaceScattering.transmissionTint", commonTrasmissionVisibility) - context:SetMaterialPropertyVisibility("subsurfaceScattering.transmissionPower", commonTrasmissionVisibility) - context:SetMaterialPropertyVisibility("subsurfaceScattering.transmissionDistortion", commonTrasmissionVisibility) - context:SetMaterialPropertyVisibility("subsurfaceScattering.transmissionAttenuation", commonTrasmissionVisibility) + context:SetMaterialPropertyVisibility("subsurfaceScattering.transmissionPower", thickTransmissionVisibility) + context:SetMaterialPropertyVisibility("subsurfaceScattering.transmissionDistortion", thickTransmissionVisibility) + context:SetMaterialPropertyVisibility("subsurfaceScattering.transmissionAttenuation", thickTransmissionVisibility) + context:SetMaterialPropertyVisibility("subsurfaceScattering.shrinkFactor", thinTransmissionVisibility) + context:SetMaterialPropertyVisibility("subsurfaceScattering.transmissionNdLBias", thinTransmissionVisibility) + context:SetMaterialPropertyVisibility("subsurfaceScattering.distanceAttenuation", thinTransmissionVisibility) context:SetMaterialPropertyVisibility("subsurfaceScattering.transmissionScale", commonTrasmissionVisibility) - UpdateTextureDependentPropertyVisibility(context, transmissionEnabled, "subsurfaceScattering.thicknessMap", "subsurfaceScattering.useThicknessMap", "subsurfaceScattering.thicknessMapUv") + + UpdateTextureDependentPropertyVisibility(context, thickTransmissionEnabled or thinTransmissionEnabled, "subsurfaceScattering.thicknessMap", "subsurfaceScattering.useThicknessMap", "subsurfaceScattering.thicknessMapUv") end diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl index faa16b205a..7ec26d8342 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl @@ -325,6 +325,7 @@ PbrLightingOutput SkinPS_Common(VSOutput IN) surface.transmission.tint = transmissionTintThickness.rgb; surface.transmission.thickness = transmissionTintThickness.w; surface.transmission.transmissionParams = MaterialSrg::m_transmissionParams; + surface.transmission.scatterDistance = MaterialSrg::m_scatterDistance; // ------- Lighting Data ------- @@ -343,14 +344,14 @@ PbrLightingOutput SkinPS_Common(VSOutput IN) // ------- Thin Object Light Transmission ------- - // Angle offset for subsurface scattering through thin objects - lightingData.transmissionNdLBias = MaterialSrg::m_transmissionNdLBias; - // Shrink (absolute) offset towards the normal opposite direction to ensure correct shadow map projection - lightingData.shrinkFactor = MaterialSrg::m_shrinkFactor; + lightingData.shrinkFactor = surface.transmission.transmissionParams.x; + + // Angle offset for subsurface scattering through thin objects + lightingData.transmissionNdLBias = surface.transmission.transmissionParams.y; // Attenuation applied to hide artifacts due to low-res shadow maps - lightingData.distanceAttenuation = MaterialSrg::m_distanceAttenuation; + lightingData.distanceAttenuation = surface.transmission.transmissionParams.z; // ------- Occlusion ------- diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype index baa48a5c44..13d2a09a2f 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype @@ -568,7 +568,7 @@ { "name": "thickness", "displayName": " Thickness", - "description": "Normalized global thickness, the maxima between this value (multiplied by thickness map if enabled) and thickness from shadow map (if applicable) will be used as final thickness of pixel", + "description": "In thick transmission mode: Normalized global thickness, the maxima between this value (multiplied by thickness map if enabled) and thickness from shadow map (if applicable) will be used as final thickness of pixel\n\nIn thin transmission mode: This value modulates the distance traversed by light inside an object.", "type": "float", "defaultValue": 0.5, "min": 0.0, @@ -644,24 +644,16 @@ "type": "float", "defaultValue": 0.005, "min": 0.0, - "softMax": 0.05, - "connection": { - "type": "ShaderInput", - "name": "m_shrinkFactor" - } + "softMax": 0.05 }, { - "name": "transmissionAngleBias", + "name": "transmissionNdLBias", "displayName": " Angle Bias", "description": "cosine of angle to extend below (N . L = 0) in scattering through thin objects", "type": "float", "defaultValue": 0.1, "min": -1.0, - "softMax": 1.0, - "connection": { - "type": "ShaderInput", - "name": "m_transmissionNdLBias" - } + "softMax": 1.0 }, { "name": "distanceAttenuation", @@ -670,20 +662,16 @@ "type": "float", "defaultValue": 0.5, "min": 0.0, - "softMax": 4.0, - "connection": { - "type": "ShaderInput", - "name": "m_distanceAttenuation" - } + "softMax": 4.0 }, { "name": "transmissionScale", "displayName": " Scale", "description": "Strength of transmission", "type": "float", - "defaultValue": 0.01, + "defaultValue": 1.0, "min": 0.0, - "softMax": 1.0 + "softMax": 5.0 } ], "wrinkleLayers": [ @@ -1050,6 +1038,9 @@ "power": "subsurfaceScattering.transmissionPower", "distortion": "subsurfaceScattering.transmissionDistortion", "attenuation": "subsurfaceScattering.transmissionAttenuation", + "shrinkFactor": "subsurfaceScattering.shrinkFactor", + "transmissionNdLBias": "subsurfaceScattering.transmissionNdLBias", + "distanceAttenuation": "subsurfaceScattering.distanceAttenuation", "tintColor": "subsurfaceScattering.transmissionTint", "thickness": "subsurfaceScattering.thickness", "enabled": "subsurfaceScattering.enableSubsurfaceScattering", diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_Common.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_Common.azsli index 630291c260..cf3bd14d8a 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_Common.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_Common.azsli @@ -64,16 +64,13 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial // Elements of m_transmissionParams: // Thick object mode: (attenuation coefficient, power, distortion, scale) - // Thin object mode: (float3 scatter distance, scale) + // Thin object mode: (shrinkFactor, transmissionNdLBias, distanceAttenuation, scale) float4 m_transmissionParams; // (float3 TintColor, thickness) float4 m_transmissionTintThickness; Texture2D m_transmissionThicknessMap; uint m_transmissionThicknessMapUvIndex; - float m_shrinkFactor; - float m_transmissionNdLBias; - float m_distanceAttenuation; Texture2D m_wrinkle_baseColor_texture1; Texture2D m_wrinkle_baseColor_texture2; 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 47ec914815..863315c28c 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 @@ -75,19 +75,19 @@ float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightI // Increase angle of influence (angle(N,L) -> angle(N,L) + acos(transmissionNdLBias)) to smooth transition regions float3 E = surface.albedo * saturate(lightingData.transmissionNdLBias + dot(-surface.normal, dirToLight)); - // Transmission distance modulated by hardcoded constant C (could be exposed as a weight of scattering distance for transmission) - const float C = 100.0f; - float s = transmissionDistance * C; + // Transmission distance modulated by hardcoded constant C and the thickness exposed parameter (in this case modulating the distance traversed by the light inside the object) + const float C = 300.0f; + float s = transmissionDistance * C * surface.transmission.thickness; // Use scattering color to weight thin object transmission color - const float3 invScattering = rcp(transmissionParams.xyz); + const float3 invScattering = rcp(max(surface.transmission.scatterDistance, float(0.00001))); // Albedo at front (surface point) is used to approximate irradiance at the back of the object // See observation 4 in [Jimenez J. et al, 2010] result = TransmissionKernel(s, invScattering) * lightIntensity * E * transmissionParams.w; // Alternative specific to skin translucency - // result = T(s) * lightIntensity * surface.albedo * E * transmissionParams.w; + // result = T(s) * lightIntensity * E * transmissionParams.w; // Distance attenuation applied to hide artifacts due to low-res projected areas onto shadowmaps (might need some work in the future) result /= max(1.0, attenuationDistance * attenuationDistance * lightingData.distanceAttenuation); diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/TransmissionSurfaceData.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/TransmissionSurfaceData.azsli index 9b575de3ec..38916199b9 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/TransmissionSurfaceData.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/TransmissionSurfaceData.azsli @@ -12,7 +12,8 @@ class TransmissionSurfaceData { float3 tint; float thickness; //!< pre baked local thickness, used for transmission - float4 transmissionParams; //!< parameters: thick mode->(attenuation coefficient, power, distortion, scale), thin mode: (float3 scatter distance, scale) + float4 transmissionParams; //!< parameters: thick mode->(attenuation coefficient, power, distortion, scale), thin mode: (shrinkFactor, transmissionNdLBias, distanceAttenuation, scale) + float3 scatterDistance; //!< scatter distance (same as in MaterialSrg) > void InitializeToZero(); }; @@ -22,4 +23,5 @@ void TransmissionSurfaceData::InitializeToZero() tint = float3(0.0f, 0.0f, 0.0f); thickness = 0.0f; transmissionParams = float4(0.0f, 0.0f, 0.0f, 0.0f); + scatterDistance = float3(0.0f, 0.0f, 0.0f); } diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/SubsurfaceTransmissionParameterFunctor.cpp b/Gems/Atom/Feature/Common/Code/Source/Material/SubsurfaceTransmissionParameterFunctor.cpp index 8c42160fff..b5d38e25fc 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Material/SubsurfaceTransmissionParameterFunctor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Material/SubsurfaceTransmissionParameterFunctor.cpp @@ -26,6 +26,9 @@ namespace AZ ->Field("m_power", &SubsurfaceTransmissionParameterFunctor::m_power) ->Field("m_distortion", &SubsurfaceTransmissionParameterFunctor::m_distortion) ->Field("m_attenuation", &SubsurfaceTransmissionParameterFunctor::m_attenuation) + ->Field("m_shrinkFactor", &SubsurfaceTransmissionParameterFunctor::m_shrinkFactor) + ->Field("m_transmissionNdLBias", &SubsurfaceTransmissionParameterFunctor::m_transmissionNdLBias) + ->Field("m_distanceAttenuation", &SubsurfaceTransmissionParameterFunctor::m_distanceAttenuation) ->Field("m_tintColor", &SubsurfaceTransmissionParameterFunctor::m_tintColor) ->Field("m_thickness", &SubsurfaceTransmissionParameterFunctor::m_thickness) ->Field("m_enabled", &SubsurfaceTransmissionParameterFunctor::m_enabled) @@ -50,6 +53,9 @@ namespace AZ auto power = context.GetMaterialPropertyValue(m_power); auto distortion = context.GetMaterialPropertyValue(m_distortion); auto attenuation = context.GetMaterialPropertyValue(m_attenuation); + auto shrinkFactor = context.GetMaterialPropertyValue(m_shrinkFactor); + auto transmissionNdLBias = context.GetMaterialPropertyValue(m_transmissionNdLBias); + auto distanceAttenuation = context.GetMaterialPropertyValue(m_distanceAttenuation); auto tintColor = context.GetMaterialPropertyValue(m_tintColor); auto thickness = context.GetMaterialPropertyValue(m_thickness); auto scatterDistanceColor = context.GetMaterialPropertyValue(m_scatterDistanceColor); @@ -67,7 +73,9 @@ namespace AZ } else { - transmissionParams.Set(scatterDistance); + transmissionParams.SetX(shrinkFactor); + transmissionParams.SetY(transmissionNdLBias); + transmissionParams.SetZ(distanceAttenuation); transmissionParams.SetW(scale); } diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/SubsurfaceTransmissionParameterFunctor.h b/Gems/Atom/Feature/Common/Code/Source/Material/SubsurfaceTransmissionParameterFunctor.h index e412687947..17096e71a5 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Material/SubsurfaceTransmissionParameterFunctor.h +++ b/Gems/Atom/Feature/Common/Code/Source/Material/SubsurfaceTransmissionParameterFunctor.h @@ -37,6 +37,9 @@ namespace AZ RPI::MaterialPropertyIndex m_power; RPI::MaterialPropertyIndex m_distortion; RPI::MaterialPropertyIndex m_attenuation; + RPI::MaterialPropertyIndex m_shrinkFactor; + RPI::MaterialPropertyIndex m_transmissionNdLBias; + RPI::MaterialPropertyIndex m_distanceAttenuation; RPI::MaterialPropertyIndex m_tintColor; RPI::MaterialPropertyIndex m_thickness; RPI::MaterialPropertyIndex m_enabled; diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/SubsurfaceTransmissionParameterFunctorSourceData.cpp b/Gems/Atom/Feature/Common/Code/Source/Material/SubsurfaceTransmissionParameterFunctorSourceData.cpp index a8ba40fb7f..140dfe8c6b 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Material/SubsurfaceTransmissionParameterFunctorSourceData.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Material/SubsurfaceTransmissionParameterFunctorSourceData.cpp @@ -25,6 +25,9 @@ namespace AZ ->Field("power", &SubsurfaceTransmissionParameterFunctorSourceData::m_power) ->Field("distortion", &SubsurfaceTransmissionParameterFunctorSourceData::m_distortion) ->Field("attenuation", &SubsurfaceTransmissionParameterFunctorSourceData::m_attenuation) + ->Field("shrinkFactor", &SubsurfaceTransmissionParameterFunctorSourceData::m_shrinkFactor) + ->Field("transmissionNdLBias", &SubsurfaceTransmissionParameterFunctorSourceData::m_transmissionNdLBias) + ->Field("distanceAttenuation", &SubsurfaceTransmissionParameterFunctorSourceData::m_distanceAttenuation) ->Field("tintColor", &SubsurfaceTransmissionParameterFunctorSourceData::m_tintColor) ->Field("thickness", &SubsurfaceTransmissionParameterFunctorSourceData::m_thickness) ->Field("enabled", &SubsurfaceTransmissionParameterFunctorSourceData::m_enabled) @@ -48,6 +51,9 @@ namespace AZ functor->m_power = context.FindMaterialPropertyIndex(Name{ m_power }); functor->m_distortion = context.FindMaterialPropertyIndex(Name{ m_distortion }); functor->m_attenuation = context.FindMaterialPropertyIndex(Name{ m_attenuation }); + functor->m_shrinkFactor = context.FindMaterialPropertyIndex(Name{ m_shrinkFactor }); + functor->m_transmissionNdLBias = context.FindMaterialPropertyIndex(Name{ m_transmissionNdLBias }); + functor->m_distanceAttenuation = context.FindMaterialPropertyIndex(Name{ m_distanceAttenuation }); functor->m_tintColor = context.FindMaterialPropertyIndex(Name{ m_tintColor }); functor->m_thickness = context.FindMaterialPropertyIndex(Name{ m_thickness }); functor->m_enabled = context.FindMaterialPropertyIndex(Name{ m_enabled }); @@ -56,7 +62,8 @@ namespace AZ if (functor->m_mode.IsNull() || functor->m_scale.IsNull() || functor->m_power.IsNull() || functor->m_distortion.IsNull() || functor->m_tintColor.IsNull() || functor->m_thickness.IsNull() || functor->m_enabled.IsNull() || functor->m_attenuation.IsNull() || functor->m_scatterDistanceColor.IsNull() || - functor->m_scatterDistanceIntensity.IsNull()) + functor->m_scatterDistanceIntensity.IsNull() || functor->m_shrinkFactor.IsNull() || functor->m_transmissionNdLBias.IsNull() || + functor->m_distanceAttenuation.IsNull()) { return Failure(); } @@ -66,6 +73,9 @@ namespace AZ AddMaterialPropertyDependency(functor, functor->m_power); AddMaterialPropertyDependency(functor, functor->m_distortion); AddMaterialPropertyDependency(functor, functor->m_attenuation); + AddMaterialPropertyDependency(functor, functor->m_shrinkFactor); + AddMaterialPropertyDependency(functor, functor->m_transmissionNdLBias); + AddMaterialPropertyDependency(functor, functor->m_distanceAttenuation); AddMaterialPropertyDependency(functor, functor->m_tintColor); AddMaterialPropertyDependency(functor, functor->m_thickness); AddMaterialPropertyDependency(functor, functor->m_enabled); diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/SubsurfaceTransmissionParameterFunctorSourceData.h b/Gems/Atom/Feature/Common/Code/Source/Material/SubsurfaceTransmissionParameterFunctorSourceData.h index 9d074551c3..8d058243fa 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Material/SubsurfaceTransmissionParameterFunctorSourceData.h +++ b/Gems/Atom/Feature/Common/Code/Source/Material/SubsurfaceTransmissionParameterFunctorSourceData.h @@ -36,6 +36,9 @@ namespace AZ AZStd::string m_power; //!< material property for thick transmission power AZStd::string m_distortion; //!< material property for thick transmission distortion towards surface normal AZStd::string m_attenuation; //!< material property for thick transmission volume absorption + AZStd::string m_shrinkFactor; //!< material property for thin transmission position shrink factor towards surface normal + AZStd::string m_transmissionNdLBias; //!< material property for thin transmission bias of the NdL value + AZStd::string m_distanceAttenuation; //!< material property for thin transmission attenuation with distance AZStd::string m_tintColor; //!< material property for transmission tint AZStd::string m_thickness; //!< material property for normalized object thickness AZStd::string m_enabled; //!< material property for subsurface scattering feature switch (enabled or disabled) From 1087e45ce3f8cb13669fd049957c6b52c9d653e9 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Wed, 2 Feb 2022 18:42:29 +0100 Subject: [PATCH 36/39] Fix typo (https://github.com/o3de/o3de/pull/6428#discussion_r797667772) Signed-off-by: Santi Paprika --- .../Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli index 5baacf4756..e6bdc13293 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli @@ -275,7 +275,7 @@ float ProjectedShadow::GetThickness() /*LOD=*/0 ).r; - // Denormalized thickness (avoid negative values given by to precission or shrinking offsets) + // Denormalized thickness (avoid negative values given by precision errors or shrinking offsets) const float viewSpaceThickness = max(UnprojectDepth(m_shadowIndex, depthValue) - UnprojectDepth(m_shadowIndex, m_shadowPosition.z), 0.0); return viewSpaceThickness; } From 9c60bd008cbda990a237a54eaf71244cca141638 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Wed, 2 Feb 2022 18:47:11 +0100 Subject: [PATCH 37/39] Enable human skin profile via preprocessor define (https://github.com/o3de/o3de/pull/6428#discussion_r797699927) Signed-off-by: Santi Paprika --- .../Assets/Materials/Types/Skin_Common.azsli | 4 ++++ .../Atom/Features/PBR/BackLighting.azsli | 17 ++++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_Common.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_Common.azsli index cf3bd14d8a..9b3c29e96d 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_Common.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_Common.azsli @@ -22,6 +22,10 @@ #include "MaterialInputs/UvSetCount.azsli" #include "MaterialInputs/DetailMapsInput.azsli" +// Use human skin profile for thin object transmission (if enabled) +// Remove this line to use a custom profile based on the scatter color +#define USE_HUMAN_SKIN_PROFILE + ShaderResourceGroup MaterialSrg : SRG_PerMaterial { // Auto-generate material SRG fields for common inputs 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 863315c28c..82a3038054 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 @@ -23,7 +23,7 @@ float3 TransmissionKernel(float t, float3 s) return 0.25 * (1.0 / exp(exponent) + 3.0 / exp(exponent / 3.0)); } -// [specific profile for SKIN (not used ATM, replaced by TransmissionKernel)] +// [specific profile for human skin] // Analytical integation (approximation) of diffusion profile over radius, could be precomputed in a LUT // From d'Eon and Luebke (https://developer.nvidia.com/gpugems/gpugems3/part-iii-rendering/chapter-14-advanced-techniques-realistic-real-time-skin, section 14.4.7) float3 T(float s) @@ -72,6 +72,8 @@ float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightI } // Irradiance arround surface point. + // Albedo at front (surface point) is used to approximate irradiance at the back of the object + // See observation 4 in [Jimenez J. et al, 2010] // Increase angle of influence (angle(N,L) -> angle(N,L) + acos(transmissionNdLBias)) to smooth transition regions float3 E = surface.albedo * saturate(lightingData.transmissionNdLBias + dot(-surface.normal, dirToLight)); @@ -82,13 +84,14 @@ float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightI // Use scattering color to weight thin object transmission color const float3 invScattering = rcp(max(surface.transmission.scatterDistance, float(0.00001))); - // Albedo at front (surface point) is used to approximate irradiance at the back of the object - // See observation 4 in [Jimenez J. et al, 2010] +#ifndef USE_HUMAN_SKIN_PROFILE + // Generic profile based on scatter color result = TransmissionKernel(s, invScattering) * lightIntensity * E * transmissionParams.w; - - // Alternative specific to skin translucency - // result = T(s) * lightIntensity * E * transmissionParams.w; - +#else // USE_HUMAN_SKIN_PROFILE + // Profile specific to human skin + result = T(s) * lightIntensity * E * transmissionParams.w; +#endif + // Distance attenuation applied to hide artifacts due to low-res projected areas onto shadowmaps (might need some work in the future) result /= max(1.0, attenuationDistance * attenuationDistance * lightingData.distanceAttenuation); } From 024933d4a177997467dc97271610dcb5f450363b Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Fri, 4 Feb 2022 12:15:45 +0100 Subject: [PATCH 38/39] Improve descriptions and comments (https://github.com/o3de/o3de/pull/6428#discussion_r799207891, https://github.com/o3de/o3de/pull/6428#discussion_r799213620) Signed-off-by: Santi Paprika --- .../Common/Assets/Materials/Types/EnhancedPBR.materialtype | 2 +- .../Feature/Common/Assets/Materials/Types/Skin.materialtype | 2 +- .../Assets/ShaderLib/Atom/Features/PBR/BackLighting.azsli | 5 ++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype index 9186efd385..846c3d0f34 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype @@ -1244,7 +1244,7 @@ { "name": "distanceAttenuation", "displayName": " Distance Attenuation", - "description": "Attenuation applied to hide artifacts due to low-res shadow maps (e.g. objects far to the camera when using directional lights or objects far to the light when using sphere/disk lights", + "description": "Attenuation of the transmission effect, used to hide artifacts due to low-res shadow maps\nFor directional lights: attenuation proportional to the distance from the object to the camera.\nFor other light sources: attenuation proportional to the distance from the object to the light source.", "type": "float", "defaultValue": 0.5, "min": 0.0, diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype index 13d2a09a2f..1edbd7e505 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype @@ -658,7 +658,7 @@ { "name": "distanceAttenuation", "displayName": " Distance Attenuation", - "description": "Attenuation applied to hide artifacts due to low-res shadow maps (e.g. objects far to the camera when using directional lights or objects far to the light when using sphere/disk lights", + "description": "Attenuation of the transmission effect, used to hide artifacts due to low-res shadow maps\nFor directional lights: attenuation proportional to the distance from the object to the camera.\nFor other light sources: attenuation proportional to the distance from the object to the light source.", "type": "float", "defaultValue": 0.5, "min": 0.0, 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 82a3038054..e43f2729b7 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 @@ -72,9 +72,8 @@ float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightI } // Irradiance arround surface point. - // Albedo at front (surface point) is used to approximate irradiance at the back of the object - // See observation 4 in [Jimenez J. et al, 2010] - // Increase angle of influence (angle(N,L) -> angle(N,L) + acos(transmissionNdLBias)) to smooth transition regions + // Albedo at front (surface point) is used to approximate irradiance at the back of the object (observation 4 in [Jimenez J. et al, 2010]) + // Increase angle of influence to smooth transition regions float3 E = surface.albedo * saturate(lightingData.transmissionNdLBias + dot(-surface.normal, dirToLight)); // Transmission distance modulated by hardcoded constant C and the thickness exposed parameter (in this case modulating the distance traversed by the light inside the object) From c173fd9357dfa3d8ef22dd3efd81f505773727d5 Mon Sep 17 00:00:00 2001 From: Santi Paprika Date: Fri, 4 Feb 2022 17:34:39 +0100 Subject: [PATCH 39/39] Remove division by constant in distance attenuation for DirectionalLight (https://github.com/o3de/o3de/pull/6428#discussion_r799216516) Signed-off-by: Santi Paprika --- .../ShaderLib/Atom/Features/PBR/Lights/DirectionalLight.azsli | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 25f0545037..03c48b6232 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 @@ -80,7 +80,7 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData) } // Transmission contribution - lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight, currentTransmissionDistance, camToSurfDist/2.0); + lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight, currentTransmissionDistance, camToSurfDist); lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight) * currentLitRatio; lightingData.specularLighting += GetSpecularLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight) * currentLitRatio;