feat: CSM 级联阴影(3 级联 × 1024²,实用分割 + 纹素对齐)
- SceneRenderer::ComputeCascades:相机视锥实用分割(λ=0.6)→ 反投影 取切片角点 → 光空间 AABB 拟合 → 纹素对齐(消除相机移动时阴影边缘 闪烁)→ [0,1] 深度重映射 - Shadow pass 单 pass 渲 3 个 region,每级联 push 各自光空间 VP - Forward:UBO lightSpace[3]+cascadeSplits(视图深度选级联),Set2 三张级联图按 binding 0/1/2 采样;vertex 输出 fragViewDepth - 光源视锥剔除用最远级联(覆盖全阴影范围);双视锥独立剔除铁律保留 - 旧单张 2048 全场景图退役;近处级联分辨率 ~128px/unit(约 2× 提升) - 编译零错误、validation 零警告、8 秒冒烟通过(10 pass 全活跃)
This commit is contained in:
@@ -12,93 +12,101 @@ namespace Engine::Passes
|
||||
{
|
||||
void ShadowPass::Register(RG::RenderGraph& rg)
|
||||
{
|
||||
// 所有渲染体都写入,不做实体级开关——castShadow 应由材质/实体
|
||||
// 数据驱动剔除,而非 pass 逻辑特判
|
||||
// 所有渲染体都写入每个级联,不做实体级开关——castShadow 应由
|
||||
// 材质/实体数据驱动剔除,而非 pass 逻辑特判。
|
||||
// (每级联独立剔除是后续优化点:shadowView 细分为 per-cascade 列表)
|
||||
rg.AddPass("Shadow", [this](RG::RenderGraphContext& ctx) {
|
||||
const vk::CommandBuffer cmd = ctx.cmd;
|
||||
|
||||
vk::RenderingAttachmentInfo depthAttachment;
|
||||
depthAttachment.setImageView(ctx.View(m_ShadowMap))
|
||||
.setImageLayout(vk::ImageLayout::eDepthAttachmentOptimal)
|
||||
.setLoadOp(vk::AttachmentLoadOp::eClear)
|
||||
.setStoreOp(vk::AttachmentStoreOp::eStore)
|
||||
.setClearValue(vk::ClearValue(
|
||||
vk::ClearDepthStencilValue(1.0f, 0)));
|
||||
for (u32 c = 0; c < kMaxCascades; ++c) {
|
||||
vk::RenderingAttachmentInfo depthAttachment;
|
||||
depthAttachment.setImageView(ctx.View(m_ShadowMaps[c]))
|
||||
.setImageLayout(vk::ImageLayout::eDepthAttachmentOptimal)
|
||||
.setLoadOp(vk::AttachmentLoadOp::eClear)
|
||||
.setStoreOp(vk::AttachmentStoreOp::eStore)
|
||||
.setClearValue(vk::ClearValue(
|
||||
vk::ClearDepthStencilValue(1.0f, 0)));
|
||||
|
||||
vk::RenderingInfo renderingInfo;
|
||||
renderingInfo.setRenderArea({{0, 0}, {kShadowMapSize, kShadowMapSize}})
|
||||
.setLayerCount(1)
|
||||
.setPDepthAttachment(&depthAttachment);
|
||||
vk::RenderingInfo renderingInfo;
|
||||
renderingInfo.setRenderArea({{0, 0}, {kCascadeRes, kCascadeRes}})
|
||||
.setLayerCount(1)
|
||||
.setPDepthAttachment(&depthAttachment);
|
||||
|
||||
cmd.beginRendering(renderingInfo);
|
||||
cmd.beginRendering(renderingInfo);
|
||||
|
||||
std::array<vk::ShaderStageFlagBits, 2> stages = {
|
||||
vk::ShaderStageFlagBits::eVertex,
|
||||
vk::ShaderStageFlagBits::eFragment
|
||||
};
|
||||
std::array<vk::ShaderEXT, 2> shaders = {m_Gpu.shadowVert, m_Gpu.shadowFrag};
|
||||
cmd.bindShadersEXT(stages, shaders);
|
||||
std::array<vk::ShaderStageFlagBits, 2> stages = {
|
||||
vk::ShaderStageFlagBits::eVertex,
|
||||
vk::ShaderStageFlagBits::eFragment
|
||||
};
|
||||
std::array<vk::ShaderEXT, 2> shaders = {m_Gpu.shadowVert, m_Gpu.shadowFrag};
|
||||
cmd.bindShadersEXT(stages, shaders);
|
||||
|
||||
// ---- 动态状态(depth-only)----
|
||||
cmd.setRasterizerDiscardEnable(VK_FALSE);
|
||||
// ---- 动态状态(depth-only)----
|
||||
cmd.setRasterizerDiscardEnable(VK_FALSE);
|
||||
|
||||
cmd.setDepthTestEnable(VK_TRUE);
|
||||
cmd.setDepthWriteEnable(VK_TRUE);
|
||||
cmd.setDepthCompareOp(vk::CompareOp::eLess);
|
||||
cmd.setDepthBoundsTestEnable(VK_FALSE);
|
||||
cmd.setDepthTestEnable(VK_TRUE);
|
||||
cmd.setDepthWriteEnable(VK_TRUE);
|
||||
cmd.setDepthCompareOp(vk::CompareOp::eLess);
|
||||
cmd.setDepthBoundsTestEnable(VK_FALSE);
|
||||
|
||||
cmd.setStencilTestEnable(VK_FALSE);
|
||||
// 深度 bias 压平 shadow acne(NDC 量级)
|
||||
cmd.setDepthBiasEnable(VK_TRUE);
|
||||
cmd.setDepthBias(0.0025f, 0.0f, 0.003f);
|
||||
cmd.setPolygonModeEXT(vk::PolygonMode::eFill);
|
||||
cmd.setCullMode(vk::CullModeFlagBits::eNone);
|
||||
cmd.setFrontFace(vk::FrontFace::eCounterClockwise);
|
||||
cmd.setPrimitiveTopology(vk::PrimitiveTopology::eTriangleList);
|
||||
cmd.setPrimitiveRestartEnable(VK_FALSE);
|
||||
cmd.setStencilTestEnable(VK_FALSE);
|
||||
// 深度 bias 压平 shadow acne(NDC 量级)
|
||||
cmd.setDepthBiasEnable(VK_TRUE);
|
||||
cmd.setDepthBias(0.0025f, 0.0f, 0.003f);
|
||||
cmd.setPolygonModeEXT(vk::PolygonMode::eFill);
|
||||
cmd.setCullMode(vk::CullModeFlagBits::eNone);
|
||||
cmd.setFrontFace(vk::FrontFace::eCounterClockwise);
|
||||
cmd.setPrimitiveTopology(vk::PrimitiveTopology::eTriangleList);
|
||||
cmd.setPrimitiveRestartEnable(VK_FALSE);
|
||||
|
||||
auto binding = Vertex::GetBindingDescription();
|
||||
auto attributes = Vertex::GetAttributeDescriptions();
|
||||
cmd.setVertexInputEXT(binding, attributes);
|
||||
auto binding = Vertex::GetBindingDescription();
|
||||
auto attributes = Vertex::GetAttributeDescriptions();
|
||||
cmd.setVertexInputEXT(binding, attributes);
|
||||
|
||||
cmd.setRasterizationSamplesEXT(vk::SampleCountFlagBits::e1);
|
||||
vk::SampleMask sampleMask = 0xFFFFFFFF;
|
||||
cmd.setSampleMaskEXT(vk::SampleCountFlagBits::e1, sampleMask);
|
||||
cmd.setAlphaToCoverageEnableEXT(VK_FALSE);
|
||||
cmd.setAlphaToOneEnableEXT(VK_FALSE);
|
||||
cmd.setRasterizationSamplesEXT(vk::SampleCountFlagBits::e1);
|
||||
vk::SampleMask sampleMask = 0xFFFFFFFF;
|
||||
cmd.setSampleMaskEXT(vk::SampleCountFlagBits::e1, sampleMask);
|
||||
cmd.setAlphaToCoverageEnableEXT(VK_FALSE);
|
||||
cmd.setAlphaToOneEnableEXT(VK_FALSE);
|
||||
|
||||
vk::Viewport viewport(0.0f, 0.0f,
|
||||
static_cast<float>(kShadowMapSize),
|
||||
static_cast<float>(kShadowMapSize),
|
||||
0.0f, 1.0f);
|
||||
cmd.setViewportWithCount(viewport);
|
||||
vk::Viewport viewport(0.0f, 0.0f,
|
||||
static_cast<float>(kCascadeRes),
|
||||
static_cast<float>(kCascadeRes),
|
||||
0.0f, 1.0f);
|
||||
cmd.setViewportWithCount(viewport);
|
||||
|
||||
vk::Rect2D scissor({0, 0}, {kShadowMapSize, kShadowMapSize});
|
||||
cmd.setScissorWithCount(scissor);
|
||||
vk::Rect2D scissor({0, 0}, {kCascadeRes, kCascadeRes});
|
||||
cmd.setScissorWithCount(scissor);
|
||||
|
||||
// ---- 绘制:GPUDriven——与 Forward 共用实例数据,但用
|
||||
// 光源视锥剔除后的 batch(相机外实体仍投影子)----
|
||||
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics,
|
||||
m_Gpu.shadowLayout, 0,
|
||||
m_Gpu.uboSets[ctx.frame.frameSlot], {});
|
||||
// ---- 绘制:GPUDriven——与 Forward 共用实例数据,但用
|
||||
// 光源视锥剔除后的 batch(相机外实体仍投影子)----
|
||||
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics,
|
||||
m_Gpu.shadowLayout, 0,
|
||||
m_Gpu.uboSets[ctx.frame.frameSlot], {});
|
||||
|
||||
// stage 必须覆盖 layout range 声明的全部 stage(VUID-01796)
|
||||
cmd.pushConstants(m_Gpu.shadowLayout,
|
||||
vk::ShaderStageFlagBits::eVertex |
|
||||
vk::ShaderStageFlagBits::eFragment,
|
||||
0, sizeof(glm::mat4), &m_Frame.ubo.lightSpace);
|
||||
// stage 必须覆盖 layout range 声明的全部 stage(VUID-01796)
|
||||
// 每级联 push 各自的光空间 VP
|
||||
cmd.pushConstants(m_Gpu.shadowLayout,
|
||||
vk::ShaderStageFlagBits::eVertex |
|
||||
vk::ShaderStageFlagBits::eFragment,
|
||||
0, sizeof(glm::mat4),
|
||||
&m_Frame.ubo.lightSpace[c]);
|
||||
|
||||
for (const auto& batch : m_Frame.shadowView.batches) {
|
||||
batch.mesh->Draw(cmd, batch.count, batch.first);
|
||||
for (const auto& batch : m_Frame.shadowView.batches) {
|
||||
batch.mesh->Draw(cmd, batch.count, batch.first);
|
||||
}
|
||||
|
||||
cmd.endRendering();
|
||||
}
|
||||
|
||||
cmd.endRendering();
|
||||
}).Write(m_ShadowMap, RG::ResourceUse::DepthAttachment);
|
||||
})
|
||||
.Write(m_ShadowMaps[0], RG::ResourceUse::DepthAttachment)
|
||||
.Write(m_ShadowMaps[1], RG::ResourceUse::DepthAttachment)
|
||||
.Write(m_ShadowMaps[2], RG::ResourceUse::DepthAttachment);
|
||||
}
|
||||
|
||||
void ShadowPass::OnTargetsRebuilt(RG::RenderGraph& rg)
|
||||
{
|
||||
m_Gpu.BindShadowMap(rg, m_ShadowMap);
|
||||
m_Gpu.BindShadowMaps(rg, m_ShadowMaps);
|
||||
}
|
||||
|
||||
} // namespace Engine::Passes
|
||||
|
||||
Reference in New Issue
Block a user