#version 450 // Tonemap pass:HDR 线性颜色 → 显示空间。 // 这是显示变换的显式建模(对齐 UE/Unity:HDR SceneColor → tonemapper → UI)。 // ACES = Narkowicz 拟合(线性域映射到 [0,1]),可经 push constant 关闭 // 退回纯 gamma(旧观感);bloom 等后处理在 HDR 域(Tonemap 之前)插 pass。 layout(location = 0) in vec2 fragUV; layout(location = 0) out vec4 outColor; layout(set = 0, binding = 0) uniform sampler2D hdrImage; layout(set = 0, binding = 1) uniform sampler2D bloomImage; // 全屏 pass 通用 push(16B,程序级统一声明,VUID-08878) layout(push_constant) uniform PushConstants { float exposure; // 曝光系数 float aces; // >0.5 启用 ACES 曲线,否则纯 gamma float bloomStrength; // bloom 叠加强度(0 = 关闭) float _pad0; } pc; vec3 acesFilm(vec3 x) { return clamp((x * (2.51 * x + 0.03)) / (x * (2.43 * x + 0.59) + 0.14), 0.0, 1.0); } void main() { // bloom 在 HDR 域叠加(半分辨率模糊图线性采样上采样) vec4 hdrTex = texture(hdrImage, fragUV); vec3 hdr = hdrTex.rgb + texture(bloomImage, fragUV).rgb * pc.bloomStrength; float alpha = hdrTex.a; hdr *= pc.exposure; vec3 mapped = (pc.aces > 0.5) ? acesFilm(hdr) : clamp(hdr, 0.0, 1.0); outColor = vec4(pow(mapped, vec3(1.0 / 2.2)), alpha); }