提高纹理映射的质量

作者:沈晨


(本文的版权由其作者沈晨保留,如果需要转载或作其他用途,请与本文作者联系)

  在这一篇文章中,我将介绍提高纹理映射质量地内容。包括Mip map,双线性过滤, 和三线性过滤。

  当一个多边形由近到远或有远到近进行变换的时候, 其投影到屏幕上的面积也会相应的从大变小或从小变大。 如此便会有一个屏幕象素对应多边形上多个点或者屏幕上多个象素对应多边形上一个点。 如果这个多边形是贴上纹理的则会是屏幕上一个象素对应多个纹理元素(texel), 或反之。这会造成闪烁或马赛克等失真效果。 Mip map技术可以用来处理屏幕象素对应多个纹理元素的情况, 双线性过滤和三线性过滤可以用来消除马赛克但也可和Mip map 一起使用以达到更好的映射效果。我首先介绍一下Mip map。

  Mip map的思想是在多边形距离观察者较近的时候贴较高分辨率的纹理, 较远时贴低分辨率的纹理。降低分辨率的方法是将原纹理缩小。 为了计算的简便通常是将原纹理按2的幂次方不断的缩小。 如果原来的纹理是8×8的则其Mip map为4×4,2×2,1×1。 为了在缩小纹理的时候不产生严重的失真我们需对原来的纹理进行过滤。 具体做法如下。

如果我们有一个纹理A其大小为8×8。每个纹理元素的值用A来表示。

纹理A
A00A10A20A30A40A50A60A70
A01A11A21A31A41A51A61A71
A02A12A22A32A42A52A62A72
A03A13A23A33A43A53A63A73
A04A14A24A34A44A54A64A74
A05A15A25A35A45A55A65A75
A06A16A26A36A46A56A66A76
A07A17A27A37A47A57A67A77
我们将其过滤再缩小一半后得到一个4×4的纹理B,如下。
纹理B
B00B10B20B30
B01B11B21B31
B02B12B22B32
B03B13B23B33
其中B00 = (A00 + A10 + A01 + A11) / 4, 其他纹理元素也可用同样的方法取得。 也就是纹理B中的一个纹理元素是其在纹理A中对应的4个相邻纹理元素的平均值。 我们还可对纹理B以相同的方法缩小,如此便得到了所要的一组Mip map。 我们可以根据多边形和观察者之间的距离来选择适当的Mip map。

  Mip map可以提高纹理映射的质量但也有一些不足。一般为了减少纹理所占的存储空间, 我们只能对原纹理进行有限次的分级,然而多边形与观察者之间的距离确可以有无数多种情况。 举例来说,如果我们有一个多边形,其对应的一组Mip map为8×8,4×4,2×2,1×1。 而在某一时刻对其最合适的纹理大小应为可能为5.7×5.7, 但其对应的Mip map里没有这种分辨率的纹理,如果我们选8×8或4×4的话都不是很准确。 还有一种情况就是,这时该多边形的最合适的Mip map是9×9的超过了这组Mip map 中最大的一个Mip map,如果我们选8×8的话就会造成马赛克效果。

解决这些问题的方法是双线性过滤和三线性过滤。我将先介绍双线性过滤。 假设我们有一个多边形其对应的Mip map为5.7×5.7, 那么我们将在8×8与4×4的Mip map中选择一个,我们选择较小的那个也就是4×4的。 当我们在用扫描线法来填充这个多边形时得到一个纹理空间坐标(0.3,0.6)其对应的 4×4Mip map的纹理元素为(1.2,2.4)。这时我们不是将其简单的取整, 而是在它的周围取4个点C1(1.0,2.0),C2(1.0,3.0),C3(2.0,2.0),C4(2.0,3.0) 然后对这4个点在X,Y方向上进行插值。首先在X方向上对C1,C3和C2,C4进行插值。 我假设这个4×4的Mip map如下。

纹理B
B00B10B20B30
B01B11B21B31
B02B12B22B32
B03B13B23B33
我们在X方向上对C1,C3进行插值得到一个新的值P1其中
P1 = 0.8*B12 + 0.2*B22。
对C2,C4进行插值得到P2,其中
P2 = 0.8*B13 + 0.2*B23。
然后对P1,P2在Y方向上进行插值得到
P3,P3 = 0.6*P1 + 0.4*P2。
其中P3就为进行双线性过滤后得到的纹理元素。

  三线性过滤于双线性过滤差不多,区别在于三线性插值还要在两个Mip map 之间进行插值。我们还以上面的Mip map为例。我们得到一个多边形及其对应的一个 5.7×5.7的Mip map。这时我们不是取4×4的Mip map而是同时取8×8和4×4 两个Mip map。在用扫描线法填充多边形时分别计算一个屏幕象素对应在这两个Mip map 上的纹理元素。然后对这两个纹理元素分别进行如前面介绍的双线性插值后得到两个纹理元素 P44,P88。然后对这两个纹理元素进行插值得到P,其中
P = (1-5.7/(8+4))*p44 + 5.7/(8+4)*p88。
其中P就为三线性过滤后得到的纹理元素。

  如果你认为有什么地方需要修改或有疑问,请发e-mail到 dawnsheen@yahoo.com