纹理压缩

导语 我们经常听说有相应的jpg,webpp,png等图像压缩格式,但你有没有听说过ETC,S3TC等格式吗?如果没听说就请看我这篇文章吧。

一、前言

游戏场景里,贴图是影响真实性的重要因素。通常贴图越大,也就越精细,但其占用的内存空间也就更大。

常用的图片文件格式有:BMP, TGA, JPG, GIF, PNG等。

不过,像JPG这种常见的图片压缩格式,对于多数应用的内存占用和显示总线带宽占用并没有带来直接的好处,因为还得对JPG进行解压缩成原始的像素,再传给显卡,而且还有加载时的解码计算负担。这是因为显卡的纹理解码硬件不理解JPG格式。所以,在没有显卡硬件支持的情况下,用压缩格式保存纹理没有什么意义,特别是对于移动设备来说,解码像JPG这种复杂格式是很浪费电的。

常用的纹理格式有:RGB_565, ARGB_4444, ARGB_1555, RGB_888, ARGB_8888等。

不论何种图片文件格式,它们都是为了存储像素信息而是用的对信息的特殊编码方式,它存储在磁盘中,或者内存中,但是并不能被GPU所识别,因为以向量计算见长的GPU对这些复杂的计算无能为力。当这些文件格式被游戏读入后,需要经过CPU解压成RGB_565,ARGB_4444, ARGB_1555, RGB_888, ARGB_8888等像素格式,才能传送到GPU里使用。纹理格式是能被GPU所识别的像素格式,能被快速的寻址并采样。

纹理格式如:RGB_565,每个像素占用:5+6+5=16 (bits),共 2 个字节。RGB_888,每个像素占 24 位,3 个字节。ARGB_8888占 32 位,4 个字节。

关于纹理格式的更多资料:http://en.wikipedia.org/wiki/High_color

二、贴图压缩方式

对于一张 512_512 的纹理,RGB_565格式的文件占用 512 KB的容量。

计算公式为:numBytes = width _ height _ bitsPerPixel / 8

ARGB_8888格式的文件需要占用1M的容量;如果是1024_1024,则需要更多。

現在一般的显卡上通常有 32MB 的显存容量。如果每个贴图都要 2MB 的話,即使不计 frame buffer 所占用的空間,也只能使用 16 张贴图。这显然是不可接受的。所以,现在的游戏通常无法使用很大的贴图。

然而,在储存一般的影像的時候,通常会使用某些压缩方式。现在常见的 JPEG 压缩,可以达到 1:6 甚至 1:12 的压缩比。如果把类似的压缩方式应用在贴图上,不就可以大量减少贴图所用的空间了吗?

不幸的是,一般的影像压缩方式,是沒有办法用在贴图上面的。因为,显示芯片在存取贴图时,是一种「随机存取」的动作。也就是说,显示芯片通常会需要以任意 的顺序存取贴图里的资料。一般的压缩方式如 JPEG,都利用了 variable length 的 coding,简单的说,它们必需以一定的顺序才能解开。因此,不能用这种方式来压缩贴图。

一种压缩方式,是改变颜色空间。例如,3dfx 的 YAB 格式,就是一种不同的颜色空间。利用 YAB,每个像素只需要 8 bits,就可以达到接近 16 bits 的效果。不过,无论如何,这样都使颜色的数目减少。因此,整个贴图的色彩变化就受到了限制。

另一种方式,就是用传统的「调色盘」结构。利用一个 256 种颜色的调色盘,就可以把贴图以 8 bits 的方式储存。不过,虽然它的色彩空间较大(可以是 24 bits 或 32 bits),但是总颜色数目还是不能超过 256 种。所以,它的应用范围仍然有限。

现在常用的贴图压缩方式,则是利用以区块为基础的方式。通常的做法是,把贴图切割成许多小区块,再对各个区块进行压缩。例如,S3TC 就是把贴图切成 4x4 的小区块。利用这种做法,就可以对区块进行某种处理(通常就是 vector quantization 或是其变形),显示芯片也可以以区块为单位,进行随机的存取动作。因此,这是适合用在贴图的方式。

不过,区块的大小会影响到压缩的效果。一般来说,区块越大,就能有越高的压缩比。不过,越大的区块也会使额外的负担增加。因为显示芯片只能以区块为单位来读取贴图,如果区块越大,则每个区块中就可能会有越多的资料是不需要的。所以,也不能任意把区块的大小加大

在Beers,Agrawala和Chaddha于1996年发表的一篇影响深远的论文基於已壓縮紋理的渲染 [1]中,他们列举四项纹理压缩的特点,使其不同于其他图片压缩技术。

解压速度:为了尽可能不影响性能,解压缩要尽可能快,最好能直接从已压缩的纹理直接渲染。(所谓解压,就是把贴图转换成GPU能识别的纹理格式:RGB_565等。)

随机访问:由于几乎不可能预测纹理像素被访问的顺序,任何纹理压缩算反必须允许对其中的纹理的随机访问。所以几乎所有的纹理压缩算法都已块为单位压缩和存储纹理像素,当某一个纹理像素被访问时,只有同一块中的若干纹理像素被读取和解压缩。这项需求也排除了很多压缩率较高的图片压缩格式,例如:JPEG和行程長度編碼。

压缩率和图像质量:由于人眼的不精确性,相比于其他应用领域,图像渲染更适宜使用有损压缩。

编码速度:纹理压缩对压缩速度的要求不高,因为绝大多数情况下,纹理只需要进行一次压缩。(但是对解压速度要求较高。)

由于其数据访问模式是事先知道的,纹理压缩常作为整个渲染管线的一部分,在绘制时动态的对已压缩数据进行解压缩(可以把解压缩放在shader里处理)。而反过来渲染管线也可以通过纹理压缩技术来降低对显卡位宽和存储的需求。在纹理贴图中,已经压缩的纹理和没有经过压缩的纹理使用起来基本没有区别,都可以被用来存储颜色数据或其他数据,例如凹凸贴图或法线贴图,也都可以和Mipmapping或各项异性过滤等共同使用。

主流的纹理压缩标准:ETC, PVRTC, S3TC。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏有趣的Python

2- OpenCV+TensorFlow 入门人工智能图像处理-opencv入门

本章内容 Anaconda一站式开发环境 OPenCV基础入门(像素,图片的封装格式,编码格式) TensorFlow基础入门 本章主要内容 OpenCV初识 ...

4555
来自专栏Code_iOS

OpenGL ES 2.0 Using Modern Mobile Graphics Hardware

四. 问题:CPU 和 GPU 的 Memory 是有数据交换的,这种交换不会出问题吗?CPU 和 GPU 的计算速度一样吗?

782
来自专栏数据小魔方

R语言可视化——REmap(路径图)

今天紧接昨天的内容,跟大家分享如何使用REmap函数制作路径图。 路径图所需要的数据结构非常简单,两列数据,左侧是起点,右侧是终点,并且每一行的终点是下一行的起...

3315
来自专栏草根博客站长有话说

说说 WordPress 文章的摘要

今天明月给大家讲解一下 WordPress 文章的“摘要”,可能很多站长从来就没有重视过文章的“摘要”,甚至很多站长们都说不清这个“摘要”有什么作用以及如何运用...

832
来自专栏编程

R 语言绘制热图的 10 种方法

说在前面 此前我们已经推送了不少深入解读的文章,今天希望做一点新的尝试——介绍 R 语言绘图。这一期分享 R 语言绘制热图的案例,希望大家通过案例感受 R 语言...

3.2K38
来自专栏数据小魔方

带涨跌箭头的柱形图

今天要跟大家分享的图表是带涨跌箭头的柱形图! 在簇状柱形图的两个数据条标签上,带上表示涨跌符号的箭头,可以清晰的展现出数据的实际涨跌趋势。 首首先还是来看一下我...

3044
来自专栏数值分析与有限元编程

可视化 | Tecplot绘制散点图

Tecplot是功能强大的数据可视化工具,可以将计算中得到的大量数据形成直观图形。Tecplot的功能包括绘制XY曲线、轮廓图、云线、等值线、向量图、离散点等。...

7025
来自专栏数据小魔方

excel数据转置——一维表与二维表之间的转化!

今天跟大家分享excel数据转置——一维表与二维表之间的转化! ▽ 我们在做数据搜集整理的时候 通常会遇到要将原始数据做转置处理 如下图案例所示 ? 这是一张典...

3785
来自专栏Crossin的编程教室

【每周一坑】生成九宫格图片

非常简单的功能,但在开发中很常见,很多网页/应用里缩略图都是对图片进行缩放+切割得到的。

1333
来自专栏数据小魔方

不等宽柱形图

今天要跟大家分享的图表是不等宽柱形图! ▽▼▽ 基础等柱形图一般只能展示一个维度的数据,但是如果想要在柱形图中同时展示两个维度的数据(柱高一个维度、柱宽另一个维...

3025

扫码关注云+社区