S3TC(S3 Texture Compression)纹理压缩格式详解

techbrood 发表于 2016-06-15 14:16:52

标签: webgl, texture, compression, format

- +

使用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

技术规范链接

https://www.opengl.org/wiki/S3_Texture_Compression

possitive(0) views14392 comments1

发送私信

最新评论

iefreer 2016-06-15 14:20:53

本文整理自网络。


请先 登录 再评论.
相关文章
  • CentOS6 Apache2.2多站点HTTPS配置

    可以使用letsencrypt(certbot)免费证书服务。支持多系统、多站点和多目录,支持wildcard(通配符域名),90天生效,可用定时任务自动更新。需要注意一点的是apache2.4以下版本需要在默认的ssl配置中添加如下的指令:NameVirtualHost

  • HTML5 And Canvas 2D Specs Are Now Feature Complete, First HTML 5.1 Working Draft Published

    We’ve been writing about HTML5 for quite a while, but, until today, the actual HTML5 specs and standards were still moving targets. Now, however, the...

  • WebGL、Asm.js和WebAssembly概念简介

    随着HTML技术的发展,网页要解决的问题已经远不止是简单的文本信息,而包括了更多的高性能图像处理和3D渲染方面。这正是要引入WebGL、Asm.js和WebAssembly这些技...

  • CSS3属性选择器特性使用详解

    CSS3除了引入动画、滤镜(用于特效)以及新的布局技术外,在选择器(selector)方面也有增强。属性选择器根据元素的属性(attributes)来匹配。这可以是一个单独...

  • React JSX语法简介

    JSX是一种类似XML的标签语法,用来简化代码,我们可以不使用JSX,但了解并使用也没什么坏处:)在React中,JSX是一个使用 React.createElement() API的快捷方式...

  • JavaScript语言多编程范式简介

    和C++等语言类似,JS支持多范式(paradigms)编程。我们常常混合这些范式来完成一些大型Web项目。JS支持3种编程范式:命令式、面向对象和函数式。命令式(Imperative JavaScript)命令式就是简单的从上而下完成任务,流水账过程式编码风格:function

  • 常见面试题JavaScript闭包(ES5语法)

    JavaScript闭包(Closure)是常见的JS面试题,是否理解闭包是一个简单的区分JS初级和高级程序员的判例。几乎每个JS程序员都在使用闭包,有意或无意间。比如编写一个jQuery鼠标点击处理函数:$(function()

  • NodeJS、Java和PHP性能考量和若干参考结论

    首先需要说明的是,严格而言NodeJS和Java、PHP并非对等概念,NodeJS是基于JS的一个应用程序,而Java/PHP是语言。我们这里实际指的是分别使用node、java和php来实...

  • CSS3弹性布局内容对齐(justify-content)属性使用详解

    内容对齐(justify-content)属性应用在弹性容器上,把弹性项沿着弹性容器的主轴线(main axis)对齐。该操作发生在弹性长度以及自动边距被确定后。 它用来在存...

  • 深入理解Three.js(WebGL)贴图(纹理映射)和UV映射

    本文将详细描述如何使用Three.js给3D对象添加贴图(Texture Map,也译作纹理映射,“贴图”的翻译要更直观,而“纹理映射”更准确。)。为了能够查看在线演示效...

  • 纹理基础知识和过滤模式详解

    1、 为什么在纹理采样时需要texture filter(纹理过滤)。
    我们的纹理是要贴到三维图形表面的,而三维图形上的pixel中心和纹理上的texel中心并不一至(pixe...

  • Canvas实例教程:图像移动、大小调整和裁剪

    本文介绍如何使用JavaScript和HTML5 Canvas元素来移动、调整大小和...

  • 如何使用纯CSS3实现一个3D泡沫

    要实现一个逼真的泡沫,涉及到比较复杂的光学/物理学知识。我们这里先简化下问题,实现一个相对简单而足够实用的泡沫元素。我们可以把基础的泡沫元素应用在很多场景中,比如水景、泡咖啡、啤酒甚至火焰特效中。泡沫首先是一个圆形元素.bubble

  • 更多...