[Unity优化]图片压缩格式
1.参考资料
游戏中的压缩纹理格式:https://www.cnblogs.com/zblade/p/10308038.html
[Unity优化] unity图片压缩格式和内存计算:https://www.jianshu.com/p/92fc1442a63e
学习笔记——Unity3D内存优化(贴图优化):https://blog.csdn.net/qq_39824797/article/details/84339886
Unity优化之贴图:https://www.cnblogs.com/ssw-men/p/10472007.html
Uinty3D性能优化之贴图科普篇:https://blog.csdn.net/acuriousguy/article/details/109492105
2.总结
(1)图片格式描述
图片文件的存储格式:用于图片文件的存储和传输,通常在磁盘文件,内存以及网络传输中使用。
常用的图像文件格式有BMP,TGA,GIF,JPG(有损不透明),PNG(无损透明)等;
(2)纹理格式描述
显卡能够直接进行采样的纹理数据的格式:是向显卡中加载纹理时使用的数据格式。
常用的纹理格式有R5G6B5,A4R4G4B4,A1R5G5B5,R8G8B8, A8R8G8B8等。
占用空间:R5G6B5,A4R4G4B4,A1R5G5B5每个像素占用2个字节(BYTE),R8G8B8每个像素占用3个字节,A8R8G8B8每个像素占用4个字节。
例如:对于一个512 * 512大小的纹理,如果使用R5G6B5的纹理格式,其大小为512 * 512 * 2 = 512KB, 用A8R8G8B8, 就是1M,可以预见,游戏中占用容量最大将是各种纹理,很容易导致游戏安装包突破上G,为了缩小纹理格式的数据占用的内存大小,对应的压缩纹理格式产生了。注意,这不是在移动游戏出现后才产生的,早在PC端游戏时代就有压缩纹理格式。
(3)压缩纹理格式
<0>移动GPU的四大厂商
<1>基于OpenGL ES的压缩纹理格式
ETC1(Ericsson texture compression)
不支持透明通道,所以仅能用于不透明纹理,OpenGL2.0支持
这种压缩纹理格式是OpenGL ES的图形标准,被所有的android设备支持,不支持透明通道,每个像素0.5个字节
ETC2
针对ETC1不支持透明通道的改进,用ETC2可以支持透明通道,不过要求OpenGL ES3.0及以上(Android4.3+),目前基本覆盖率在9成以上
PVRTC(PowerVR texture compression)
支持GPU为PowerVR SGX系列,基本的压缩参数有:
RGB_PVRTC_4Bit, RGB, 每个像素0.5个字节
RGB_PVRTC_2Bit, RGB, 每个像素0.25个字节
RGBA_PVRTC_4Bit, RGBA, 每个像素0.5个字节
RGBA_PVRTC_2Bit, RGBA, 每个像素0.25个字节
ATITC(ATI texture compression)
支持GPU为Qualcomm的Adreno系列, 基本的压缩参数有:
ATC_RGB_AMD, RGB, 每个像素0.5字节
ATC_RGBA_EXPLICIT_ALPHA_AMD, RGBA, 每个像素1个字节
ATC_RGBA_INTERPOLATED_ALPHA_AMD, RGBA, 每个像素1个字节
ASTC
目前各大厂商主推的压缩纹理格式,压缩质量高,压缩块方案多,代价是压缩时间长(需要不断尝试压缩结果,算法决定)
DXTC(又名S3TC,S3 texture compression)
是一种有损纹理压缩算法,可以说DXT是目前应用最广泛的纹理压缩格式,可以认为所有的PC端显卡都支持DXT压缩。在多数纹理压缩选择中都是最佳方案,几乎可以认为是PC下的标准压缩格式。
基本的压缩参数有:
RGB_S3TC_DXT1, RGB, 每个像素0.5个字节
RGBA_S3TC_DXT1, RGBA, 每个像素0.5个字节
RGBA_S3TC_DXT3, RGBA, 每个像素1个字节
RGBA_S3TC_DXT5, RGBA,每个像素1个字节
<2>Unity纹理格式总结
每位的像素点(bpp)是单个像素所需的存储量。该值越低,可以在GPU的缓存中存储的像素越多,从而可以更快地进行纹理访问。
可变比特率(VBR)表示每个像素的比特不是固定值,而是取决于实际内容。VBR仅适用于Crunch压缩,并且仅适用于磁盘上的纹理大小。内存中的大小与使用基础纹理格式时的大小相同(例如,对于RGB Crunched DXT1,使用RGB Compressed DXT1)。
Crunch compression是DXT或ETC Texture压缩之上的一种有损压缩格式(部分数据在压缩过程中丢失)。纹理在CPU上被解压缩为DXT或ETC,然后在运行时加载到GPU。
Crunch compression有助于Texture使用尽可能少的磁盘空间,但对运行时内存使用没有影响。
Crunch compression可能需要很长时间才能压缩,但是在运行时进行解压缩非常快。
质量和压缩时间之间的平衡:质量越高,文件大小越大。为了获得最佳性能,尤其是在移动设备上,请使用应用程序所针对的硬件所支持的每像素位数最少的格式,只要该格式能够提供足够的视觉质量即可。
<3>推荐使用的压缩纹理格式
[1]描述
移动端:android使用ETC2, ios使用PVRTC或者ASTC
PC端:DXT
[2]具体
通常
清晰度
1.(高清晰无压缩)采用RGBA32
2.(中清晰中压缩)RGBA16+Dithering 要采用Floyd Steinberg抖动处理,不然渐变很明显,拉伸就会差距
3.(低清晰高压缩)ETC2 PVRTC
4.ASTC压缩率和清晰度都会比较好,支持的GPU :
tvOS (all), iOS (A8以上,5S以下), Android (PowerVR 6XT, Mali T600 series, Adreno 400 series, Tegra K1)
2016年之后的安卓手机基本支持这种压缩格式
iphone6以及之后的机型支持这种压缩格式
例子:
(4)图片格式和纹理格式关系
没有关系。如果图片要传输给显卡使用,则必须转换成显卡能够识别的纹理格式,这个在游戏引擎中,会对应自动转换,也可以通过相关的代码设置显式的转换。
这样的过程,有一个问题,就是加压缩,解码,重新编码压缩的过程比较消耗CPU,如果在游戏总实时的执行这样的一个过程,会出现明显的卡顿掉帧。
一般在项目中,在资源导入或者打bundle的时候,会执行相关配套的纹理格式转换,最终打入游戏包或者Bundle中的是已经预先转换好的纹理格式,这样加载的时候优化了解码和转换的过程,能够提高加载速度。这也是为什么不同平台的bundle不能跨平台使用的原因之一。
注:使用目标平台支持的纹理压缩格式时,GPU可以直接使用它,没有增加消耗;
如果目标平台不支持纹理压缩格式时,默认会将纹理解压成RGBA32或RGB32,然后与压缩的纹理一起存储在内存中,会增加纹理加载时间和增加额外内存。