1 为什么要进行纹理压缩
要渲染看起来真实的场景,最好是使用高分辨率而且颜色丰富的纹理,因为物节的表现最重要的还是靠贴图来实现的,但这样的纹理可能会耗费大量的内存,例如,一张每像素16位颜色的256 x 256纹理将使用128KB的内存。如果在该纹理中使用LOD,还需要额外的内存。一个使用50张这种纹理的场景将需要8MB的内存,如果需要更强的真实性,可以使用每像素32位颜色的512 x 512纹理,但那就需要8倍的内存。
为了减少纹理消耗的系统带宽和内存空间,Direct3D支持纹理压缩和实时解压,即DXT纹理压缩。压缩后的纹理被存储在Direct3D纹理指针中,当Direct3D渲染物体时,Direct3D引擎自动对纹理进行解压。应用DXT压缩纹理不仅可以节省内存空间,而且能有效地降低纹理传输带宽,提高图形系统的整体性能。
随着DirectX对纹理压缩格式的推广,目前大部分显卡都支持DXT压缩纹理,而且DXT压缩纹理在图形质量和运行速度之间取得了很好的平衡。
2 DXT纹理压缩是什么
DXT是一种DirectDraw表面,它以压缩形式存储图形数据,该表面可以节省大量的系统带宽和内存。即使不直接使用DXT表面渲染,也可以通过DXT格式创建纹理的方法节省磁盘空间。Direct3D提供了D3DFMT_DXT1 ~ D3DFMT_DXT5共5种压缩纹理格式。其中,D3DFMT_DXT1支持15位RGB和1位alpha图形格式,D3DFMT_DXT2、D3DFMT_DXT3支持12位RGB和4位alpha,D3DFMT_DXT4、D3DFMT_DXT5则采取了线性插值方式生成alpha。
3 DXT1 ~ DXT5的具体算法
DXT1格式对于完全RGB565格式的贴图的压缩比是4 : 1(4x4块16位RGB纹理元素可压缩为64位,2个16位RGB565值和16个2位索引),这样的压缩比并不很高,但足以有效地将3D加速卡用于存储纹理的容量提高4倍
如上图,DXT1中的两个RGB颜色负责表示所在压缩的4×4像素块中颜色的两个极端值,然后通过线性插值我们可以再计算出两个中间颜色值,而16个2位索引则表明了这4×4个像素块所在像素的颜色值,以及是否全透明的信息。
2位可以表示4种状态,刚好可以完整表示color_0,color_1以及我们通过插值计算出的中间颜色值color_2和color_3,而对于具有一位Alpha的贴图,则只计算一个中间颜色值,color_3用来表示完全透明。
对于如何判断DXT1格式所标识的一个块儿,是表示不透明还是具有1位alpha的贴图,则是通过两个颜色值color_0和color_1来实现的,如果color_0的数值大于color_1则表示贴图是完全不透明的,反之则表示具有一位透明信息。
总结一下就是,DXT1对于16位的RGB图具有4倍压缩,并且不能表示半透。
DXT2和DXT3可以表示具有半透明信息的贴图,这两种格式采用的是显式的Alpha表示。
在DXT1中,我们使用64位数据来描述4*4的像素块的颜色信息,在DXT2和DXT3中,这部分颜色信息是不变的,而是通过另附加64位数据也就是每个像素4位来表示他们的Alpha透明信息,而这4位的Alpha的信息通常情况下我们可以采用直接编码的方式来表示即可。
这样每个4×4像素块占用128位也就是8个字,0~3字表示透明信息;4~7表示前面描述的颜色的信息。
DXT2和DXT3的不同之处在于,DXT2中颜色是已经完成了Premultiplied by alpha操作(已完成颜色与alpha的混合,当透明度发生改变时,直接改变整体颜色值,不必再单独复合),DXT3的Alpha信息则是相对独立的,之所以要区分开了则是为了适应不同的需要,因为有些场合需要独立的Alpha信息。
总结:DXT3 就是在 DXT1 的基础上,增加了 4bit 的 alpha 通道,每个 4x4 块多用了 64bit 来保存这些 alpha 通道信息。
DXT4、DXT5也是用于表示具有半透明信息的贴图,与2和3不同的是4和5的Alpha信息是通过线性插值计算所得,类似于DXT1的颜色信息。同样的,每4×4的像素块的透明信息占用64位,所不同的是,64位中采用了2个8位的alpha值和16个3位的索引值,既然每个像素的索引占3位,那么可以表示8种不同的透明状态。
在这里插值的方法有两种,一种用于表示具有完全透明和完全不透明的状态,另一种则是仅在给出的极端值alpha_0和alpha_1中进行插值。区分的方法也是通过比较alpha_0和alpha_1的大小来实现的,如果alpha_0大于alpha_1,则通过插值计算剩下的6个中间alpha值;否则,只通过插值计算4个中间alpha值,alpha_6直接赋值0,alpha_7直接赋值255。
DXT4和DXT5的区别同DXT2和DXT3的区别相同,DXT4的颜色值是理解为已经完成Premultiplied by alpha操作的。
另外需要注意的是,所有的压缩纹理格式都是2的幂,因为纹理压缩的单位是4×4像素,所以如果贴图的大小位16×2或者8×1这样的比例,系统会同样采用4×4的单位进行压缩,会造成一定的空间浪费,同样的大小会被占用,只是不会参与使用而已。
总结: DXT2 和 DXT4 实际用的不多,从数据压缩算法上来讲,它们完全等同于 DXT3 和 DXT5 。区别只在于颜色数据是否经过 alpha 预乘。