Reorganize directory layout: editor panels/, grouped shaders, drop stale header

- App/editor: move 7 panels into panels/ (Editor core stays at root)
- shaders/: group into pbr/ post/ debug/ env/ (runtime load paths updated)
- Delete outdated duplicate Engine/src/Renderer/VulkanAssetUploader.h
This commit is contained in:
2026-10-07 09:52:17 +08:00
parent cc837bc605
commit f73e52926f
55 changed files with 23 additions and 83 deletions
+29
View File
@@ -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);
}
+34
View File
@@ -0,0 +1,34 @@
#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() {
// 5 tap 十字预滤波(中心 0.4 + 四邻 0.15):TAA 残留的亚像素震荡
// 在进阈值前被抹平——1px 级抖动的能量摊到 ~4×4 足印,泛光不再脉冲。
// 半分辨率输出中心的双线性已覆盖 2×2 块,此步把足印扩到近似 4×4
vec2 ts = 1.0 / vec2(textureSize(hdrImage, 0));
vec3 c = texture(hdrImage, fragUV).rgb * 0.4
+ (texture(hdrImage, fragUV + vec2(ts.x, 0.0)).rgb
+ texture(hdrImage, fragUV + vec2(-ts.x, 0.0)).rgb
+ texture(hdrImage, fragUV + vec2(0.0, ts.y)).rgb
+ texture(hdrImage, fragUV + vec2(0.0, -ts.y)).rgb) * 0.15;
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);
}
+82
View File
@@ -0,0 +1,82 @@
#version 450
// TAA resolve:时域抗锯齿。
// 1. velocity 反推历史像素位置,取历史累积色
// 2. 方差裁剪(YCoCg):历史色钳向邻域均值 ± γσ(∩ AABB 极值盒)——
// 比 RGB min/max 盒稳得多:AABB 盒子被逐帧抖动的高亮像素拽来拽去,
// 收敛历史持续被重钳 → 周期性残差经 bloom 阈值放大 = 静态模型泛光闪烁
// 3. mix(cur, hist, alpha) 时域累积
// 输出写入 TAAColor,它同时也是下一帧的历史(ReadHistory 自引用)。
layout(location = 0) in vec2 fragUV;
layout(location = 0) out vec4 outColor;
layout(set = 0, binding = 0) uniform sampler2D curImage; // 当前帧 HDR
layout(set = 0, binding = 1) uniform sampler2D velocityImage; // 运动向量(UV 空间)
layout(set = 0, binding = 2) uniform sampler2D historyImage; // 上一帧累积结果
// 全屏 pass 通用 push(16B,程序级统一声明,VUID-08878)
layout(push_constant) uniform PushConstants {
float exposure; // 与其它全屏 pass 布局一致(本 pass 不用)
float alpha; // 历史权重(0.9 = 90% 历史)
float param1;
float param2;
} pc;
// YCoCg 感知空间:亮度/色度分离,方差裁剪不在 HDR RGB 直接做
//(RGB 各通道独立 σ 会偏色;Y 通道主导几何相关性)
vec3 RgbToYCoCg(vec3 c) {
return vec3(0.25 * c.r + 0.5 * c.g + 0.25 * c.b,
0.5 * c.r - 0.5 * c.b,
-0.25 * c.r + 0.5 * c.g - 0.25 * c.b);
}
vec3 YCoCgToRgb(vec3 c) {
return vec3(c.x + c.y - c.z,
c.x + c.z,
c.x - c.y - c.z);
}
void main() {
vec4 cur = texture(curImage, fragUV);
vec2 vel = texture(velocityImage, fragUV).xy;
vec2 histUV = fragUV - vel;
vec3 result = cur.rgb;
// 历史采样:越出画面(相机快速平移)直接用当前帧,不累积
if (all(greaterThanEqual(histUV, vec2(0.0))) &&
all(lessThanEqual(histUV, vec2(1.0)))) {
vec3 hist = texture(historyImage, histUV).rgb;
// 邻域统计(3×3,YCoCg):均值 m1、均方 m2、极值盒 [mn, mx]
vec2 ts = 1.0 / vec2(textureSize(curImage, 0));
vec3 m1 = vec3(0.0);
vec3 m2 = vec3(0.0);
vec3 mn = vec3(1e9);
vec3 mx = vec3(-1e9);
for (int y = -1; y <= 1; ++y) {
for (int x = -1; x <= 1; ++x) {
vec3 c = RgbToYCoCg(texture(curImage, fragUV + vec2(x, y) * ts).rgb);
m1 += c;
m2 += c * c;
mn = min(mn, c);
mx = max(mx, c);
}
}
m1 /= 9.0;
m2 /= 9.0;
vec3 sigma = sqrt(max(m2 - m1 * m1, vec3(0.0)));
// 方差裁剪盒:均值 ± 1.25σ 再 ∩ 极值盒。历史被钳向"稳定均值"
// 而非抖动极值 → 收敛残差大幅下降(泛光闪烁的治本点)。
// 极值盒交集保证不引入邻域外颜色(鬼影上界)
const float kGamma = 1.25;
vec3 lo = max(m1 - kGamma * sigma, mn);
vec3 hi = min(m1 + kGamma * sigma, mx);
vec3 clamped = YCoCgToRgb(clamp(RgbToYCoCg(hist), lo, hi));
result = mix(cur.rgb, clamped, pc.alpha);
}
outColor = vec4(result, cur.a);
}
+28
View File
@@ -0,0 +1,28 @@
#version 450
// TemporalDiff:帧历史链路调试视图。
// 输出 |上一帧 HDR − 当前帧 HDR| × 增益:
// - 静止画面应接近纯黑(两帧内容一致)
// - 运动的实体边缘发光(时域差异可见)
// - 全屏噪声 / 错位残影 = 帧历史 barrier 或槽位镜像绑定错误
// 这是 RenderGraph 帧历史资源(ReadHistory)的验证消费端。
layout(location = 0) in vec2 fragUV;
layout(location = 0) out vec4 outColor;
layout(set = 0, binding = 0) uniform sampler2D prevImage; // 帧历史(上一帧槽位镜像)
layout(set = 0, binding = 1) uniform sampler2D currImage; // 当前帧
// 全屏 pass 通用 push(16B,程序级统一声明,VUID-08878)
layout(push_constant) uniform PushConstants {
float exposure; // 与其它全屏 pass 布局一致(本 pass 不用)
float gain; // 差异增益
float param1;
float param2;
} pc;
void main() {
vec3 prev = texture(prevImage, fragUV).rgb;
vec3 curr = texture(currImage, fragUV).rgb;
outColor = vec4(abs(prev - curr) * pc.gain, 1.0);
}
+129
View File
@@ -0,0 +1,129 @@
#version 450
// Tonemap pass:HDR(+bloom)→ 显示空间,写 PresentTarget(offscreen,
// 由 ImGui::Image 呈现;输出位置可自由摆放)。
// 这是显示变换的显式建模(对齐 UE/Unity:HDR SceneColor → tonemapper → UI)。
// ACES = Narkowicz 拟合(线性域映射到 [0,1]),可经 push constant 关闭
// 退回纯 gamma(旧观感)。
//
// 调试视图:pc.debugView 整型路由到已绑定的中间目标(绑定超集静态成立,
// 运行时零重绑)。HDR 域资源过同一套 exposure/tonemap 保证观感可比;
// LDR 类(velocity/深度)直接可视化。
layout(location = 0) in vec2 fragUV;
layout(location = 0) out vec4 outColor;
layout(set = 0, binding = 0) uniform sampler2D taaImage; // TAA 后 HDR(主输入)
layout(set = 0, binding = 1) uniform sampler2D bloomImage;
layout(set = 0, binding = 2) uniform sampler2D temporalDiffImage;
layout(set = 0, binding = 3) uniform sampler2D rawHdrImage; // Forward 直出(TAA 前)
layout(set = 0, binding = 4) uniform sampler2D velocityImage;
layout(set = 0, binding = 5) uniform sampler2D shadowMap0Image; // D32 深度(r 分量)
layout(set = 0, binding = 6) uniform sampler2D shadowMap1Image;
layout(set = 0, binding = 7) uniform sampler2D shadowMap2Image;
// 环境调试视图源(随环境切换重绑,静态绑定超集)
layout(set = 0, binding = 8) uniform samplerCube envCubeImage;
layout(set = 0, binding = 9) uniform samplerCube irradianceImage;
layout(set = 0, binding = 10) uniform samplerCube prefilterImage;
layout(set = 0, binding = 11) uniform sampler2D brdfLutImage;
// 与 Passes::DebugView 枚举同步(FullscreenGpu.h)
const int VIEW_FINAL = 0;
const int VIEW_TEMPORALDIFF = 1;
const int VIEW_RAW_HDR = 2;
const int VIEW_TAA = 3;
const int VIEW_BLOOM = 4;
const int VIEW_VELOCITY = 5;
const int VIEW_SHADOW0 = 6;
const int VIEW_SHADOW1 = 7;
const int VIEW_SHADOW2 = 8;
const int VIEW_ENV_CUBE = 9;
const int VIEW_IRRADIANCE = 10;
const int VIEW_PREFILTER = 11;
const int VIEW_BRDF_LUT = 12;
const int VIEW_TRANSPARENT = 13;
// 全屏 pass 通用 push(16B,程序级统一声明,VUID-08878)
layout(push_constant) uniform PushConstants {
float exposure; // 曝光系数
float aces; // >0.5 启用 ACES 曲线,否则纯 gamma
float bloomStrength; // bloom 叠加强度(0 = 关闭)
float debugView; // 调试视图枚举(整型经 float 传)
} 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);
}
vec3 tonemap(vec3 hdr) {
hdr *= pc.exposure;
vec3 mapped = (pc.aces > 0.5) ? acesFilm(hdr) : clamp(hdr, 0.0, 1.0);
return pow(mapped, vec3(1.0 / 2.2));
}
// 深度可视化:反相(近=白,与调试截图风格一致)
vec3 depthView(sampler2D depthImage) {
float d = texture(depthImage, fragUV).r;
return vec3(pow(1.0 - d, 2.2));
}
// 全屏 uv → 球面方向(cube 调试视图的经纬展开:横向经度、纵向极角)
vec3 latLongDir(vec2 uv) {
float phi = (uv.x * 2.0 - 1.0) * 3.14159265358979; // -π..π 经度
float theta = (1.0 - uv.y) * 3.14159265358979; // 0..π 极角(顶=天顶)
return vec3(sin(theta) * cos(phi), cos(theta), sin(theta) * sin(phi));
}
// cube 视图统一走 tonemap(HDR 域,观感与场景一致);
// prefilter 纵向映射 mip 链(上锐下糙,直观验证 roughness 分级)
vec3 cubeView(samplerCube cube, float lod) {
return tonemap(textureLod(cube, latLongDir(fragUV), lod).rgb);
}
void main() {
int view = int(pc.debugView + 0.5);
// ---- 调试视图路由 ----
if (view != VIEW_FINAL) {
switch (view) {
case VIEW_TEMPORALDIFF: {
// 帧历史差异:静止=黑,运动边缘发光
vec3 d = clamp(texture(temporalDiffImage, fragUV).rgb, 0.0, 1.0);
outColor = vec4(pow(d, vec3(1.0 / 2.2)), 1.0);
return;
}
// Transparent 视图:场景侧已跳过天空盒/不透明绘制,
// raw HDR = 清屏色 + 透明队列内容(与 RAW_HDR 同一显示路径)
case VIEW_RAW_HDR:
case VIEW_TRANSPARENT:
outColor = vec4(tonemap(texture(rawHdrImage, fragUV).rgb), 1.0); return;
case VIEW_TAA: outColor = vec4(tonemap(texture(taaImage, fragUV).rgb), 1.0); return;
case VIEW_BLOOM: outColor = vec4(tonemap(texture(bloomImage, fragUV).rgb * 4.0), 1.0); return;
case VIEW_VELOCITY: {
// |velocity| × 增益:静止=黑,运动越快越亮
vec2 vel = texture(velocityImage, fragUV).xy;
float mag = clamp(length(vel) * 8.0, 0.0, 1.0);
outColor = vec4(vec3(mag), 1.0);
return;
}
case VIEW_SHADOW0: outColor = vec4(depthView(shadowMap0Image), 1.0); return;
case VIEW_SHADOW1: outColor = vec4(depthView(shadowMap1Image), 1.0); return;
case VIEW_SHADOW2: outColor = vec4(depthView(shadowMap2Image), 1.0); return;
case VIEW_ENV_CUBE: outColor = vec4(cubeView(envCubeImage, 0.0), 1.0); return;
case VIEW_IRRADIANCE: outColor = vec4(cubeView(irradianceImage, 0.0), 1.0); return;
case VIEW_PREFILTER: outColor = vec4(cubeView(prefilterImage, fragUV.y * 4.0), 1.0); return;
case VIEW_BRDF_LUT: {
// LUT 是 (F 缩放, F 偏置) 双通道,R/G 直读可视化
vec2 ab = texture(brdfLutImage, fragUV).rg;
outColor = vec4(ab, 0.0, 1.0);
return;
}
}
}
// ---- 正常路径:TAA 后 HDR + bloom 叠加 → tonemap ----
vec4 hdrTex = texture(taaImage, fragUV);
vec3 hdr = hdrTex.rgb + texture(bloomImage, fragUV).rgb * pc.bloomStrength;
outColor = vec4(tonemap(hdr) * hdrTex.a, hdrTex.a);
}
+23
View File
@@ -0,0 +1,23 @@
#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;
// 全屏 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),
float(gl_VertexIndex & 2));
fragUV = p;
gl_Position = vec4(p * 2.0 - 1.0, 0.0, 1.0);
}