赞
踩
纹理压缩(Texture compression)是一种专为在三维计算机图形渲染系统中存储纹理而使用的图像压缩技术。与普通图像压缩算法的不同之处在于,纹理压缩算法为纹素的随机存取做了优化。
常见的纹理压缩格式有S3纹理压缩,PowerVR纹理压缩(PVRTC),OpengGL ES纹理压缩(ETC)和由ARM开发的自适应可伸缩纹理压缩(Adaptive Scalable Texture Compression);
1.图片格式
图片格式一般指我们从美术工具中导出的文件格式,用于在磁盘中存储的格式;如jpg,png,tga等;
文件格式是图像为了存储信息而使用的编码方式,但是他不能被CPU所识别,GPU的特性是做向量运算;因此这些文件被游戏读入时还需要CPU解压成R8G8B8等像素格式,再传送到GPU端使用;而在运行时做解压无疑是非常耗的,所以一般在图片源文件导入时就会为其生成纹理格式的文件。
纹理格式是可以被GPU所识别的像素格式,可以被快速寻址采样。
但是直接使用这种纹理格式会导致资源的加载时间长、内存占用大的问题,尤其在移动平台上更加明显,因此,为了解决这个问题,就出现了压缩纹理格式;
Unity支持许多图片格式的源文件,但是3D图形的实时渲染中不会用这些格式,3D图形硬件要求纹理以专门格式进行压缩,这些格式对快速纹理采样进行了优化,DXT,ETC等压缩纹理格式可以在游戏运行中无需CPU解压就被GPU直接采样。每个不同的平台和设备都有自己的专有格式,因此在选择压缩方式时需要考虑兼容性。
Unity文档中给出了所有支持的纹理压缩格式(https://docs.unity3d.com/cn/2018.4/Manual/class-TextureImporterOverride.html):
这里简单归纳一下,不做一一阐述:
压缩率很高,但是解压缩需要耗时,Unity也在持续优化该压缩格式;
分别对应着RGB和RGBA纹理,适用于android平台;ETC1没有alpha通道,但是适应于所有安卓平台;ETC2有alpha通道,但是要求OpenGL ES 3.0以上;
主要是PowerVR平台下的硬件使用,适用于IOS平台;
近年来使用频率越来越高的一种方式,安卓和iOS都开始支持ASTC,它具有多种压缩比例,而且使用于pot和npot,从4x4每个像素占用8bit到12x12每个像素仅占用0.89个;ASTC压缩的不同设置决定了压缩的大小,和纹理是否带有alpha通道没有关系;
无Alpha通道的贴图建议压缩格式为ASTC 8x8。如果贴图为法线贴图,建议压缩格式为ASTC 5x5。有更高要求的贴图(比如面部、场景地面),可以设置压缩格式为ASTC 6x6,法线贴图为ASTC 4x4。
有Alpha通道的贴图建议压缩格式为ASTC 5x5。有更高要求的贴图(比如特效、UI),可以设置压缩格式为ASTC 4x4。
真实色彩的压缩格式,其中RGBA16位是低质量的真实色彩;
在Unity文档中还给出了每个平台下的默认格式,如下所示,它给出了不同平台、不同颜色模型(有无Alpha通道)下的压缩格式,包括了高质量、正常质量(默认设置)、低质量;
其中高质量一般是8位/像素,基本无压缩;正常质量一般在4-8位/像素;低质量一般在4位/像素以下;
注意兼容性:使用目标平台不支持的纹理压缩格式时,纹理将解压缩RGBA32(因为RGBA32是真彩色,并有alpha通道,它是最高质量的压缩格式,并使用于所有平台)并与压缩纹理一起存储在内存中,解压缩纹理以及存储两次浪费了时间和内存,因此需要针对不同的平台选择兼容的格式。
纹理过大会导致资源的加载、卸载耗时以及内存的占用增加(纹理资源的加载和内存占用一般是正相关的),纹理过大也会导致渲染时的带宽问题;而质量越高、文件越大,因此这是在品质和性能找到一个平衡;
mipmap属性也会导致内存增加,也需要注意,一般UI资源都不需要勾选这两项的;
读写属性会导致内存加倍,而且一般不会用到;
NPOT和POT:主要和mipmap,纹理的存储优化,以及纹理采样的地址计算等有关。如果是p2的话,做起上边这些就很简单了,基本上就是移位移位再移位,硬件做起来很简单,P2对硬件更加友好;这里一般要求美术资源在制作时就是满足pot的,如果美术资源不是,那么使用pot则会出现效果问题;
如果美术资源已经有alpha通道,也可以在导入设置中设置Alpha Source为None;
没有什么比直接减少分辨率更直接有效的工作,就像我们都知道的道理:80%的优化来源于20%的工作,那剩下20%的优化才是真正耗费时间的。
要去限制美术出图的大小,他们不关心性能只关心效果,可能每一张图都想要2048x2048甚至更高,所以有的时候必须要在效果可以接受的基础上来降低分辨率,降低一个级别就是四倍的优化。
我们的思路是让需要展示出高品质的纹理占用更多的资源,让那些没必要展示高品质的纹理占用更少的资源;
尽量避免RGBA32和ARGB32纹理的使用,因为这种格式一般属于高清晰的,但也比较耗;
RGBA16格式的加载效率也很高,接近于ETC1/PVRTC,设备越好,差距越小,因此在ETC1/PVRTC的效果不够好时,可以尝试用RGBA16;
UI贴图要注意Mipmap和read&write属性的设置;
粒子贴图大小一般要在256x256一下;
对于模型、场景贴图,我们需要根据不同用途的贴图做不同的压缩处理,如果使用ASTC格式,可以参考NVIDIA官网给出的测试数据来选择;
在支持OpenGLES3.0的安卓设备上,ETC2是一个很好的处理带透明度的纹理格式,但是游戏需要在OpenGLES2.0设备上,则不要使用ETC2,因为该版本不支持ETC2,这样就会导致ETC2会被转成RGBA32导致双倍的内存占用;
纹理资源一般可以做分档处理,最简单的可分为高中低三档,也可以根据需要加入不同的档次,依据档次来选择压缩格式;
在执行上,一般需要hook和check工具,在导入时对纹理进行一些hook判断和处理,同时check工具要能够获取到项目中所有纹理的大小、压缩格式等信息统计。
Unity Manual:特定于平台的覆盖的压缩纹理格式;https://docs.unity3d.com/cn/2018.4/Manual/class-TextureImporterOverride.html
Unity Connect:说说Unity纹理压缩技术与策略;https://connect.unity.com/p/shuo-shuo-unitywen-li-ya-suo-ji-zhu-yu-you-hua-yi
各种移动GPU压缩纹理的使用方法,介绍了一些纹理格式、图片格式、压缩格式的联系:https://huailiang.github.io/blog/2019/texture/
UWA:Unity加载模块深度解析(纹理篇):https://blog.uwa4d.com/archives/LoadingPerformance_Texture.html
NVIDIA官网:ASTC压缩纹理格式详细分析数据:https://developer.nvidia.com/astc-texture-compression-for-game-asset
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。