本文主要整理简绍来自互联网的各项异性滤波的知识。
原文链接:http://www.linuxgraphics.cn/graphics/using_anisotropic_texture_filtering_in_opengl.html
主要的纹理过滤
纹理是数据的简单矩阵排列——比如。颜色数据、亮度数据或者颜色和alpha(透明度)数据。纹理数组中的每个独立的数值通常称为一个纹理单元。
纹理映射是一种将纹理图像应用于物体表面的技术(就是把图像贴到构成物体表面的多边形上去),就像该图像是一种贴画纸或玻璃纸附着于物体的表面上。
那么什么是纹理过滤呢?当三维空间里面的多边形经过坐标变换、投影、光栅化等过程,变成二维屏幕上的一组象素的时候。对每一个象素须要到对应纹理图像中进行採样,这个过程就称为纹理过滤。
纹理过滤通常分为2种情况:
- 纹理被缩小。比方说一个8 x 8的纹理贴到一个平行于xy平面的正方形上,最后该正方形在屏幕上仅仅占4 x 4的象素矩阵,这样的情况下一个象素相应着多个纹理单元。
- 纹理被放大。
这样的情况刚好跟上面相反。假如我们放大该正方形,最后正方形在屏幕上占了一个16 x 16的象素矩阵,这样就变成一个纹理单元相应着多个象素。
通常的纹理过滤的方法有2种:线性过滤和三线性过滤。也能够设置不进行不论什么过滤操作。(OpenGL同意为上面两种情况分别设置不同的过滤方法)
- 不进行不论什么过滤操作的速度最快也最简单。仅仅是针对每个象素对最接近它的纹理单元进行採样。可用于上面两种情况。
可是这样的纹理过滤方法的效果最差,在屏幕显示的图像会显得十分模糊。 - 线性过滤也比較简单。每个象素要对最接近它的2 x 2的纹理单元矩阵进行採样,取4个纹理单元的平均值。也可用于上面的两种情况。这样的纹理过滤方法的效果比上面的要好非常多。
- 三线性过滤相对的比較复杂,它仅仅能用于纹理被缩小的情况,须要先构造纹理图像的mipmap,mip的意思是“在狭窄的地方里的很多东西”,mipmap就是对最初的纹理图像构造的一系列分辨率降低而且预先过滤的纹理图。对于一个8 x 8的纹理来说须要为它构造4 x 4、2 x 2、1 x 1这三个mipmap。
假设正方形被缩小到在屏幕上占6 x 6的象素矩阵,一个象素的採样过程就变成这样。首先是到8 x 8的纹理图中进行对最接近它2
x 2的纹理单元矩阵进行採样(也就是上面的线性过滤);其次是到4 x 4的纹理图中反复上面的过程;接着把上面两次採样的结果进行加权平均,得到最后的採样数据。能够看出整个过程一共进行了三次的线性过滤。所以这样的方法叫做三线性过滤,它的效果是三种纹理过滤方法里面最好的。
各异向性纹理过滤
各异向性纹理过滤不是单独使用而是和前面所述的其它过滤方法结合一起使用的。
如果Px为纹理在x坐标方向上的缩放的比例因子。Py为纹理在y坐标方向上的缩放的比例因子。Pmax为Px和Py中的最大值。Pmin为Px和Py中的最小值。当Pmax/Pmin等于1时。也就是说Px等于Py,纹理的缩放是各同向的;可是如果Pmax/Pmin不等于1而是大于1,Px不等于Py,也就是说纹理在x坐标方向和在y坐标方向缩放的比例不一样,纹理的缩放是各异向的,Pmax/Pmin代表了各异向的程度。
举个样例来说,64 x 64的纹理贴到一个開始平行于xy平面的正方形上。可是正方形绕y轴旋转60度。最后投影到屏幕上占了16 x 32的象素矩阵。
纹理在x坐标方向上缩放的比例因子为64/16等于4,在y坐标方向缩放的比例因子为64/32等于2,Pmax等于4,Pmin等于2。缩放的各异向程度为2。
当把各异向性过滤和线性过滤结合起来的时候。应该是对最接近象素的4 x 2的纹理单元矩阵採样才合理,由于一个象素在x坐标方向上相应了很多其它的纹理单元(Px > Py)。
即使是纹理在一个轴方向上缩小而在还有一个轴方向上放大,处理的过程也是一样的(注意的是如果纹理在一个轴方向上缩小而在还有一个轴方向上放大,OpenGL仍然把它当作是纹理被缩小的情况。将採用为纹理缩小情况设置的过滤方法为基本过滤方法。然后再加上各异向性过滤)。如果被贴图的正方形最后在屏幕上占了一个128
x 32 的象素矩阵。纹理在x坐标方向上缩放的比例因子为64/128等于0.5,在y坐标方向缩放的比例因子为64/32等于2,因为Py > Px 且 Pmax/Pmin等于4,所以当把各异向性过滤和线性过滤结合起来的时候。应该对最接近象素的2 x 8的纹理单元矩阵进行採样。
三线性过滤和各异向性过滤结合的过滤方法的步骤跟前面单独的三线性过滤方法大致是一样的,仅仅是前面两步採用了各异向性过滤和线性过滤结合的方法。
通常情况下採取线性过滤或者三线性过滤就能够得不错的效果。可是在某些特殊的情况下,特别是把一个都是线状条纹的纹理图贴到一个绕x或者是y轴旋转角度非常大的多边形上的时候,比方将人的头发纹理贴到构成人的头顶的多边形,即使是三线性过滤的效果也不能令人惬意,仅仅有将各异向过滤方法和三线性过滤或者线性过滤的方法结合起来才干得到完美的效果。
如何在OpenGL中使用各异向性纹理过滤
在OpenGL里面使用各异向性纹理过滤首先要系统执行的OpenGL实现支持EXT_texture_filter_anisotropic
这个OpenGL扩展。
OpenGL里面的各异向性纹理过滤的參数设置是独立于纹理缩小和放大这两种情况的。也就是说不须要为这两种情况进行分别设置。參数设置十分简单,仅仅有一个參数就是最大各异向程度(TEXTURE_MAX_ANISOTROPY_EXT)。由于纹理缩放的各异向程度越大,就须要对很多其它的纹理单元进行採样,这样在处理速度上是不可接受的,所以必须设置一个最大各异向程度。当OpenGL进行各异向性过滤的时候,採用的各异向程度參数为纹理缩放的各异向程度和最大各异向程度之间的最小值。也就是说当纹理缩放的各异向程度大于设置的最大各异向程度时。将使用设置的最大各异向程度作为过滤使用的參数。
显然可见,当该參数设置为1的时候就是不进行各异向性过滤。1也是OpenGL为这个參数设定的缺省设置。另外还能够通过查询MAX_TEXTURE_MAX_ANISOTROPY_EXT获得该OpenGL实现支持的最大各异向程度。
以下是使用各异向性纹理过滤的演示样例代码:
glGenTextures(1, &texture_id)); glBindTexture(GL_TEXTURE_2D, texture_id); //Create a 2D texture with Mipmap gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, m_width, m_height, GL_RGB, GL_UNSIGNED_BYTE, image_data); //获得执行的 Opengl 实现支持的最大各异向程度. GLfloat largest_supported_anisotropic; glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropic); //设置纹理缩小时採用的过滤方法。这里设置的是三线性过滤 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); //设置纹理放大时採用的过滤方法,这里设置的是线性过滤 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //用 OpenGL 实现支持的最大各异向程度设置最大各异向程度參数 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropic);
各向异性过滤让表面倾斜物体纹理更加清晰锐利同一时候看上去非常密集。透明度又让密集的纹理变得模糊平缓。
各向异性过滤 (Anisotropic Filtering ):
它是用来过滤、处理当视角变化导致3D物体表面倾斜时造成的纹理错误。
传统的双线性和三线性过滤技术都是指“Isotropy”(各向同性)的,其各方向上矢量值是一致的,就像正方形和正方体。三线性过滤原理同双线性过滤一样。都是是将相邻像素及彼此之间的相对关系都记忆下来。然后在视角改变的时候绘制出来。
仅仅只是三线性过滤的採集范围更大。计算更精确,画面更细腻。
当然占用资源也很多其它。Anisotropic Filt技术的过滤单元并非“四四方方”的。其典型单元是矩形,还能够变形为梯形和平行四边形。画面上的一个象素,在一个方向上能够包括不同纹理单元的信息。
这就须要一个“非正多边形”的过滤单元。来保证准确的透视关系和透明度。不然,假设在某个轴上的纹理部分有大量信息。或是某个方向上的图象和纹理有个倾角,那么得到的终于纹理就会变得非常滑稽,比例也会失调。当视角为90度,或是处理物体边缘纹理时。情况会更糟。
各向异性过滤是最新型的过滤方法(相对各向同性2/3线性过滤),它须要对映射点周围方形8个或很多其它的像素进行取样。获得平均值后映射到像素点上。对于很多3D加速卡来说,採用8个以上像素取样的各向异性过滤差点儿是不可能的,由于它比三线性过滤须要很多其它的像素填充率。可是对于3D游戏来说,各向异性过滤则是非常重要的一个功能,由于它能够使画面更加逼真,自然处理起来也比三线性过滤会更慢。
原文链接:http://smartblack.iteye.com/blog/762948
1、 为什么在纹理採样时须要texture filter(纹理过滤)。
我们的纹理是要贴到三维图形表面的,而三维图形上的pixel中心和纹理上的texel中心并不一至(pixel不一定相应texture上的採样中心texel)。大小也不一定一至。
当纹理大于三维图形表面时,导至一个像素被映射到很多纹理像素上;当维理小于三维图形表面时。很多个象素都映射到同一纹理。
当这些情况发生时,贴图就会变得模糊或发生错位,马赛克。要解决此类问题。必须通过技术平滑texel和pixel之间的相应。
这样的技术就是纹理滤波。
不同的过滤模式。计算复杂度不一样,会得到不同的效果。过滤模式由简单到复杂包含:Nearest Point Sampling(近期点採样)。Bilinear(双线性过滤)、Trilinear(三线性过滤)、Anisotropic Filtering(各向异性过滤)。
在了解这些之前,有必要了解什么是MipMap和什么时各向同性。各向异性。
2、 什么是MipMap?
Mipmap由Lance Williams 在1983的一篇文章“Pyramidal parametrics”中提出。Wiki中有非常具体的介绍( http://en.wikipedia.org/wiki/Mipmap )
. 比方一张256X256的图,在长和宽方向每次降低一倍,生成:128X128,64X64,32X32,16X16,8X8,4X4,2X2,1X1。八张图,组成MipMap,例如以下图示。
Mipmap早已被硬件支持,硬件会自己主动为创建的Texture生成mipmap的各级。在D3D的API:CreateTexture中有一个參数levels,就是用于指定生成mipmap到哪个级别,当不指定时就一直生成到1X1。
3、 什么是各向同性和各向异性?
当须要贴图的三维表面平行于屏幕(viewport),则是各向同性的。当要贴图的三维表面与屏幕有一定角度的倾斜,则是各向异性的。
也能够这样理解。当一个texture贴到三维表面上从Camera看来没有变形。投射到屏幕空间中后U方向和V方向比例仍然是一样的,便能够理解成各向同性。
反之则觉得是各向异性。
4、 Nearest Point Sampling(近期点採样)
这个最简单,每一个像素的纹理坐标,并非刚好相应Texture上的一个採样点texel。怎么办呢?近期点採样取最接近的texel进行採样。
当纹理的大小与贴图的三维图形的大小几乎相同时,这样的方法很有效和快捷。假设大小不同,纹理就须要进行放大或缩小。这样,结果就会变得矮胖、变形或模糊。
5、 Bilinear(双线性过滤)
双线性过滤以pixel相应的纹理坐标为中心,採该纹理坐标周围4个texel的像素,再取平均,以平均值作为採样值。
双线性过滤像素之间的过渡更加平滑,可是它仅仅作用于一个MipMap Level,它选取texel和pixel之间大小最接近的那一层MipMap进行採样。当和pixel大小匹配的texel大小在两层Mipmap level之间时,双线性过滤在有些情况效果就不太好。于是就有了三线性过滤。
6、 Trilinear(三线性过滤)
三线性过滤以双线性过滤为基础。会对pixel大小与texel大小最接近的两层Mipmap level分别进行双线性过滤,然后再对两层得到的结果进生线性插值。
三线性过滤在普通情况下效果很理想了。可是到眼下为止,我们均是如果是texture投射到屏幕空间是各向同性的。可是当各向异性的情况时,效果仍然不理想。于是产生了Anisotropic Filtering(各向异性过滤)。
7、 Anisotropic Filtering(各向异性过滤)
各向同性的过滤在採样的时候。是对正方形区域里行採样。
各向异性过滤把纹理与屏幕空间的角度这个因素考虑时去。简单地说,它会考滤一个pixel(x:y=1:1)相应到纹理空间中在u和v方向上u和v的比例关系,当u:v不是1:1时,将会按比例在各方向上採样不同数量的点来计算终于的结果(这时採样就有可能是长方形区域)。
我们一般指的Anisotropic Filtering(AF)均是基于三线过滤的Anisotropic Filtering,因此当u:v不为1:1时,则Anisotropic Filtering比Trilinear须要採样很多其它的点,详细要採多少,取决于是多少X的AF,如今的显卡最多技持到16X AF。
当开启16X AF的时候,硬件并非对全部的texture採样都用16X AF。而是须要先计算屏幕空间与纹理空间的夹角(量化后便是上面所说的u:v),仅仅有当夹角大到须要16X时,才会真正使用16X.
假设想了解AF的实现原理,能够查阅此篇Paper: “Implementing an anisotropic texture filter”. 如今AF都是硬件实现,因此仅仅有少数人才清楚AF就尽是如何实现了(事实上细节我也没搞清楚),事实上全然能够由Pixel
Shader来实现AF,当然性能和由硬件做是没得比的。
8、 各过滤模式性能比較。
下表是各种过滤模式採一个pixel须要sample的次数:
Sample Number |
|
Nearest Point Sampling |
1 |
Bilinear |
4 |
Trilinear |
8 |
Anisotropic Filtering 4X |
32 |
Anisotropic Filtering 16X |
128 |
4X是三次过滤的四倍,是以三次过滤为基准进行比較的。
Anisotropic Filtering 16X效果最好。可是显卡Performance会下降非常多,当然也是測试你手中显卡Texture Unit的好方法。假设你认为你的显卡够牛。那么就把AA和AF都打到最高再试试吧:)
各项异性过滤
各项异性过滤(AF)是一种通用的纹理质量增强技术。可影响纹理在非正交视角下的外观。
纹理是包括各种数据的图像,比方颜色、透明度、反射率和平滑度(法线)。
这些数据映射到物体并经过GPU处理。以便于在屏幕上呈现真实的外观。但就其原始维度来说,大多数纹理都由于计算开销过大而不能在场景中无限制重用。由于物体的纹素(1像素纹理)与照相机之间的相对距离会影响细节的可见程度。这常常会导致浪费大量处理时间来获取3D场景中不成比例的小曲面上应用的多重纹理样本。
为了同一时候保证性能和图像质量,AF使用了mipmap;mipmap是以较低分辨率呈现的主纹理副本。当对应曲面与照相机之间的距离达到指点值时。图形引擎便可调用它。经过适当过滤之后。在一个场景中使用多种mipmap水平不仅不会对其外观造成的太大的影响,同一时候还能够极大地优化性能。
因为mipmap的维度一般是2的幂,或者小于原始纹理,因此有时须要为一个纹素採样多个mipmap,而这要求使用过滤方法来避免模糊和其它失真现象。默认的双线过滤是最简单、计算开销最小的过滤方法:它计算纹理的终于颜色。依据图形引擎对适当点(目标纹理存在于屏幕上时)定义的mipmap运行4次採样,这些样本的颜色数据将合成为终于结果。尽管这在一定程度上会造成纹理角度扭曲,但双线过滤仅对图形引擎确定的mipmap运行採样,这意味着调用了两种不同mipmap大小的纹理在出现角度扭曲后会对其清晰度产生显著的影响。
作为双线过滤的视觉连续方法,三线过滤能够连续对目标纹素的相邻mipmap採样和拉平纹理数据,因此在mipmap之间提供了平滑的转换。
但这样的方法与双线过滤都假定纹理在照相机前显示为方块。从而影响纹理在较小视角下的质量。其原因在于纹素比mipmap样本长或宽会分别造成过度採样或採样不足,从而导致图像模糊。
各项异性过滤的目的是在各种情况下都能提供出色的图像质量,同一时候将性能开销控制在较低的水平。
依据计算机科学的定义,各项异性是处理同一空间中相异坐标的质量,这适用于在显示时未与照相机绝对正交的纹理。
如前所述。当採样纹理与照相机斜交时。双线和三线过滤终于都会造成质量丢失,由于两种方法在从mipmap获取纹理採样时都假定映射纹理在所呈现的空间中为绝对的方形。这非常少能产生真实的效果。
mipmap的等方性(即使用同样的维度)也是造成质量丢失的还有一个原因,因此当纹素为梯形时就无法在两个方向上充足採样。为了解决此问题,各项异性过滤将依据纹理的角度扭曲程度按比例扩展mipmap的高度和宽度。该比例取决于所指定的最大採样值。然后将运行适当的採样。
AF支持的各项异性水平范围是1(无扩展)到16,这些值定义了mipmap可扩展的最大程度,但AF为用户提供的扩展水平通常为2的幂:即2x、4x、8x和16x。
这些设置之间的差别在于AF过滤纹理的最大角度不同。
举例来说,4x过滤纹理的角度比2x陡两倍。但仍然在2x范围内对纹理运行标准2x过滤来优化性能。使用的AF设置越高,能获得的收益也会更小,由于它们所适用的角度会呈指数形式降低。