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 daed3a2921..3b8379e7fa 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 @@ -14,6 +14,7 @@ #include #include "BicubicPcfFilters.azsli" #include "Shadow.azsli" +#include "NormalOffsetShadows.azsli" // ProjectedShadow calculates shadowed area projected from a light. class ProjectedShadow @@ -123,6 +124,7 @@ float ProjectedShadow::GetThickness(uint shadowIndex, float3 worldPosition) ProjectedShadow shadow; shadow.m_worldPosition = worldPosition; + shadow.m_normalVector = 0; // The normal vector is used to reduce acne, this is not an issue when using the shadowmap to determine thickness. shadow.m_shadowIndex = shadowIndex; shadow.SetShadowPosition(); return shadow.GetThickness(); @@ -317,8 +319,13 @@ bool ProjectedShadow::IsShadowed(float3 shadowPosition) void ProjectedShadow::SetShadowPosition() { + const float normalBias = ViewSrg::m_projectedShadows[m_shadowIndex].m_normalShadowBias; + const float shadowmapSize = ViewSrg::m_projectedFilterParams[m_shadowIndex].m_shadowmapSize; + const float3 shadowOffset = ComputeNormalShadowOffset(normalBias, m_normalVector, shadowmapSize); const float4x4 depthBiasMatrix = ViewSrg::m_projectedShadows[m_shadowIndex].m_depthBiasMatrix; - float4 shadowPositionHomogeneous = mul(depthBiasMatrix, float4(m_worldPosition, 1)); + + float4 shadowPositionHomogeneous = mul(depthBiasMatrix, float4(m_worldPosition + shadowOffset, 1)); + m_shadowPosition = shadowPositionHomogeneous.xyz / shadowPositionHomogeneous.w; m_bias = ViewSrg::m_projectedShadows[m_shadowIndex].m_bias / shadowPositionHomogeneous.w; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h index 5aa2dfb800..98220fae15 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h @@ -86,6 +86,8 @@ namespace AZ virtual void SetShadowsEnabled(LightHandle handle, bool enabled) = 0; //! Sets the shadow bias virtual void SetShadowBias(LightHandle handle, float bias) = 0; + //! Sets the normal shadow bias + virtual void SetNormalShadowBias(LightHandle handle, float bias) = 0; //! Sets the shadowmap size (width and height) of the light. virtual void SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize) = 0; //! Specifies filter method of shadows. diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/PointLightFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/PointLightFeatureProcessorInterface.h index 1a5a776cdf..52b1402b24 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/PointLightFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/PointLightFeatureProcessorInterface.h @@ -74,6 +74,8 @@ namespace AZ virtual void SetFilteringSampleCount(LightHandle handle, uint16_t count) = 0; //! Sets the Esm exponent to use. Higher values produce a steeper falloff in the border areas between light and shadow. virtual void SetEsmExponent(LightHandle handle, float exponent) = 0; + //! Sets the normal shadow bias. Reduces acne by biasing the shadowmap lookup along the geometric normal. + virtual void SetNormalShadowBias(LightHandle handle, float bias) = 0; //! Sets all of the the point data for the provided LightHandle. virtual void SetPointData(LightHandle handle, const PointLightData& data) = 0; }; diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp index acf81ede32..e362ee3afc 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp @@ -313,6 +313,11 @@ namespace AZ SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetShadowBias, bias); } + void DiskLightFeatureProcessor::SetNormalShadowBias(LightHandle handle, float bias) + { + SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetNormalShadowBias, bias); + } + void DiskLightFeatureProcessor::SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize) { SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetShadowmapMaxResolution, shadowmapSize); diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h index 275712f84f..bafddacc65 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h @@ -51,6 +51,7 @@ namespace AZ void SetConeAngles(LightHandle handle, float innerDegrees, float outerDegrees) override; void SetShadowsEnabled(LightHandle handle, bool enabled) override; void SetShadowBias(LightHandle handle, float bias) override; + void SetNormalShadowBias(LightHandle handle, float bias) override; void SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize) override; void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) override; void SetFilteringSampleCount(LightHandle handle, uint16_t count) override; diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.cpp index dcf412c35d..c5d6c3bf78 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.cpp @@ -302,5 +302,10 @@ namespace AZ SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetEsmExponent, esmExponent); } + void PointLightFeatureProcessor::SetNormalShadowBias(LightHandle handle, float bias) + { + SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetNormalShadowBias, bias); + } + } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.h index 54cb0303cc..df97fa0a52 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.h @@ -52,6 +52,7 @@ namespace AZ void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) override; void SetFilteringSampleCount(LightHandle handle, uint16_t count) override; void SetEsmExponent(LightHandle handle, float esmExponent) override; + void SetNormalShadowBias(LightHandle handle, float bias) override; void SetPointData(LightHandle handle, const PointLightData& data) override; const Data::Instance GetLightBuffer() const; diff --git a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp index 70ccaa5702..c0cc93d7e0 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp @@ -155,8 +155,9 @@ namespace AZ::Render { AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetNormalShadowBias()."); - ShadowProperty& shadowProperty = GetShadowPropertyFromShadowId(id); - shadowProperty.m_normalShadowBias = normalShadowBias; + ShadowData& shadowData = m_shadowData.GetElement(id.GetIndex()); + shadowData.m_normalShadowBias = normalShadowBias; + m_deviceBufferNeedsUpdate = true; } void ProjectedShadowFeatureProcessor::SetShadowmapMaxResolution(ShadowId id, ShadowmapSize size) diff --git a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h index 8939f1845d..a892e77b7f 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h @@ -68,7 +68,7 @@ namespace AZ::Render uint32_t m_filteringSampleCount = 0; AZStd::array m_unprojectConstants = { {0, 0} }; float m_bias; - float m_normalShadowBias; + float m_normalShadowBias = 0; float m_esmExponent = 87.0f; float m_padding[3]; }; @@ -79,7 +79,6 @@ namespace AZ::Render ProjectedShadowDescriptor m_desc; RPI::ViewPtr m_shadowmapView; float m_bias = 0.1f; - float m_normalShadowBias = 0.0f; ShadowId m_shadowId; }; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightBus.h index 72c4ef97a8..b9c62e6fe2 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightBus.h @@ -132,6 +132,13 @@ namespace AZ //! Sets the Esm exponent. Higher values produce a steeper falloff between light and shadow. virtual void SetEsmExponent(float exponent) = 0; + //! Reduces acne by biasing the shadowmap lookup along the geometric normal. + //! @return Returns the amount of bias to apply. + virtual float GetNormalShadowBias() const = 0; + + //! Reduces acne by biasing the shadowmap lookup along the geometric normal. + //! @param normalShadowBias Sets the amount of normal shadow bias to apply. + virtual void SetNormalShadowBias(float normalShadowBias) = 0; }; //! The EBus for requests to for setting and getting light component properties. diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h index c76c922385..130e066e1a 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h @@ -57,6 +57,7 @@ namespace AZ // Shadows (only used for supported shapes) bool m_enableShadow = false; float m_bias = 0.1f; + float m_normalShadowBias = 0.0f; ShadowmapSize m_shadowmapMaxSize = ShadowmapSize::Size256; ShadowFilterMethod m_shadowFilterMethod = ShadowFilterMethod::None; uint16_t m_filteringSampleCount = 12; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp index f0418a5024..91f8f1aa36 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp @@ -34,6 +34,7 @@ namespace AZ // Shadows ->Field("Enable Shadow", &AreaLightComponentConfig::m_enableShadow) ->Field("Shadow Bias", &AreaLightComponentConfig::m_bias) + ->Field("Normal Shadow Bias", &AreaLightComponentConfig::m_normalShadowBias) ->Field("Shadowmap Max Size", &AreaLightComponentConfig::m_shadowmapMaxSize) ->Field("Shadow Filter Method", &AreaLightComponentConfig::m_shadowFilterMethod) ->Field("Filtering Sample Count", &AreaLightComponentConfig::m_filteringSampleCount) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp index 36cb2a7f5a..7668477690 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp @@ -70,6 +70,8 @@ namespace AZ::Render ->Event("SetEnableShadow", &AreaLightRequestBus::Events::SetEnableShadow) ->Event("GetShadowBias", &AreaLightRequestBus::Events::GetShadowBias) ->Event("SetShadowBias", &AreaLightRequestBus::Events::SetShadowBias) + ->Event("GetNormalShadowBias", &AreaLightRequestBus::Events::GetNormalShadowBias) + ->Event("SetNormalShadowBias", &AreaLightRequestBus::Events::SetNormalShadowBias) ->Event("GetShadowmapMaxSize", &AreaLightRequestBus::Events::GetShadowmapMaxSize) ->Event("SetShadowmapMaxSize", &AreaLightRequestBus::Events::SetShadowmapMaxSize) ->Event("GetShadowFilterMethod", &AreaLightRequestBus::Events::GetShadowFilterMethod) @@ -91,6 +93,7 @@ namespace AZ::Render ->VirtualProperty("ShadowsEnabled", "GetEnableShadow", "SetEnableShadow") ->VirtualProperty("ShadowBias", "GetShadowBias", "SetShadowBias") + ->VirtualProperty("NormalShadowBias", "GetNormalShadowBias", "SetNormalShadowBias") ->VirtualProperty("ShadowmapMaxSize", "GetShadowmapMaxSize", "SetShadowmapMaxSize") ->VirtualProperty("ShadowFilterMethod", "GetShadowFilterMethod", "SetShadowFilterMethod") ->VirtualProperty("FilteringSampleCount", "GetFilteringSampleCount", "SetFilteringSampleCount") @@ -302,6 +305,7 @@ namespace AZ::Render if (m_configuration.m_enableShadow) { m_lightShapeDelegate->SetShadowBias(m_configuration.m_bias); + m_lightShapeDelegate->SetNormalShadowBias(m_configuration.m_normalShadowBias); m_lightShapeDelegate->SetShadowmapMaxSize(m_configuration.m_shadowmapMaxSize); m_lightShapeDelegate->SetShadowFilterMethod(m_configuration.m_shadowFilterMethod); m_lightShapeDelegate->SetFilteringSampleCount(m_configuration.m_filteringSampleCount); @@ -474,6 +478,20 @@ namespace AZ::Render } } + void AreaLightComponentController::SetNormalShadowBias(float bias) + { + m_configuration.m_normalShadowBias = bias; + if (m_lightShapeDelegate) + { + m_lightShapeDelegate->SetNormalShadowBias(bias); + } + } + + float AreaLightComponentController::GetNormalShadowBias() const + { + return m_configuration.m_normalShadowBias; + } + ShadowmapSize AreaLightComponentController::GetShadowmapMaxSize() const { return m_configuration.m_shadowmapMaxSize; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.h index cc6223e7e5..81299a0372 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.h @@ -86,6 +86,8 @@ namespace AZ void SetFilteringSampleCount(uint32_t count) override; float GetEsmExponent() const override; void SetEsmExponent(float exponent) override; + float GetNormalShadowBias() const override; + void SetNormalShadowBias(float bias) override; void HandleDisplayEntityViewport( const AzFramework::ViewportInfo& viewportInfo, diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp index dfb6cf6946..f060018099 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp @@ -138,6 +138,14 @@ namespace AZ::Render } } + void DiskLightDelegate::SetNormalShadowBias(float bias) + { + if (GetShadowsEnabled() && GetLightHandle().IsValid()) + { + GetFeatureProcessor()->SetNormalShadowBias(GetLightHandle(), bias); + } + } + void DiskLightDelegate::SetShadowmapMaxSize(ShadowmapSize size) { if (GetShadowsEnabled() && GetLightHandle().IsValid()) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.h index 2be782c69c..c19a8d37ae 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.h @@ -46,6 +46,7 @@ namespace AZ void SetShadowFilterMethod(ShadowFilterMethod method) override; void SetFilteringSampleCount(uint32_t count) override; void SetEsmExponent(float exponent) override; + void SetNormalShadowBias(float bias) override; private: diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp index db46434d9a..02c9f77436 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp @@ -136,7 +136,7 @@ namespace AZ ->Attribute(Edit::Attributes::Min, 0.0f) ->Attribute(Edit::Attributes::Max, 100.0f) ->Attribute(Edit::Attributes::SoftMin, 0.0f) - ->Attribute(Edit::Attributes::SoftMax, 2.0f) + ->Attribute(Edit::Attributes::SoftMax, 10.0f) ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::ShadowsDisabled) @@ -171,7 +171,16 @@ namespace AZ ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsEsmDisabled) - ; + ->DataElement( + Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_normalShadowBias, "Normal Shadow Bias\n", + "Reduces acne by biasing the shadowmap lookup along the geometric normal.\n" + "If this is 0, no biasing is applied.") + ->Attribute(Edit::Attributes::Min, 0.f) + ->Attribute(Edit::Attributes::Max, 10.0f) + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) + ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::ShadowsDisabled) + ; } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h index 336c67f55d..8b096b0367 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h @@ -58,7 +58,8 @@ namespace AZ void SetShadowFilterMethod([[maybe_unused]] ShadowFilterMethod method) override {}; void SetFilteringSampleCount([[maybe_unused]] uint32_t count) override {}; void SetEsmExponent([[maybe_unused]] float esmExponent) override{}; - + void SetNormalShadowBias([[maybe_unused]] float bias) override{}; + protected: void InitBase(EntityId entityId); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h index 9bb8188898..40ffaf392d 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h @@ -79,6 +79,8 @@ namespace AZ virtual void SetFilteringSampleCount(uint32_t count) = 0; //! Sets the Esm exponent to use. Higher values produce a steeper falloff between light and shadow. virtual void SetEsmExponent(float exponent) = 0; + //! Sets the normal bias. Reduces acne by biasing the shadowmap lookup along the geometric normal. + virtual void SetNormalShadowBias(float bias) = 0; }; } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp index 661b0c6b25..f2e1f41008 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp @@ -107,4 +107,13 @@ namespace AZ::Render GetFeatureProcessor()->SetEsmExponent(GetLightHandle(), esmExponent); } } + + void SphereLightDelegate::SetNormalShadowBias(float bias) + { + if (GetShadowsEnabled() && GetLightHandle().IsValid()) + { + GetFeatureProcessor()->SetNormalShadowBias(GetLightHandle(), bias); + } + } + } // namespace AZ::Render diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.h index 8bdee2442a..bad00e597c 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.h @@ -36,6 +36,7 @@ namespace AZ void SetShadowFilterMethod(ShadowFilterMethod method) override; void SetFilteringSampleCount(uint32_t count) override; void SetEsmExponent(float esmExponent) override; + void SetNormalShadowBias(float bias) override; private: