Atom/mriegger/normaloffsetbias (#4841)

* Adding directional light shadow bias

Signed-off-by: mrieggeramzn <mriegger@amazon.com>

* Adding normal offset bias to the directional shadow maps

Signed-off-by: mrieggeramzn <mriegger@amazon.com>

* not time yet for this

Signed-off-by: mrieggeramzn <mriegger@amazon.com>

* small comment fix

Signed-off-by: mrieggeramzn <mriegger@amazon.com>

* fixing tabs

Signed-off-by: mrieggeramzn <mriegger@amazon.com>
This commit is contained in:
mrieggeramzn
2021-10-22 09:48:04 -07:00
committed by GitHub
parent 476ff637c2
commit 8c6900eb06
23 changed files with 132 additions and 29 deletions
@@ -54,6 +54,7 @@ VSOutput ShadowCatcherVS(VSInput IN)
DirectionalLightShadow::GetShadowCoords(
ViewSrg::m_shadowIndexDirectionalLight,
worldPosition,
OUT.m_worldNormal,
OUT.m_shadowCoords);
return OUT;
@@ -112,13 +112,15 @@ VSOutput EnhancedPbr_ForwardPassVS(VSInput IN)
PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depth)
{
const float3 vertexNormal = normalize(IN.m_normal);
// ------- Tangents & Bitangets -------
float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz };
float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz };
if ((o_parallax_feature_enabled && !o_enableSubsurfaceScattering) || o_normal_useTexture || (o_clearCoat_enabled && o_clearCoat_normal_useTexture) || o_detail_normal_useTexture)
{
PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents);
PrepareGeneratedTangent(vertexNormal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents);
}
// ------- Depth & Parallax -------
@@ -137,7 +139,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3();
float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3();
GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset,
GetParallaxInput(vertexNormal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset,
ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse,
IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, depth, IN.m_position.w, displacementIsClipped);
@@ -150,7 +152,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight;
if (o_enableShadows && shadowIndex < SceneSrg::m_directionalLightCount)
{
DirectionalLightShadow::GetShadowCoords(shadowIndex, IN.m_worldPosition, IN.m_shadowCoords);
DirectionalLightShadow::GetShadowCoords(shadowIndex, IN.m_worldPosition, vertexNormal, IN.m_shadowCoords);
}
}
}
@@ -185,7 +187,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
float2 normalUv = IN.m_uv[MaterialSrg::m_normalMapUvIndex];
float3x3 uvMatrix = MaterialSrg::m_normalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); // By design, only UV0 is allowed to apply transforms.
float detailLayerNormalFactor = MaterialSrg::m_detail_normal_factor * detailLayerBlendFactor;
surface.vertexNormal = normalize(IN.m_normal);
surface.vertexNormal = vertexNormal;
surface.normal = GetDetailedNormalInputWS(
isFrontFace, IN.m_normal,
tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex], MaterialSrg::m_normalMap, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_normalFactor, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, uvMatrix, o_normal_useTexture,
@@ -302,6 +302,7 @@ ProcessedMaterialInputs ProcessStandardMaterialInputs(StandardMaterialInputs inp
PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depthNDC)
{
const float3 vertexNormal = normalize(IN.m_normal);
depthNDC = IN.m_position.z;
s_blendMaskFromVertexStream = IN.m_blendMask;
@@ -321,7 +322,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
|| o_layer3_o_clearCoat_normal_useTexture
)
{
PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents);
PrepareGeneratedTangent(vertexNormal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents);
}
// ------- Debug Modes -------
@@ -368,7 +369,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight;
if (o_enableShadows && shadowIndex < SceneSrg::m_directionalLightCount)
{
DirectionalLightShadow::GetShadowCoords(shadowIndex, IN.m_worldPosition, IN.m_shadowCoords);
DirectionalLightShadow::GetShadowCoords(shadowIndex, IN.m_worldPosition, vertexNormal, IN.m_shadowCoords);
}
}
}
@@ -445,7 +446,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
normalTS = ReorientTangentSpaceNormal(normalTS, lightingInputLayer3.m_normalTS);
}
// [GFX TODO][ATOM-14591]: This will only work if the normal maps all use the same UV stream. We would need to add support for having them in different UV streams.
surface.vertexNormal = normalize(IN.m_normal);
surface.vertexNormal = vertexNormal;
surface.normal = normalize(TangentSpaceToWorld(normalTS, IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex]));
// ------- Combine Albedo, roughness, specular, roughness ---------
@@ -98,6 +98,8 @@ VSOutput StandardPbr_ForwardPassVS(VSInput IN)
PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depthNDC)
{
const float3 vertexNormal = normalize(IN.m_normal);
// ------- Tangents & Bitangets -------
float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz };
float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz };
@@ -128,7 +130,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight;
if (o_enableShadows && shadowIndex < SceneSrg::m_directionalLightCount)
{
DirectionalLightShadow::GetShadowCoords(shadowIndex, IN.m_worldPosition, IN.m_shadowCoords);
DirectionalLightShadow::GetShadowCoords(shadowIndex, IN.m_worldPosition, vertexNormal, IN.m_shadowCoords);
}
}
}
@@ -146,7 +148,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
float2 normalUv = IN.m_uv[MaterialSrg::m_normalMapUvIndex];
float3x3 uvMatrix = MaterialSrg::m_normalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); // By design, only UV0 is allowed to apply transforms.
surface.vertexNormal = normalize(IN.m_normal);
surface.vertexNormal = vertexNormal;
surface.normal = GetNormalInputWS(MaterialSrg::m_normalMap, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, isFrontFace, IN.m_normal,
tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex], uvMatrix, o_normal_useTexture, MaterialSrg::m_normalFactor);
@@ -14,6 +14,7 @@
#include "ShadowmapAtlasLib.azsli"
#include "BicubicPcfFilters.azsli"
#include "ReceiverPlaneDepthBias.azsli"
#include "NormalOffsetShadows.azsli"
// Before including this azsli file, a PassSrg must be defined with the following members:
// Texture2DArray<float> m_directionalLightShadowmap;
@@ -45,6 +46,7 @@ class DirectionalLightShadow
static void GetShadowCoords(
uint lightIndex,
float3 worldPosition,
float3 worldNormal,
out float3 shadowCoords[ViewSrg::MaxCascadeCount]);
//! This calculates visibility ratio of the surface from the light origin.
@@ -109,18 +111,22 @@ class DirectionalLightShadow
void DirectionalLightShadow::GetShadowCoords(
uint lightIndex,
float3 worldPosition,
float3 worldNormal,
out float3 shadowCoords[ViewSrg::MaxCascadeCount])
{
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)
{
float4 lightSpacePos = mul(worldToLightViewMatrices[index], float4(worldPosition, 1.));
lightSpacePos.z += shadowBias;
const uint cascadeCount = ViewSrg::m_directionalLightShadows[lightIndex].m_cascadeCount;
const float3 shadowOffset = ComputeNormalShadowOffset(ViewSrg::m_directionalLightShadows[lightIndex].m_normalShadowBias, worldNormal, ViewSrg::m_directionalLightShadows[lightIndex].m_shadowmapSize);
for (uint index = 0; index < cascadeCount; ++index)
{
float4 lightSpacePos = mul(worldToLightViewMatrices[index], float4(worldPosition + shadowOffset, 1.));
lightSpacePos.z += shadowBias;
const float4 clipSpacePos = mul(lightViewToShadowmapMatrices[index], lightSpacePos);
shadowCoords[index] = clipSpacePos.xyz / clipSpacePos.w;
}
@@ -0,0 +1,22 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
// Helper functions for normal offset shadow mapping.
// Normal Offset is an alternative to slope-scale depth bias.
// We bias the shadow map lookup by transforming the world-position along the geometric normal before hand.
// http://web.archive.org/web/20140810230446/https://www.dissidentlogic.com/old/#Normal%20Offset%20Shadows
//
// Apply the following to the world position. Then use this modified world position to look up in the shadow map
float3 ComputeNormalShadowOffset(const float normalOffsetBias, const float3 worldNormal, const float shadowMapDimension)
{
const float shadowmapSize = 2.0f / shadowMapDimension;
return float3(worldNormal * normalOffsetBias * shadowmapSize);
}
@@ -47,6 +47,7 @@ void VertexHelper(in VSInput IN, inout VSOutput OUT, float3 worldPosition, bool
DirectionalLightShadow::GetShadowCoords(
shadowIndex,
worldPosition,
OUT.m_normal,
OUT.m_shadowCoords);
}
}
@@ -81,10 +81,10 @@ partial ShaderResourceGroup ViewSrg
uint m_shadowmapArraySlice; // array slice who has shadowmap in the atlas.
uint m_shadowFilterMethod;
float m_boundaryScale;
uint m_predictionSampleCount;
uint m_filteringSampleCount;
float2 m_unprojectConstants;
float m_bias;
float m_normalShadowBias;
float m_esmExponent;
float3 m_padding;
};
@@ -109,7 +109,7 @@ partial ShaderResourceGroup ViewSrg
uint m_shadowmapSize; // width and height of shadowmap
uint m_cascadeCount;
float m_shadowBias;
uint m_predictionSampleCount;
float m_normalShadowBias;
uint m_filteringSampleCount;
uint m_debugFlags;
uint m_shadowFilterMethod;
@@ -160,6 +160,9 @@ namespace AZ
//! Reduces acne by applying a small amount of bias along shadow-space z.
virtual void SetShadowBias(LightHandle handle, float bias) = 0;
//! Reduces acne by biasing the shadowmap lookup along the geometric normal.
virtual void SetNormalShadowBias(LightHandle handle, float normalShadowBias) = 0;
};
} // namespace Render
} // namespace AZ
@@ -48,11 +48,13 @@ namespace AZ::Render
virtual void SetAspectRatio(ShadowId id, float aspectRatio) = 0;
//! Sets the field of view for the shadow in radians in the Y direction.
virtual void SetFieldOfViewY(ShadowId id, float fieldOfView) = 0;
//! Sets the maximum resolution of the shadow map
//! Sets the maximum resolution of the shadow map.
virtual void SetShadowmapMaxResolution(ShadowId id, ShadowmapSize size) = 0;
//! Sets the shadow bias
//! Sets the shadow bias.
virtual void SetShadowBias(ShadowId id, float bias) = 0;
//! Sets the shadow filter method
//! Sets the normal shadow bias.
virtual void SetNormalShadowBias(ShadowId id, float normalShadowBias) = 0;
//! Sets the shadow filter method.
virtual void SetShadowFilterMethod(ShadowId id, ShadowFilterMethod method) = 0;
//! Sets the sample count for filtering of the shadow boundary, max 64.
virtual void SetFilteringSampleCount(ShadowId id, uint16_t count) = 0;
@@ -598,6 +598,15 @@ namespace AZ
m_shadowBufferNeedsUpdate = true;
}
void DirectionalLightFeatureProcessor::SetNormalShadowBias(LightHandle handle, float normalShadowBias)
{
for (auto& it : m_shadowData)
{
it.second.GetData(handle.GetIndex()).m_normalShadowBias = normalShadowBias;
}
m_shadowBufferNeedsUpdate = true;
}
void DirectionalLightFeatureProcessor::OnRenderPipelineAdded(RPI::RenderPipelinePtr pipeline)
{
PrepareForChangingRenderPipelineAndCameraView();
@@ -92,8 +92,9 @@ namespace AZ
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;
float m_shadowBias = 0.0f;
// Reduces acne by biasing the shadowmap lookup along the geometric normal.
float m_normalShadowBias;
uint32_t m_filteringSampleCount = 0;
uint32_t m_debugFlags = 0;
uint32_t m_shadowFilterMethod = 0;
@@ -101,6 +102,8 @@ namespace AZ
float m_padding[3];
};
static_assert(sizeof(DirectionalLightShadowData) % 16 == 0); // Structured buffers need alignment to be a multiple of 16 bytes.
class DirectionalLightFeatureProcessor final
: public DirectionalLightFeatureProcessorInterface
{
@@ -216,6 +219,7 @@ namespace AZ
void SetFilteringSampleCount(LightHandle handle, uint16_t count) override;
void SetShadowReceiverPlaneBiasEnabled(LightHandle handle, bool enable) override;
void SetShadowBias(LightHandle handle, float bias) override;
void SetNormalShadowBias(LightHandle handle, float normalShadowBias) override;
const Data::Instance<RPI::Buffer> GetLightBuffer() const;
uint32_t GetLightCount() const;
@@ -151,6 +151,14 @@ namespace AZ::Render
shadowProperty.m_bias = bias;
}
void ProjectedShadowFeatureProcessor::SetNormalShadowBias(ShadowId id, float normalShadowBias)
{
AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetNormalShadowBias().");
ShadowProperty& shadowProperty = GetShadowPropertyFromShadowId(id);
shadowProperty.m_normalShadowBias = normalShadowBias;
}
void ProjectedShadowFeatureProcessor::SetShadowmapMaxResolution(ShadowId id, ShadowmapSize size)
{
AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetShadowmapMaxResolution().");
@@ -48,6 +48,7 @@ namespace AZ::Render
void SetFieldOfViewY(ShadowId id, float fieldOfViewYRadians) override;
void SetShadowmapMaxResolution(ShadowId id, ShadowmapSize size) override;
void SetShadowBias(ShadowId id, float bias) override;
void SetNormalShadowBias(ShadowId id, float normalShadowBias) override;
void SetShadowFilterMethod(ShadowId id, ShadowFilterMethod method) override;
void SetFilteringSampleCount(ShadowId id, uint16_t count) override;
void SetShadowProperties(ShadowId id, const ProjectedShadowDescriptor& descriptor) override;
@@ -64,10 +65,10 @@ namespace AZ::Render
uint32_t m_shadowmapArraySlice = 0; // array slice who has shadowmap in the atlas.
uint32_t m_shadowFilterMethod = 0; // filtering method of shadows.
float m_boundaryScale = 0.f; // the half of boundary of lit/shadowed areas. (in degrees)
uint32_t m_predictionSampleCount = 0; // sample count to judge whether it is on the shadow boundary or not.
uint32_t m_filteringSampleCount = 0;
AZStd::array<float, 2> m_unprojectConstants = { {0, 0} };
float m_bias;
float m_normalShadowBias;
float m_esmExponent = 87.0f;
float m_padding[3];
};
@@ -78,6 +79,7 @@ namespace AZ::Render
ProjectedShadowDescriptor m_desc;
RPI::ViewPtr m_shadowmapView;
float m_bias = 0.1f;
float m_normalShadowBias = 0.0f;
ShadowId m_shadowId;
};
@@ -176,6 +176,14 @@ namespace AZ
//! 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;
//! 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;
};
using DirectionalLightRequestBus = EBus<DirectionalLightRequests>;
@@ -101,6 +101,9 @@ namespace AZ
//! Method of shadow's filtering.
ShadowFilterMethod m_shadowFilterMethod = ShadowFilterMethod::None;
// Reduces acne by biasing the shadowmap lookup along the geometric normal.
float m_normalShadowBias = 0.0f;
//! Sample Count for filtering (from 4 to 64)
//! It is used only when the pixel is predicted as on the boundary.
uint16_t m_filteringSampleCount = 32;
@@ -39,7 +39,8 @@ namespace AZ
->Field("ShadowFilterMethod", &DirectionalLightComponentConfig::m_shadowFilterMethod)
->Field("PcfFilteringSampleCount", &DirectionalLightComponentConfig::m_filteringSampleCount)
->Field("ShadowReceiverPlaneBiasEnabled", &DirectionalLightComponentConfig::m_receiverPlaneBiasEnabled)
->Field("Shadow Bias", &DirectionalLightComponentConfig::m_shadowBias);
->Field("Shadow Bias", &DirectionalLightComponentConfig::m_shadowBias)
->Field("Normal Shadow Bias", &DirectionalLightComponentConfig::m_normalShadowBias);
}
}
@@ -86,6 +86,8 @@ namespace AZ
->Event("SetShadowReceiverPlaneBiasEnabled", &DirectionalLightRequestBus::Events::SetShadowReceiverPlaneBiasEnabled)
->Event("GetShadowBias", &DirectionalLightRequestBus::Events::GetShadowBias)
->Event("SetShadowBias", &DirectionalLightRequestBus::Events::SetShadowBias)
->Event("GetNormalShadowBias", &DirectionalLightRequestBus::Events::GetNormalShadowBias)
->Event("SetNormalShadowBias", &DirectionalLightRequestBus::Events::SetNormalShadowBias)
->VirtualProperty("Color", "GetColor", "SetColor")
->VirtualProperty("Intensity", "GetIntensity", "SetIntensity")
->VirtualProperty("AngularDiameter", "GetAngularDiameter", "SetAngularDiameter")
@@ -101,7 +103,8 @@ namespace AZ
->VirtualProperty("ShadowFilterMethod", "GetShadowFilterMethod", "SetShadowFilterMethod")
->VirtualProperty("FilteringSampleCount", "GetFilteringSampleCount", "SetFilteringSampleCount")
->VirtualProperty("ShadowReceiverPlaneBiasEnabled", "GetShadowReceiverPlaneBiasEnabled", "SetShadowReceiverPlaneBiasEnabled")
->VirtualProperty("ShadowBias", "GetShadowBias", "SetShadowBias");
->VirtualProperty("ShadowBias", "GetShadowBias", "SetShadowBias")
->VirtualProperty("NormalShadowBias", "GetNormalShadowBias", "SetNormalShadowBias");
;
}
}
@@ -423,6 +426,20 @@ namespace AZ
return m_configuration.m_shadowBias;
}
void DirectionalLightComponentController::SetNormalShadowBias(float bias)
{
m_configuration.m_normalShadowBias = bias;
if (m_featureProcessor)
{
m_featureProcessor->SetNormalShadowBias(m_lightHandle, bias);
}
}
float DirectionalLightComponentController::GetNormalShadowBias() const
{
return m_configuration.m_normalShadowBias;
}
void DirectionalLightComponentController::SetFilteringSampleCount(uint32_t count)
{
const uint16_t count16 = GetMin(Shadow::MaxPcfSamplingCount, aznumeric_cast<uint16_t>(count));
@@ -517,6 +534,7 @@ namespace AZ
SetDebugColoringEnabled(m_configuration.m_isDebugColoringEnabled);
SetShadowFilterMethod(m_configuration.m_shadowFilterMethod);
SetShadowBias(m_configuration.m_shadowBias);
SetNormalShadowBias(m_configuration.m_normalShadowBias);
SetFilteringSampleCount(m_configuration.m_filteringSampleCount);
SetShadowReceiverPlaneBiasEnabled(m_configuration.m_receiverPlaneBiasEnabled);
@@ -81,7 +81,9 @@ namespace AZ
bool GetShadowReceiverPlaneBiasEnabled() const override;
void SetShadowReceiverPlaneBiasEnabled(bool enable) override;
float GetShadowBias() const override;
void SetShadowBias(float width) override;
void SetShadowBias(float bias) override;
float GetNormalShadowBias() const override;
void SetNormalShadowBias(float bias) override;
private:
friend class EditorDirectionalLightComponent;
@@ -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, 1.0f)
->Attribute(Edit::Attributes::SoftMax, 2.0f)
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows)
->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::ShadowsDisabled)
@@ -134,7 +134,7 @@ namespace AZ
->EnumAttribute(ShadowFilterMethod::EsmPcf, "ESM+PCF")
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
->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"
"This is used only when the pixel is predicted to be on the boundary.\n"
"Specific to PCF and ESM+PCF.")
->Attribute(Edit::Attributes::Min, 4)
->Attribute(Edit::Attributes::Max, 64)
@@ -154,6 +154,13 @@ namespace AZ
->Attribute(Edit::Attributes::Min, 0.f)
->Attribute(Edit::Attributes::Max, 0.2)
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
->DataElement(
Edit::UIHandlers::Slider, &DirectionalLightComponentConfig::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)
;
}
}
@@ -465,7 +465,7 @@ void ApplyLighting(inout Surface surface, inout LightingData lightingData)
const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight;
if (o_enableShadows && shadowIndex < SceneSrg::m_directionalLightCount)
{
DirectionalLightShadow::GetShadowCoords(shadowIndex, surface.position, lightingData.shadowCoords);
DirectionalLightShadow::GetShadowCoords(shadowIndex, surface.position, surface.vertexNormal, lightingData.shadowCoords);
}
// Light loops application.
@@ -59,6 +59,7 @@ VSOutput TerrainPBR_MainPassVS(VertexInput IN)
DirectionalLightShadow::GetShadowCoords(
shadowIndex,
worldPosition,
OUT.m_normal,
OUT.m_shadowCoords);
}