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 一起放大?
windowed sinc 保留采样带宽,但硬合成边缘可能出现衰减振铃。
本章主题 Advanced High-Quality Filtering 的核心不是“选择最锐的核”,而是让离散样本、连续模型与目标像素的覆盖区域一致,然后分别控制 blur、aliasing、ringing 和计算成本。
1. 从 normalized coordinate 回到 texel center
图像滤波器常需要访问确切的离散样本,而 texture API 通常接收零到一的实数坐标。设 texture size 为 、归一化坐标为 ,对应 sample index 是
这个式子在说:先把连续坐标量化到整数 sample,再加半个 texel 回到该 sample 的中心;中心比 corner 更能抵抗 round-off。若 sampler 明确使用 nearest/point filtering,可让硬件自动吸附到最近样本,但 linear filtering 会改变语义。
相邻像素访问不必每次 floor。可以把 、 及其正负组合预计算进 uniform,从当前 coordinate 一次加减得到八邻域。必须验证 API 的 texel-center 约定、border texels 与 wrap/clamp;跨 API 照抄 half-texel 规则常会整体偏一格。
2. 连续 kernel 如何落到离散图像
↡把连续 convolution kernel 精确居中在当前非整数纹理位置,再从周围离散 texels 取样的过滤方式。普通离散 convolution 假设 kernel 总是对齐某个 texel center。图像放大或 warp 时,输出 coordinate 往往落在 texels 之间;若仍用固定离散 coefficients,kernel phase 会跳动。更高质量的做法是把 kernel 视为连续函数 ,根据当前 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 必须写进契约。
↡把颜色加权和除以本次实际采到的 kernel 权重和,使常量输入在任意 subpixel phase 下保持原亮度。对邻域 、输出中心 ,归一化结果是
这个式子在说:连续 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
↡可写成横向一维函数与纵向一维函数乘积的二维卷积核;它允许先滤 rows、再滤 columns。若 ,一个 taps 的 2D convolution 可拆成两个 taps 的 passes。Gaussian 和 box kernel 都可 separable;radius 4 时,square path 要 81 samples,而 two-pass path 只要 18 samples。
两 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 决定平均区域
↡一个屏幕像素映射到 texture space 后覆盖的区域;透视与非均匀缩放会把正方形变成倾斜、拉长的四边形。minification 若跳过预滤波,高于目标 Nyquist bandwidth 的细节会折回低频,产生 moiré 和 shimmer。理想抗锯齿是对每个像素覆盖的 texture area 求平均;mipmap 是高效近似,但不能在所有透视方向上最优保留信号。
对屏幕到 texture 的映射 ,在当前像素中心 做一阶局部展开:
这个式子在说:用 texture-coordinate Jacobian 把屏幕空间像素正方形近似映射成 texture-space quadrilateral。线性只在局部成立,所以这是 quasi-optimal antialiasing,而非任意非线性 warp 的全局精确解。
实现时先用 derivatives 或 fwidth 构造 conservative bounding box,再遍历候选 texels。把 texel offset 乘 变回 pixel coordinates,只有两个绝对分量都不超过 0.5 才纳入平均。只平均整个 bounding box 类似粗糙 anisotropic filter,会多吃 footprint 外 samples,透视方向因此更糊。
5. 放大:Gaussian 与 windowed sinc
↡依据采样定理,用 sinc 低通核从离散样本恢复带限连续信号,再在新分辨率重新采样的方法。bilinear interpolation support 小、速度快,却会把放大图像变得 fuzzy。理想 sinc kernel 能保留原 sampled signal 的带宽,但 impulse response 无限、衰减很慢,直接实现成本不可接受。因此需要截断并乘 Gaussian 等 window,让 kernel 具有有限 support。
windowed sinc 在自然照片中往往更好保留纹理与颗粒;硬合成 intensity step 缺失无限高频,重建会在边缘两侧 resonation。Gaussian cutoff 更平滑,不产生明显 ringing,但会衰减高频细节。选型不能只比较中心锐度,还要检查硬边 overshoot、undershoot、平坦区噪声和不同 subpixel phases。
6. 去模糊:shock filtering 的迭代边界
↡根据图像 gradient 与 second-derivative 符号选择扩散方向,经过多次小步迭代把平滑过渡压缩成更陡边缘的非线性锐化方法。传统 sharpen 常整体放大高频,连噪声一起增强。shock filtering 根据 convexity 改变 diffusion 方向:second derivative 为正时沿反 gradient 搬运颜色,为负时沿 gradient 搬运,使模糊 transition 逐步变陡。原章示例使用五点邻域估计,并以 magnitude 0.05 运行八 passes。
这类 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 和去模糊强度。
第一步:验证 sample centers 与归一化
对整数中心、半像素 phase、四条边和 constant image 运行 subpixel convolution。所有 phase 的 constant output 应相同;RGB/weight sum 探针能定位地址偏移或漏除问题。
本章小结
- 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