feat: ACES tonemap + Bloom 后处理链(Extract/BlurH/BlurV 半分辨率)
- ACES(Narkowicz) 经 push 开关启用,exposure 接 ImGui 滑条 - RG: TextureDesc 支持 sizeScale 相对尺寸;per-pass 渲染尺寸解析 (半分辨率 pass 的 viewport 由此决定) - RG Toposort 重写:RAW+WAR+WAW 按声明序逐资源建边,支持多写者 ping-pong 资源(旧逻辑对 reader 连接所有 writer,ping-pong 成环) - GetPhysicalView 缺物理镜像时 throw(ENGINE_FATAL 只记日志不中止) - 全屏 pass 通用 16B push + 公共录制 lambda,Extract/Blur/Tonemap 复用
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
#version 450
|
||||
|
||||
// Bloom 高斯模糊:可分离 9-tap,方向由 push 给出(H/V 各跑一次)。
|
||||
// 源图为半分辨率,线性采样 + 权重对应的偏移天然抗锯齿。
|
||||
|
||||
layout(location = 0) in vec2 fragUV;
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D srcImage;
|
||||
|
||||
layout(push_constant) uniform PushConstants {
|
||||
float exposure; // 未用(程序级统一布局)
|
||||
float stepX; // param0: UV 步长 x(水平 pass = 1/width,垂直 = 0)
|
||||
float stepY; // param1: UV 步长 y
|
||||
float _pad0;
|
||||
} pc;
|
||||
|
||||
const float weights[5] = float[](0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);
|
||||
|
||||
void main() {
|
||||
vec2 off = vec2(pc.stepX, pc.stepY);
|
||||
|
||||
vec3 c = texture(srcImage, fragUV).rgb * weights[0];
|
||||
for (int i = 1; i < 5; ++i) {
|
||||
c += texture(srcImage, fragUV + off * float(i)).rgb * weights[i];
|
||||
c += texture(srcImage, fragUV - off * float(i)).rgb * weights[i];
|
||||
}
|
||||
outColor = vec4(c, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#version 450
|
||||
|
||||
// Bloom 提取:从 HDR 颜色图中滤出超过阈值的部分(软阈值,保留超出比例)。
|
||||
// 全屏 pass 通用 push(16B):param0 = 亮度阈值(HDR 域,1.0 = 仅高光溢出)。
|
||||
|
||||
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; // 未用(程序级统一布局)
|
||||
float threshold; // param0
|
||||
float _pad0;
|
||||
float _pad1;
|
||||
} pc;
|
||||
|
||||
void main() {
|
||||
vec3 c = texture(hdrImage, fragUV).rgb;
|
||||
float l = max(c.r, max(c.g, c.b));
|
||||
|
||||
// 软阈值:只保留超出 threshold 的能量比例,避免硬切产生的块状边缘
|
||||
float k = max(l - pc.threshold, 0.0) / max(l, 1e-4);
|
||||
outColor = vec4(c * k, 1.0);
|
||||
}
|
||||
+24
-9
@@ -2,22 +2,37 @@
|
||||
|
||||
// Tonemap pass:HDR 线性颜色 → 显示空间。
|
||||
// 这是显示变换的显式建模(对齐 UE/Unity:HDR SceneColor → tonemapper → UI)。
|
||||
// 当前 = 曝光 + gamma 编码(与旧 Srgb 附件行为等价,观感不变);
|
||||
// ACES/Reinhard 色调曲线、bloom 等后处理在此 pass 基础上扩展。
|
||||
// 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; // 曝光系数(后续接 ImGui)
|
||||
float exposure; // 曝光系数
|
||||
float aces; // >0.5 启用 ACES 曲线,否则纯 gamma
|
||||
float bloomStrength; // bloom 叠加强度(0 = 关闭)
|
||||
float _pad0;
|
||||
} 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);
|
||||
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 域叠加(半分辨率模糊图线性采样上采样)
|
||||
vec3 hdr = texture(hdrImage, fragUV).rgb
|
||||
+ texture(bloomImage, fragUV).rgb * pc.bloomStrength;
|
||||
|
||||
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)), 1.0);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,14 @@
|
||||
// 光栅化插值后屏幕内 UV 恰好落在 [0,1]。
|
||||
layout(location = 0) out vec2 fragUV;
|
||||
|
||||
// 全屏 pass 通用 push(16B,与 tonemap.frag 及所有全屏 pass 一致,VUID-08878)
|
||||
layout(push_constant) uniform PushConstants {
|
||||
float exposure;
|
||||
float aces;
|
||||
float _pad0;
|
||||
float _pad1;
|
||||
} pc;
|
||||
|
||||
void main() {
|
||||
vec2 p = vec2(
|
||||
float((gl_VertexIndex << 1) & 2),
|
||||
|
||||
Reference in New Issue
Block a user