我们先不谈纹理压缩在做什么,我们先看下自然状态下没有压缩的纹理的问题
目前的渲染管线中,对于3D物体表面的细节,主要还是靠纹理贴图来表现,分辨率越高,精度越高的纹理,在细节表现上自然越强,但是同时会导致内存开销增大,以及带宽等问题。
对于RGBA四通道的纹理,每像素需要8bits*4=32bits=4Bytes的空间。使用512X512的贴图,一张图就需要占用1M的内存。假设还开启了Mipmap(多级渐进纹理)还需要额外的1/3大小的空间,也就是1.33M。一个场景如果使用了100张这样的纹理,单独纹理的内存开销就需要133M的内存。如果没有纹理压缩,只能通过降低纹理尺寸来减少内存开销
纹理占用内存大,自然也会导致带宽开销变大,与此同时包体大小也会受到影响。而带宽和包体大小对于移动端游戏来讲都是非常稀缺的系统资源,每多用一分都要额外注意,当然内存也是如此。对于需要适配低端设备或者其他部分内存开销很大的游戏,尤其如此。
不同于我们通常理解上的图片压缩(png,jpg等),纹理压缩是服务于在3D 图像渲染系统的纹理图片存储技术,因此要充分满足随机访问的特性。
为了能够直接从压缩的纹理中直接采样数据,解压速度必须足够快,而且基本上不能影响到渲染性能
因为预先知道纹理采样的顺序几乎是不可能的,任何纹理压缩技术必须能够快速随机访问解压过的纹理数据。这就和一些常见的图片压缩方法产生冲突,例如JPEG.
对于渲染来讲,有损压缩是可以接受的。一些纹理压缩库,例如crunch ,允许开发者 灵活的在压缩率和纹理质量见进行平衡。例如Unity的纹理中就支持在选择crunch方式时,设置1-100的纹理质量,数值越低压缩率越高,而纹理的视觉效果也会更差。
纹理压缩,对于压缩/解压速率的极度不对称是完全可以容忍的,因为通常纹理压缩只需要在游戏打包时进行一次,对于用户运行时体验完全没有影响。
基于以上特性,大多数纹理压缩算法会把固定大小的像素块的某种形式的固定速率有损矢量量化(lossy vector quantization )包含进固定大小的编码字节块中,有时还会配合一些额外的预处理和后处理步骤。块截断编码(Block Truncation Coding )是这种类型的算法的很常见的一个例子。
因为他们的数据访问模式是明确定义的,纹理解压缩过程是作为图像管线的一部分在运行时进行的,这样可以降低渲染系统对带宽和存储空间的需求。除了纹理贴图,纹理压缩可以应用于其他类型的渲染贴图,包括凹凸贴图和表面法线贴图。同时,纹理压缩可以和其他贴图处理流程共同使用,例如Mip maps和各向异性过滤。
通俗来讲,纹理压缩不同于其他图片压缩方式(jpg,png),在使用中,不会在CPU中进行解压缩,而是直接把压缩内容传给GPU,而且在GPU中也不会一次把整张图片进行解压缩,只会在需要采样特定区域的纹理时对这一区域的纹理进行解压缩。
因为使用的是有损压缩,3D表面细节会产生一定程度的损失,这属于典型的效果换性能的妥协。
Unity 支持4种格式的ETC纹理压缩格式,主要应用于安卓设备的OpenGL es 上
对于现代的移动端GPU,几乎都支持OpenGL es 3.x,因此可以根据需要放心的使用所有的ETC格式。
Unity 支持两种DXT纹理压缩格式,RGB DXT1 和RGBA DXT5。主要应用于DirectX中
对于PC平台,大多数RGB格式图片推荐DXT1压缩格式,而对于RGBA格式图片使用DXT5压缩格式。
当目标平台是DX11类型的硬件时(modern PC,PS 4, XboxOne)时,使用BC7可能是更好的选择,因为此时压缩质量会更好。
该格式在Android平台不管是选择OpenGL es3.x或者Vulkan都不支持,实际占用的内存比预期要高
平台 | RGB 推荐格式 | RGBA 推荐格式 | HDR |
---|---|---|---|
PC/Console | DXT1 | DXT5 | BC6H |
Android | ETC 4bit / ETC2 4bit | ETC2 8bit | |
iOS |
如果使用了硬件不支持的纹理压缩格式,Unity在运行时会对纹理进行解压所到无压缩格式,而这种无压缩格式只是格式上是无压缩的,但是因为原始数据是有损压缩,所以视觉上纹理精度和压缩格式是一致的,因此单从视觉上很难察觉,而且占用的内存是双份纹理的开销,而带宽开销是无压缩格式的纹理大小所占用的开销。
例如:ETC格式在PC端Dx11的显卡是不支持的,如果使用,开销计算如下
而如果贴图格式在目标设备上支持,则不会发生内存中的解压缩操作,压缩过的图大小是多少,在内存中的设备上大小就是多少:
对于移动平台游戏,如果勾选了Unity中的 贴图设置中的Override for Android ,一定要注意,除非你特别清楚你的贴图在目标设备上的兼容情况,否则不要使用ETC格式以外的纹理压缩格式,否则造成的额外内存开销是巨大的。
iOS这里因为没有在真机测试,因此没有做说明,将在另一篇文章单独讨论iOS设备上的纹理压缩格式。