TANotes

💡学点儿丨关于纹理的亿点点补课1 - 纹理压缩

by ERIN.Z, 2022-04-29


之前写插件的时候,写入纹理时发现与原图的压缩格式不同,做设计课前再来摸会儿🐟补补课。 Compressed

纹理导入

文件格式

文件格式是图像为了存储信息而使用的对信息的特殊编码方式,它存储在磁盘中,或者内存中,但是并不能被GPU所识别,因为以向量计算见长的GPU对于这些复杂的计算无能为力。

Unity 支持读取以下文件格式 BMP,EXR,GIF,HDR,IFF,JPG,PICT,PNG,PSD,TGA,TIFF Unity 可导入多层PSD文件,导入时自动展平,但图层在资源本身中维护。 decode

这些文件格式当被游戏读入后,还是需要经过CPU解压成R5G6B5,A4R4G4B4,A1R5G5B5,R8G8B8, A8R8G8B8等像素格式,再传送到GPU端进行使用。

纹理尺寸大小

理想情况下,纹理尺寸大小应该是每边为2的整数次幂。Unity 允许使用NOPT(非2的幂)纹理大小;但是,NPOT纹理大小通常需要多一点内存,并且GPU的采样速度可能更慢。

如果平台或GPU不支持NPOT纹理带下,Unity会对纹理进行缩放和填充已达到下一个2的幂的大小。纹理导入后可将Advanced选项选择Not Power of 2,在导入时放大NPOT纹理资源。

纹理压缩

在解释一切之前,先划重点:

PC

不带透明通道压缩成DXT1,带透明通道压缩为ETC5,不被4整除的回退到RGBA32

Android

不带透明通道压缩成ETC1,带透明通道压缩成ETC2,不被4整除的回退到RGBA32

IOS

不带透明通道压缩成RGB PVRTC,带透明通道压缩成RGBA PVRTC ,不是2的整数次幂回退到RGBA32

Compression

Texture图片拖入的时候,如下图所示; unity会默认设置ToNerest,这样会自动保证Android平台下图片被4整除,IOS平台下图片是2的整除次幂,所以默认情况下图片都可以得到最好的压缩。 ToNearest

BPP

每像素位数 (bpp) 表示单个纹理像素所需的存储量。较低的 bpp 值也意味着 GPU 使用较少的内存带宽来读取纹理像素。GPU 内存带宽通常是帧率的瓶颈,因此纹理压缩有助于避免这一问题。

  • 未压缩纹理
Format BPP 1024*1024(Mb)
A8R8G8B8(ARGB32) 32 4
A4R4B4G4(ARGB16) 16 2
R8G8B8(RGB24) 24 3 disk, 4 GPU
R5G6B5(RGB16) 16 2
  • 压缩纹理
Format BPP 1024*1024(Mb)
RGB Compressed DXT1 4 0.5
RGB Compressed ETC2 4 0.5
RGBA Compressed ETC2 8 1
RGB Compressed PVRTC 4 bits 4 0.5
RGB Compressed PVRTC 2 bits 2 0.25

纹理资源的视觉质量越高,每像素的位数就越高;因此,这会增大构建大小、加载时间和运行时内存使用。在某种程度上,所有纹理压缩格式都是有损的。通常,为了获得最佳运行时性能和磁盘占用空间,对于大多数纹理资源,应该选择目标设备支持的纹理压缩格式,并且实现所需的视觉质量的最小每像素位数。

不同于png、jgp这种硬盘压缩方式而言,DXT,ETC等纹理压缩方式可以在游戏运行中无需CPU解压就被GPU直接采样,可以极大的减少内存和带宽的占用,提升运行效率。

DXT压缩

DXT是一种有损纹理压缩算法,微软的DirectX中支持,DXT的格式包括DXT1~DXT5,其中DXT1和DXT5较为多见,可以认为所有的PC端显卡都支持DXT压缩,是PC下的标准压缩格式。 DXT压缩要求像素长宽必须是4的倍数。另外RGB的24位转为了16位颜色,16位中R&B各占5位,但是G占了6位,这是因为人眼对绿色最为敏感。

DXT1 DXT1格式主要适用于不具透明度的贴图或仅具一位Alpha的贴图(非完全透明则即完全不透明),对于完全RGB565格式的贴图,DXT1具有4:1的压缩比,即平均每个像素颜色占4位. DXT1将每4×4个像素块视为一个压缩单位,压缩后的4×4个像素块占用64位,其中有2个16位的RGB颜色和16个2位索引. DXT

DXT5 DXT5要比DXT1大一倍,对alpha通道的储存作了改进,它依旧用64bit储存16个alpha信息。前面2个字节(16bit)保存了当前块的最大alpha值和最小alpha值。接下来的48 bit,每个像素占用3bit空间,刚好描述 4x4个像素。 当alpha_0大于alpha_1 时,我们后面的3bit可以表示8级的插值;反之则保留110和111分别表示alpha为0和255的情况,中间可以有 6 级过度的插值。

DXT并没有在移动端得到很大的支持,在iOS设备中支持的是PVR压缩,在Android中支持的是ETC压缩。

PVRTC

PVRTC (PowerVR Texture Compression)由Imagination公司专为PowerVR显卡核心设计,由于专利原因一般它只被用于苹果的设备,仅Iphone、Ipad和部分PowerVR的安卓机支持。 PVRTC不同于DXT和ETC这类基于块的算法,而将整张纹理分为了高频信号和低频信号,低频信号由两张低分辨率的图像A和B表示,这两张图在两个维度上都缩小了4倍,高频信号则是全分辨率但低精度的调制图像M,M记录了每个像素混合的权重。要解码时,A和B图像经过双线性插值(bilinearly)宽高放大4倍,然后与M图上的权重进行混合。 有别于其他压缩方案,PVRTC 利用了跨块边界的颜色的相似性。因此这种方案本身支持平滑梯度。 PVRTC

ETC

ETC(Ericsson Texture Compression)最初为移动设备开发,如今它是安卓的标准压缩方案。将图像中的chromatic和luminance分开存储的方式,而在解码时使用luminance对chromatic进行调制进而重现原始图像信息。 其原理简单来说,是将4x4 的像素块编码为2x4或4x2像素的两个块的方法,每个块指定一个基色,每个像素的颜色通过一个编码为相对于这些基色偏移的灰度值确定。 ETC Unity几种ETC纹理压缩格式:

RGB ETC1 4 bit :4 bits/pixel,对RGB压缩比6:1,不支持Alpha,绝大部分安卓设备都支持。

RGB ETC2 4 bit :4 bits/pixel,对RGB压缩比6:1。不支持Alpha,ETC2兼容ETC1,压缩质量可能更高,但对于色度变化大的块误差也更大,需要在OpenGL ES 3.0和OpenGL 4.3以上版本。

RGBA ETC2 8bit :8 bits/pixel,对RGBA压缩比4:1。支持完全的透明通道,版本要求同上。

RGB +1bit Alpha ETC2 4bit :4 bits/pixel。支持1bit的Alpha通道,也就是只支持镂空图,图片只有透明和不透明部分,没有中间的透明度。

EAC:核心原理与ETC相同,但它只用于单通道或双通道数据,OpenGL ES 3.0和OpenGL 4.3后的设备大部分支持,但由于安卓平台五花八门的兼容性,一般不建议用单双通道贴图。

Crunch 压缩

Crunch 是一种压缩格式,基于 DXT 或 ETC 压缩,通过提供额外的可变比特率压缩。当 Unity 加载一个经过 Crunch 压缩的纹理时,它会在 CPU 上将该纹理解压缩为 DXT 或 ETC,然后将 DXT 或 ETC 压缩纹理数据上传至 GPU。 Crunch 压缩有助于纹理在磁盘上使用尽可能少的空间,但对于运行时内存使用量没有影响。Crunch 纹理可能需要很长时间进行压缩,但在运行时的解压缩速度非常快。您可以调整 Crunch 压缩的有损程度,以在文件大小和质量之间取得平衡。

ATI1/2

ATI1/2是ATI公司开发的纹理压缩格式,也被称为BC4,其每个数据块存储单个颜色的数据通道。以与DXT5中的Alpha数据相同的方式进行编码。常用于存储高度图,光滑度贴图。效果与原始图像基本没有差异。 ATI2也被称为BC5,每一个块中存储两个颜色通道的数据,同上以与DXT5中Alpha数据相同的方式进行编码,相当于存储了两个BC4块。 如果是在将法线存储在XY双通道中采用BC5格式压缩,由于每个通道都有自己的索引,因此法线贴图XY信息可以比在BC1中保留更多的保真度,缺点是需要使用两倍内存,也需要更多的带宽才能将纹理传递到着色器中。

格式选择

下表显示了每个平台上可用的纹理压缩格式选项以及生成的压缩文件大小(基于 256 像素平方图像)。选择纹理压缩格式需要在文件大小和质量之间取得平衡;质量越高,文件越大。 Compressed format

讲完了!

回看一下这四张图片的压缩选项,由于我的项目默认平台是PC,因此默认的压缩是DXT形式。

  • _albedo&_height:不含A通道信息,所以压缩格式是DXT1。不过_height其实我们只需要一个通道的信息,使用BC4会更加合理。
  • _mask:含A通道信息,所以压缩格式是DXT5,不含Gamma。
  • _normal:DXTnm是基于DXT5,Unity的法线压缩方法:压缩后R(归为1)G(不变)B(归为1)A(原R通道值)。 A通道精度最高(自己独占64bit),用来存储视觉上影响较大的左右分量x;RGB中G精度最高,用来存储分量y。 Compressed
参考文章:

by ERIN.Z

2024 © typecho & elise