提取图片纹理_Fundamentals Of Computer Graphics 第十一章 纹理映射(中)

本文探讨了纹理映射中的抗锯齿问题,特别是如何处理像素覆盖区以避免图像中的锯齿效应。介绍了使用Mipmap进行纹理过滤的基础知识,包括多级渐远纹理的概念,以及如何通过Mipmap实现更高效的纹理采样。此外,还讨论了各向异性滤波以解决观察角度引起的图像模糊问题。
摘要由CSDN通过智能技术生成

eda38d1bba2fdbf44394160adeadd8ac.png

本文翻译虎书第十一章纹理映射的11.3部分

11.3 抗锯齿纹理查询

纹理映射的第二个基本问题是抗锯齿。渲染纹理映射的图像是一个采样过程:将纹理映射到表面上,然后将表面投影到图像中,将在整个图像平面上产生2D函数,我们以像素为单位对其进行采样。就像我们在第9章中看到的那样,当图像包含细节或锐利边缘时,使用点样本执行此操作会产生锯齿失真-并且由于纹理的整个点都要引入细节,因此它们成为像我们在图11.3中看到的锯齿问题的主要来源。

就像线条或三角形的抗锯齿光栅化,抗锯齿光线跟踪(参见第13.4节)或对图像进行降采样(参见第9.4节)一样,解决方案是使每个像素不是点样本,而是图像面积的平均值,区域类似像素的大小。使用用于抗锯齿光栅化和光线跟踪的相同超级采样方法,如果有足够的样本,则可以在不更改纹理映射机制的情况下获得出色的结果:像素区域内的许多样本将落在纹理图中的不同位置,并平均使用不同纹理查找计算出的阴影结果是一种精确的方法,可以估算像素上图像的平均颜色。但是,使用详细的纹理需要很多样本才能获得良好的结果,这很慢。在表面存在纹理的情况下,高效地计算该面积平均值是纹理抗锯齿的第一个重要的主题。

纹理图像通常由光栅图像定义,因此,与升采样图像一样,也要考虑重采样问题(参见第9.4节)。解决方案同样可以运用在纹理上:使用重采样滤波在纹理像素之间进行插值。

在以下各节中,我们将对每个主题进行扩展

11.3.1 一个像素的覆盖区

使抗锯齿纹理比其他类型的抗锯齿更为复杂的原因在于,渲染图像与纹理之间的关系不断变化。每个像素值都应计算为图像中属于像素的区域的平均颜色,在通常情况下,像素对应单个表面,这相当于对表面上的区域求平均。 如果表面颜色来自纹理,则依次对纹理的相应部分进行取平均,这称为像素的纹理空间覆盖区。 图11.18说明了正方形区域(可能是较低分辨率图像中的像素区域)覆盖区如何映射到地板纹理空间中大小和形状完全不同的区域

c555918adfecbf3d570aed3d526bf91b.png
图11.18 图像中相同大小的正方形区域在纹理空间中的覆盖区的大小和形状都不同。

回忆一下使用纹理进行渲染所涉及的三个空间:将3D点映射到图像中的投影π和将3D点映射到纹理空间中的纹理坐标函数

。为了处理像素覆盖区,我们需要了解这两个映射的组合:首先向后跟随π,从图像到表面,然后向前跟随
。组合
决定了像素覆盖区:像素覆盖区是图片在
映射下的像素的方形区域

纹理抗锯齿的核心问题是计算像素覆盖区上纹理的平均值。通常,要精确地做到这一点可能是一件相当复杂的工作:对于一个具有复杂表面形状的遥远物体,覆盖区可能在纹理空间中覆盖了大面积的复杂的形状,或者可能是几个不连续的区域。但是在典型情况下,像素落在表面的平滑区域中,该区域映射到纹理中的单个区域。

因为

既包含从图像到表面的映射,又包含从表面到纹理的映射,所以覆盖区的大小和形状取决于观察情况和纹理坐标函数。当表面更靠近相机时,像素覆盖区会更小;当同一表面移得更远时,占地面积会更大。当以倾斜角度观察表面时,像素在表面上的覆盖区会变长,这通常意味着它在纹理空间中也会变长。即使使用固定的视图,纹理坐标函数也会导致覆盖区变化:如果覆盖区变形,则覆盖区的大小也会发生变化;如果变形,则即使是俯视图也可以将其拉长。

但是,为了找到一个用于计算抗锯齿查询的高效算法,需要一些近似值。

8d1a8cb04e7dd8b7bb5add193a7ca92c.png
图 11.19 可以使用从(x,y)到(u,v)的映射的导数来近似像素的纹理空间覆盖区。 x和y的偏导数与x和y等值线的图像平行(蓝色),并跨过一个平行四边形(橙色阴影),近似于精确轮廓线的弯曲形状(黑色轮廓)

当一个函数是平滑的,一个线性近似值通常是有用的。对于纹理抗锯齿的情况,这意味着从图片空间到纹理空间的

映射被近似看作一个从2D到2D的映射:

是一个2X2的,有些类似
的导数的矩阵。如果我们表示图片空间的
点和纹理空间的
点,他就是

5e9d1530b78534ebfc5e3f73427e60c0.png

这四个导数描述了纹理坐标

是如何随着一个在图片中的点
变化而变化的。

这种近似的几何解释是,它表示图像中以x为中心的单位大小的正方形像素区域将近似映射到纹理空间中以

为中心且其边缘与矢量
平行的平行四边形中。

导数矩阵

很有用,因为它讲述了整个图像(近似)纹理空间覆盖区变化的整个过程。数量较大的导数表示较大的纹理空间覆盖区,并且导数向量
之间的关系表示形状。当它们正交且长度相同时,覆盖区为正方形,并且它们变得偏斜和/或长度相差很大,覆盖区将会被拉长。

现在,我们已经得到了通常被认为是这种形式问题的“正确答案”:在特定图像空间位置处过滤的纹理样本应该是此点纹理坐标导数定义的平行四边形形状轮廓上的纹理贴图的平均值。这已经有了一些假设,即从图像到纹理的映射是平滑的,但是对于获得出色的图像质量来说它是足够准确的。但是,该平行四边形面积平均值已经太昂贵而无法精确计算,因此使用了各种近似值。纹理抗锯齿的方法在逼近此查找时在速度/质量折衷方面有所不同。我们将在以下各节中讨论这些

11.3.2 重采样

当覆盖区小于纹理像素时,我们会将纹理映射到图像中时将其放大。 这种情况类似于对图像进行上采样,并且主要考虑因素是在纹理像素之间进行插值以生成平滑的图像,其中纹理像素网格不明显。 就像在图像上采样中一样,此平滑过程由重建滤波器定义,该重采样滤波器用于计算纹理空间中任意位置的纹理样本。(参见图11.20。)

bd7e90c8352852240f96b9a640aeacc8.png
图11.20 纹理过滤中的主要问题随覆盖区大小而变化。 对于覆盖区(左),需要在像素之间进行插值以避免块状失真; 对于大覆盖区,挑战在于有效地找到许多像素的平均值

注意事项与图像重采样几乎相同,但有一个重要区别。在图像重采样中,任务是在规则的网格上计算输出样本,并且在可分离的重采样滤波器的情况下,这种规则性实现了重要的优化。在纹理过滤中,查找模式不规则,必须分别计算样本。这意味着大型高质量的重建滤波器使用起来非常昂贵,因此,通常用于纹理的最高质量滤波器就是双线性插值。

双线性插值纹理样本的计算与计算通过双线性插值上采样的图像中的一个像素相同。首先,我们根据纹理像素坐标(实值)表示纹理空间采样点,然后读取四个相邻纹理像素的值并取其平均值。纹理通常在单位平方上进行参数设置,并且纹理像素的位置与任何图像中的像素相同,在

方向上以
的间隔和在
中以
的间隔放置,纹素(0,0)被插入到边缘半个纹理像素处以保持对称.(有关完整说明,请参见第9章。)
Color tex_sample_bilinear(Texture t, float u, float v) 
{
    u_p = u * t.width - 0.5
    v_p = v * t.height - 0.5
    iu0 = floor(u_p); iu1 = iu0 + 1
    iv0 = floor(v_p); iv1 = iv0 + 1
    a_u = (iu1 - u_p); b_u = 1 - a_u
    a_v = (iv1 - v_p); b_v = 1 - a_v
    return a_u * a_v * t[iu0][iv0] + a_u * b_v * t[iu0][iv1] +
            b_u * a_v * t[iu1][iv0] + b_u * b_v * t[iu1][iv1]
}

在许多系统中,此操作成为重要的性能瓶颈,主要是因为从纹理数据中获取四个纹素值涉及到内存延迟。纹理的采样点的模式是不规则的,因为从图像到纹理空间的映射是任意的,但通常是连贯的,因为附近的图像点倾向于映射到可能读取相同纹理像素的附近纹理点。因此,高性能系统具有专门用于纹理采样的特殊硬件,该硬件可处理插值并管理最近使用的纹理数据的缓存,以最大程度地减少从存储纹理数据的内存中提取慢速数据的次数。

阅读第9章后,您可能会抱怨线性插值对于某些要求苛刻的应用程序可能不够平滑。但是,始终可以通过使用更好的滤波器将纹理重新采样到更高的分辨率来使其足够好,从而使纹理足够平滑以至于双线性插值效果良好。

11.3.3 多级渐远纹理

仅在放大纹理的情况下做好插值就足够了:像素占位面积比纹理像素间距小。当像素覆盖区覆盖许多纹理像素时,良好的抗锯齿功能需要计算许多纹理像素的平均值以平滑信号,以便可以对其进行安全采样。

一种计算覆盖区上的平均纹理值的非常准确的方法是找到覆盖区中的所有纹理像素并将其相加。但是,当占用空间很大时,这可能会非常昂贵-仅一次查找就可能需要读取数千个纹素。更好的方法是在不同大小和位置的各个区域上预先计算并存储纹理的平均值。

这个想法的一个非常流行的版本被称为“MIP映射”或mipmapping。Mipmap是一系列纹理,这些纹理均包含相同的图像,但分辨率越来越低。原始的全分辨率纹理图像称为mipmap的基本级别或级别0,而级别1则是通过获取该图像并将其在每个维度中降采样2倍而生成的,从而得到具有像素数量的四分之一。大致来说,此图像中的纹素是0级图像中面积为2乘2纹素的正方形区域的平均值。

可以继续进行此过程,以定义所需的任意多个mipmap级别:通过对k级图像进行降采样2倍来计算k - 1级图像。级别k的纹素对应于原始纹理中面积为

纹素的正方形区域。例如,从1024×1024纹理图像开始,我们可以生成具有11个级别的mipmap:0级为1024×1024;级别1为512×512,依此类推,直到级别10,只有一个纹理像素。这种具有以一系列越来越低的采样率表示相同内容的图像的结构,被称为图像金字塔,其基于将所有较小图像堆叠在原始图像顶部的视觉隐喻。

11.3.4 使用Mipmap进行基础的纹理滤波

使用mipmap或图像金字塔,与单独访问许多纹理像素相比,可以更有效地完成纹理过滤。当我们需要在大面积上平均的纹理值时,我们只使用来自更高级别的mipmap的值,这些值已经是图像大面积上的平均值。最简单,最快的方法是从mipmap查找单个值,然后选择级别,以使该级别上的纹素覆盖的大小与像素覆盖区的整体大小大致相同。当然,像素覆盖区的形状可能与纹素表示的(始终为正方形)区域的形状完全不同,我们可以预期会产生一些失真。

暂时搁置一个问题,当像素覆盖区具有拉长的形状时该怎么做,假设覆盖区是宽度D的平方,以全分辨率纹理中的像素表示。哪个级别的mipmap适合采样?由于第k级的纹理像素覆盖了宽度为

的正方形,因此选择k

所以我们让

。当然,这在大多数情况下会给出k的非整数值,并且我们只存储了整数级别的mipmap图像。 两种可能的解决方案是,仅针对最接近k的整数查找值(高效,但会在级别之间的突然过渡处产生接缝),或者查找针对k的两个最接近整数的值并线性插值(两次,但更流畅)。在我们实际写下对mipmap进行采样的算法之前,我们必须决定当覆盖区不是正方形时如何选择“宽度”D。 一些可能的方法是使用面积的平方根或找到覆盖区的最长轴并将其称为宽度。易于计算的实际折衷方法是使用最长边的长度:

d8466f1ebe89936bba6d2e14fd7a182b.png
Color mipmap_sample_trilinear(Texture mip[], float u, float v,matrix J) 
{
    D = max_column_norm(J)
    k = log2(D)
    k0 = floor(k); k1 = k0 + 1
    a = k1 - k; b = 1 - a
    c0 = tex_sample_bilinear(mip[k0], u, v)
    c1 = tex_sample_bilinear(mip[k1], u, v)
    return a * c0 + b * c1
}

基本的mipmapping可以很好地消除锯齿,但是由于它无法处理细长的或各向异性的像素覆盖区,因此在以掠射角度查看表面时效果不佳。在代表观察者站立的表面的大平面上最常见。 可以以非常陡峭的角度观察地板上较远的点,从而产生非常各向异性的覆盖区,该覆盖区在较大的正方形区域内会发生映射。生成的图像将在水平方向上显得模糊。

11.3.5 各向异性滤波

Mipmap可以与多个查询一起使用,以更好地近似伸长的覆盖区。 这个想法是根据覆盖区的最短轴而不是最大轴选择mipmap级别,然后将沿长轴间隔的几个查找平均在一起。(见图11.21。)

0375e41d44c6b1700b67390a722e59aa.png
图11.21 使用三种不同策略对具有挑战性的测试场景进行抗锯齿的结果(参考图像左侧显示了详细的结构):简单地通过最近邻插值获取单个点样本; 使用mipmap金字塔对每个像素的纹理中的正方形区域求平均; 使用来自mipmap的几个样本来平均纹理中的各向异性区域。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值