S3TC(S3 Texture Compression)纹理压缩格式详解
使用S3TC格式存储的压缩纹理是以4X4的纹理单元块(texel blocks)为基本单位存储的,每纹理单元块(texel blocks)有64bit或者128bit的纹理单元数据(texel data)。这样就要求每张贴图长度和宽度应该是4的倍数。图像如同一般的做法按照行列顺序存放这些4X4的纹理单元块(texel blocks),每个texel blocks被看成是一个图像的“像素”。对于那些长度不为4的倍数的贴图,多出来的那些纹理单元在压缩的时候要么舍弃不被放到图像中或者不足4的会被补上空位按4处理。
对于一个长度为w,宽为h,并且块大小为blocksize的图像,它的大小为(用字节计算)
ceil(w/4) * ceil(h/4) * blocksize
在解码一个S3TC图像的时候,可以通过下面的式子得到一个纹理单元(x,y)所位于的块的地址(用字节计算)
blocksize * (ceil(w/4) * floor(y/3) + floor(x/4))
通过纹理单元(x,y)获得它所处于的块的下标:
(x % 4 , y % 4)
有4种不同的S3TC图像格式:
1.COMPRESSED_RGB_S3TC_DXT1_EXT
每个4X4的纹理单元块包含8个字节的RGB数据,也就是说每个图像块被编码为顺序的8个字节(64bit),按照地址的顺序,它们分别是:
c0_lo,c0_hi,
c1_lo,c1_hi,
bits_0,bits_1,bits_2,bits_3
块的8个字节被用来表达3个量:
color0 = c0_lo + c0_hi * 256
color1 = c1_lo + c1_hi * 256
bits = bits_0 + 256 * (bits_1 + 256 * (bits_2 + 256 * bits_3))
color0和color1是16位的无符号整数,用来表达颜色,格式是RGB - UNSIGNED_SHORT_5_6_5。分别用RGB0和RGB1来表示
bits是一个32位的无符号整数,从bits可以求出位于(x,y)的纹理单元的2位控制码:(x,y介于0-3之间)
code(x,y) = bits[2 * (4 * y + x) + 1..2 * (4 * y + x) + 0] 即,2 * (4 * y + x) + 1位和2 * (4 * y + x)位
bits的第31位是高位,第0位是低位
这样可以求出位于(x,y)的纹理单元的RGB值:
RGB0, if color0 > color1 and code(x,y) == 0
RGB1, if color0 > color1 and code(x,y) == 1
(2*RGB0+RGB1)/3, if color0 > color1 and code(x,y) == 2
(RGB0+2*RGB1)/3, if color0 > color1 and code(x,y) == 3
RGB0, if color0 <= color1 and code(x,y) == 0
RGB1, if color0 <= color1 and code(x,y) == 1
(RGB0+RGB1)/2, if color0 <= color1 and code(x,y) == 2
BLACK, if color0 <= color1 and code(x,y) == 3
这些算术运算都是矢量运算,分别对各个分量R,G,B进行计算。BLACK=RGB(0,0,0)
这种格式的S3TC图像不含有Alpha,所以整个图像都是不透明的
2.COMPRESSED_RGBA_S3TC_DXT1_EXT
每个4*4块包含8字节的RGB颜色和最小限度的Alpha透明度数据,颜色数据的提取方式和COMPRESSED_RGB_S3TC_DXT1_EXT是完全一样的,区别在于Alpha数据:
对于(x,y)处纹理单元的Alpha值,计算方式如下:
0.0, if color0 <= color1 and code(x,y) == 3
1.0, otherwise
注意:
首先,把一个RGBA图像压缩成为只含有1位Alpha的压缩格式,所有Alpha<0.5的像素的Alpha值被置为0.0,而Alpha>=0.5的像素的Alpha值被置为1.0. 而把一个RGBA图像压缩成为COMPRESSED_RGBA_S3TC_DXT1_EXT格式的时候。
其次,如果某个纹理单元最终的Alpha为0.0,那么此纹理单元的R,G,B颜色值都将被置为0.
最后,对于是用此格式的应用,必须遵守这个规则。另外,当一个通用的内部格式被指定后,也许可以使用COMPRESSED_RGB_S3TC_DXT1_EXT格式,但不允许使用COMPRESSED_RGBA_S3TC_DXT1_EXT(应该跟OpenGL有关系)
3.COMPRESSED_RGBA_S3TC_DXT3_EXT
每个4*4块中包含64bit的未压缩Alpha数据和64bit的RGB颜色数据,其中颜色数据按照和COMPRESSED_RGB_S3TC_DXT1_EXT一样的方式编码,唯一的区别在于2位控制码被以不明显的方式编码,换句话说,就像知道Color0 > Color1,而不需要知道Color0和Color1的具体值。
每个块的纹理单元的Alpha值被顺次编码为8个字节:
a0, a1, a2, a3, a4, a5, a6, a7
通过这8个字节可以得到一个64位的无符号整数:
alpha = a0 + 256 * (a1 + 256 * (a2 + 256 * (a3 + 256 * (a4 + 256 * (a5 + 256 * (a6 + 256 * a7))))))
高位是63位,低位是0位
通过这个alpha就可以获得位于(x,y)处纹理单元的Alpha值
alpha(x,y) = bits[4*(4*y+x)+3..4*(4*y+x)+0]
4位数字所能表示的最大值是15,所以折算到[0.0,1.0],Alpha = alpha(x,y) / 15
4.COMPRESSED_RGBA_S3TC_DXT5_EXT
每个4*4块中包含64bit的压缩过的Alpha数据和64bit的RGB颜色数据,颜色数据部分压缩方式和COMPRESSED_RGBA_S3TC_DXT3_EXT完全一致。
Alpha数据是8个字节的压缩数据,这8个字节:
alpha0, alpha1, bits_0, bits_1, bits_2, bits_3, bits_4, bits_5
其中alpha0和alpha1为unsigned char类型数据,转化为实际的Alpha值需要乘上 1 / 255.0
其他的6个数字bits_N,则可以被解码成为一个48位的无符号整数
bits = bits_0 + 256 * (bits_1 + 256 * (bits_2 + 256 * (bits_3 + 256 * (bits_4 + 256 * bits_5))))
通过bits(高位47低位0),可以求得位于(x,y)纹理单元的3位控制码:
code(x,y) = bits[3*(4*y+x)+1..3*(4*y+x)+0]
根据bits、code(x,y)、alpha0以及alpha1就可以求得(x,y)处纹理单元的Alpha值:
alpha0, code(x,y) == 0
alpha1, code(x,y) == 1
(6*alpha0 + 1*alpha1)/7, alpha0 > alpha1 and code(x,y) == 2
(5*alpha0 + 2*alpha1)/7, alpha0 > alpha1 and code(x,y) == 3
(4*alpha0 + 3*alpha1)/7, alpha0 > alpha1 and code(x,y) == 4
(3*alpha0 + 4*alpha1)/7, alpha0 > alpha1 and code(x,y) == 5
(2*alpha0 + 5*alpha1)/7, alpha0 > alpha1 and code(x,y) == 6
(1*alpha0 + 6*alpha1)/7, alpha0 > alpha1 and code(x,y) == 7
(4*alpha0 + 1*alpha1)/5, alpha0 <= alpha1 and code(x,y) == 2
(3*alpha0 + 2*alpha1)/5, alpha0 <= alpha1 and code(x,y) == 3
(2*alpha0 + 3*alpha1)/5, alpha0 <= alpha1 and code(x,y) == 4
(1*alpha0 + 4*alpha1)/5, alpha0 <= alpha1 and code(x,y) == 5
0.0, alpha0 <= alpha1 and code(x,y) == 6
1.0, alpha0 <= alpha1 and code(x,y) == 7
技术规范链接
- 相关文章
Monaco Editor 编辑器拷贝粘贴功能调用和获取选中文本
有时候需要在monaco editor外部调用编辑器的内置功能比如希望在页面主工具栏实现一些快捷操作。button
CentOS6 Apache2.2用域名配置多虚拟机
在CentOS下使用域名配置多虚拟机的步骤如下:
1. 使用WebGL Roadmap
Unity 5.0 shipped with a working preview of our WebGL technology in March this year. Since then, Google has disabled (by default) NPAPI support in the...
ES6小知识:动态对象键(Dynamic Object Keys)语法简介
在ES5,对象的键(key)总是被解释为字符串。ES6允许我们使用计算的值作为对象的键,使用方括号:[myKey]const
如何使用CSS3合成模式(blend-mode)和滤镜(filter)实现彩色蜡笔(时光机)照片特效
在之前的文章中我们已经详细讲解过CSS3滤镜(filter,也可称之为过滤器)的工作方式,本文将实现一个当下流行的时光机相片特效实例来说明其实际用途。
我们...使用SVG和CSS3创建圆形进度条动画
圆形进度条是一个经典的控制面板元素,常用于显示任务进度,比如用户档案的完整程度,或者升级状态。有很多方法来实现圆形进度条,比如用JS, CSS3, Canvas, SVG...
WebVR简介和常用资源链接
什么是WebVR这是一个实验性的JavaScript API,提供了在用户网页浏览器中访问虚拟现实设备的统一接口。当前主流VR设备如Oculus Rift DK2、谷歌的CardBoard、三星...
如何使用WebGL创建一个逼真的下雨动画
之前写过文章来分别讲解如何使用CSS3和Canvas2D实现过雨滴和下雨动画。通过背景处理看起来也有视觉上的3D效果,但并非真正的3D场景,如果要加入用户交互,进行36...
WebGL入门教程2 - GPU基本概念和工作流水线(渲染管道)
如何基于Canvas来模拟真实雨景Part2:重力掉落和雨滴融合
如何基于Canvas来模拟真实雨景Part1:预备知识和创建基本对象
D3.js读取外部json数据
D3.js是一个很好的数据可视化工具,支持从web服务读取json数据,或者从外部文件如.json, .csv文件中直接读取。由于部分服务比如flickrs上的图文数据服务需要VPN...
如何使用CSS3/SCSS实现逼真的车窗雨滴效果
在天气预报类的Web移动应用中,常常需要实现屏幕的雨滴效果,表示阴雨天气。感觉上比较神奇,其实想通了,这个效果的实现只需要一点物理知识和CSS3的简单变换。实现一个小雨滴首先雨滴是一个个小的椭圆形元素:.raindrop
在PHP网页程序中执行Sass/Compass命令
我们需要在wow云开发平台支持sass/compass等预编译样式语言,为此我们首先尝试了scssphp扩展,但是在支持最新语法上,经常会出现异常。所以我们采用了代理的方式...
更多...