Fix bloom glow flicker on static geometry under TAA jitter

TAA subpixel jitter makes rasterized HDR specular highlights oscillate
per frame. The old RGB min/max neighborhood clamp re-clamped the
converged history against jitter-driven extremes every frame, leaving a
periodic residual that the bloom threshold then amplified into visible
glow pulsing on static models.

- TAA: replace the RGB AABB clamp with YCoCg variance clipping
  (history clamped toward the stable neighborhood mean +/- 1.25 sigma,
  intersected with the min/max box as a ghosting upper bound)
- Bloom extract: 5-tap cross prefilter before the threshold spreads
  surviving 1px jitter energy over a ~4x4 footprint so the glow no
  longer pulses
This commit is contained in:
2026-10-05 12:08:53 +08:00
parent 5d88ed2057
commit 6c80693618
2 changed files with 48 additions and 9 deletions
+10 -1
View File
@@ -16,7 +16,16 @@ layout(push_constant) uniform PushConstants {
} pc;
void main() {
vec3 c = texture(hdrImage, fragUV).rgb;
// 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 的能量比例,避免硬切产生的块状边缘