Merge pull request #4734 from aws-lumberyard-dev/Atom/mriegger/directionallightbias
Atom/mriegger/directionallightbias
This commit is contained in:
+9
-7
@@ -111,16 +111,18 @@ void DirectionalLightShadow::GetShadowCoords(
|
||||
float3 worldPosition,
|
||||
out float3 shadowCoords[ViewSrg::MaxCascadeCount])
|
||||
{
|
||||
const float4x4 depthBiasMatrices[ViewSrg::MaxCascadeCount] =
|
||||
ViewSrg::m_directionalLightShadows[lightIndex].m_depthBiasMatrices;
|
||||
const uint cascadeCount = ViewSrg::m_directionalLightShadows[lightIndex].m_cascadeCount;
|
||||
|
||||
const float shadowBias = ViewSrg::m_directionalLightShadows[lightIndex].m_shadowBias;
|
||||
const float4x4 lightViewToShadowmapMatrices[ViewSrg::MaxCascadeCount] = ViewSrg::m_directionalLightShadows[lightIndex].m_lightViewToShadowmapMatrices;
|
||||
const float4x4 worldToLightViewMatrices[ViewSrg::MaxCascadeCount] = ViewSrg::m_directionalLightShadows[lightIndex].m_worldToLightViewMatrices;
|
||||
|
||||
for (uint index = 0; index < cascadeCount; ++index)
|
||||
{
|
||||
const float4x4 depthBiasMatrix = depthBiasMatrices[index];
|
||||
const float4 shadowCoordHomogeneous = mul(depthBiasMatrix,
|
||||
float4(worldPosition, 1.));
|
||||
shadowCoords[index] = shadowCoordHomogeneous.xyz / shadowCoordHomogeneous.w;
|
||||
float4 lightSpacePos = mul(worldToLightViewMatrices[index], float4(worldPosition, 1.));
|
||||
lightSpacePos.z += shadowBias;
|
||||
|
||||
const float4 clipSpacePos = mul(lightViewToShadowmapMatrices[index], lightSpacePos);
|
||||
shadowCoords[index] = clipSpacePos.xyz / clipSpacePos.w;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -102,18 +102,19 @@ partial ShaderResourceGroup ViewSrg
|
||||
|
||||
struct DirectionalLightShadow
|
||||
{
|
||||
float4x4 m_depthBiasMatrices[MaxCascadeCount];
|
||||
float4x4 m_lightViewToShadowmapMatrices[MaxCascadeCount];
|
||||
float4x4 m_worldToLightViewMatrices[MaxCascadeCount];
|
||||
float m_slopeBiasBase[MaxCascadeCount];
|
||||
float m_boundaryScale;
|
||||
uint m_shadowmapSize; // width and height of shadowmap
|
||||
uint m_cascadeCount;
|
||||
float m_shadowBias;
|
||||
uint m_predictionSampleCount;
|
||||
uint m_filteringSampleCount;
|
||||
uint m_debugFlags;
|
||||
uint m_shadowFilterMethod;
|
||||
float m_far_minus_near;
|
||||
float3 m_padding;
|
||||
};
|
||||
|
||||
enum ShadowFilterMethod
|
||||
|
||||
+3
@@ -157,6 +157,9 @@ namespace AZ
|
||||
//! Sets whether the directional shadowmap should use receiver plane bias.
|
||||
//! This attempts to reduce shadow acne when using large pcf filters.
|
||||
virtual void SetShadowReceiverPlaneBiasEnabled(LightHandle handle, bool enable) = 0;
|
||||
|
||||
//! Reduces acne by applying a small amount of bias along shadow-space z.
|
||||
virtual void SetShadowBias(LightHandle handle, float bias) = 0;
|
||||
};
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
+9
-4
@@ -589,6 +589,15 @@ namespace AZ
|
||||
m_shadowProperties.GetData(handle.GetIndex()).m_isReceiverPlaneBiasEnabled = enable;
|
||||
}
|
||||
|
||||
void DirectionalLightFeatureProcessor::SetShadowBias(LightHandle handle, float bias)
|
||||
{
|
||||
for (auto& it : m_shadowData)
|
||||
{
|
||||
it.second.GetData(handle.GetIndex()).m_shadowBias = bias;
|
||||
}
|
||||
m_shadowBufferNeedsUpdate = true;
|
||||
}
|
||||
|
||||
void DirectionalLightFeatureProcessor::OnRenderPipelineAdded(RPI::RenderPipelinePtr pipeline)
|
||||
{
|
||||
PrepareForChangingRenderPipelineAndCameraView();
|
||||
@@ -1522,10 +1531,6 @@ namespace AZ
|
||||
|
||||
for (uint16_t cascadeIndex = 0; cascadeIndex < GetCascadeCount(handle); ++cascadeIndex)
|
||||
{
|
||||
const Matrix4x4& worldToLightClipMatrix = property.m_segments.at(cameraView)[cascadeIndex].m_view->GetWorldToClipMatrix();
|
||||
const Matrix4x4 depthBiasMatrix = Shadow::GetClipToShadowmapTextureMatrix() * worldToLightClipMatrix;
|
||||
shadowData.m_depthBiasMatrices[cascadeIndex] = depthBiasMatrix;
|
||||
|
||||
const Matrix4x4& lightViewToLightClipMatrix = property.m_segments.at(cameraView)[cascadeIndex].m_view->GetViewToClipMatrix();
|
||||
const Matrix4x4 lightViewToShadowmapMatrix = Shadow::GetClipToShadowmapTextureMatrix() * lightViewToLightClipMatrix;
|
||||
shadowData.m_lightViewToShadowmapMatrices[cascadeIndex] = lightViewToShadowmapMatrix;
|
||||
|
||||
@@ -72,12 +72,6 @@ namespace AZ
|
||||
// [GFX TODO][ATOM-15172] Look into compacting struct DirectionalLightShadowData
|
||||
struct DirectionalLightShadowData
|
||||
{
|
||||
AZStd::array<Matrix4x4, Shadow::MaxNumberOfCascades> m_depthBiasMatrices =
|
||||
{ {
|
||||
Matrix4x4::CreateIdentity(),
|
||||
Matrix4x4::CreateIdentity(),
|
||||
Matrix4x4::CreateIdentity(),
|
||||
Matrix4x4::CreateIdentity() } };
|
||||
AZStd::array<Matrix4x4, Shadow::MaxNumberOfCascades> m_lightViewToShadowmapMatrices =
|
||||
{ {
|
||||
Matrix4x4::CreateIdentity(),
|
||||
@@ -97,11 +91,14 @@ namespace AZ
|
||||
float m_boundaryScale = 0.f;
|
||||
uint32_t m_shadowmapSize = 1; // width and height of shadowmap
|
||||
uint32_t m_cascadeCount = 1;
|
||||
// Reduce acne by applying a small amount of bias to apply along shadow-space z.
|
||||
float m_shadowBias = 0.0f;
|
||||
uint32_t m_predictionSampleCount = 0;
|
||||
uint32_t m_filteringSampleCount = 0;
|
||||
uint32_t m_debugFlags = 0;
|
||||
uint32_t m_shadowFilterMethod = 0;
|
||||
float m_far_minus_near = 0;
|
||||
float m_padding[3];
|
||||
};
|
||||
|
||||
class DirectionalLightFeatureProcessor final
|
||||
@@ -218,6 +215,7 @@ namespace AZ
|
||||
void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) override;
|
||||
void SetFilteringSampleCount(LightHandle handle, uint16_t count) override;
|
||||
void SetShadowReceiverPlaneBiasEnabled(LightHandle handle, bool enable) override;
|
||||
void SetShadowBias(LightHandle handle, float bias) override;
|
||||
|
||||
const Data::Instance<RPI::Buffer> GetLightBuffer() const;
|
||||
uint32_t GetLightCount() const;
|
||||
|
||||
+8
@@ -168,6 +168,14 @@ namespace AZ
|
||||
//! Sets whether the directional shadowmap should use receiver plane bias.
|
||||
//! @param enable flag specifying whether to enable the receiver plane bias feature
|
||||
virtual void SetShadowReceiverPlaneBiasEnabled(bool enable) = 0;
|
||||
|
||||
//! Shadow bias reduces acne by applying a small amount of offset along shadow-space z.
|
||||
//! @return Returns the amount of bias to apply.
|
||||
virtual float GetShadowBias() const = 0;
|
||||
|
||||
//! Shadow bias reduces acne by applying a small amount of offset along shadow-space z.
|
||||
//! @param Sets the amount of bias to apply.
|
||||
virtual void SetShadowBias(float bias) = 0;
|
||||
};
|
||||
using DirectionalLightRequestBus = EBus<DirectionalLightRequests>;
|
||||
|
||||
|
||||
+3
@@ -109,6 +109,9 @@ namespace AZ
|
||||
//! This uses partial derivatives to reduce shadow acne when using large pcf kernels.
|
||||
bool m_receiverPlaneBiasEnabled = true;
|
||||
|
||||
//! Reduces shadow acne by applying a small amount of offset along shadow-space z.
|
||||
float m_shadowBias = 0.0f;
|
||||
|
||||
bool IsSplitManual() const;
|
||||
bool IsSplitAutomatic() const;
|
||||
bool IsCascadeCorrectionDisabled() const;
|
||||
|
||||
+2
-1
@@ -38,7 +38,8 @@ namespace AZ
|
||||
->Field("IsDebugColoringEnabled", &DirectionalLightComponentConfig::m_isDebugColoringEnabled)
|
||||
->Field("ShadowFilterMethod", &DirectionalLightComponentConfig::m_shadowFilterMethod)
|
||||
->Field("PcfFilteringSampleCount", &DirectionalLightComponentConfig::m_filteringSampleCount)
|
||||
->Field("ShadowReceiverPlaneBiasEnabled", &DirectionalLightComponentConfig::m_receiverPlaneBiasEnabled);
|
||||
->Field("ShadowReceiverPlaneBiasEnabled", &DirectionalLightComponentConfig::m_receiverPlaneBiasEnabled)
|
||||
->Field("Shadow Bias", &DirectionalLightComponentConfig::m_shadowBias);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
-1
@@ -84,6 +84,8 @@ namespace AZ
|
||||
->Event("SetFilteringSampleCount", &DirectionalLightRequestBus::Events::SetFilteringSampleCount)
|
||||
->Event("GetShadowReceiverPlaneBiasEnabled", &DirectionalLightRequestBus::Events::GetShadowReceiverPlaneBiasEnabled)
|
||||
->Event("SetShadowReceiverPlaneBiasEnabled", &DirectionalLightRequestBus::Events::SetShadowReceiverPlaneBiasEnabled)
|
||||
->Event("GetShadowBias", &DirectionalLightRequestBus::Events::GetShadowBias)
|
||||
->Event("SetShadowBias", &DirectionalLightRequestBus::Events::SetShadowBias)
|
||||
->VirtualProperty("Color", "GetColor", "SetColor")
|
||||
->VirtualProperty("Intensity", "GetIntensity", "SetIntensity")
|
||||
->VirtualProperty("AngularDiameter", "GetAngularDiameter", "SetAngularDiameter")
|
||||
@@ -98,7 +100,8 @@ namespace AZ
|
||||
->VirtualProperty("DebugColoringEnabled", "GetDebugColoringEnabled", "SetDebugColoringEnabled")
|
||||
->VirtualProperty("ShadowFilterMethod", "GetShadowFilterMethod", "SetShadowFilterMethod")
|
||||
->VirtualProperty("FilteringSampleCount", "GetFilteringSampleCount", "SetFilteringSampleCount")
|
||||
->VirtualProperty("ShadowReceiverPlaneBiasEnabled", "GetShadowReceiverPlaneBiasEnabled", "SetShadowReceiverPlaneBiasEnabled");
|
||||
->VirtualProperty("ShadowReceiverPlaneBiasEnabled", "GetShadowReceiverPlaneBiasEnabled", "SetShadowReceiverPlaneBiasEnabled")
|
||||
->VirtualProperty("ShadowBias", "GetShadowBias", "SetShadowBias");
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -406,6 +409,20 @@ namespace AZ
|
||||
return aznumeric_cast<uint32_t>(m_configuration.m_filteringSampleCount);
|
||||
}
|
||||
|
||||
void DirectionalLightComponentController::SetShadowBias(float bias)
|
||||
{
|
||||
m_configuration.m_shadowBias = bias;
|
||||
if (m_featureProcessor)
|
||||
{
|
||||
m_featureProcessor->SetShadowBias(m_lightHandle, bias);
|
||||
}
|
||||
}
|
||||
|
||||
float DirectionalLightComponentController::GetShadowBias() const
|
||||
{
|
||||
return m_configuration.m_shadowBias;
|
||||
}
|
||||
|
||||
void DirectionalLightComponentController::SetFilteringSampleCount(uint32_t count)
|
||||
{
|
||||
const uint16_t count16 = GetMin(Shadow::MaxPcfSamplingCount, aznumeric_cast<uint16_t>(count));
|
||||
@@ -499,6 +516,7 @@ namespace AZ
|
||||
SetViewFrustumCorrectionEnabled(m_configuration.m_isCascadeCorrectionEnabled);
|
||||
SetDebugColoringEnabled(m_configuration.m_isDebugColoringEnabled);
|
||||
SetShadowFilterMethod(m_configuration.m_shadowFilterMethod);
|
||||
SetShadowBias(m_configuration.m_shadowBias);
|
||||
SetFilteringSampleCount(m_configuration.m_filteringSampleCount);
|
||||
SetShadowReceiverPlaneBiasEnabled(m_configuration.m_receiverPlaneBiasEnabled);
|
||||
|
||||
|
||||
+2
@@ -80,6 +80,8 @@ namespace AZ
|
||||
void SetFilteringSampleCount(uint32_t count) override;
|
||||
bool GetShadowReceiverPlaneBiasEnabled() const override;
|
||||
void SetShadowReceiverPlaneBiasEnabled(bool enable) override;
|
||||
float GetShadowBias() const override;
|
||||
void SetShadowBias(float width) override;
|
||||
|
||||
private:
|
||||
friend class EditorDirectionalLightComponent;
|
||||
|
||||
+13
-4
@@ -133,8 +133,8 @@ namespace AZ
|
||||
->EnumAttribute(ShadowFilterMethod::Esm, "ESM")
|
||||
->EnumAttribute(ShadowFilterMethod::EsmPcf, "ESM+PCF")
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
|
||||
->DataElement(Edit::UIHandlers::Slider, &DirectionalLightComponentConfig::m_filteringSampleCount, "Filtering sample count",
|
||||
"This is used only when the pixel is predicted as on the boundary. "
|
||||
->DataElement(Edit::UIHandlers::Slider, &DirectionalLightComponentConfig::m_filteringSampleCount, "Filtering sample count\n",
|
||||
"This is used only when the pixel is predicted as on the boundary.\n"
|
||||
"Specific to PCF and ESM+PCF.")
|
||||
->Attribute(Edit::Attributes::Min, 4)
|
||||
->Attribute(Edit::Attributes::Max, 64)
|
||||
@@ -142,10 +142,19 @@ namespace AZ
|
||||
->Attribute(Edit::Attributes::ReadOnly, &DirectionalLightComponentConfig::IsShadowPcfDisabled)
|
||||
->DataElement(
|
||||
Edit::UIHandlers::CheckBox, &DirectionalLightComponentConfig::m_receiverPlaneBiasEnabled,
|
||||
"Shadow Receiver Plane Bias Enable",
|
||||
"Shadow Receiver Plane Bias Enable\n",
|
||||
"This reduces shadow acne when using large pcf kernels.")
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
|
||||
->Attribute(Edit::Attributes::ReadOnly, &DirectionalLightComponentConfig::IsShadowPcfDisabled);
|
||||
->Attribute(Edit::Attributes::ReadOnly, &DirectionalLightComponentConfig::IsShadowPcfDisabled)
|
||||
->DataElement(
|
||||
Edit::UIHandlers::Slider, &DirectionalLightComponentConfig::m_shadowBias,
|
||||
"Shadow Bias\n",
|
||||
"Reduces acne by applying a fixed bias along z in shadow-space.\n"
|
||||
"If this is 0, no biasing is applied.")
|
||||
->Attribute(Edit::Attributes::Min, 0.f)
|
||||
->Attribute(Edit::Attributes::Max, 0.2)
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user