[Unity] 几种主流贴图压缩算法的实现原理

查看:983 |回复:16 | 2018-3-6 13:25:00

您需要 登录 才可以下载或查看,没有账号?注册

x
本帖最后由 /bj蝈蝈 于 2018-3-6 16:15 编辑

前段时间一直在搞项目上线前的各种优化,关于贴图压缩这块也是需要针对不同的平台做不同的设置,这里备忘一下在各种平台中常使用的几种贴图压缩格式及其细节,以便更加适宜地选择在特定设备下的压缩格式以便节省资源。关于移动平台和硬件设备与压缩格式的对应关系可以参考下这里,基本上比较清楚了。

1. DXTC

DXTC(或BC)为微软为DX而推出的基于block的贴图压缩格式,其主要采用调色板的原理来进行压缩。

BC1:

基于4x4block来进行,不含有alpha通道,每个block内记录两个16bits的颜色做为基准颜色,然后解压时再使用两个基准色调制出另外两个颜色做为块内4个压缩颜色。其计算方式为:

basecolor2 = 2/3 *basecolor0 + 1/3 * basecolor1

basecolro3 = 1/3 *basecolor0 + 2/3 * basecolor1

对于每个块内的texel,存储2bits的索引,用来指向到4个基准颜色中的一个。所以对于BC1的压缩状态为64bits:


  • 32bits:两个RGB565格式的基准颜色;
  • 32bits:16个2bits的索引;

BC3:

在BC1的基础上支持alpha通道。首先,颜色的存储方式与BC1相同,需要64bits;对于alpha部分,使用与颜色部分相同的策略来处理。在block存储两个基准的alpha值,然后在其基础上插值得到其它6个共计8个alpha值,来做为alpha的调色板;然后对于每个texel存储一个3bits的索引,用来指向到这8个alpha中的一个。所以其对应的存储状态为:


  • 32bits:两个RGB565格式的基准颜色;
  • 32bits:16个2bits的颜色索引;
  • 48bits:16个3bits的alpha索引;
  • 16bits:2个8bits的基准alpha;

同时,两个alpha值中的不同的标记情况也对应着不同的插值操作:

若alpha0 > alpha1
alphai = (7 - i) / 7 *alpha0 + i/7 * alpha1;(2<=i<=7);
若alpha0 < alpha1
alphai = (5 - i) / 5 *alpha0 + i/5 * alpha1;(2<=i<=5);

alpha6 = 0;

alpha7=255;

2. ETCETC压缩算法采用将图像中的chromatic和luminance分开存储的方式,而在解码时使用luminance对chromatic进行调制进而重现原始图像信息。

20160315222603205.jpg

ETC也主要有两种方法:ETC1和改进后的ETC2。

ETC1:

采用4x2的block进行分割(原始为4*2*24=192,压缩后为32,压缩率为6):

对于所有图片都使用一个全局的16个组table codeword,每组中有四个数值,且其中是有规律可循的,如下所示:

0123456789101112131415
-8-12-31-34-50-47-80-127-16-24-62-68-100-94-160-254
-2-4-6-12-8-19-28-42-4-8-12-24-16-38-56-84
24612819284248122416385684
81231345047801271624626810094160254

  • 12bits:RBG444的一个basecolor,其在使用是需要被扩展到8bits;每个block使用32bits进行编辑存储;比如对于RGB=(0,2,15) -> (0000 ,0010 , 1111),扩展后为(000000,00100010 , 11111111)->(0 , 34 , 255),扩展方法为直接将原始4位复制后拼接为8位即可;
  • 4bits:用来索引16个table codeword中的一组,比如{-10 , -1 , 4 , 7};
  • 16bits:对于block中的每个pixel分配2bits,就有4个值,用来索引当前像素对应于table codeword中的每个modifier,该modifier需要组成三个通道的调整值,比如,对于某个pixel其对应的modifier索引值为2,也即对应上述table codeword中的4,如此一来该pixel的RGB = (0,34,255) + (4,4,4)=(4,38,259),最后需要将其clamp至0,255,因而即为(4,38,255)。

改进后采用4x4的block进行分割(原始为4*4*24= 384, 压缩后为64, 压缩率为6):

主要针对某两个4x2的block间的颜色差异相对较小,因而可以使用一个更多的bit来表示一个更高精度的basecolor,而另外一个basecolor则在其基础上通过一个bit较小的diff来进行动态计算得来。

对于所有图片都使用一个全局的8个组table codeword,每组中有四个数值:

01234567
-8-17-29-42-60-80-106-183
-2-5-9-13-18-24-33-47
2591318243347
81729426080106183

  • 1bit:用来记录两个字block是采用常规的4*2编码还是基于差值的编码;
  • 1bit:用来记录4x4的block内两个子block的朝向(可以两个4*2,也可以两个2*4)
  • 32bits:对于16个pixel,每个分配2bits的索引,指向到对应的modifier;
  • 6bits:对于每个子block,有一个3bits的索引,指向8个table codeword中的某一个(由原始的16组codeword缩减为8个);
  • 24bits: 分别对应两个basecolor。对于常规编码时,则是两个RGB444,然后对每个扩展到RGB888;对于差值编码时,则是一个RGB555(精度较高)的basecolor和一个差值RGB333(较低精度),先计算出先求值,然后再扩展。

ETC2:


根据ETC1的实现方式,如果其块内的颜色分布不均匀的话,则其存储的两个basecolor会较远的分布于插值趋线的较远的两侧,进行解压后会得到较低的压缩质量,

20160315223448474.jpg


因而ETC2就是解决如何针对这些较为特殊的颜色分布来选择更加优化的压缩策略。

改进主要针对ETC1中的diff为1的情况下展开,即basecolor为RGB555和差值RGB333,此时另外一个颜色值= RGB555 + dRGB333,而其中的三个通道也是可以独立开来计算的,比如对于红色通道即为R = R5 + dR3,此时,若其中的R5为0且dR3为负值时得到的红色通道值就没有意义,此种情况下就可以对该block重新定义编码方式。

1. 对于红色通道的溢出情况:


  • 1bit: diff mode
  • 8bits: R5,dR3,

剩余64-1-8 =55bits可用来存储其它的信息,但是注意这些其中的R5与dR3之间的溢出方式有不同的16种,而也可以将其转换为对应的数据存储(可以存储4bits的信息),因而整个信息存储位数为59bits.

2. 对于绿色通道的溢出情况:


  • 1bit: diff mode
  • 8bits: R5,dR3
  • 8bits: G5, dG3

剩余64-1-8-8 =47bits可用来存储其它的信息,但是注意此时R通道是没有溢出的,共有256-16种状态,因而其可以存储7bits的信息,G通道是有溢出的,其与R通道的溢出相同,也有16种不同的状态,而也可以将其转换为对应的数据存储(可以存储4bits的信息),所以通过RG两通道的状态可以额外存储的信息bits数为7+4=11bits。所有在这种情况下的信息存储总数量为47+11=58bits。

3. 对于蓝色通道的溢出情况:


  • 1bit: diff mode
  • 8bits: R5,dR3
  • 8bits: G5, dG3
  • 8bits:B5, dB3

剩余64-1-8-8-8=39bits可用来存储其它的信息。同样对于RGB三个通道进行额外的信息存储之后的存储空间为7+7+4=18bits。所以此种情况下的信息存储空间即为:39+18=57bits。

上述操作就巧妙地利用了三个通道中的信息,来得到扩展的存储空间,然后使用这些存储空间来对图像信息进行编码与压缩即可。但注意:这些通过三个通道的溢出情况来确定对应模式,并将其中的溢出状态也利用为对应的存储空间,看起来比较绕,为什么不直接使用1位之外的其它63bits进行数据存储呢?这里主要是因为原始的ETC1采用了三个通道这样的存储方式,而ETC2又必须要兼容ETC1,所以只能使用如此的方法。

接下来即需要合理利用57,58,59这三种情况下的bits存储空间来进行原始数据的压缩。针对颜色分布不均匀的状态,将其细分为了三种不同的分布情况:

T字型分布,一部分颜色沿插值趋线分布,另外的颜色分布于距离较远的位置上,这里将颜色分为不同的两组,每组颜色统计出其对应的basecolor0,basecolor1(对应图中的蓝色点),每个basecolor为RGB444,而对于位于右下方的basecolor0存储一个3bits的索引值,用来索引到一个operator(共有8个),然后得到其周围的两上basecolor3, basecolor4,如此一来就有4个basecolor,而block中的每个pixel均索引到4个basecolor中的一个。因而共需要存储位数为:


  • 12bits: RGB444 basecolor0
  • 12bits: RGB444 basecolor1
  • 3bits: operator
  • 32bits: 对于16个pixel,每个2bits的索引值

转自“http://blog.csdn.net/bugrunner/article/details/50538770

评分

参与人数 2元素币 +20 活跃度 +20 展开 理由
Pla4Q释然 + 10
狼之独步 + 20 + 10 【给力】阅贴无数,楼主最强!

查看全部评分

2018-3-6 13:25:00  
 赞 赞 0

使用道具 登录

16个回答,把该问题分享到群,邀请大神一起回答。
2#
不错
回复 收起回复
2018-3-6 14:53:54   回复
 赞 赞 0

使用道具 登录

3#
不错~
回复 收起回复
2018-3-6 21:32:55   回复
 赞 赞 0

使用道具 登录

4#
666
回复 收起回复
2018-3-12 11:04:37   回复
 赞 赞 0

使用道具 登录

5#
666
回复 收起回复
2018-4-11 09:23:41   回复
 赞 赞 0

使用道具 登录

7#
资源甚好,发帖艰辛,且阅且珍惜!
回复 收起回复
2018-11-17 10:21:06   回复
 赞 赞 0

使用道具 登录

8#
从业不识微元素,做遍项目也枉然
回复 收起回复
2018-11-17 10:24:36   回复
 赞 赞 0

使用道具 登录

9#
谢谢大佬分享 辛苦辛苦
回复 收起回复
2018-11-17 10:48:19   回复
 赞 赞 0

使用道具 登录

10#
神贴降临,吓死本宝宝了!
回复 收起回复
2018-11-17 11:19:02   回复
 赞 赞 0

使用道具 登录

11#
千点万点,不如微元素指点
回复 收起回复
2018-11-17 11:23:35   回复
 赞 赞 0

使用道具 登录

12#

很好的资源,谢谢分享。
回复 收起回复
2018-11-19 09:24:50   回复
 赞 赞 0

使用道具 登录

13#
回复 收起回复
2018-11-19 10:48:32   回复
 赞 赞 0

使用道具 登录

14#
资源哪里好,肯定元素找!
回复 收起回复
2018-11-19 10:58:17   回复
 赞 赞 0

使用道具 登录

15#
不错
回复 收起回复
2019-2-18 17:34:54   回复
 赞 赞 0

使用道具 登录

16#
路过看看 感谢分享
回复 收起回复
2019-2-18 20:23:13   回复
 赞 赞 0

使用道具 登录

17#
路过看看 感谢分享
回复 收起回复
2019-2-18 20:23:14   回复
 赞 赞 0

使用道具 登录

18#
11
回复 收起回复
2019-2-19 10:33:02   回复
 赞 赞 0

使用道具 登录

CG 游戏行业专业问题

Unity3D技术手机游戏引擎手游引擎
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表