Atom/mriegger/normaloffsetbiasarealight (#4917)

* Adding directional light shadow bias
* Adding normal offset bias for projected shadows

Signed-off-by: mrieggeramzn <mriegger@amazon.com>
monroegm-disable-blank-issue-2
mrieggeramzn 4 years ago committed by GitHub
parent d468cbad85
commit dd1d515e37
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -14,6 +14,7 @@
#include <Atom/RPI/Math.azsli>
#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;

@ -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.

@ -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;
};

@ -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);

@ -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;

@ -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

@ -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<RPI::Buffer> GetLightBuffer() const;

@ -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<ShadowDataIndex>(id.GetIndex());
shadowData.m_normalShadowBias = normalShadowBias;
m_deviceBufferNeedsUpdate = true;
}
void ProjectedShadowFeatureProcessor::SetShadowmapMaxResolution(ShadowId id, ShadowmapSize size)

@ -68,7 +68,7 @@ namespace AZ::Render
uint32_t m_filteringSampleCount = 0;
AZStd::array<float, 2> 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;
};

@ -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.

@ -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;

@ -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)

@ -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;

@ -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,

@ -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())

@ -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:

@ -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,6 +171,15 @@ 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)
;
}
}

@ -58,6 +58,7 @@ 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);

@ -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

@ -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

@ -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:

Loading…
Cancel
Save