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:
2026-09-22 19:00:56 +08:00
parent 4fd88248fc
commit 952ba8135d
10 changed files with 231 additions and 11 deletions
+23
View File
@@ -0,0 +1,23 @@
#version 450
// Tonemap pass:HDR 线性颜色 → 显示空间。
// 这是显示变换的显式建模(对齐 UE/Unity:HDR SceneColor → tonemapper → UI)。
// 当前 = 曝光 + gamma 编码(与旧 Srgb 附件行为等价,观感不变);
// ACES/Reinhard 色调曲线、bloom 等后处理在此 pass 基础上扩展。
layout(location = 0) in vec2 fragUV;
layout(location = 0) out vec4 outColor;
layout(set = 0, binding = 0) uniform sampler2D hdrImage;
layout(push_constant) uniform PushConstants {
float exposure; // 曝光系数(后续接 ImGui)
} pc;
void main() {
vec3 hdr = texture(hdrImage, fragUV).rgb * pc.exposure;
// 显示编码:linear → sRGB(gamma 2.2 近似)。
// TODO: ACES 拟合曲线接入点(HDR 泛光/色调映射时替换此行)
outColor = vec4(pow(clamp(hdr, 0.0, 1.0), vec3(1.0 / 2.2)), 1.0);
}
+15
View File
@@ -0,0 +1,15 @@
#version 450
// 全屏三角形:无顶点缓冲,从 gl_VertexIndex 派生 UV。
// 0 → (-1,3)? 经典三角覆盖整个屏幕:
// idx0:(-1,-1) idx1:(3,-1) idx2:(-1,3),UV 相应 [0..2],
// 光栅化插值后屏幕内 UV 恰好落在 [0,1]。
layout(location = 0) out vec2 fragUV;
void main() {
vec2 p = vec2(
float((gl_VertexIndex << 1) & 2),
float(gl_VertexIndex & 2));
fragUV = p;
gl_Position = vec4(p * 2.0 - 1.0, 0.0, 1.0);
}