GPU Gems 2 · Chapter 27. Advanced High-Quality Filtering

从 texel-center 访问和归一化连续卷积出发,对比缩小 footprint 抗锯齿、Gaussian/windowed-sinc 放大重建与 shock filter 去模糊。

学习目标

  • 能解释 Advanced High-Quality Filtering 如何把离散图像样本、连续 filter kernel 与屏幕像素 footprint 对齐
  • 能实现归一化 subpixel convolution、separable/large-kernel 路径和 Jacobian footprint 抗锯齿,并核对权重、读取与精度预算
  • 能回答:自然照片、合成硬边、透视缩小与均匀模糊分别应选 windowed sinc、Gaussian、footprint averaging 还是 shock filtering,以及会引入什么伪影

同一张图,放大、缩小和变清晰不是一个问题

把照片放大时,屏幕上新增的位置没有原始颜色,需要从邻近样本推算;把纹理缩小时,许多细节挤进一个像素,需要先做面积平均;修复模糊边缘时,又要把过宽的过渡收紧。三种任务都叫“过滤”,但错误地共用一个办法会分别造成发糊、闪烁或光晕。

硬件内置方法速度快,却只覆盖常见折中。本章把取样区域、重建曲线和迭代锐化拆开,使每条路径都有可计算的输入、成本与失败模式。先预测:在实验里选 sinc、radius 8,再叠加 10 次 shock,硬边附近会更清楚,还是先出现 ringing 与 halo?

Advanced High-Quality Filtering 实验

先预测:在硬边上把 sinc radius 加大,再叠加 8 次 shock,会保留细节,还是把 ringing 与 halo 一起放大?

high-quality filter lab · magnify / sincsample footprint · anisotropy 1:1filter recordradius4 px2D taps81separable taps18raw weight Σ0.997shock passes0ringing visible near hard edges输出始终除以当前 phase 的 weight sum;kernel、footprint 与 deblur 必须按任务分开验收

windowed sinc 保留采样带宽,但硬合成边缘可能出现衰减振铃。

本章主题 Advanced High-Quality Filtering 的核心不是“选择最锐的核”,而是让离散样本、连续模型与目标像素的覆盖区域一致,然后分别控制 blur、aliasing、ringing 和计算成本。

1. 从 normalized coordinate 回到 texel center

图像滤波器常需要访问确切的离散样本,而 texture API 通常接收零到一的实数坐标。设 texture size 为 NN、归一化坐标为 uu,对应 sample index 是

i=uN,ui=i+0.5N.i=\lfloor uN\rfloor,\qquad u_i=\frac{i+0.5}{N}.

这个式子在说:先把连续坐标量化到整数 sample,再加半个 texel 回到该 sample 的中心;中心比 corner 更能抵抗 round-off。若 sampler 明确使用 nearest/point filtering,可让硬件自动吸附到最近样本,但 linear filtering 会改变语义。

连续 texture coordinates 与离散 image samples 必须显式对齐normalized coordinateu = 0.43resolution-independentinteger samplefloor(u · size)sampleCoord = 3texel center(sample + 0.5)÷ texture sizeround-off safe离散 kernel lookup 用 sample centers;只有 point filter 时才可让 sampler 自动完成 snapping

相邻像素访问不必每次 floor。可以把 1/Nx1/N_x1/Ny1/N_y 及其正负组合预计算进 uniform,从当前 coordinate 一次加减得到八邻域。必须验证 API 的 texel-center 约定、border texels 与 wrap/clamp;跨 API 照抄 half-texel 规则常会整体偏一格。

2. 连续 kernel 如何落到离散图像

普通离散 convolution 假设 kernel 总是对齐某个 texel center。图像放大或 warp 时,输出 coordinate 往往落在 texels 之间;若仍用固定离散 coefficients,kernel phase 会跳动。更高质量的做法是把 kernel 视为连续函数 k(s,t)k(s,t),根据当前 subpixel center 对每个邻域 sample 重新求权重。

连续 kernel 可以预计算进 2D texture。对 rotationally invariant kernel,只存一条径向 cross section 能节省内存,但 inner loop 每次要计算距离;若 ALU 比 texture memory 更紧,2D table 可能反而更快。kernel texture 的 domain、center、format 和 linear interpolation 必须写进契约。

continuous kernel + discrete samples:每个 subpixel phase 都要重新归一化kernel centered at fractional coordinateactual subpixel centerone-pass accumulationRGB = Σ color · weightA = Σ weightoutput = RGB / Amean intensity preserved连续 kernel 落在离散网格上时权重和随 phase 改变,不做除法会产生亮度泵动

对邻域 Ω\Omega、输出中心 (s0,t0)(s_0,t_0),归一化结果是

C(s0,t0)=(s,t)ΩI(s,t)k(ss0,tt0)(s,t)Ωk(ss0,tt0).C(s_0,t_0)= \frac{\sum_{(s,t)\in\Omega}I(s,t)k(s-s_0,t-t_0)} {\sum_{(s,t)\in\Omega}k(s-s_0,t-t_0)}.

这个式子在说:连续 kernel 被离散采样后,weight sum 会随 phase 和裁剪边界变化;最后除以本次权重和,才能让 constant image 的 steady-state response 保持 1。原章把 RGB 用于 color sum、alpha 用于 weight sum,可减少 instructions;若 alpha 本身要处理,就必须另存 sum。

vec4 accum = vec4(0.0);
for (int y = -RADIUS; y <= RADIUS; ++y) {
  for (int x = -RADIUS; x <= RADIUS; ++x) {
    vec2 sampleUv = (base + vec2(x, y) + 0.5) / imageSize;
    float weight = texture(kernelLut, kernelUv(sampleUv, uv)).r;
    accum += vec4(texture(image, sampleUv).rgb, 1.0) * weight;
  }
}
return vec4(accum.rgb / accum.a, 1.0);

3. separable kernel 与超大 support

K(x,y)=kx(x)ky(y)K(x,y)=k_x(x)k_y(y),一个 (2r+1)2(2r+1)^2 taps 的 2D convolution 可拆成两个 2r+12r+1 taps 的 passes。Gaussian 和 box kernel 都可 separable;radius 4 时,square path 要 81 samples,而 two-pass path 只要 18 samples。

kernel support 决定读取结构:2D、separable 或 tiled accumulationdirect 2D5×5 = 25 samplesseparable5 + 5 = 10 sampleslarge tiledfloat accumulationdivide once at end两 pass 不总更快:小 kernel 要计 render-target 往返;超大 kernel 才值得拆解或分 tile

两 pass 会增加 render-target write/read 和同步,所以小 kernel 未必获益。超大、不可 separable 的 kernel 则可按 tiles 分多 pass:每个 pass 累计 color 与 weight 到 floating-point target,所有 tiles 完成后才统一除 weight sum。若每 tile 各自 normalize,再相加,tile 边界会获得错误相对权重。

4. 缩小:让 pixel footprint 决定平均区域

minification 若跳过预滤波,高于目标 Nyquist bandwidth 的细节会折回低频,产生 moiré 和 shimmer。理想抗锯齿是对每个像素覆盖的 texture area 求平均;mipmap 是高效近似,但不能在所有透视方向上最优保留信号。

对屏幕到 texture 的映射 f(i,j)f(i,j),在当前像素中心 (i0,j0)(i_0,j_0) 做一阶局部展开:

f(i,j)f(i0,j0)+J0[ii0jj0].f(i,j)\approx f(i_0,j_0)+J_0 \begin{bmatrix}i-i_0\\j-j_0\end{bmatrix}.

这个式子在说:用 texture-coordinate Jacobian J0J_0 把屏幕空间像素正方形近似映射成 texture-space quadrilateral。线性只在局部成立,所以这是 quasi-optimal antialiasing,而非任意非线性 warp 的全局精确解。

pixel footprint 经 Jacobian 映射后不是轴对齐方块screen spacepixel area: ±0.5texture space · Jbbox candidates · quadrilateral testJ⁻¹ testmap back|i| ≤ 0.5|j| ≤ 0.5average只平均 fwidth 矩形会纳入 footprint 外 texels;四边形测试能保留透视方向的锐度

实现时先用 derivatives 或 fwidth 构造 conservative bounding box,再遍历候选 texels。把 texel offset 乘 J01J_0^{-1} 变回 pixel coordinates,只有两个绝对分量都不超过 0.5 才纳入平均。只平均整个 bounding box 类似粗糙 anisotropic filter,会多吃 footprint 外 samples,透视方向因此更糊。

5. 放大:Gaussian 与 windowed sinc

bilinear interpolation support 小、速度快,却会把放大图像变得 fuzzy。理想 sinc kernel sin(πx)/(πx)\sin(\pi x)/(\pi x) 能保留原 sampled signal 的带宽,但 impulse response 无限、衰减很慢,直接实现成本不可接受。因此需要截断并乘 Gaussian 等 window,让 kernel 具有有限 support。

reconstruction kernel 选择:细节保留与 edge ringing 的取舍bilinear · fuzzyGaussian · no ringingwindowed sinc · detailsynthetic intensity step自然图像常受益于 sinc 带宽保留;硬合成边缘更适合无振铃的 Gaussian

windowed sinc 在自然照片中往往更好保留纹理与颗粒;硬合成 intensity step 缺失无限高频,重建会在边缘两侧 resonation。Gaussian cutoff 更平滑,不产生明显 ringing,但会衰减高频细节。选型不能只比较中心锐度,还要检查硬边 overshoot、undershoot、平坦区噪声和不同 subpixel phases。

6. 去模糊:shock filtering 的迭代边界

传统 sharpen 常整体放大高频,连噪声一起增强。shock filtering 根据 convexity 改变 diffusion 方向:second derivative 为正时沿反 gradient 搬运颜色,为负时沿 gradient 搬运,使模糊 transition 逐步变陡。原章示例使用五点邻域估计,并以 magnitude 0.05 运行八 passes。

shock filtering:按二阶导数符号把模糊过渡推回陡峭边缘five-sample estimategradient + convexity signiterative edge profileinput blur4 passes8 passessmall magnitude · many passesshock filter 适合均匀二维模糊;透视场景中的非均匀 anisotropic blur 需要额外分布信息

这类 filter 适合 blur distribution 较均匀的 2D reconstructed image。透视 3D scene 的 blur 会随深度、方向和 footprint 改变,而 shock shader 看不到这份分布,容易在错误方向制造 halo。多次迭代还会强化 ringing 与噪声,因此要保存每一 pass,而不是只看最后一张图。

vec4 center = sample(uv);
vec4 laplacian = 4.0 * center - sample(left) - sample(right)
               - sample(up) - sample(down);
vec2 gradient = vec2(
  dot(sample(right) - sample(left), laplacian),
  dot(sample(up) - sample(down), laplacian)
);
gradient *= magnitude / (length(gradient) + 1e-5);
return diffuseAlongSignedGradient(center, gradient);

7. lookup table、时间重建与交付边界

复杂 kernel 函数可预计算进 texture lookup table,但必须按用途选择 format、domain、resolution 与 sampler:periodic function 用 wrap,horizontal asymptote 用 clamp;需要连续值时可 linear filter,离散索引则必须 point。若 floating-point texture 不支持 linear filtering,要提高 resolution 或在 shader 手工插值。

同一重建框架可扩展到时间轴:把 frames 视为 3D signal,在 time dimension 上做 subpixel interpolation,可得到比 frame blending 更平滑、比 motion estimation 更简单的 slow motion。若重建后仍保留过长 shutter blur,可把 shock diffusion 只沿时间方向应用,但快速运动通常需要更大 temporal support。

这些算法优先质量而非 full-screen game frame rate,更适合医疗/科学图像、照片和影片编辑、合成、格式转换、专业渲染或离线纹理预处理。交付必须报告 taps、passes、intermediate precision、edge/ramp/natural fixtures 与目标 GPU 时间,不能只写“高质量”。

三步验收:地址、footprint、伪影

三个阶段使用相同 checkerboard、hard step、natural crop 与 flat field。先证明读到了正确 texels,再证明采样区域符合任务,最后才选择 kernel 和去模糊强度。

分步1 / 3

第一步:验证 sample centers 与归一化

对整数中心、半像素 phase、四条边和 constant image 运行 subpixel convolution。所有 phase 的 constant output 应相同;RGB/weight sum 探针能定位地址偏移或漏除问题。

continuous kernel + discrete samples:每个 subpixel phase 都要重新归一化kernel centered at fractional coordinateactual subpixel centerone-pass accumulationRGB = Σ color · weightA = Σ weightoutput = RGB / Amean intensity preserved连续 kernel 落在离散网格上时权重和随 phase 改变,不做除法会产生亮度泵动

本章小结

  • subpixel filtering 必须从 texel centers 采样,并按实际 weight sum 归一化。
  • separable kernel 降低大 support 读取;tiled kernel 最后统一除权重。
  • minification 应平均 Jacobian sampling footprint,而非任意放大窗口。
  • windowed sinc 保细节但会 ringing;Gaussian 更平滑但损失高频。
  • shock filter 用小步迭代收紧均匀模糊,不能替代未知 blur model。

练习

问题 1|计算读取成本。 radius 6 的 square Gaussian 有多少 taps?使用 separable 两 pass 后是多少?还需要纳入哪些隐藏成本?

问题 2|选择过滤路径。 透视缩小的 checkerboard、放大的自然照片、放大的硬边 UI 和均匀 blur 的二维照片分别应使用什么基线?

问题 3|修改实验并提供发布证据。 在 FilteringLab 中选择 sinc、radius 8、deblur 和 10 shock passes。你会怎样把配置改到可交付状态?

名词解释

本章出现的专业名词,用大白话再讲一遍。

subpixel filtering
normalized convolution
separable kernel
sampling footprint
Shannon-Nyquist reconstruction
shock filter

资料与写作方式声明

本章以GPU Gems 2 · Chapter 27. Advanced High-Quality Filtering权威目录界定学习范围,并结合正文列出的技术资料独立重写;不宣称复现原书正文,也不沿用原作表述。

原作版权归作者与出版社所有;本站原创教学结构与表述仅供学习交流。

讨论

评论区加载中…