纹理过滤与 Mipmap
Texture Filtering & Mipmap
纹理在屏幕上被放大时需要插值,被缩小时一个像素覆盖许多纹素,必须预先滤波才能避免混叠。放大用最近邻、双线性或双三次;缩小的主流方案是 mipmap + 三线性插值,斜视角下用各向异性过滤减少过度模糊。注意:过滤纹理值只在输入与着色结果线性相关时等价于过滤最终颜色。
过滤输入 vs 过滤输出
抗锯齿理论上要过滤最终像素颜色。颜色这类与输出线性相关的输入,过滤纹理等价于过滤结果;法线、粗糙度等与输出非线性相关,标准过滤可能导致混叠(改进方法见 9.13 节)。
放大
| 方法 | 做法 | 效果 |
|---|---|---|
| 最近邻(盒式滤波) | 取最近纹素 | 像素化 (pixelation),只取 1 个纹素 |
| 双线性 | 最近 2×2 纹素二维线性插值 | 偏模糊,锯齿大多消失 |
| 三次卷积(双三次) | 4×4 或 5×5 纹素加权 | 质量高,硬件一般不原生支持,可在着色器中实现 |
双线性公式( 为样本在四个纹素中心构成的坐标系中的位置): 砖墙例子:(81.92, 74.24) 减去 (0.5, 0.5) 得 (81.42, 73.74),四个纹素是 (81,73) 到 (82,74),,右上纹素权重 0.42×0.74 = 0.3108。
- 细节纹理:把高频重复的细节(手机划痕、地形灌木)以不同尺度叠加到放大的低频纹理上,效果接近一张高分辨率纹理。
- 重映射:对黑白棋盘格,把低于 0.4 的灰映射为黑、高于 0.6 映射为白,中间拉伸,既保持格子又有过渡。
- 许多高阶滤波器可写成重复线性插值,从而复用硬件双线性单元。Quílez 的便宜方法:把 用 smoothstep 或五次曲线 (二阶导在端点也为 0)变换后再交给硬件双线性,结果平滑,但每个纹素处有平台,呈阶梯感。
缩小
- 最近邻在远处地平线附近严重混叠,运动时更明显(时间混叠);双线性只比它好一点,像素覆盖超过 4 个纹素就失效。
- 由奈奎斯特极限,每像素最多一个纹素才能避免混叠。提高像素采样率(抗锯齿)作用有限,所以要预处理纹理,用固定时间和固定样本数近似大量纹素的影响。
Mipmap
- "mip" 意为 multum in parvo(小空间里的许多东西)。原图(0 级)每 2×2 求平均得下一级,递归到一边为 1 纹素,构成 mipmap 链。
- 质量关键:好的滤波器——2×2 平均是盒式滤波,几乎最差,会不必要地模糊低频、保留引起混叠的高频,最好用高斯、Lanczos、Kaiser 等;纹理边缘要考虑是否重复。gamma 校正——非线性编码的颜色纹理直接过滤会改变感知亮度,远处物体变暗、对比与细节受影响;应转到线性空间过滤再转回 sRGB 存储(多数 API 的 sRGB 纹理会自动处理)。
- 法线等非线性纹理在生成 mipmap 时尤其敏感,因为一次要过滤成百上千个像素,需要专门方法(9.13 节)。
- 层级 (OpenGL 叫 ,即纹理 LOD):用像素单元投影到纹理上的四边形的长边估计,或用四个导数 、、、 的最大绝对值。导数在 SM 3.0 起对像素着色器可用;动态流程控制中不可用,需事先算好;顶点着色器访问纹理时要自己计算梯度或 LOD。
- 三线性插值:在 上下两级各做双线性,再按 的小数部分线性插值,逐像素执行。
- LOD 偏移:加到 上。原本就偏糊的图可用负偏移,过滤不好(有混叠)的合成图可用正偏移;可按纹理整体或逐像素设置,也可直接提供 或导数。
- 优点:无论缩小多少,耗时固定。主要缺点是过度模糊:贴近表面斜看时,像素在 u 方向覆盖很多纹素、v 方向很少(甚至一个方向缩小、另一个方向放大),mipmap 只能取正方形区域,为避免混叠取最大覆盖,所以偏糊。
积分表 (SAT)
- 预计算每个位置到原点矩形内所有纹素之和(需更高精度,如每通道 16 位以上);用像素投影的包围矩形四角查表求平均:
- 是一种各向异性过滤,但只对水平、竖直方向有效;沿对角线看时包围矩形过大,仍然过糊。16×16 及以下的纹理至少要两倍内存,更大的纹理需要更高精度。
- 在现代 GPU 上可实现,能改进光泽反射、景深、阴影贴图、模糊反射等需要区域采样的技术。
无约束各向异性过滤
- 当前硬件最常用:把像素单元反投影成纹理上的四边形,用短边确定 (每个 mipmap 样本覆盖区更小、更清晰),沿长边中线(各向异性线)取多个 mipmap 样本。各向异性比在 1:1 到 2:1 之间取 2 个样本,更高比例取更多。
- 方向任意,不需要额外内存。书中对比图:16:1 各向异性在地平线处比三线性 mipmap 清晰得多且混叠极少。
- 不同实现对沿轴样本(probe)加权不同:等权、两端半权、高斯权重;它们接近软件中椭圆加权平均 (EWA) 的质量,EWA 也可在 GPU 着色器中实现。
GEA 的视角:纹素密度与过滤(卷 II 11.3.14.5–11.3.14.7)
屏幕空间纹素密度
- 纹素密度是纹素与像素之比。全屏四边形贴一张与屏幕同分辨率的纹理时密度为 1;同一个四边形移远后屏幕面积变小,密度大于 1(卷 II 11.3.14.5)。
- 密度远小于 1 时纹素比像素大得多,能看到纹素边缘;远大于 1 时多个纹素挤进一个像素,产生摩尔纹,像素颜色还会随相机微动而游动闪烁;远处物体用高分辨率纹理也浪费内存。
- mipmap 让密度尽量接近 1:每级宽高减半,64×64 的纹理有 64、32、16、8、4、2、1 七级。硬件按三角形离相机的距离选级,例如在屏幕上占 40×40 时可能选 64×64,占 10×10 时可能选 16×16;三线性过滤时可能混合 16×16 和 8×8 两级。
世界空间纹素密度
- "纹素密度"也可指纹素数与世界空间面积之比,GEA 称之为世界空间纹素密度:边长 2 米的立方体贴 256×256 纹理时为 (卷 II 11.3.14.6)。
- 它的数值取决于世界单位,不必接近 1,但同一场景中应大致一致,否则立方体某一面会显得比其他面模糊。许多工作室给美术提供纹素密度规范和引擎内可视化工具来保证这一点。
四种过滤方式
| 方式 | 采样 | 开 mipmap 时选级 |
|---|---|---|
| 最近邻 | 取中心离像素中心最近的纹素 | 选分辨率最接近且高于理想值的一级 |
| 双线性 | 像素中心周围 4 个纹素按距离加权 | 选最近的一级 |
| 三线性 | 在相邻两级(一高一低)各做双线性再线性插值 | 两级混合,消除屏幕上 mip 级的突变边界 |
| 各向异性 | 双线性和三线性都采 2×2 方块,只对正视表面正确;各向异性按视角对应的梯形区域采样 | 提升斜视表面的质量 |
(卷 II 11.3.14.7)这与本页「缩小」「Mipmap」中 RTR4 的内容一致,GEA 没有涉及 SAT 等更高级的方法。
书中前后不一致:GEA 说最近邻开 mipmap 时选"分辨率最接近且高于理想值的一级",双线性则选"最近的一级"。实际上 mip 级的选择方式与级内过滤方式是独立的两个设置(D3D 的
MIN_MAG_MIP_POINT、MIN_MAG_LINEAR_MIP_POINT等组合;OpenGL 的GL_NEAREST_MIPMAP_NEAREST、GL_LINEAR_MIPMAP_NEAREST):mip 用 point 方式时都是取按 LOD 四舍五入的最近一级,不论级内用最近邻还是双线性(OpenGL 4.6 规范 8.14.3 "Mipmapping";MS Learn "D3D11_FILTER enumeration")。 梯度来自 2×2 quad 的差分,见 光栅化。
PBRT 的视角:离线渲染器的纹理过滤(PBRT 4e 10.1、10.4)
与图像采样的区别
几何边缘和硬阴影保证图像必然走样,但纹理往往有解析形式或已知的离散样本,可以在采样前去掉高频,因此做好纹理过滤后通常每像素一个样本就没有纹理走样(光照的蒙特卡洛噪声另当别论)。采样率由光线微分得到,见 光线微分与纹理足迹。
理想重采样与实际简化(10.1.4)
理想做法:先用 sinc 把 带限,再与像素滤波器 卷积。实际几乎总是用盒式滤波做带限、忽略第二步(相当于像素滤波器为盒式),从而全部在纹理空间完成: 其他手段:已知频谱的纹理(各项频率已知的和)把超过奈奎斯特的项换成均值,等效 sinc 预滤波;都不行时在纹理空间超采样,比提高图像采样率便宜,因为不用多追光线。EWA 是例外,它假设高斯像素滤波器。
MIPMap(10.4.3–10.4.4)
- 纹理采样与图像采样的不同:取样只是查数组;纹理函数完全由样本定义,不存在"样本之间是什么"的不确定性。难点是采样率逐像素变化,要能高效过滤任意大小的区域。
- 金字塔每级分辨率减半,顶层一个纹素为全图均值,最多多占 内存。第 级分辨率为 ,宽度 对应 (取浮点值,超出层数时返回顶层像素)。
- 各向同性滤波器(点采样、双线性=三角滤波、三线性)取覆盖 、 两个方向中较大者的保守宽度,选使滤波区域覆盖约 4 个纹素的级别;斜视时会糊。三线性在相邻两级各做双线性再按小数部分混合,掩盖级别跳变;它与在原图上做三角滤波并不严格相等,但差异可接受。
- EWA(Greene–Heckbert 1986,Heckbert 1989 理论化):用两条微分向量拟合椭圆,以高斯加权;它是统一重采样滤波器,同时计入纹理空间高斯滤波和图像空间高斯重建。步骤:取较短轴选 mip 级;长短轴之比过大时加长短轴以限制纹素数(略糊但时间有界);在相邻两级各做一次并混合;椭圆隐式式 的值恰是"到中心距离与到边界距离之比的平方" ,直接用来查高斯表。表中存 (,按 索引,减去常数使其在边界归零)。结果为 。书中图 10.16:在球的两极和边缘这类强各向异性区域,EWA 比三线性清晰得多。
- 内存管理:同一文件、同一过滤与环绕参数的 MIPMap 只加载一次(
std::map缓存加互斥锁,读文件前释放锁);场景解析后并行加载纹理。
与上文(RTR4、GEA)的对照与分歧
| 话题 | RTR4 / GEA(上文) | PBRT 4e |
|---|---|---|
| 各向异性 | 硬件沿各向异性线取多个 mipmap 探针,接近 EWA 质量 | 直接在软件中做 EWA,作为高质量选项 |
| mip 级选择依据 | 屏幕上 2×2 四元组的导数(硬件),GEA 讲纹素密度 | 光线微分或相机近似;EWA 用椭圆短轴 |
| 像素滤波器 | 不讨论 | 指出常规做法等于假设盒式像素滤波器,EWA 才计入高斯重建 |
| 积分表 (SAT) | 作为各向异性方案介绍 | 只在延伸阅读中提到(Crow 1984,仅适合轴对齐区域) |
原书问题(10.1.4、10.4.3)
- 盒式滤波区域:网页公式为 、(SVG 确认各有两个连续符号),且导数没取绝对值。应为 ;不取绝对值时负导数会让区域反向或为零(同节图 10.5 的图注用的就是绝对值)。
- 10.4.3 说"必须去掉高于相邻样本距离两倍的频率",频率与距离混用;按奈奎斯特应为:采样间距为 时去掉高于 的频率(措辞问题)。
PBRT 的视角:图像金字塔的构建(PBRT 4e B.5.4–B.5.5)
Image::GeneratePyramid()要求分辨率是 2 的幂:不是的话先用FloatResizeUp()放大到下一个 2 的幂。放大用可分离滤波器分两次一维重采样(先 后 ),每个新像素最多由 4 个原像素加权,权重归一化以免整体变亮或变暗;求第一个落在滤波器支撑内的像素时,要在支撑下界加 0.5 再取 floor(中心 2.75、半径 2 的滤波器覆盖 ,起始像素是 1 而不是 0)。- 每一层用 2×2 盒式滤波取平均得到上一层;非正方形图像在较短维度到 1 之后保持 1、继续缩小另一维度,直到 1×1。中间计算用 32 位浮点,最终各层恢复原像素格式以免占用更多内存。
- 代价:放大到 2 的幂最坏时让内存变成约 4 倍(513×513 → 1024×1024);练习 B.1 建议用 Guthe–Heckbert(2005)的非 2 的幂 Mipmap,练习 B.2 建议用 Lanczos 滤波代替盒式滤波。
LearnOpenGL 的视角:NEAREST/LINEAR 与 mipmap 过滤枚举(Getting Started / Textures)
教程用放大/缩小时清晰的像素块 vs 平滑过渡对比 GL_NEAREST 与 GL_LINEAR,并列出缩小过滤四枚举:NEAREST_MIPMAP_NEAREST、LINEAR_MIPMAP_NEAREST、NEAREST_MIPMAP_LINEAR、LINEAR_MIPMAP_LINEAR(三线性)。常见组合:缩小 GL_LINEAR_MIPMAP_LINEAR,放大 GL_LINEAR。与上文 RTR/GEA/PBRT 的过滤讨论同目标,此处只补 OpenGL 枚举名与「mipmap 仅用于缩小」的 API 陷阱。
出处
- realtime_rendering_4ed.pdf 第 6 章 Texturing
- Game_Engine_Architecture_4th_Edtion_Volume_2_-_Jason_Gregory.pdf
- Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 II 第 11 章 11.3.14.5–11.3.14.7 节
- PBRT 4e source excerpt: chapter 10 (Textures and Materials)
- Pharr, Jakob, Humphreys《Physically Based Rendering: From Theory to Implementation》第 4 版(MIT Press, 2023)第 10 章 10.1–10.5 节,pbr-book.org/4ed/Textures_and_Materials
- PBRT 4e source excerpt: chapter B (Utilities)
- Pharr, Jakob, Humphreys《Physically Based Rendering: From Theory to Implementation》第 4 版(MIT Press, 2023)附录 B B.2–B.7 节与延伸阅读,pbr-book.org/4ed/Utilities
- Getting Started — Textures
- learnopengl.com/Getting-started/Textures