rendering: formalize main light shadow bias settings
This commit is contained in:
@@ -65,7 +65,6 @@ Shader "Builtin Shadow Caster"
|
|||||||
Cull Back
|
Cull Back
|
||||||
ZWrite On
|
ZWrite On
|
||||||
ZTest LEqual
|
ZTest LEqual
|
||||||
Offset 1.0, 2
|
|
||||||
HLSLPROGRAM
|
HLSLPROGRAM
|
||||||
#pragma target 4.5
|
#pragma target 4.5
|
||||||
#pragma vertex MainVS
|
#pragma vertex MainVS
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <XCEngine/Core/Math/Vector4.h>
|
#include <XCEngine/Core/Math/Vector4.h>
|
||||||
#include <XCEngine/Rendering/FrameData/RenderCameraData.h>
|
#include <XCEngine/Rendering/FrameData/RenderCameraData.h>
|
||||||
#include <XCEngine/Rendering/FrameData/RenderEnvironmentData.h>
|
#include <XCEngine/Rendering/FrameData/RenderEnvironmentData.h>
|
||||||
|
#include <XCEngine/Rendering/Shadow/DirectionalShadowSettings.h>
|
||||||
#include <XCEngine/Rendering/FrameData/VisibleGaussianSplatItem.h>
|
#include <XCEngine/Rendering/FrameData/VisibleGaussianSplatItem.h>
|
||||||
#include <XCEngine/Rendering/FrameData/VisibleRenderItem.h>
|
#include <XCEngine/Rendering/FrameData/VisibleRenderItem.h>
|
||||||
#include <XCEngine/Rendering/FrameData/VisibleVolumeItem.h>
|
#include <XCEngine/Rendering/FrameData/VisibleVolumeItem.h>
|
||||||
@@ -63,20 +64,23 @@ static_assert(
|
|||||||
|
|
||||||
struct RenderDirectionalShadowSamplingData {
|
struct RenderDirectionalShadowSamplingData {
|
||||||
float enabled = 0.0f;
|
float enabled = 0.0f;
|
||||||
float receiverDepthBias = 0.0f;
|
DirectionalShadowSamplingSettings settings = {};
|
||||||
float normalBiasScale = 0.0f;
|
|
||||||
float shadowStrength = 0.0f;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(
|
static_assert(
|
||||||
sizeof(RenderDirectionalShadowSamplingData) == sizeof(float) * 4u,
|
sizeof(RenderDirectionalShadowSamplingData) == sizeof(float) * 4u,
|
||||||
"RenderDirectionalShadowSamplingData must stay float4-sized for GPU constant layout");
|
"RenderDirectionalShadowSamplingData must stay float4-sized for GPU constant layout");
|
||||||
|
|
||||||
|
struct RenderDirectionalShadowCasterBiasData {
|
||||||
|
DirectionalShadowCasterBiasSettings settings = {};
|
||||||
|
};
|
||||||
|
|
||||||
struct RenderDirectionalShadowData {
|
struct RenderDirectionalShadowData {
|
||||||
bool enabled = false;
|
bool enabled = false;
|
||||||
Math::Matrix4x4 viewProjection = Math::Matrix4x4::Identity();
|
Math::Matrix4x4 viewProjection = Math::Matrix4x4::Identity();
|
||||||
RenderDirectionalShadowMapMetrics mapMetrics = {};
|
RenderDirectionalShadowMapMetrics mapMetrics = {};
|
||||||
RenderDirectionalShadowSamplingData sampling = {};
|
RenderDirectionalShadowSamplingData sampling = {};
|
||||||
|
RenderDirectionalShadowCasterBiasData casterBias = {};
|
||||||
RHI::RHIResourceView* shadowMap = nullptr;
|
RHI::RHIResourceView* shadowMap = nullptr;
|
||||||
|
|
||||||
bool IsValid() const {
|
bool IsValid() const {
|
||||||
|
|||||||
@@ -171,6 +171,10 @@ private:
|
|||||||
ResolvedShaderPass ResolveSurfaceShaderPass(
|
ResolvedShaderPass ResolveSurfaceShaderPass(
|
||||||
const RenderSceneData& sceneData,
|
const RenderSceneData& sceneData,
|
||||||
const Resources::Material* material) const;
|
const Resources::Material* material) const;
|
||||||
|
Resources::MaterialRenderState ResolveEffectiveDepthRenderState(
|
||||||
|
const Resources::ShaderPass* shaderPass,
|
||||||
|
const Resources::Material* material,
|
||||||
|
const RenderSceneData& sceneData) const;
|
||||||
bool TryBuildSupportedBindingPlan(
|
bool TryBuildSupportedBindingPlan(
|
||||||
const Resources::ShaderPass& shaderPass,
|
const Resources::ShaderPass& shaderPass,
|
||||||
BuiltinPassResourceBindingPlan& outPlan,
|
BuiltinPassResourceBindingPlan& outPlan,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <XCEngine/Rendering/RenderContext.h>
|
#include <XCEngine/Rendering/RenderContext.h>
|
||||||
#include <XCEngine/Rendering/RenderPass.h>
|
#include <XCEngine/Rendering/RenderPass.h>
|
||||||
#include <XCEngine/Rendering/RenderSurface.h>
|
#include <XCEngine/Rendering/RenderSurface.h>
|
||||||
|
#include <XCEngine/Rendering/Shadow/DirectionalShadowSettings.h>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@@ -131,6 +132,8 @@ struct DirectionalShadowRenderPlan {
|
|||||||
float texelWorldSize = 0.0f;
|
float texelWorldSize = 0.0f;
|
||||||
float nearClipPlane = 0.1f;
|
float nearClipPlane = 0.1f;
|
||||||
float farClipPlane = 0.0f;
|
float farClipPlane = 0.0f;
|
||||||
|
DirectionalShadowSamplingSettings sampling = {};
|
||||||
|
DirectionalShadowCasterBiasSettings casterBias = {};
|
||||||
uint32_t mapWidth = 0;
|
uint32_t mapWidth = 0;
|
||||||
uint32_t mapHeight = 0;
|
uint32_t mapHeight = 0;
|
||||||
RenderCameraData cameraData = {};
|
RenderCameraData cameraData = {};
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ class Scene;
|
|||||||
|
|
||||||
namespace Rendering {
|
namespace Rendering {
|
||||||
|
|
||||||
// Planning-only knobs for fitting the single main-light shadow camera to the
|
// Planner-owned knobs for the single main-light shadow, including both camera
|
||||||
// current view. Receiver-side bias/filtering parameters live in runtime shadow
|
// fitting and the default sampling / caster bias values emitted into the
|
||||||
// data and are not configured here.
|
// runtime shadow contract.
|
||||||
struct DirectionalShadowPlanningSettings {
|
struct DirectionalShadowPlanningSettings {
|
||||||
uint32_t mapDimension = 1024u;
|
uint32_t mapDimension = 1024u;
|
||||||
float minFocusDistance = 5.0f;
|
float minFocusDistance = 5.0f;
|
||||||
@@ -24,6 +24,8 @@ struct DirectionalShadowPlanningSettings {
|
|||||||
float minDepthRange = 20.0f;
|
float minDepthRange = 20.0f;
|
||||||
float boundsPadding = 1.0f;
|
float boundsPadding = 1.0f;
|
||||||
float minDepthPadding = 2.0f;
|
float minDepthPadding = 2.0f;
|
||||||
|
DirectionalShadowSamplingSettings sampling = {};
|
||||||
|
DirectionalShadowCasterBiasSettings casterBias = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
class SceneRenderRequestPlanner {
|
class SceneRenderRequestPlanner {
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace XCEngine {
|
||||||
|
namespace Rendering {
|
||||||
|
|
||||||
|
struct DirectionalShadowSamplingSettings {
|
||||||
|
float receiverDepthBias = 0.0015f;
|
||||||
|
float normalBiasScale = 1.5f;
|
||||||
|
float shadowStrength = 0.85f;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DirectionalShadowCasterBiasSettings {
|
||||||
|
float depthBiasFactor = 1.0f;
|
||||||
|
int32_t depthBiasUnits = 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Rendering
|
||||||
|
} // namespace XCEngine
|
||||||
@@ -19,10 +19,6 @@ namespace Rendering {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr float kDirectionalShadowReceiverDepthBias = 0.0015f;
|
|
||||||
constexpr float kDirectionalShadowNormalBiasScale = 1.5f;
|
|
||||||
constexpr float kDirectionalShadowStrength = 0.85f;
|
|
||||||
|
|
||||||
std::shared_ptr<const RenderPipelineAsset> CreateDefaultPipelineAsset() {
|
std::shared_ptr<const RenderPipelineAsset> CreateDefaultPipelineAsset() {
|
||||||
static const std::shared_ptr<const RenderPipelineAsset> s_defaultPipelineAsset =
|
static const std::shared_ptr<const RenderPipelineAsset> s_defaultPipelineAsset =
|
||||||
std::make_shared<Pipelines::BuiltinForwardPipelineAsset>();
|
std::make_shared<Pipelines::BuiltinForwardPipelineAsset>();
|
||||||
@@ -395,9 +391,8 @@ RenderDirectionalShadowData BuildDirectionalShadowData(
|
|||||||
1.0f / static_cast<float>(plan.mapHeight));
|
1.0f / static_cast<float>(plan.mapHeight));
|
||||||
shadowData.mapMetrics.worldTexelSize = texelWorldSize;
|
shadowData.mapMetrics.worldTexelSize = texelWorldSize;
|
||||||
shadowData.sampling.enabled = 1.0f;
|
shadowData.sampling.enabled = 1.0f;
|
||||||
shadowData.sampling.receiverDepthBias = kDirectionalShadowReceiverDepthBias;
|
shadowData.sampling.settings = plan.sampling;
|
||||||
shadowData.sampling.normalBiasScale = kDirectionalShadowNormalBiasScale;
|
shadowData.casterBias.settings = plan.casterBias;
|
||||||
shadowData.sampling.shadowStrength = kDirectionalShadowStrength;
|
|
||||||
return shadowData;
|
return shadowData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ RHI::GraphicsPipelineDesc CreatePipelineDesc(
|
|||||||
const Resources::ShaderPass& shaderPass,
|
const Resources::ShaderPass& shaderPass,
|
||||||
const Containers::String& passName,
|
const Containers::String& passName,
|
||||||
const Resources::ShaderKeywordSet& keywordSet,
|
const Resources::ShaderKeywordSet& keywordSet,
|
||||||
const Resources::Material* material,
|
const Resources::MaterialRenderState& renderState,
|
||||||
const RenderSurface& surface,
|
const RenderSurface& surface,
|
||||||
const RHI::InputLayoutDesc& inputLayout) {
|
const RHI::InputLayoutDesc& inputLayout) {
|
||||||
RHI::GraphicsPipelineDesc pipelineDesc = {};
|
RHI::GraphicsPipelineDesc pipelineDesc = {};
|
||||||
@@ -116,7 +116,7 @@ RHI::GraphicsPipelineDesc CreatePipelineDesc(
|
|||||||
pipelineDesc.topologyType = static_cast<uint32_t>(RHI::PrimitiveTopologyType::Triangle);
|
pipelineDesc.topologyType = static_cast<uint32_t>(RHI::PrimitiveTopologyType::Triangle);
|
||||||
::XCEngine::Rendering::Internal::ApplySurfacePropertiesToGraphicsPipelineDesc(surface, pipelineDesc);
|
::XCEngine::Rendering::Internal::ApplySurfacePropertiesToGraphicsPipelineDesc(surface, pipelineDesc);
|
||||||
pipelineDesc.inputLayout = inputLayout;
|
pipelineDesc.inputLayout = inputLayout;
|
||||||
ApplyResolvedRenderState(&shaderPass, material, pipelineDesc);
|
ApplyRenderState(renderState, pipelineDesc);
|
||||||
|
|
||||||
if (!shaderPass.hasFixedFunctionState) {
|
if (!shaderPass.hasFixedFunctionState) {
|
||||||
pipelineDesc.blendState.blendEnable = false;
|
pipelineDesc.blendState.blendEnable = false;
|
||||||
@@ -345,6 +345,20 @@ BuiltinDepthStylePassBase::ResolvedShaderPass BuiltinDepthStylePassBase::Resolve
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Resources::MaterialRenderState BuiltinDepthStylePassBase::ResolveEffectiveDepthRenderState(
|
||||||
|
const Resources::ShaderPass* shaderPass,
|
||||||
|
const Resources::Material* material,
|
||||||
|
const RenderSceneData& sceneData) const {
|
||||||
|
Resources::MaterialRenderState renderState = ResolveEffectiveRenderState(shaderPass, material);
|
||||||
|
if (m_passType == BuiltinMaterialPass::ShadowCaster) {
|
||||||
|
renderState.depthBiasFactor =
|
||||||
|
sceneData.lighting.mainDirectionalShadow.casterBias.settings.depthBiasFactor;
|
||||||
|
renderState.depthBiasUnits =
|
||||||
|
sceneData.lighting.mainDirectionalShadow.casterBias.settings.depthBiasUnits;
|
||||||
|
}
|
||||||
|
return renderState;
|
||||||
|
}
|
||||||
|
|
||||||
bool BuiltinDepthStylePassBase::TryBuildSupportedBindingPlan(
|
bool BuiltinDepthStylePassBase::TryBuildSupportedBindingPlan(
|
||||||
const Resources::ShaderPass& shaderPass,
|
const Resources::ShaderPass& shaderPass,
|
||||||
BuiltinPassResourceBindingPlan& outPlan,
|
BuiltinPassResourceBindingPlan& outPlan,
|
||||||
@@ -466,8 +480,9 @@ RHI::RHIPipelineState* BuiltinDepthStylePassBase::GetOrCreatePipelineState(
|
|||||||
}
|
}
|
||||||
|
|
||||||
PipelineStateKey pipelineKey = {};
|
PipelineStateKey pipelineKey = {};
|
||||||
pipelineKey.renderState =
|
const Resources::MaterialRenderState effectiveRenderState =
|
||||||
BuildStaticPipelineRenderStateKey(ResolveEffectiveRenderState(resolvedShaderPass.pass, material));
|
ResolveEffectiveDepthRenderState(resolvedShaderPass.pass, material, sceneData);
|
||||||
|
pipelineKey.renderState = BuildStaticPipelineRenderStateKey(effectiveRenderState);
|
||||||
pipelineKey.shader = resolvedShaderPass.shader;
|
pipelineKey.shader = resolvedShaderPass.shader;
|
||||||
pipelineKey.passName = resolvedShaderPass.passName;
|
pipelineKey.passName = resolvedShaderPass.passName;
|
||||||
pipelineKey.keywordSignature = ::XCEngine::Rendering::Internal::BuildShaderKeywordSignature(keywordSet);
|
pipelineKey.keywordSignature = ::XCEngine::Rendering::Internal::BuildShaderKeywordSignature(keywordSet);
|
||||||
@@ -493,7 +508,7 @@ RHI::RHIPipelineState* BuiltinDepthStylePassBase::GetOrCreatePipelineState(
|
|||||||
*resolvedShaderPass.pass,
|
*resolvedShaderPass.pass,
|
||||||
resolvedShaderPass.passName,
|
resolvedShaderPass.passName,
|
||||||
keywordSet,
|
keywordSet,
|
||||||
material,
|
effectiveRenderState,
|
||||||
surface,
|
surface,
|
||||||
BuildCommonInputLayout());
|
BuildCommonInputLayout());
|
||||||
RHI::RHIPipelineState* pipelineState = context.device->CreatePipelineState(pipelineDesc);
|
RHI::RHIPipelineState* pipelineState = context.device->CreatePipelineState(pipelineDesc);
|
||||||
@@ -743,7 +758,7 @@ bool BuiltinDepthStylePassBase::DrawVisibleItem(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const Resources::MaterialRenderState effectiveRenderState =
|
const Resources::MaterialRenderState effectiveRenderState =
|
||||||
ResolveEffectiveRenderState(resolvedShaderPass.pass, material);
|
ResolveEffectiveDepthRenderState(resolvedShaderPass.pass, material, sceneData);
|
||||||
|
|
||||||
PassLayoutKey passLayoutKey = {};
|
PassLayoutKey passLayoutKey = {};
|
||||||
passLayoutKey.shader = resolvedShaderPass.shader;
|
passLayoutKey.shader = resolvedShaderPass.shader;
|
||||||
|
|||||||
@@ -111,6 +111,27 @@ DirectionalShadowPlanningSettings SanitizeDirectionalShadowPlanningSettings(
|
|||||||
if (sanitized.minDepthPadding < 0.0f) {
|
if (sanitized.minDepthPadding < 0.0f) {
|
||||||
sanitized.minDepthPadding = defaults.minDepthPadding;
|
sanitized.minDepthPadding = defaults.minDepthPadding;
|
||||||
}
|
}
|
||||||
|
if (!std::isfinite(sanitized.sampling.receiverDepthBias) ||
|
||||||
|
sanitized.sampling.receiverDepthBias < 0.0f) {
|
||||||
|
sanitized.sampling.receiverDepthBias = defaults.sampling.receiverDepthBias;
|
||||||
|
}
|
||||||
|
if (!std::isfinite(sanitized.sampling.normalBiasScale) ||
|
||||||
|
sanitized.sampling.normalBiasScale < 0.0f) {
|
||||||
|
sanitized.sampling.normalBiasScale = defaults.sampling.normalBiasScale;
|
||||||
|
}
|
||||||
|
if (!std::isfinite(sanitized.sampling.shadowStrength)) {
|
||||||
|
sanitized.sampling.shadowStrength = defaults.sampling.shadowStrength;
|
||||||
|
} else {
|
||||||
|
sanitized.sampling.shadowStrength =
|
||||||
|
std::clamp(sanitized.sampling.shadowStrength, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
if (!std::isfinite(sanitized.casterBias.depthBiasFactor) ||
|
||||||
|
sanitized.casterBias.depthBiasFactor < 0.0f) {
|
||||||
|
sanitized.casterBias.depthBiasFactor = defaults.casterBias.depthBiasFactor;
|
||||||
|
}
|
||||||
|
if (sanitized.casterBias.depthBiasUnits < 0) {
|
||||||
|
sanitized.casterBias.depthBiasUnits = defaults.casterBias.depthBiasUnits;
|
||||||
|
}
|
||||||
|
|
||||||
return sanitized;
|
return sanitized;
|
||||||
}
|
}
|
||||||
@@ -340,6 +361,8 @@ DirectionalShadowRenderPlan BuildDirectionalShadowRenderPlan(
|
|||||||
plan.texelWorldSize = std::max(shadowTexelSizeX, shadowTexelSizeY);
|
plan.texelWorldSize = std::max(shadowTexelSizeX, shadowTexelSizeY);
|
||||||
plan.nearClipPlane = minZ;
|
plan.nearClipPlane = minZ;
|
||||||
plan.farClipPlane = maxZ;
|
plan.farClipPlane = maxZ;
|
||||||
|
plan.sampling = shadowSettings.sampling;
|
||||||
|
plan.casterBias = shadowSettings.casterBias;
|
||||||
plan.mapWidth = shadowSettings.mapDimension;
|
plan.mapWidth = shadowSettings.mapDimension;
|
||||||
plan.mapHeight = shadowSettings.mapDimension;
|
plan.mapHeight = shadowSettings.mapDimension;
|
||||||
plan.cameraData.view = view.Transpose();
|
plan.cameraData.view = view.Transpose();
|
||||||
|
|||||||
@@ -44,7 +44,8 @@ struct MockPipelineState {
|
|||||||
bool lastHasMainDirectionalShadow = false;
|
bool lastHasMainDirectionalShadow = false;
|
||||||
XCEngine::RHI::RHIResourceView* lastShadowMap = nullptr;
|
XCEngine::RHI::RHIResourceView* lastShadowMap = nullptr;
|
||||||
XCEngine::Math::Matrix4x4 lastShadowViewProjection = XCEngine::Math::Matrix4x4::Identity();
|
XCEngine::Math::Matrix4x4 lastShadowViewProjection = XCEngine::Math::Matrix4x4::Identity();
|
||||||
XCEngine::Math::Vector4 lastShadowParams = XCEngine::Math::Vector4::Zero();
|
RenderDirectionalShadowMapMetrics lastShadowMapMetrics = {};
|
||||||
|
RenderDirectionalShadowSamplingData lastShadowSampling = {};
|
||||||
bool lastHasMainDirectionalShadowKeyword = false;
|
bool lastHasMainDirectionalShadowKeyword = false;
|
||||||
RenderEnvironmentMode lastEnvironmentMode = RenderEnvironmentMode::None;
|
RenderEnvironmentMode lastEnvironmentMode = RenderEnvironmentMode::None;
|
||||||
bool lastHasSkybox = false;
|
bool lastHasSkybox = false;
|
||||||
@@ -327,7 +328,8 @@ public:
|
|||||||
m_state->lastHasMainDirectionalShadow = sceneData.lighting.HasMainDirectionalShadow();
|
m_state->lastHasMainDirectionalShadow = sceneData.lighting.HasMainDirectionalShadow();
|
||||||
m_state->lastShadowMap = sceneData.lighting.mainDirectionalShadow.shadowMap;
|
m_state->lastShadowMap = sceneData.lighting.mainDirectionalShadow.shadowMap;
|
||||||
m_state->lastShadowViewProjection = sceneData.lighting.mainDirectionalShadow.viewProjection;
|
m_state->lastShadowViewProjection = sceneData.lighting.mainDirectionalShadow.viewProjection;
|
||||||
m_state->lastShadowParams = sceneData.lighting.mainDirectionalShadow.shadowParams;
|
m_state->lastShadowMapMetrics = sceneData.lighting.mainDirectionalShadow.mapMetrics;
|
||||||
|
m_state->lastShadowSampling = sceneData.lighting.mainDirectionalShadow.sampling;
|
||||||
m_state->lastHasMainDirectionalShadowKeyword =
|
m_state->lastHasMainDirectionalShadowKeyword =
|
||||||
XCEngine::Resources::ShaderKeywordSetContains(
|
XCEngine::Resources::ShaderKeywordSetContains(
|
||||||
sceneData.globalShaderKeywords,
|
sceneData.globalShaderKeywords,
|
||||||
@@ -1338,10 +1340,10 @@ TEST(CameraRenderer_Test, AutoAllocatesDirectionalShadowSurfaceFromShadowPlan) {
|
|||||||
EXPECT_FLOAT_EQ(pipelineState->lastShadowViewProjection.m[0][3], 11.0f);
|
EXPECT_FLOAT_EQ(pipelineState->lastShadowViewProjection.m[0][3], 11.0f);
|
||||||
EXPECT_FLOAT_EQ(pipelineState->lastShadowViewProjection.m[1][3], 12.0f);
|
EXPECT_FLOAT_EQ(pipelineState->lastShadowViewProjection.m[1][3], 12.0f);
|
||||||
EXPECT_FLOAT_EQ(pipelineState->lastShadowViewProjection.m[2][3], 13.0f);
|
EXPECT_FLOAT_EQ(pipelineState->lastShadowViewProjection.m[2][3], 13.0f);
|
||||||
EXPECT_FLOAT_EQ(pipelineState->lastShadowParams.x, 0.0015f);
|
EXPECT_FLOAT_EQ(pipelineState->lastShadowSampling.settings.receiverDepthBias, 0.0015f);
|
||||||
EXPECT_FLOAT_EQ(pipelineState->lastShadowParams.y, 1.0f / 256.0f);
|
EXPECT_FLOAT_EQ(pipelineState->lastShadowMapMetrics.inverseMapSize.x, 1.0f / 256.0f);
|
||||||
EXPECT_FLOAT_EQ(pipelineState->lastShadowParams.z, 1.0f / 128.0f);
|
EXPECT_FLOAT_EQ(pipelineState->lastShadowMapMetrics.inverseMapSize.y, 1.0f / 128.0f);
|
||||||
EXPECT_FLOAT_EQ(pipelineState->lastShadowParams.w, 0.85f);
|
EXPECT_FLOAT_EQ(pipelineState->lastShadowSampling.settings.shadowStrength, 0.85f);
|
||||||
EXPECT_TRUE(pipelineState->lastHasMainDirectionalShadowKeyword);
|
EXPECT_TRUE(pipelineState->lastHasMainDirectionalShadowKeyword);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -224,6 +224,11 @@ TEST(SceneRenderRequestPlanner_Test, AppliesConfiguredDirectionalShadowPlanningS
|
|||||||
settings.maxFocusDistance = 12.0f;
|
settings.maxFocusDistance = 12.0f;
|
||||||
settings.perspectiveFocusFactor = 0.01f;
|
settings.perspectiveFocusFactor = 0.01f;
|
||||||
settings.minDepthRange = 80.0f;
|
settings.minDepthRange = 80.0f;
|
||||||
|
settings.sampling.receiverDepthBias = 0.0025f;
|
||||||
|
settings.sampling.normalBiasScale = 2.0f;
|
||||||
|
settings.sampling.shadowStrength = 0.75f;
|
||||||
|
settings.casterBias.depthBiasFactor = 2.5f;
|
||||||
|
settings.casterBias.depthBiasUnits = 4;
|
||||||
planner.SetDirectionalShadowPlanningSettings(settings);
|
planner.SetDirectionalShadowPlanningSettings(settings);
|
||||||
|
|
||||||
const std::vector<CameraRenderRequest> requests = planner.BuildRequests(
|
const std::vector<CameraRenderRequest> requests = planner.BuildRequests(
|
||||||
@@ -241,6 +246,11 @@ TEST(SceneRenderRequestPlanner_Test, AppliesConfiguredDirectionalShadowPlanningS
|
|||||||
EXPECT_EQ(request.shadowCaster.cameraDataOverride.viewportHeight, 2048u);
|
EXPECT_EQ(request.shadowCaster.cameraDataOverride.viewportHeight, 2048u);
|
||||||
EXPECT_GE(request.directionalShadow.focusPoint.z, 6.0f);
|
EXPECT_GE(request.directionalShadow.focusPoint.z, 6.0f);
|
||||||
EXPECT_LE(request.directionalShadow.focusPoint.z, 6.3f);
|
EXPECT_LE(request.directionalShadow.focusPoint.z, 6.3f);
|
||||||
|
EXPECT_FLOAT_EQ(request.directionalShadow.sampling.receiverDepthBias, 0.0025f);
|
||||||
|
EXPECT_FLOAT_EQ(request.directionalShadow.sampling.normalBiasScale, 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(request.directionalShadow.sampling.shadowStrength, 0.75f);
|
||||||
|
EXPECT_FLOAT_EQ(request.directionalShadow.casterBias.depthBiasFactor, 2.5f);
|
||||||
|
EXPECT_EQ(request.directionalShadow.casterBias.depthBiasUnits, 4);
|
||||||
EXPECT_GE(
|
EXPECT_GE(
|
||||||
request.directionalShadow.farClipPlane - request.directionalShadow.nearClipPlane,
|
request.directionalShadow.farClipPlane - request.directionalShadow.nearClipPlane,
|
||||||
80.0f);
|
80.0f);
|
||||||
@@ -258,6 +268,11 @@ TEST(SceneRenderRequestPlanner_Test, SanitizesInvalidDirectionalShadowPlanningSe
|
|||||||
invalidSettings.minDepthRange = 0.0f;
|
invalidSettings.minDepthRange = 0.0f;
|
||||||
invalidSettings.boundsPadding = -1.0f;
|
invalidSettings.boundsPadding = -1.0f;
|
||||||
invalidSettings.minDepthPadding = -3.0f;
|
invalidSettings.minDepthPadding = -3.0f;
|
||||||
|
invalidSettings.sampling.receiverDepthBias = -0.5f;
|
||||||
|
invalidSettings.sampling.normalBiasScale = -2.0f;
|
||||||
|
invalidSettings.sampling.shadowStrength = 3.0f;
|
||||||
|
invalidSettings.casterBias.depthBiasFactor = -1.0f;
|
||||||
|
invalidSettings.casterBias.depthBiasUnits = -6;
|
||||||
planner.SetDirectionalShadowPlanningSettings(invalidSettings);
|
planner.SetDirectionalShadowPlanningSettings(invalidSettings);
|
||||||
|
|
||||||
const DirectionalShadowPlanningSettings& settings =
|
const DirectionalShadowPlanningSettings& settings =
|
||||||
@@ -270,4 +285,9 @@ TEST(SceneRenderRequestPlanner_Test, SanitizesInvalidDirectionalShadowPlanningSe
|
|||||||
EXPECT_FLOAT_EQ(settings.minDepthRange, 20.0f);
|
EXPECT_FLOAT_EQ(settings.minDepthRange, 20.0f);
|
||||||
EXPECT_FLOAT_EQ(settings.boundsPadding, 1.0f);
|
EXPECT_FLOAT_EQ(settings.boundsPadding, 1.0f);
|
||||||
EXPECT_FLOAT_EQ(settings.minDepthPadding, 2.0f);
|
EXPECT_FLOAT_EQ(settings.minDepthPadding, 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(settings.sampling.receiverDepthBias, 0.0015f);
|
||||||
|
EXPECT_FLOAT_EQ(settings.sampling.normalBiasScale, 1.5f);
|
||||||
|
EXPECT_FLOAT_EQ(settings.sampling.shadowStrength, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(settings.casterBias.depthBiasFactor, 1.0f);
|
||||||
|
EXPECT_EQ(settings.casterBias.depthBiasUnits, 2);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user