突破内存的桎梏:移动端纹理压缩应用与分析

作者:Lingtonke(柯灵杰)

导语

最近一段时间AR技术成为了时下热门,越来越多的应用开发者投身到这些技术中来。应用中出现了3D的AR场景,图形学也成为了必备的技术基础。在开发过程中,往往为了追求更好的效果而使用了更加高清的素材,使得本就内存吃紧的手机面对更加严峻的挑战,尤其是对iOS开发者而言。 为了解决这个问题,我们使用了纹理压缩技术。使用这个技术可以大幅度的降低APP的内存(共享显存)占用,从而在有限的内存限制下,使用更丰富的素材。

1 前言

最近一段时间AR技术成为了时下热门,越来越多的应用开发者投身到这些技术中来。应用中出现了3D的AR场景,图形学也成为了必备的技术基础。在开发过程中,往往为了追求更好的效果而使用了更加高清的素材,使得本就内存吃紧的手机面对更加严峻的挑战,尤其是对iOS开发者而言。

为了解决这个问题,我们使用了纹理压缩技术。使用这个技术可以大幅度的降低APP的内存(共享显存)占用,从而在有限的内存限制下,使用更丰富的素材。

2 什么是纹理压缩

常见的图片文件格式,比如PNG,JPG,BMP等,是图像为了存储信息而使用的对信息的特殊编码方式。它存储在磁盘中,或者内存中,但是并不能被GPU所识别。

这些文件格式当被读入后,还是需要经过CPU解压成bitmap,再传送到GPU端进行使用。

纹理格式是能被GPU所识别的像素格式,能被快速寻址并采样。压缩纹理,是一种GPU能直接读取并显示的格式,使得图像无需解压即可进行渲染,节约大量的内存。

3 常见的压缩纹理格式

3.1 DXT

DXT纹理压缩格式来源于S3(Silicon & Software Systems)公司提出的S3TC(S3 Texture Compression),基本思想是把4x4的像素块压缩成一个64或128位的数据块,是有损压缩方式。DXT1-DXT5是S3TC算法的五种变化,用于各种Windows设备。

压缩率:DXT1,DXT4,DXT5为4:1,DXT2、DXT3为2:1

主要支持Windows平台及Tegra系列的GPU的Android手机

支持GPU:

3.2 ETC

Ericsson Texture Compression,是由 Khronos 支持的开放标准,在移动平台中广泛采用。它是一种为感知质量设计的有损算法,其依据是人眼对亮度改变的反应要高于色度改变。类似于DXT,ETC也是把4x4的像素块压缩成一个64或128位的数据块,也是有损压缩。

Alpha

压缩率

适用

ETC1

N

6:1

OpenGLES 2.0

ETC2

Y

6:1

OpenGLES3.0

这个系列,可以说是适用机型最广的格式。

ETC1支持几乎所有市面上的Android机,所有iPhone

ETC2支持大部分高端Android机,iPhone 5S及以上

3.3 PVRTC

PowerVR Texture Compression,PVRTC格式与基于块的压缩格式,比如S3TC、ETC的不同之处是,它使用2张双线性放大的低分辨率图,根据精度和每个像素的权重,融合到一起来呈现纹理,并且2-bpp和4-bpp都支持ARGB数据。PVRTC格式压缩比较高,也是有损压缩。

Alpha

压缩率

适用

PVRTC 2BPP

Y

16:1

OpenGLES 2.0

PVRTC 4BPP

Y

8:1

OpenGLES2.0

这个系列,是iPhone支持最广的格式

只支持长宽相等且为2的幂次方的纹理

支持部分Android机(GPU:PowerVR系列),iPhone全系列机型

支持的GPU

3.4 ASTC

ASTC(Adaptive Scalable Texture Compression,自适应扩展纹理压缩),这是ARM提出的,去年被Khronos组织认可,纳入到标准中来,不过并不是强制性的

有多种压缩方式可选,具有不同的压缩率

Block footprint

Bit rate

压缩率

4x4

8.00

25%

5x4

6.40

25%

5x5

5.12

20%

6x5

4.27

20%

6x6

3.56

14%

8x5

3.20

20%

8x6

2.67

5%

10x5

2.56

20%

10x6

2.13

7%

8x8

2.00

25%

10x8

1.60

25%

10x10

1.28

20%

12x10

1.07

20%

12x12

0.89

这个系列,可以说是综合性能和使用便捷性最好的系列。

支持部分高端Android机型,iPhone6及以上机型

4 主要优缺点

在几乎不损害图片质量和显示性能的情况下,大幅度降低内存(显存)开销,纹理压缩就是这样的一个技术。

不过,任何的技术都有其适用范围和优缺点,需要仔细评估再决定。

4.1 主要优点

占用内存(显存)大幅度降低

无额外性能开销

使用方便,只需少量代码

4.2 主要缺点

硬件相关,要考虑兼容性

压缩纹理文件大小比常规PNG和JPG文件大

需要额外的制作工具,无法直接在移动端生成

5 如何使用压缩纹理

5.1 保存格式

压缩纹理是图片数据的一种编码方式,我们还缺少一个容器去承载。就像MP4文件是H264的视频的容器一样。

我们选择了使用KTX的格式。

KTX是一个为OpenGL和OpenGLES程序设计的纹理存储格式。它可以简单的辨别里面所存储的纹理格式和其他相关信息。

5.2 文件结构

Byte[12] identifier
UInt32 endianness
UInt32 glType
UInt32 glTypeSize
UInt32 glFormat
Uint32 glInternalFormat
Uint32 glBaseInternalFormat
UInt32 pixelWidth
UInt32 pixelHeight
UInt32 pixelDepth
UInt32 numberOfArrayElements
UInt32 numberOfFaces
UInt32 numberOfMipmapLevels
UInt32 bytesOfKeyValueData

for each keyValuePair that fits in bytesOfKeyValueData
    UInt32   keyAndValueByteSize
    Byte     keyAndValue[keyAndValueByteSize]
    Byte     valuePadding[3 - ((keyAndValueByteSize + 3) % 4)]
end

for each mipmap_level in numberOfMipmapLevels*
    UInt32 imageSize; 
    for each array_element in numberOfArrayElements*
       for each face in numberOfFaces
           for each z_slice in pixelDepth*
               for each row or row_of_blocks in pixelHeight*
                   for each pixel or block_of_pixels in pixelWidth
                       Byte data[format-specific-number-of-bytes]**
                   end
end
           end
           Byte cubePadding[0-3]
       end
    end
    Byte mipPadding[3 - ((imageSize + 3) % 4)]
end

5.3 使用KTX格式

typedef struct __attribute__((packed))
{
    uint8_t identifier[12];
    uint32_t endianness;
    uint32_t glType;
    uint32_t glTypeSize;
    uint32_t glFormat;
    uint32_t glInternalFormat;
    uint32_t glBaseInternalFormat;
    uint32_t width;
    uint32_t height;
    uint32_t depth;
    uint32_t arrayElementCount;
    uint32_t faceCount;
    uint32_t mipmapCount;
    uint32_t keyValueDataLength;
} KTXHeader;




KTXHeader *header = (KTXHeader *)[data bytes];

BOOL endianSwap = (header->endianness == 0x01020304);

self.width = endianSwap ? CFSwapInt32(header->width) : header->width;
self.height = endianSwap ? CFSwapInt32(header->height) : header->height;
self.internalFormat = endianSwap ? CFSwapInt32(header->glInternalFormat) : header->glInternalFormat;

uint32_t mipCount = endianSwap ? CFSwapInt32(header->mipmapCount) : header->mipmapCount;
uint32_t keyValueDataLength = endianSwap ? CFSwapInt32(header->keyValueDataLength) : header->keyValueDataLength;

const uint8_t *bytes = [data bytes] + sizeof(KTXHeader) + keyValueDataLength;
constsize_tdataLength = [data length] - (sizeof(KTXHeader) + keyValueDataLength);

NSMutableArray *levelDatas = [NSMutableArrayarrayWithCapacity:MAX(mipCount, 1)];

const uint32_t blockSize = 16;
uint32_t dataOffset = 0;
uint32_t levelWidth = self.width, levelHeight = self.height;
while (dataOffset<dataLength)
{
    uint32_t levelSize = *(uint32_t *)(bytes + dataOffset);
    dataOffset += sizeof(uint32_t);

    NSData *mipData = [NSDatadataWithBytes:bytes + dataOffsetlength:levelSize];
    [levelDatasaddObject:mipData];

    dataOffset += levelSize;

    levelWidth = MAX(levelWidth / 2, 1);
    levelHeight = MAX(levelHeight / 2, 1);
}

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏java一日一条

如何用Python写一个贪吃蛇AI

这两天在网上看到一张让人涨姿势的图片,图片中展示的是贪吃蛇游戏, 估计大部分人都玩过。但如果仅仅是贪吃蛇游戏,那么它就没有什么让人涨姿势的地方了。 问题的关键在...

612
来自专栏PPV课数据科学社区

【完整案例】如何用R实现空间数据可视化

image.png 流行病学的数据讲究“三间分布”,即人群分布、时间分布和空间分布。其中的“空间分布”最好是在地图上展示,才比较清楚。R软件集统计分析与高级...

5307
来自专栏木子昭的博客

泰坦尼克乘客存活状况(决策树案例)

1912年4月15日凌晨2点20分,“永不沉没”的“泰坦尼克”走完了它短暂的航程,缓缓沉入大西洋这座安静冰冷的坟墓。 ? 欢迎你们说我幼稚荒诞,也欢迎你...

34512
来自专栏Data Analysis & Viz

手把手教你完成一个数据科学小项目(3):数据异常与清洗

本系列将全面涉及本项目从爬虫、数据提取与准备、数据异常发现与清洗、分析与可视化等细节,并将代码统一开源在GitHub:DesertsX/gulius-proje...

1033
来自专栏华章科技

用 Python 20 秒画完小猪佩奇“社会人”!附效果视频+完整代码

导读:今年社交平台上最火的带货女王是谁?范冰冰?杨幂?Angelababy?不,是猪猪女孩小猪佩奇。

835
来自专栏量化投资与机器学习

根据期权价格估算风险中性密度

1352
来自专栏生信技能树

y叔的ChIP-seq数据分析大礼包

CS0: ChIPseq从入门到放弃 接下来要出一个ChIPseq系列,讲一讲ChIPseq和我的ChIPseeker包,从入门到放弃是我自己的个人写照。我做C...

43110
来自专栏大数据杂谈

Python爬虫:爬取拉勾网职位并分析

本文从拉勾网爬取深圳市数据分析的职位信息,并以CSV格式保存至电脑,之后进行数据清洗,生成词云,进行描述统计和回归分析,最终得出结论。

1222
来自专栏大数据挖掘DT机器学习

R语言绘制中国地图,并展示流行病学数据

本文作者:姜晓东,博士毕业于上海交通大学,目前任教于湖南师范大学医学院,专业神经毒理学。 流行病学的数据讲究“三间分布”,即人群分布、时间分布和空间分布。其中...

8656
来自专栏日常学python

爬取《悲伤逆流成河》猫眼信息 | 郭敬明五年电影最动人之作

知道《悲伤逆流成河》上映还是在qq空间看见学弟发了说说,突然想起初中追小四的书,每天看到晚上10点多,昨天看了枪版的《悲伤逆流成河》,整个故事情节几乎和小说一模...

902

扫码关注云+社区