界面纹理压缩(CbCr + YAlpha)

最近一个月都在做Unity3D的相关优化,在一个庞大的实际项目中做优化。 内存占用,帧消耗,加载速度等。。。

上周在做内存占用优化时,突发奇想了一个纹理压缩的思路:YCbCr,接下来做了实验和集成,发现效果很不错。

背景

我们的项目的UI纹理比较多,Atlas也都较大。然而etc压缩格式不支持Alpha通道,而pvrtc格式多alpha通道压缩质量也堪忧。 于是我们采用了拆分alpha,加一次采样的方式,对Android和iOS的格式和质量进行统一。

将原本的rgba纹理,拆分为rgb + alpha两张etc/pvrtc4rgb纹理。大小也就是4bpp + 4bpp = 8bpp,和dxt5的大小一直,只是需要多一次采样。 效果上完全达到要求。

修改

在分析内存占用时,发现在gpu对象中,ui纹理的占比非常大。遂思考直接降分辨率,结果效果惨不忍睹

晚上突发奇想,想起之前crysis3的gbuffer带宽优化方法,有一个基于视频算法的trick,大概就是利用了YCbCr这种方式。 将原始的r,g,b三个通道,转换为亮度,色度r,色度b三个通道。一般的讲,亮度是最为高频的信号,而两个色度相对低频。 因此就可以将亮度以原尺寸保留,而两个色度通道以半精度,甚至四分之一精度保存。来降低带宽。

我们目前的ui纹理,已经拆分为两张纹理,正好可以利用yuv,将信号按高低频区分,分别存储,再在shader中组合,岂不妙哉!

实现

说干就干,实现分为了以下步骤:

  1. 纹理预处理

  2. 材质复写

  3. shader修改

效果和对比

RGBA32原图

RGB + A全精度图

RG 1/4 + YA全精度图

总结和展望


blog comments powered by Disqus