码迷,mamicode.com
首页 > 其他好文 > 详细

各项异性滤波简介Anisotropic Filtering(AF)

时间:2015-03-20 00:05:46      阅读:346      评论:0      收藏:0      [点我收藏+]

标签:各向异性过滤

本文主要整理简绍来自互联网的各项异性滤波的知识。


原文链接:http://www.linuxgraphics.cn/graphics/using_anisotropic_texture_filtering_in_opengl.html

基本的纹理过滤

纹理是数据的简单矩阵排列——例如,颜色数据、亮度数据或者颜色和alpha(透明度)数据。纹理数组中的每一个独立的数值通常称为一个纹理单元。纹理映射是一种将纹理图像应用于物体表面的技术(就是把图像贴到构成物体表面的多边形上去),就像该图像是一种贴画纸或玻璃纸附着于物体的表面上。

那么什么是纹理过滤呢?当三维空间里面的多边形经过坐标变换、投影、光栅化等过程,变成二维屏幕上的一组象素的时候,对每个象素需要到相应纹理图像中进行采样,这个过程就称为纹理过滤。

纹理过滤通常分为2种情况:

  1. 纹理被缩小。比如说一个8 x 8的纹理贴到一个平行于xy平面的正方形上,最后该正方形在屏幕上只占4 x 4的象素矩阵,这种情况下一个象素对应着多个纹理单元。
  2. 纹理被放大。 这种情况刚好跟上面相反,假如我们放大该正方形,最后正方形在屏幕上占了一个16 x 16的象素矩阵,这样就变成一个纹理单元对应着多个象素。

通常的纹理过滤的方法有2种:线性过滤和三线性过滤。也可以设置不进行任何过滤操作。(OpenGL允许为上面两种情况分别设置不同的过滤方法)

  1. 不进行任何过滤操作的速度最快也最简单,只是针对每一个象素对最接近它的纹理单元进行采样,可用于上面两种情况。但是这种纹理过滤方法的效果最差,在屏幕显示的图像会显得十分模糊。
  2. 线性过滤也比较简单,每个象素要对最接近它的2 x 2的纹理单元矩阵进行采样,取4个纹理单元的平均值,也可用于上面的两种情况。这种纹理过滤方法的效果比上面的要好很多。
  3. 三线性过滤相对的比较复杂,它只能用于纹理被缩小的情况,需要先构造纹理图像的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设置越高,能获得的收益也会更小,因为它们所适用的角度会呈指数形式减少。

技术分享










各项异性滤波简介Anisotropic Filtering(AF)

标签:各向异性过滤

原文地址:http://blog.csdn.net/u013467442/article/details/44466069

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!