Add directional shadow integration coverage
This commit is contained in:
@@ -14,22 +14,32 @@
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
|
||||
namespace {
|
||||
|
||||
struct OwnedShadowSurfaceResources {
|
||||
struct CameraRenderer::DirectionalShadowSurfaceResources {
|
||||
RHI::RHIDevice* device = nullptr;
|
||||
uint32_t width = 0;
|
||||
uint32_t height = 0;
|
||||
RHI::RHITexture* depthTexture = nullptr;
|
||||
RHI::RHIResourceView* depthView = nullptr;
|
||||
RHI::RHIResourceView* shaderView = nullptr;
|
||||
RenderSurface surface = {};
|
||||
|
||||
OwnedShadowSurfaceResources() = default;
|
||||
OwnedShadowSurfaceResources(const OwnedShadowSurfaceResources&) = delete;
|
||||
OwnedShadowSurfaceResources& operator=(const OwnedShadowSurfaceResources&) = delete;
|
||||
DirectionalShadowSurfaceResources() = default;
|
||||
DirectionalShadowSurfaceResources(const DirectionalShadowSurfaceResources&) = delete;
|
||||
DirectionalShadowSurfaceResources& operator=(const DirectionalShadowSurfaceResources&) = delete;
|
||||
|
||||
~OwnedShadowSurfaceResources() {
|
||||
~DirectionalShadowSurfaceResources() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
bool Matches(const RenderContext& context, const DirectionalShadowRenderPlan& plan) const {
|
||||
return device == context.device &&
|
||||
width == plan.mapWidth &&
|
||||
height == plan.mapHeight &&
|
||||
depthTexture != nullptr &&
|
||||
depthView != nullptr &&
|
||||
shaderView != nullptr;
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
if (shaderView != nullptr) {
|
||||
shaderView->Shutdown();
|
||||
@@ -49,10 +59,15 @@ struct OwnedShadowSurfaceResources {
|
||||
depthTexture = nullptr;
|
||||
}
|
||||
|
||||
device = nullptr;
|
||||
width = 0;
|
||||
height = 0;
|
||||
surface = RenderSurface();
|
||||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
bool InitializePassSequence(
|
||||
RenderPassSequence* sequence,
|
||||
const RenderContext& context,
|
||||
@@ -150,67 +165,6 @@ bool ExecuteScenePassRequest(
|
||||
return pass->Execute(passContext);
|
||||
}
|
||||
|
||||
bool CreateDirectionalShadowSurface(
|
||||
const RenderContext& context,
|
||||
const DirectionalShadowRenderPlan& plan,
|
||||
OwnedShadowSurfaceResources& outResources) {
|
||||
if (!context.IsValid() || !plan.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RHI::TextureDesc depthDesc = {};
|
||||
depthDesc.width = plan.mapWidth;
|
||||
depthDesc.height = plan.mapHeight;
|
||||
depthDesc.depth = 1;
|
||||
depthDesc.mipLevels = 1;
|
||||
depthDesc.arraySize = 1;
|
||||
depthDesc.format = static_cast<uint32_t>(RHI::Format::D24_UNorm_S8_UInt);
|
||||
depthDesc.textureType = static_cast<uint32_t>(RHI::TextureType::Texture2D);
|
||||
depthDesc.sampleCount = 1;
|
||||
depthDesc.sampleQuality = 0;
|
||||
depthDesc.flags = 0;
|
||||
|
||||
RHI::RHITexture* depthTexture = context.device->CreateTexture(depthDesc);
|
||||
if (depthTexture == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RHI::ResourceViewDesc depthViewDesc = {};
|
||||
depthViewDesc.format = static_cast<uint32_t>(RHI::Format::D24_UNorm_S8_UInt);
|
||||
depthViewDesc.dimension = RHI::ResourceViewDimension::Texture2D;
|
||||
depthViewDesc.mipLevel = 0;
|
||||
|
||||
RHI::RHIResourceView* depthView =
|
||||
context.device->CreateDepthStencilView(depthTexture, depthViewDesc);
|
||||
if (depthView == nullptr) {
|
||||
depthTexture->Shutdown();
|
||||
delete depthTexture;
|
||||
return false;
|
||||
}
|
||||
|
||||
RHI::ResourceViewDesc shaderViewDesc = {};
|
||||
shaderViewDesc.format = depthDesc.format;
|
||||
shaderViewDesc.dimension = RHI::ResourceViewDimension::Texture2D;
|
||||
shaderViewDesc.mipLevel = 0;
|
||||
RHI::RHIResourceView* shaderView =
|
||||
context.device->CreateShaderResourceView(depthTexture, shaderViewDesc);
|
||||
if (shaderView == nullptr) {
|
||||
depthView->Shutdown();
|
||||
delete depthView;
|
||||
depthTexture->Shutdown();
|
||||
delete depthTexture;
|
||||
return false;
|
||||
}
|
||||
|
||||
outResources.Reset();
|
||||
outResources.depthTexture = depthTexture;
|
||||
outResources.depthView = depthView;
|
||||
outResources.shaderView = shaderView;
|
||||
outResources.surface = RenderSurface(plan.mapWidth, plan.mapHeight);
|
||||
outResources.surface.SetDepthAttachment(depthView);
|
||||
return true;
|
||||
}
|
||||
|
||||
RenderDirectionalShadowData BuildDirectionalShadowData(
|
||||
const DirectionalShadowRenderPlan& plan,
|
||||
RHI::RHIResourceView* shadowMapView) {
|
||||
@@ -343,6 +297,75 @@ void CameraRenderer::ResetPipeline(std::unique_ptr<RenderPipeline> pipeline) {
|
||||
}
|
||||
}
|
||||
|
||||
CameraRenderer::DirectionalShadowSurfaceResources* CameraRenderer::AcquireDirectionalShadowSurface(
|
||||
const RenderContext& context,
|
||||
const DirectionalShadowRenderPlan& plan) {
|
||||
if (!context.IsValid() || !plan.IsValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (m_directionalShadowSurface == nullptr) {
|
||||
m_directionalShadowSurface = std::make_unique<DirectionalShadowSurfaceResources>();
|
||||
}
|
||||
|
||||
if (!m_directionalShadowSurface->Matches(context, plan)) {
|
||||
RHI::TextureDesc depthDesc = {};
|
||||
depthDesc.width = plan.mapWidth;
|
||||
depthDesc.height = plan.mapHeight;
|
||||
depthDesc.depth = 1;
|
||||
depthDesc.mipLevels = 1;
|
||||
depthDesc.arraySize = 1;
|
||||
depthDesc.format = static_cast<uint32_t>(RHI::Format::D24_UNorm_S8_UInt);
|
||||
depthDesc.textureType = static_cast<uint32_t>(RHI::TextureType::Texture2D);
|
||||
depthDesc.sampleCount = 1;
|
||||
depthDesc.sampleQuality = 0;
|
||||
depthDesc.flags = 0;
|
||||
|
||||
RHI::RHITexture* depthTexture = context.device->CreateTexture(depthDesc);
|
||||
if (depthTexture == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHI::ResourceViewDesc depthViewDesc = {};
|
||||
depthViewDesc.format = static_cast<uint32_t>(RHI::Format::D24_UNorm_S8_UInt);
|
||||
depthViewDesc.dimension = RHI::ResourceViewDimension::Texture2D;
|
||||
depthViewDesc.mipLevel = 0;
|
||||
RHI::RHIResourceView* depthView =
|
||||
context.device->CreateDepthStencilView(depthTexture, depthViewDesc);
|
||||
if (depthView == nullptr) {
|
||||
depthTexture->Shutdown();
|
||||
delete depthTexture;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHI::ResourceViewDesc shaderViewDesc = {};
|
||||
shaderViewDesc.format = depthDesc.format;
|
||||
shaderViewDesc.dimension = RHI::ResourceViewDimension::Texture2D;
|
||||
shaderViewDesc.mipLevel = 0;
|
||||
RHI::RHIResourceView* shaderView =
|
||||
context.device->CreateShaderResourceView(depthTexture, shaderViewDesc);
|
||||
if (shaderView == nullptr) {
|
||||
depthView->Shutdown();
|
||||
delete depthView;
|
||||
depthTexture->Shutdown();
|
||||
delete depthTexture;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
m_directionalShadowSurface->Reset();
|
||||
m_directionalShadowSurface->device = context.device;
|
||||
m_directionalShadowSurface->width = plan.mapWidth;
|
||||
m_directionalShadowSurface->height = plan.mapHeight;
|
||||
m_directionalShadowSurface->depthTexture = depthTexture;
|
||||
m_directionalShadowSurface->depthView = depthView;
|
||||
m_directionalShadowSurface->shaderView = shaderView;
|
||||
m_directionalShadowSurface->surface = RenderSurface(plan.mapWidth, plan.mapHeight);
|
||||
m_directionalShadowSurface->surface.SetDepthAttachment(depthView);
|
||||
}
|
||||
|
||||
return m_directionalShadowSurface.get();
|
||||
}
|
||||
|
||||
bool CameraRenderer::Render(
|
||||
const CameraRenderRequest& request) {
|
||||
if (!request.IsValid() || m_pipeline == nullptr) {
|
||||
@@ -363,20 +386,20 @@ bool CameraRenderer::Render(
|
||||
}
|
||||
|
||||
ShadowCasterRenderRequest resolvedShadowCaster = request.shadowCaster;
|
||||
OwnedShadowSurfaceResources ownedShadowSurface;
|
||||
DirectionalShadowSurfaceResources* directionalShadowSurface = nullptr;
|
||||
if (resolvedShadowCaster.IsRequested()) {
|
||||
if (!resolvedShadowCaster.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
} else if (request.directionalShadow.IsValid()) {
|
||||
if (!CreateDirectionalShadowSurface(
|
||||
request.context,
|
||||
request.directionalShadow,
|
||||
ownedShadowSurface)) {
|
||||
directionalShadowSurface = AcquireDirectionalShadowSurface(
|
||||
request.context,
|
||||
request.directionalShadow);
|
||||
if (directionalShadowSurface == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
resolvedShadowCaster.surface = ownedShadowSurface.surface;
|
||||
resolvedShadowCaster.surface = directionalShadowSurface->surface;
|
||||
if (!resolvedShadowCaster.hasCameraDataOverride) {
|
||||
resolvedShadowCaster.hasCameraDataOverride = true;
|
||||
resolvedShadowCaster.cameraDataOverride = request.directionalShadow.cameraData;
|
||||
@@ -393,7 +416,8 @@ bool CameraRenderer::Render(
|
||||
}
|
||||
|
||||
if (request.directionalShadow.IsValid()) {
|
||||
RHI::RHIResourceView* shadowMapView = ownedShadowSurface.shaderView;
|
||||
RHI::RHIResourceView* shadowMapView =
|
||||
directionalShadowSurface != nullptr ? directionalShadowSurface->shaderView : nullptr;
|
||||
sceneData.lighting.mainDirectionalShadow =
|
||||
BuildDirectionalShadowData(request.directionalShadow, shadowMapView);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user