From 959ec14df63280f116297c1444ad37c69b1e54f9 Mon Sep 17 00:00:00 2001 From: mriegger Date: Thu, 10 Jun 2021 15:29:38 -0700 Subject: [PATCH] Exposing esm exponent --- .../Features/Shadow/ProjectedShadow.azsli | 16 ++++++++----- .../CoreLights/ViewSrg.azsli | 2 ++ .../Shaders/Shadow/DepthExponentiation.azsl | 16 ++++++++----- .../DiskLightFeatureProcessorInterface.h | 5 +++- .../PointLightFeatureProcessorInterface.h | 2 ++ .../CoreLights/DiskLightFeatureProcessor.cpp | 5 ++++ .../CoreLights/DiskLightFeatureProcessor.h | 1 + .../CoreLights/PointLightFeatureProcessor.cpp | 5 ++++ .../CoreLights/PointLightFeatureProcessor.h | 1 + .../ProjectedShadowFeatureProcessor.cpp | 7 ++++++ .../Shadows/ProjectedShadowFeatureProcessor.h | 3 +++ .../CommonFeatures/CoreLights/AreaLightBus.h | 7 ++++++ .../CoreLights/AreaLightComponentConfig.h | 3 +++ .../CoreLights/AreaLightComponentConfig.cpp | 11 +++++++-- .../AreaLightComponentController.cpp | 24 ++++++++++++++++--- .../CoreLights/AreaLightComponentController.h | 2 ++ .../Source/CoreLights/DiskLightDelegate.cpp | 8 +++++++ .../Source/CoreLights/DiskLightDelegate.h | 1 + .../CoreLights/EditorAreaLightComponent.cpp | 16 +++++++++++-- .../Source/CoreLights/LightDelegateBase.h | 1 + .../CoreLights/LightDelegateInterface.h | 2 ++ .../Source/CoreLights/SphereLightDelegate.cpp | 9 +++++++ .../Source/CoreLights/SphereLightDelegate.h | 1 + 23 files changed, 128 insertions(+), 20 deletions(-) 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 e4cb87802a..8668ac10d8 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 @@ -226,7 +226,7 @@ float ProjectedShadow::GetVisibilityEsm() } const float invAtlasSize = ViewSrg::m_invShadowmapAtlasSize; - const Texture2DArray expShadowmap = PassSrg::m_projectedExponentialShadowmap; + const Texture2DArray shadowmap = PassSrg::m_projectedExponentialShadowmap; if (m_shadowPosition.x >= 0 && m_shadowPosition.x * size < size - PixelMargin && m_shadowPosition.y >= 0 && m_shadowPosition.y * size < size - PixelMargin) @@ -243,10 +243,12 @@ float ProjectedShadow::GetVisibilityEsm() const float depth = PerspectiveDepthToLinear( m_shadowPosition.z, coefficients); - const float expDepthInShadowmap = expShadowmap.Sample( + const float occluder = shadowmap.Sample( PassSrg::LinearSampler, float3(atlasPosition.xy * invAtlasSize, atlasPosition.z)).r; - const float ratio = exp(-EsmExponentialShift * depth) * expDepthInShadowmap; + + const float exponent = -ViewSrg::m_projectedShadows[m_shadowIndex].m_esmExponent * (depth - occluder); + const float ratio = exp(exponent); // pow() mitigates light bleeding to shadows from near shadow casters. return saturate( pow(ratio, 8) ); } @@ -265,7 +267,7 @@ float ProjectedShadow::GetVisibilityEsmPcf() } const float invAtlasSize = ViewSrg::m_invShadowmapAtlasSize; - const Texture2DArray expShadowmap = PassSrg::m_projectedExponentialShadowmap; + const Texture2DArray shadowmap = PassSrg::m_projectedExponentialShadowmap; if (m_shadowPosition.x >= 0 && m_shadowPosition.x * size < size - PixelMargin && m_shadowPosition.y >= 0 && m_shadowPosition.y * size < size - PixelMargin) @@ -282,10 +284,12 @@ float ProjectedShadow::GetVisibilityEsmPcf() const float depth = PerspectiveDepthToLinear( m_shadowPosition.z, coefficients); - const float expDepthInShadowmap = expShadowmap.Sample( + const float occluder = shadowmap.Sample( PassSrg::LinearSampler, float3(atlasPosition.xy * invAtlasSize, atlasPosition.z)).r; - float ratio = exp(-EsmExponentialShift * depth) * expDepthInShadowmap; + + const float exponent = -ViewSrg::m_projectedShadows[m_shadowIndex].m_esmExponent * (depth - occluder); + float ratio = exp(exponent); static const float pcfFallbackThreshold = 1.04; if (ratio > pcfFallbackThreshold) diff --git a/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/CoreLights/ViewSrg.azsli b/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/CoreLights/ViewSrg.azsli index 7a51d4c629..37b021e148 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/CoreLights/ViewSrg.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/CoreLights/ViewSrg.azsli @@ -92,6 +92,8 @@ partial ShaderResourceGroup ViewSrg uint m_filteringSampleCount; float2 m_unprojectConstants; float m_bias; + float m_esmExponent; + float3 m_padding; }; StructuredBuffer m_projectedShadows; diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/DepthExponentiation.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/DepthExponentiation.azsl index bea63c6b0b..c212718bf5 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/DepthExponentiation.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/DepthExponentiation.azsl @@ -69,8 +69,15 @@ void MainCS(uint3 dispatchId: SV_DispatchThreadID) // So this converts it to "depth" to emphasize the difference // within the frustum. depth = (depthInClip - distanceMin) / (1. - distanceMin); - } + + // Todo: Expose Esm exponent slider for directional lights + // This would remove the exp calculation below, collapsing it into a subtraction in DirectionalLightShadow.azsli + // ATOM-15775 + const float outValue = exp(EsmExponentialShift * depth); + PassSrg::m_outputShadowmap[dispatchId].r = outValue; break; + + } case ShadowmapLightType::Spot: { const float3 coefficients = float3( @@ -84,12 +91,9 @@ void MainCS(uint3 dispatchId: SV_DispatchThreadID) // and it often causes light bleeding with ESM. // So this converts it to a linear depth to emphasize the // difference like a orthogonal depth. - depth = PerspectiveDepthToLinear(depthInClip, coefficients); - } + PassSrg::m_outputShadowmap[dispatchId].r = PerspectiveDepthToLinear(depthInClip, coefficients); break; + } } - - const float outValue = exp(EsmExponentialShift * depth); - PassSrg::m_outputShadowmap[dispatchId].r = outValue; } 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 ce911fecf7..f777cbbc27 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 @@ -100,10 +100,13 @@ namespace AZ virtual void SetFilteringSampleCount(LightHandle handle, uint16_t count) = 0; //! Sets the shadowmap Pcf (percentage closer filtering) method. virtual void SetPcfMethod(LightHandle handle, PcfMethod method) = 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 all of the the disk data for the provided LightHandle. virtual void SetDiskData(LightHandle handle, const DiskLightData& data) = 0; - + + }; } // namespace Render } // namespace AZ 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 30d88cb839..c781030220 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 @@ -82,6 +82,8 @@ namespace AZ virtual void SetFilteringSampleCount(LightHandle handle, uint16_t count) = 0; //! Sets the shadowmap Pcf (percentage closer filtering) method. virtual void SetPcfMethod(LightHandle handle, PcfMethod method) = 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 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 d0fb702d5a..b3a39e8fe3 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp @@ -343,6 +343,11 @@ namespace AZ SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetPcfMethod, method); } + void DiskLightFeatureProcessor::SetEsmExponent(LightHandle handle, float exponent) + { + SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetEsmExponent, exponent); + } + void DiskLightFeatureProcessor::UpdateShadow(LightHandle handle) { const DiskLightData& diskLight = m_diskLightData.GetData(handle.GetIndex()); diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h index 8391506f63..1147272204 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h @@ -60,6 +60,7 @@ namespace AZ void SetPredictionSampleCount(LightHandle handle, uint16_t count) override; void SetFilteringSampleCount(LightHandle handle, uint16_t count) override; void SetPcfMethod(LightHandle handle, PcfMethod method) override; + void SetEsmExponent(LightHandle handle, float esmExponent) override; void SetDiskData(LightHandle handle, const DiskLightData& data) override; diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.cpp index bb81c52b15..a5cb59e73c 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.cpp @@ -312,5 +312,10 @@ namespace AZ SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetPcfMethod, method); } + void PointLightFeatureProcessor::SetEsmExponent(LightHandle handle, float esmExponent) + { + SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetEsmExponent, esmExponent); + } + } // 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 c0c377e960..897bf6dc3e 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.h @@ -57,6 +57,7 @@ namespace AZ void SetPredictionSampleCount(LightHandle handle, uint16_t count) override; void SetFilteringSampleCount(LightHandle handle, uint16_t count) override; void SetPcfMethod(LightHandle handle, PcfMethod method) override; + void SetEsmExponent(LightHandle handle, float esmExponent) 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 da174ab0d5..98b2fb9574 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp @@ -168,6 +168,13 @@ namespace AZ::Render m_deviceBufferNeedsUpdate = true; } + void ProjectedShadowFeatureProcessor::SetEsmExponent(ShadowId id, float exponent) + { + ShadowData& shadowData = m_shadowData.GetElement(id.GetIndex()); + shadowData.m_esmExponent = exponent; + m_deviceBufferNeedsUpdate = true; + } + void ProjectedShadowFeatureProcessor::SetShadowFilterMethod(ShadowId id, ShadowFilterMethod method) { AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetShadowFilterMethod()."); diff --git a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h index a131c914f2..bf03e490a6 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h @@ -52,6 +52,7 @@ namespace AZ::Render void SetFieldOfViewY(ShadowId id, float fieldOfViewYRadians) override; void SetShadowmapMaxResolution(ShadowId id, ShadowmapSize size) override; void SetPcfMethod(ShadowId id, PcfMethod method); + void SetEsmExponent(ShadowId id, float exponent); void SetShadowFilterMethod(ShadowId id, ShadowFilterMethod method) override; void SetSofteningBoundaryWidthAngle(ShadowId id, float boundaryWidthRadians) override; void SetPredictionSampleCount(ShadowId id, uint16_t count) override; @@ -73,6 +74,8 @@ namespace AZ::Render uint32_t m_filteringSampleCount = 0; AZStd::array m_unprojectConstants = { {0, 0} }; float m_bias; + float m_esmExponent = 87.0f; + float m_padding[3]; }; // CPU data used for constructing & updating ShadowData 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 f4cb319c2f..9279326333 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightBus.h @@ -143,6 +143,13 @@ namespace AZ //! Sets the type of Pcf (percentage-closer filtering) to use. virtual void SetPcfMethod(PcfMethod method) = 0; + + //! Gets the Esm exponent. Higher values produce a steeper falloff between light and shadow. + virtual float GetEsmExponent() const = 0; + + //! Sets the Esm exponent. Higher values produce a steeper falloff between light and shadow. + virtual void SetEsmExponent(float exponent) = 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 31cdb34ddd..e003d6a178 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h @@ -66,6 +66,7 @@ namespace AZ float m_boundaryWidthInDegrees = 0.25f; uint16_t m_predictionSampleCount = 4; uint16_t m_filteringSampleCount = 12; + float m_esmExponent = 87.0f; // The following functions provide information to an EditContext... @@ -124,6 +125,8 @@ namespace AZ //! Returns true if pcf boundary search is disabled. bool IsPcfBoundarySearchDisabled() const; + //! Returns true if exponential shadow maps are disabled. + bool IsEsmDisabled() const; }; } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp index 8f10204ae9..c9211e87a0 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp @@ -21,7 +21,7 @@ namespace AZ if (auto serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(5) // ATOM-14637 + ->Version(6) // ATOM-15654 ->Field("LightType", &AreaLightComponentConfig::m_lightType) ->Field("Color", &AreaLightComponentConfig::m_color) ->Field("IntensityMode", &AreaLightComponentConfig::m_intensityMode) @@ -41,7 +41,8 @@ namespace AZ ->Field("Softening Boundary Width", &AreaLightComponentConfig::m_boundaryWidthInDegrees) ->Field("Prediction Sample Count", &AreaLightComponentConfig::m_predictionSampleCount) ->Field("Filtering Sample Count", &AreaLightComponentConfig::m_filteringSampleCount) - ->Field("Pcf Method", &AreaLightComponentConfig::m_pcfMethod); + ->Field("Pcf Method", &AreaLightComponentConfig::m_pcfMethod) + ->Field("Esm Exponent", &AreaLightComponentConfig::m_esmExponent) ; } } @@ -200,5 +201,11 @@ namespace AZ return m_pcfMethod != PcfMethod::BoundarySearch; } + + bool AreaLightComponentConfig::IsEsmDisabled() const + { + return !(m_shadowFilterMethod == ShadowFilterMethod::Esm || m_shadowFilterMethod == ShadowFilterMethod::EsmPcf); + } + } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp index c1c957ed4c..f7e0d15c92 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp @@ -84,7 +84,9 @@ namespace AZ::Render ->Event("SetFilteringSampleCount", &AreaLightRequestBus::Events::SetFilteringSampleCount) ->Event("GetPcfMethod", &AreaLightRequestBus::Events::GetPcfMethod) ->Event("SetPcfMethod", &AreaLightRequestBus::Events::SetPcfMethod) - + ->Event("GetEsmExponent", &AreaLightRequestBus::Events::GetEsmExponent) + ->Event("SetEsmExponent", &AreaLightRequestBus::Events::SetEsmExponent) + ->VirtualProperty("AttenuationRadius", "GetAttenuationRadius", "SetAttenuationRadius") ->VirtualProperty("Color", "GetColor", "SetColor") ->VirtualProperty("EmitsLightBothDirections", "GetEmitsLightBothDirections", "SetEmitsLightBothDirections") @@ -101,8 +103,9 @@ namespace AZ::Render ->VirtualProperty("SofteningBoundaryWidthAngle", "GetSofteningBoundaryWidthAngle", "SetSofteningBoundaryWidthAngle") ->VirtualProperty("PredictionSampleCount", "GetPredictionSampleCount", "SetPredictionSampleCount") ->VirtualProperty("FilteringSampleCount", "GetFilteringSampleCount", "SetFilteringSampleCount") - ->VirtualProperty("PcfMethod", "GetPcfMethod", "SetPcfMethod"); - ; + ->VirtualProperty("PcfMethod", "GetPcfMethod", "SetPcfMethod") + ->VirtualProperty("EsmExponent", "GetEsmExponent", "SetEsmExponent"); + ; } } @@ -314,6 +317,7 @@ namespace AZ::Render m_lightShapeDelegate->SetPredictionSampleCount(m_configuration.m_predictionSampleCount); m_lightShapeDelegate->SetFilteringSampleCount(m_configuration.m_filteringSampleCount); m_lightShapeDelegate->SetPcfMethod(m_configuration.m_pcfMethod); + m_lightShapeDelegate->SetEsmExponent(m_configuration.m_esmExponent); } } } @@ -565,6 +569,20 @@ namespace AZ::Render } } + float AreaLightComponentController::GetEsmExponent() const + { + return m_configuration.m_esmExponent; + } + + void AreaLightComponentController::SetEsmExponent(float esmExponent) + { + m_configuration.m_esmExponent = esmExponent; + if (m_lightShapeDelegate) + { + m_lightShapeDelegate->SetEsmExponent(esmExponent); + } + } + void AreaLightComponentController::CreateLightShapeDelegate() { switch (m_configuration.m_lightType) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.h index b5f342a522..a65f0be45f 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.h @@ -92,6 +92,8 @@ namespace AZ void SetFilteringSampleCount(uint32_t count) override; PcfMethod GetPcfMethod() const override; void SetPcfMethod(PcfMethod method) override; + float GetEsmExponent() const override; + void SetEsmExponent(float exponent) 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 8abc790ada..b8b82bc8bb 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp @@ -175,5 +175,13 @@ namespace AZ::Render } } + void DiskLightDelegate::SetEsmExponent(float exponent) + { + if (GetShadowsEnabled() && GetLightHandle().IsValid()) + { + GetFeatureProcessor()->SetEsmExponent(GetLightHandle(), exponent); + } + } + } // namespace AZ::Render diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.h index 5511b435d4..3e2704fd61 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.h @@ -51,6 +51,7 @@ namespace AZ void SetPredictionSampleCount(uint32_t count) override; void SetFilteringSampleCount(uint32_t count) override; void SetPcfMethod(PcfMethod method) override; + void SetEsmExponent(float exponent) override; private: diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp index 69bec21a6c..9f6a427bf4 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp @@ -179,8 +179,20 @@ namespace AZ ->EnumAttribute(PcfMethod::BoundarySearch, "Boundary search") ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) - ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsShadowPcfDisabled); - ; + ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsShadowPcfDisabled) + ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsShadowPcfDisabled) + ->DataElement( + Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_esmExponent, "Esm Exponent", + "Exponent used by Esm shadows." + "Larger values increase the sharpness of the border between lit and unlit areas.") + ->Attribute(Edit::Attributes::Min, 50.0f) + ->Attribute(Edit::Attributes::Max, 5000.0f) + ->Attribute(AZ::Edit::Attributes::Decimals, 0) + ->Attribute(AZ::Edit::Attributes::SliderCurveMidpoint, 0.05) + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) + ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsEsmDisabled) + ; } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h index da221341c3..d106a13c07 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h @@ -63,6 +63,7 @@ namespace AZ void SetPredictionSampleCount([[maybe_unused]] uint32_t count) override {}; void SetFilteringSampleCount([[maybe_unused]] uint32_t count) override {}; void SetPcfMethod([[maybe_unused]] PcfMethod method) override {}; + void SetEsmExponent([[maybe_unused]] float esmExponent) 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 b3f5fb6014..7d6096d65f 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h @@ -85,6 +85,8 @@ namespace AZ virtual void SetFilteringSampleCount(uint32_t count) = 0; //! Sets the Pcf (Percentage closer filtering) method to use. virtual void SetPcfMethod(PcfMethod method) = 0; + //! Sets the Esm exponent to use. Higher values produce a steeper falloff between light and shadow. + virtual void SetEsmExponent(float exponent) = 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 afb63dce9b..e701e3c22a 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp @@ -122,5 +122,14 @@ namespace AZ } } + void SphereLightDelegate::SetEsmExponent(float esmExponent) + { + if (GetShadowsEnabled() && GetLightHandle().IsValid()) + { + GetFeatureProcessor()->SetEsmExponent(GetLightHandle(), esmExponent); + } + } + + } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.h index 178540fd01..f964254d76 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.h @@ -41,6 +41,7 @@ namespace AZ void SetPredictionSampleCount(uint32_t count) override; void SetFilteringSampleCount(uint32_t count) override; void SetPcfMethod(PcfMethod method) override; + void SetEsmExponent(float esmExponent) override; private: