纹理

3.7k words

纹理管线

纹理重复平铺问题

纹理重复平铺超过三次后,会导致看起来不自然,避免这种周期性问题的常见方法上,将纹理值与另外一个非重复平铺的纹理相结合。

商业地形渲染系统

商业地形渲染系统可以根据地形类型、高度、坡度等因素,对多种纹理进行组合。同时纹理图像也会与几何模型在场景中的位置相关

使用着色器程序来实现一些特殊的转换函数,从而将纹理图案和瓦片贴图进行随机重组。

改善地形贴图密铺重复感的若干种采样方法 - 破晓的文章 - 知乎

使命召唤中的地形处理

图像纹理

所有纹理抗锯齿算法背后的思想基本相同:对纹理进行预处理,创建某种数据结构,从而快速近似计算一组纹素对像素的影响。对于实时渲染而言,这些算法在执行过程中具有使用固定时间开销和资源开销的特点。通过这种方式,每个像素会采集固定数量的样本,并将这些结果组合起来,从而计算大量纹素对像素的影响。

放大

底层的图像系统需要将纹理进行放大时,会使用放大过滤技术执行

邻近过滤(使用了box滤波器)
单个纹素可能会变得十分明显,这种效果被称为像素化;因为放大时,会选取距离每个像素中心最近的纹素,从而产生了块状外观,只需要为每个像素获取一个像素即可。虽然质量差
双线性插值
需要找到四个相邻的纹素,并在二维上进行线性插值,从而获得混合后的像素值。最后结果比较模糊,但并不会像邻近过滤那样出现锯齿。
并不是所有时候都需要进行双线性插值,比如国际象棋盘

三次卷积插值(双三次插值)
使用4x4或者5x5范围纹素的加权和,可以实现更高质量的放大。虽然硬件并不原生支持三次卷积插值,但是可以在着色器程序中进行执行,计算成本比双线性插值更高,但是许多的高阶滤波器都可以被表示为重复的线性插值,因此可以通过若干次简单的线性插值,来充分利用纹理单元中用于线性插值操作的GPU硬件。
降低计算成本的方法:在一组2x2的纹素之间,使用一个平滑的曲线来进行插值。最常用的时smoothstep和quintic曲线。

缩小

当纹理被压缩时,平面上一个像素单元格可能会占据好几个纹素。为了得到这个像素的颜色值,应当将这几个纹素对像素的影响整合起来。

邻近过滤
直接选择位于像素中心可见的纹素值,来作为自身的像素值,会产生严重的锯齿问题。会产生严重的锯齿问题,因为只是在影响像素的众多纹素中,选择一个纹素来代表该点的颜色,当表面发生移动时,这种瑕疵会变得更加明显,时域锯齿
Mipmap
将原始纹理反复过滤成更小的图像,在实际渲染发生前,原始纹理图像会生成一系列较小尺寸的版本。原始纹理会被下采样到原始尺寸的四分之一,每个新生成的纹素值,通常为原始纹理中四个相邻纹素的平均值,这个新生成的纹理有时也会被叫做原始纹理的字纹理。这个下采样的过程会被递归执行,直到最终生成的某个纹理的维度为1.
生成高质量mipmap的重要因素:
使用良好的过滤。生成mipmap的常用方法是将每2x2的纹素进行平均,从而获得下一级mip所对应的纹素值。具体使用的是一个box滤波器,这可能会导致较差的质量,因为它会对低频信息进行模糊,同时保留一些产生锯齿的高频信息。最好是使用高斯、Lanczos、Kaiser或者类似的滤波器
伽马校正,对于在非线性颜色空间中进行编码的纹理,在过滤时忽略伽马校正会修改该层级mipmap的感知亮度。如果使用了未校正的mipmap,相机距离物体越远,物体整体看起来越暗,对比度和表面细节也会受影响。会在线性空间中完成mipmap的生成和过滤,然后将生产的结果转换回sRGB颜色空间中并进行存储。
纹理化时访问mipmap的过程:计算纹理细节,为了确定沿着mipmap金字塔轴进行采样的层级。(计算第三个纹理坐标d)。方法1:利用像素单元格投影后所形成的四边形,取其中较长的那个边来对像素的覆盖范围进行近似;方法2:使用四个梯度中绝对值最大的那个作为度量。在得到d之后,根据坐标(u,v)对mipmap分别进行双线性插值,获得两个纹理值。最后按照参数d再对这两个纹理值进行一次线性插值。可以通过细节层次偏移(LOD bias),来对坐标d进行一定的控制,这是一个加在坐标d上的偏移量,影响了纹理的相对感知锐度。 好处:并不是单独计算每个纹素对像素的影响,而是对预先生成的纹素几何进行访问和插值,时间开销固定;缺陷:过度模糊,如下图所示。
SAT(面积积分表)
创建一个尺寸与纹理相同的数组,但是颜色存储的精度要更高(单个通道占据16个bit),像素单元格会被反向投影到纹理上,并被一个轴对齐矩形包围盒所包围,包围盒的四个角会用于访问SAT。
可以提供更好的质量,并且额外的内存开销合理,在现代广泛应用
无约束的各向异性过滤
重用现有的mipmap硬件。将像素单元格反向投影到纹理上,然后再对纹理上的四边形区域进行多次采样,最后将采样的结果整合在一起,作为该像素的颜色。
这可能会导致采样到很多无关纹素,使得表面变得模糊。

点采样(邻近过滤)、mipmap、SAT

体积纹理

高精度体积纹理

立方体贴图

纹理压缩

百人计划

图片和纹理区别:图片格式,图片文件的存储格式,通常在硬盘、内存中存储,传输文件时使用。无法减少显存占用率,且需要CPU压缩后才能被GPU读取,在显卡中解码都是RGBA的纹理格式。纹理格式,是显卡能够直接进行采样的纹理数据格式,通常在显卡中加载纹理时使用。对于贴图,设置纹理压缩格式后,CPU会对其进行压缩,然后传递给GPU读取。不设置的话,会压缩为RGBA32格式,但是占用高。

目的是为了直接解决内存、带宽以及缓冲问题。通过让GPU对纹理进行实时的解码压缩,能够使得纹理占据更少的内存,从而增加有效的缓存大小。这样的纹理使用起来会更加有效,因为访问纹理时,对于内存带宽的开销变少了。

Compressonator,可以查看压缩后图片的信息。

Improving Texture Compression in Games,Basis相对于其他格式,支持多平台,文件离线压缩为Basis,在运行时转码到需要的GPU格式,目前支持ETC1和DXT。


DXTC/BC
块压缩方法,优点在于可以创建大小固定的压缩图像,具有独立编码的片段,并且解码过程简单(所以速度快)。每个压缩部分都可以被单独解码,没有共享查找表或者其他依赖关系,简化解码过程。
将4x4的像素块压缩成一个64或者128位的数据块。
变体:BC1(6:1)、BC2(4:1)、BC3(4:1)、BC4(4:1)、BC5(2:1)、BC6H(6:1)(针对HDR图像)、BC7(3:1)(专门针对LDR)
Unity对贴图类型位法线的贴图,会采用DXTnm格式,基于DXT5,将法线贴图的R通道存入A通道,然后将RB通道清位1,可以将法线xy信息分别存入RGB和A中进行压缩,获取更高的精度。


通过两个颜色可以通过线性插值再获得其他两个中间颜色,索引代表这四个颜色中的选择。(RGB565)
有损压缩,无法从压缩纹理中还原出原始图像。
ETC
内置在OPENGL的API中,与BC一样拥有快速解码、随机访问、无间接查找和固定压缩比的特点。将4x4的纹素块压缩为64bit,每个像素4bit。
每2x4块(4x2)会存储一个基色。纹素块会从一个很小的静态查找表中选择四个常量,纹素块中的每个纹素,都可以选择其上的一个值,这会逐像素的修改其亮度值。压缩质量与DXTC相当。


亮度索引图

PVRTC
广泛用于iphone和ipad上。对4x4的纹素块进行压缩,同时对每个纹素提供两种存储方案,2bit和4bit。提供两个图像的低频信号,信号通过对相邻纹素块进行插值获得,解码时,每个纹素会使用1bit或者2bit的插值因子,来在这两个信号之间进行插值。
ASTC
自适应可伸缩纹理压缩,可以将nxm的纹理块压缩成128bit,其中纹素块的尺寸范围可以从4x4(8bit)到12x12(0.89bit),纹素块尺寸大小会导致不同压缩比,不支持iphone6以下的设备。兼容性不够,且解码时间较长,图片尺寸不需要为2的幂次

实际应用中的选择

PC:低质量使用DXT1格式不支持A通道,DXT5格式支持A通道
安卓:低质量:ETC1格式,不支持A通道;ETC2,支持A通道,但要求OpenGL ES 3.0/OpenGl 4.3以上版本;高质量使用ASTC格式,需要在安卓5.0/Opengl ES 3.1以上版本;
IOS:高质量ASTC,需要iphone6以上版本;低质量使用PVRTC2格式,支持Iphone6以下版本;
实际移动端使用上常用ASTC。

Alpha映射

alpha测试存在的问题,过度放大、过度缩小。当alpha测试和mipmap一起使用时,如果不进行特殊处理,效果会很差

右边为:根据覆盖率重新调整alpha值的alpha测试结果

出现这种问题是因为计算的透明度阈值固定,mipmap进行阈值为0.5的alpha测试处理。

透明度测试在放大的情况下会出现波纹瑕疵,可以通过将alpha贴图预先计算为一个距离场来避免。

Alpha to Coverage,以及类似的透明度自适应抗锯齿,可以将片元的透明度值转换为像素内覆盖的样本书。