feat: HDR 管线 + Tonemap pass,显示变换显式建模
管线:Shadow → Forward(写 HDRColor R16G16B16A16F) → Tonemap → ImGui(loadOp=Load) → Present。对齐 UE/Unity 结构:场景线性值 进 HDR 离屏图,Tonemap(全屏三角,exposure push + gamma 编码) 显式完成显示变换,Backbuffer 只接收显示空间颜色。 - Swapchain 改 B8G8R8A8Unorm:Srgb 附件会硬件二次提亮,UI 泛白 (#4296FA→#8CCBFC);Unorm 下写什么显示什么,编码责任归 Tonemap - Shader object push range 规则落地:程序级声明——同一 pass 的 全部 shader EXT range 定义必须一致(VUID-08878),layout 同样 按 vertex|fragment 声明,push 调用点覆盖全部声明 stage(VUID-01796) - Tonemap 装配:Set0 = HDR 图(per-frame-slot 描述符 + GetPhysicalView), clamp 占位待 ACES 替换,bloom/FXAA 等后处理在 HDR 域插 pass - CMake 加 imgui_demo.cpp(ShowDemoWindow 链接) - 修复:m_TonemapDescriptorSets 未 resize 即下标写入(启动即崩) 验证:5 pass 全活,validation 0 error 0 warning,UI 原生色彩无泛白
This commit is contained in:
@@ -115,14 +115,19 @@ namespace Engine
|
||||
return m_Device.GetDevice().createPipelineLayout(info);
|
||||
}
|
||||
|
||||
vk::PipelineLayout DescriptorManager::CreatePipelineLayout(const std::vector<vk::DescriptorSetLayout>& layouts,u32 pushConstantSize)
|
||||
vk::PipelineLayout DescriptorManager::CreatePipelineLayout(const std::vector<vk::DescriptorSetLayout>& layouts,
|
||||
u32 pushConstantSize)
|
||||
{
|
||||
vk::PipelineLayoutCreateInfo info;
|
||||
info.setSetLayouts(layouts);
|
||||
|
||||
std::array<vk::PushConstantRange, 1> pushRanges;
|
||||
if (pushConstantSize > 0) {
|
||||
pushRanges[0].setStageFlags(vk::ShaderStageFlagBits::eVertex)
|
||||
// 与 ShaderManager 一致:程序级 vertex|fragment 声明。
|
||||
// 注意 vkCmdPushConstants 的 stageFlags 必须覆盖 range 的
|
||||
// 全部 stage(VUID-01796),因此 push 调用点也要带双 stage
|
||||
pushRanges[0].setStageFlags(vk::ShaderStageFlagBits::eVertex |
|
||||
vk::ShaderStageFlagBits::eFragment)
|
||||
.setOffset(0)
|
||||
.setSize(pushConstantSize);
|
||||
info.setPushConstantRanges(pushRanges);
|
||||
|
||||
@@ -57,7 +57,12 @@ ShaderObject ShaderManager::CreateFromSPIRV(const std::vector<u32>& spirv,
|
||||
|
||||
std::array<vk::PushConstantRange, 1> pushRanges;
|
||||
if (pushConstantSize > 0) {
|
||||
pushRanges[0].setStageFlags(vk::ShaderStageFlagBits::eVertex)
|
||||
// push range 是"程序级"声明:shader object 要求同一程序绑定的
|
||||
// 全部 shader(vert+frag)push range 定义完全一致(VUID-08878),
|
||||
// 因此统一按 vertex|fragment 声明;shader 实际读取哪些字节由
|
||||
// GLSL 的 push_constant block 决定,声明范围只是能力上限
|
||||
pushRanges[0].setStageFlags(vk::ShaderStageFlagBits::eVertex |
|
||||
vk::ShaderStageFlagBits::eFragment)
|
||||
.setOffset(0)
|
||||
.setSize(pushConstantSize);
|
||||
createInfo.setPushConstantRanges(pushRanges);
|
||||
|
||||
@@ -134,9 +134,13 @@ namespace Engine
|
||||
|
||||
vk::SurfaceFormatKHR Swapchain::ChooseSurfaceFormat(const std::vector<vk::SurfaceFormatKHR>& formats)
|
||||
{
|
||||
// 用 Unorm 而非 Srgb:当前管线(场景光照 + ImGui)都是把
|
||||
// "显示空间"颜色直接写进 framebuffer,若用 Srgb 附件硬件会再
|
||||
// 做一次 linear→sRGB 提亮 → 整体泛白(ImGui 原生蓝 #4296FA
|
||||
// 会被洗成 #8CCBFC)。等上 HDR/tonemap 管线后再切回 Srgb。
|
||||
for (const auto& f : formats)
|
||||
{
|
||||
if (f.format == vk::Format::eB8G8R8A8Srgb &&
|
||||
if (f.format == vk::Format::eB8G8R8A8Unorm &&
|
||||
f.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear)
|
||||
{
|
||||
return f;
|
||||
|
||||
Reference in New Issue
Block a user