Add forward shadow receiving support

This commit is contained in:
2026-04-04 23:01:34 +08:00
parent 353d129613
commit 96a44da2cb
22 changed files with 889 additions and 89 deletions

View File

@@ -143,8 +143,12 @@ private:
ComPtr<ID3D12GraphicsCommandList> m_commandList;
ComPtr<ID3D12CommandAllocator> m_commandAllocator;
ComPtr<ID3D12DescriptorHeap> m_rtvHeap;
ComPtr<ID3D12DescriptorHeap> m_shaderVisibleCbvSrvUavHeap;
ComPtr<ID3D12DescriptorHeap> m_shaderVisibleSamplerHeap;
ID3D12Device* m_device = nullptr;
CommandQueueType m_type;
uint32_t m_shaderVisibleCbvSrvUavHeapCapacity = 0;
uint32_t m_shaderVisibleSamplerHeapCapacity = 0;
std::unordered_map<ID3D12Resource*, ResourceStates> m_resourceStateMap;
std::vector<ID3D12Resource*> m_trackedResources;

View File

@@ -42,6 +42,8 @@ public:
D3D12_GPU_DESCRIPTOR_HANDLE GetGPUHandle(uint32_t index = 0) const;
D3D12_GPU_DESCRIPTOR_HANDLE GetGPUHandleForBinding(uint32_t binding) const;
D3D12_CPU_DESCRIPTOR_HANDLE GetCPUHandleForBinding(uint32_t binding) const;
uint32_t GetDescriptorCountForBinding(uint32_t binding) const;
uint32_t GetOffset() const { return m_offset; }
uint32_t GetCount() const { return m_count; }
D3D12DescriptorHeap* GetHeap() const { return m_heap; }

View File

@@ -68,6 +68,12 @@ private:
Math::Vector4 mainLightColorAndFlags = Math::Vector4::Zero();
};
struct ShadowReceiverConstants {
Math::Matrix4x4 worldToShadow = Math::Matrix4x4::Identity();
Math::Vector4 shadowBiasAndTexelSize = Math::Vector4::Zero();
Math::Vector4 shadowOptions = Math::Vector4::Zero();
};
struct FallbackPerMaterialConstants {
Math::Vector4 baseColorFactor = Math::Vector4::One();
};
@@ -97,8 +103,11 @@ private:
std::vector<OwnedDescriptorSet> staticDescriptorSets;
PassResourceBindingLocation perObject = {};
PassResourceBindingLocation material = {};
PassResourceBindingLocation shadowReceiver = {};
PassResourceBindingLocation baseColorTexture = {};
PassResourceBindingLocation linearClampSampler = {};
PassResourceBindingLocation shadowMapTexture = {};
PassResourceBindingLocation shadowMapSampler = {};
};
struct DynamicDescriptorSetKey {
@@ -132,7 +141,8 @@ private:
struct CachedDescriptorSet {
OwnedDescriptorSet descriptorSet = {};
Core::uint64 materialVersion = 0;
RHI::RHIResourceView* textureView = nullptr;
RHI::RHIResourceView* baseColorTextureView = nullptr;
RHI::RHIResourceView* shadowMapTextureView = nullptr;
};
struct ResolvedShaderPass {
@@ -190,7 +200,9 @@ private:
Core::uint64 objectId,
const Resources::Material* material,
const MaterialConstantPayloadView& materialConstants,
RHI::RHIResourceView* textureView);
const ShadowReceiverConstants& shadowReceiverConstants,
RHI::RHIResourceView* baseColorTextureView,
RHI::RHIResourceView* shadowMapTextureView);
void DestroyOwnedDescriptorSet(OwnedDescriptorSet& descriptorSet);
void DestroyPassResourceLayout(PassResourceLayout& passLayout);
@@ -214,6 +226,7 @@ private:
std::unordered_map<PipelineStateKey, RHI::RHIPipelineState*, PipelineStateKeyHash> m_pipelineStates;
std::unordered_map<DynamicDescriptorSetKey, CachedDescriptorSet, DynamicDescriptorSetKeyHash> m_dynamicDescriptorSets;
RHI::RHISampler* m_sampler = nullptr;
RHI::RHISampler* m_shadowSampler = nullptr;
RHI::RHITexture* m_fallbackTexture = nullptr;
RHI::RHIResourceView* m_fallbackTextureView = nullptr;
RenderPassSequence m_passSequence;

View File

@@ -37,8 +37,11 @@ enum class BuiltinPassResourceSemantic : Core::uint8 {
Unknown = 0,
PerObject,
Material,
ShadowReceiver,
BaseColorTexture,
LinearClampSampler
ShadowMapTexture,
LinearClampSampler,
ShadowMapSampler
};
struct BuiltinPassResourceBindingDesc {
@@ -57,8 +60,11 @@ struct BuiltinPassResourceBindingPlan {
bool usesSamplers = false;
PassResourceBindingLocation perObject = {};
PassResourceBindingLocation material = {};
PassResourceBindingLocation shadowReceiver = {};
PassResourceBindingLocation baseColorTexture = {};
PassResourceBindingLocation linearClampSampler = {};
PassResourceBindingLocation shadowMapTexture = {};
PassResourceBindingLocation shadowMapSampler = {};
const BuiltinPassResourceBindingDesc* FindBinding(BuiltinPassResourceSemantic semantic) const {
for (const BuiltinPassResourceBindingDesc& binding : bindings) {
@@ -78,8 +84,13 @@ struct BuiltinPassSetLayoutMetadata {
bool shaderVisible = false;
bool usesPerObject = false;
bool usesMaterial = false;
bool usesShadowReceiver = false;
bool usesTexture = false;
bool usesBaseColorTexture = false;
bool usesShadowMapTexture = false;
bool usesSampler = false;
bool usesLinearClampSampler = false;
bool usesShadowMapSampler = false;
};
inline Containers::String NormalizeBuiltinPassMetadataValue(const Containers::String& value) {
@@ -198,15 +209,30 @@ inline BuiltinPassResourceSemantic ResolveBuiltinPassResourceSemantic(
return BuiltinPassResourceSemantic::Material;
}
if (semantic == Containers::String("shadowreceiver") ||
semantic == Containers::String("shadowreceiverconstants")) {
return BuiltinPassResourceSemantic::ShadowReceiver;
}
if (semantic == Containers::String("basecolortexture") ||
semantic == Containers::String("maintex")) {
return BuiltinPassResourceSemantic::BaseColorTexture;
}
if (semantic == Containers::String("shadowmaptexture") ||
semantic == Containers::String("shadowmap")) {
return BuiltinPassResourceSemantic::ShadowMapTexture;
}
if (semantic == Containers::String("linearclampsampler")) {
return BuiltinPassResourceSemantic::LinearClampSampler;
}
if (semantic == Containers::String("shadowmapsampler") ||
semantic == Containers::String("shadowsampler")) {
return BuiltinPassResourceSemantic::ShadowMapSampler;
}
return BuiltinPassResourceSemantic::Unknown;
}
@@ -286,11 +312,14 @@ inline bool IsBuiltinPassResourceTypeCompatible(
switch (semantic) {
case BuiltinPassResourceSemantic::PerObject:
case BuiltinPassResourceSemantic::Material:
case BuiltinPassResourceSemantic::ShadowReceiver:
return type == Resources::ShaderResourceType::ConstantBuffer;
case BuiltinPassResourceSemantic::BaseColorTexture:
case BuiltinPassResourceSemantic::ShadowMapTexture:
return type == Resources::ShaderResourceType::Texture2D ||
type == Resources::ShaderResourceType::TextureCube;
case BuiltinPassResourceSemantic::LinearClampSampler:
case BuiltinPassResourceSemantic::ShadowMapSampler:
return type == Resources::ShaderResourceType::Sampler;
case BuiltinPassResourceSemantic::Unknown:
default:
@@ -336,12 +365,21 @@ inline bool TryBuildBuiltinPassResourceBindingPlan(
case BuiltinPassResourceSemantic::Material:
location = &outPlan.material;
break;
case BuiltinPassResourceSemantic::ShadowReceiver:
location = &outPlan.shadowReceiver;
break;
case BuiltinPassResourceSemantic::BaseColorTexture:
location = &outPlan.baseColorTexture;
break;
case BuiltinPassResourceSemantic::LinearClampSampler:
location = &outPlan.linearClampSampler;
break;
case BuiltinPassResourceSemantic::ShadowMapTexture:
location = &outPlan.shadowMapTexture;
break;
case BuiltinPassResourceSemantic::ShadowMapSampler:
location = &outPlan.shadowMapSampler;
break;
case BuiltinPassResourceSemantic::Unknown:
default:
break;
@@ -520,11 +558,24 @@ inline bool TryBuildBuiltinPassSetLayouts(
case BuiltinPassResourceSemantic::Material:
setLayout.usesMaterial = true;
break;
case BuiltinPassResourceSemantic::ShadowReceiver:
setLayout.usesShadowReceiver = true;
break;
case BuiltinPassResourceSemantic::BaseColorTexture:
setLayout.usesTexture = true;
setLayout.usesBaseColorTexture = true;
break;
case BuiltinPassResourceSemantic::ShadowMapTexture:
setLayout.usesTexture = true;
setLayout.usesShadowMapTexture = true;
break;
case BuiltinPassResourceSemantic::LinearClampSampler:
setLayout.usesSampler = true;
setLayout.usesLinearClampSampler = true;
break;
case BuiltinPassResourceSemantic::ShadowMapSampler:
setLayout.usesSampler = true;
setLayout.usesShadowMapSampler = true;
break;
case BuiltinPassResourceSemantic::Unknown:
default:

View File

@@ -1,5 +1,6 @@
#pragma once
#include <XCEngine/Core/Math/Vector4.h>
#include <XCEngine/Core/Math/Vector3.h>
#include <XCEngine/Rendering/RenderCameraData.h>
#include <XCEngine/Rendering/VisibleRenderObject.h>
@@ -14,6 +15,10 @@ class GameObject;
class Scene;
} // namespace Components
namespace RHI {
class RHIResourceView;
} // namespace RHI
namespace Rendering {
struct RenderDirectionalLightData {
@@ -24,12 +29,28 @@ struct RenderDirectionalLightData {
Math::Color color = Math::Color::White();
};
struct RenderDirectionalShadowData {
bool enabled = false;
Math::Matrix4x4 viewProjection = Math::Matrix4x4::Identity();
Math::Vector4 shadowParams = Math::Vector4::Zero();
RHI::RHIResourceView* shadowMap = nullptr;
bool IsValid() const {
return enabled && shadowMap != nullptr;
}
};
struct RenderLightingData {
RenderDirectionalLightData mainDirectionalLight;
RenderDirectionalShadowData mainDirectionalShadow;
bool HasMainDirectionalLight() const {
return mainDirectionalLight.enabled;
}
bool HasMainDirectionalShadow() const {
return mainDirectionalShadow.IsValid();
}
};
struct RenderSceneData {