作者:STANCH

1.纹理过滤概述

当纹理被应用到三维物体上时,随着物体表面的形状和相机视角的变化,会导致纹理在渲染过程中出现一些问题,如锯齿状边缘、失真、模糊等。

纹理过滤的作用是解决这些问题,以获得更好的渲染效果。其目的是在纹理被应用到三维模型上时,通过对纹理上的像素进行插值或采样,使得纹理在不同距离和角度下呈现出更平滑、更真实的外观。

原始图片(左)和贴图到三维表面失真现象(右),来源:fundamentals-of-computer-graphics-4th

2.为什么需要纹理过滤

对于任意的3D表面在纹理映射过程中,需要进行纹理查找来找到屏幕上的一个像素对应于纹理上的哪一个纹素(纹理上一个颜色点)。纹理映射的过程会根据目标点离相机的远近,占用屏幕上不同大小的范围的像素,例如一个三角面在距离相机20m时占用100个屏幕像素,当三角面离相机更远时会看起来更小,此时可能占用20个屏幕像素,但是在两种情况下这个三角面使用的纹理贴图的大小是不变的。

屏幕的一个像素与它在对应的纹素之间可以存在不同类型的对应关系。这取决于纹理化表面相对于观察者的位置,有两种情况:

  • 每个纹素映射到多个像素,这被称为放大(magnification)
  • 每个纹素映射少于一个像素,这被称为缩小(minification)

比如,给定映射到世界中的正方形表面的正方形纹理,假设在某个观看位置,一个屏幕像素的大小与一个纹理像素完全相同。当观察者靠近时,纹素大小大于屏幕像素,需要适当放大。更远时,每个纹素大小小于一个像素,因此一个像素覆盖多个纹素。在这种情况下,必须通过纹理缩小来基于所覆盖的纹理元素拾取适当的颜色。

注意,即使在像素和纹素是完全相同的大小的情况下,一个像素也不一定完全匹配一个纹素。它们可能未对齐或发生旋转,一个像素可能覆盖多达四个相邻纹素的部分。因此,仍然需要某种形式的过滤。

3.多级渐远纹理(Mipmap)

假设我们有一个包含着上千物体的大房间,每个物体上都有纹理。有些物体会很远,但其纹理会拥有与近处物体同样高的分辨率。由于远处的物体可能只产生很少的片段,OpenGL从高分辨率纹理中为这些片段获取正确的颜色值就很困难,因为它需要对一个跨过纹理很大部分的片段只拾取一个纹理颜色。在小物体上这会产生不真实的感觉,更不用说对它们使用高分辨率纹理浪费内存的问题了。

多级渐远纹理(Mipmap)的概念来解决这个问题,它简单来说就是一系列的纹理图像,后一个纹理图像是前一个的二分之一(纹理图像的尺寸必须为2幂次方)。假设我们有一个正方形的纹理贴图,分辨率为512x512像素。该纹理贴图用于映射到一个距离相对远的平面上。它们旨在提高渲染速度并减少锯齿伪影。高分辨率 mipmap 图像用于高密度样本,例如靠近相机的物体;当物体看起来较远时,使用较低分辨率的图像。

来源:JoeyDeVries

在没有Mipmap的情况下,如果我们直接将512x512的纹理贴图映射到远处的平面上,由于远处的像素数量较少,会导致纹理缩小的情况。这可能会导致失真和锯齿效应。

现在,我们使用Mipmap来优化纹理过滤。根据Mipmap的原理,我们生成一系列不同分辨率的图像,每个级别是前一级别的一半分辨率。假设我们生成了以下级别的Mipmap纹理:

Level 0: 512x512
Level 1: 256x256
Level 2: 128x128
Level 3: 64x64
Level 4: 32x32
Level 5: 16x16
Level 6: 8x8
Level 7: 4x4
Level 8: 2x2
Level 9: 1x1

在渲染过程中,当我们将纹理映射到远处的平面上时,根据距离和像素数量,我们选择最接近所需分辨率的Mipmap级别进行插值。

假设远处的平面上每个像素区域相当于纹理上的4x4像素区域。在这种情况下,Level 7的分辨率是4x4,因此,应该使用Level 7的Mipmap级别进行插值计算,将Level 7的纹理映射到远处的每个像素上。

4.纹理过滤技术

  • 最近点采样(Nearest Point Sampling)

在放大和缩小过程中,最近点采样算法选择中心点最接近纹理坐标的那个像素。下图中可以看到四个像素,加号代表纹理坐标。左上角那个纹理像素的中心距离纹理坐标最近,所以它会被选择为样本颜色:

来源:JoeyDeVries

  • 双线性过滤(Bilinear)

双线性过滤算法通过对目标像素周围的四个最近纹理像素进行加权平均,计算出一个插值,近似出这些纹理像素之间的颜色。一个纹理像素的中心距离纹理坐标越近,那么这个纹理像素的颜色对最终的样本颜色的贡献越大。下图中返回的颜色是邻近像素的混合色:

来源:JoeyDeVries

那么这两种纹理过滤方式有怎样的视觉效果呢?让我们看看在一个很大的物体上应用一张低分辨率的纹理会发生什么吧(纹理被放大了,每个纹理像素都能看到):

来源:JoeyDeVries

最近邻插值产生了锯齿状的边缘和马赛克效果,但我们能够清晰看到组成纹理的像素,而双线性插值能够产生更平滑的图案,但很难看出单个的纹理像素,会比较模糊。

  • 三线性过滤(Trilinear)

三线性过滤是对双线性过滤中当纹理距离相机的距离刚好处于两个mipmap等级的交界处时,会出现明显的一个过渡现象的解决方案(下图红框)。三线性插值在双线性插值的基础上再进行了一次线性插值,最接近的两层Mipmap 层级分别进行双线性过滤,然后再对两层得到的结果进生线性插值。这种方法在处理近大远小的纹理映射时能够提供更好的质量和平滑度。

双线性过滤(左),和三线性过滤(右),来源:https://blog.csdn.net/u013746357/article/details/90723268

  • 各向异性过滤(Anisotropic Filtering)

在纹理采样时,需要贴图的三维表面平行于屏幕,则是各向同性的。当要贴图的三维表面与屏幕有一定角度的倾斜,则是各向异性的,上面过滤方法都是各向同性过滤方法。事实上,各向异性过滤是当前消费级显卡中的最高质量的过滤方法。各向同性方案只使用了正方形的mipmap来应用于双线性或三线性纹理过滤(各向同性是指在所有方向上都相同,用来描述所有的mipmap贴图都是正方形而不是在某一个轴向上有压缩的长方形或者其他形状)。各向异性过滤通过改变纹理采样的方式,使得在视线方向附近的纹理细节得到更高质量的采样,而在远离视线方向时则采样较低质量的纹理。这样可以提高纹理的清晰度和真实感,特别是在斜视角或观察远处物体时。

各向同性Mipmap存储模式(左),各向异性Mipmap图片存储模式(右),来源: 维基百科

当一个物体的表面和相机有很大的夹角时,纹理在屏幕上的对应填充区域就不是方形的。例如一个地板,距离相机远的地方,填充区域的宽高是不对等的,此时方形的纹理贴图就不是很合适了,此时就会导致模糊或者闪烁或者两者皆有。各向异性过滤通过采样一个非方形纹理解决了这个问题。

三线性过滤(左),和各向异性过滤(右),来源:techbrood

LearnOpenGL - Textures

渲染的本质: 纹理过滤(Texture filtering)技术-CSDN博客


 关注Mapmost,持续更新GIS、三维美术、计算机技术干货

Mapmost是一套以三维地图和时空计算为特色的数字孪生底座平台,包含了空间数据管理工具(Studio)、应用开发工具(SDK)、应用创作工具(Alpha)。平台能力已覆盖城市时空数据的集成、多源数据资源的发布管理,以及数字孪生应用开发工具链,满足企业开发者用户快速搭建数字孪生场景的切实需求,助力实现行业领先。

欢迎进入官网体验使用:Mapmost——让人与机器联合创作成为新常态

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐