obsidian/笔记文件/2.笔记/各种移动GPU压缩纹理的使用方法.md
2025-03-26 00:02:56 +08:00

6.7 KiB
Raw Blame History

#unity/日常积累

介绍了各种移动设备所使用的GPU以及各个GPU所支持的压缩纹理的格式和使用方法。

1. 移动GPU大全
目前移动市场的GPU主要有四大厂商系列

1Imagination Technologies的PowerVR SGX系列

!Pasted image 20240402143017.png

代表型号PowerVR SGX 535、PowerVR SGX 540、PowerVR SGX 543MP、PowerVR SGX 554MP等
代表作  Apple iPhone全系、iPad全系三星I9000、P3100等

2Qualcomm(高通)的Adreno系列

!Pasted image 20240402143023.png

代表型号Adreno 200、Adreno 205、Adreno 220、Adreno 320等
代表作  HTC G10、G14小米1、2等

3ARM的Mali系列

!Pasted image 20240402143029.png

代表型号Mali-400、Mali-T604等
代表作  三星Galaxy SII、Galaxy SIII、Galaxy Note1、Galaxy Note2(亚版)等

4nVIDIA(英伟达)的Tegra系列

!Pasted image 20240402143036.png

代表型号nVIDIA Tegra2、nVIDIA Tegra3等
代表作  Google Nexus 7HTC One X等

2. 压缩纹理的必要性

首先要说一下图像文件格式和纹理格式的区别。 常用的图像文件格式有BMPTGAJPGGIFPNG等 常用的纹理格式有R5G6B5A4R4G4B4A1R5G5B5R8G8B8, A8R8G8B8等。

文件格式是图像为了存储信息而使用的对信息的特殊编码方式它存储在磁盘中或者内存中但是并不能被GPU所识别因为以向量计算见长的GPU对于这些复杂的计算无能为力。这些文件格式当被游戏读入后还是需要经过CPU解压成R5G6B5A4R4G4B4A1R5G5B5R8G8B8, A8R8G8B8等像素格式再传送到GPU端进行使用。

纹理格式是能被GPU所识别的像素格式能被快速寻址并采样。 举个例子DDS文件是游戏开发中常用的文件格式它内部可以包含A4R4G4B4的纹理格式也可以包含A8R8G8B8的纹理格式甚至可以包含DXT1的纹理格式。在这里DDS文件有点容器的意味。

OpenGL ES 2.0支持以上提到的R5G6B5A4R4G4B4A1R5G5B5R8G8B8A8R8G8B8等纹理格式其中 R5G6B5A4R4G4B4A1R5G5B5每个像素占用2个字节(BYTE)R8G8B8每个像素占用3个字节A8R8G8B8每个像素占用 4个字节。

!Pasted image 20240402143207.png

对于一张512512的纹理的话R5G6B5格式的文件需要占用512KB的容量A8R8G8B8格式的文件需要占用1MB的容量如果是10241024的纹理则各需要2M和4M的容量这对于动辄需要几十、几百张甚至更多纹理的游戏上G容量的游戏在移动平台上是不容易被接受的(当然还是有1、2G的大作的里面包含了几千张的纹理)。

聪明的设计师们在想,有没有其他办法,既能表现丰富的色彩和细节,又能是最小失真的情况下,达到更小的纹理容量呢。压缩纹理格式应运而生(当然,并不是在移动平台后才有的产物)。

  1. 常见的压缩纹理格式 基于OpenGL ES的压缩纹理有常见的如下几种实现 1ETC1Ericsson texture compression) 2PVRTC (PowerVR texture compression) 3ATITC (ATI texture compression) 4S3TC (S3 texture compression)

ETC1: ETC1格式是OpenGL ES图形标准的一部分并且被所有的Android设备所支持。 扩展名为: GL_OES_compressed_ETC1_RGB8_texture不支持透明通道所以仅能用于不透明纹理。 当加载压缩纹理时,参数支持如下格式: GL_ETC1_RGB8_OES(RGB每个像素0.5个字节)

PVRTC: 支持的GPU为Imagination Technologies的PowerVR SGX系列。 OpenGL ES的扩展名为: GL_IMG_texture_compression_pvrtc。 当加载压缩纹理时,参数支持如下几种格式: GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG (RGB每个像素0.5个字节) GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG (RGB每个像素0.25个字节) GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG (RGBA每个像素0.5个字节) GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG (RGBA每个像素0.25个字节)

ATITC: 支持的GPU为Qualcomm的Adreno系列。 支持的OpenGL ES扩展名为: GL_ATI_texture_compression_atitc。 当加载压缩纹理时,参数支持如下类型的纹理: GL_ATC_RGB_AMD (RGB每个像素0.5个字节) GL_ATC_RGBA_EXPLICIT_ALPHA_AMD (RGBA每个像素1个字节) GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD (RGBA每个像素1个字节)

S3TC 也被称为DXTC在PC上广泛被使用但是在移动设备上还是属于新鲜事物。支持的GPU为NVIDIA Tegra系列。 OpenGL ES扩展名为: GL_EXT_texture_compression_dxt1和GL_EXT_texture_compression_s3tc。 当加载压缩纹理时,的参数有如下几种格式: GL_COMPRESSED_RGB_S3TC_DXT1 (RGB每个像素0.5个字节) GL_COMPRESSED_RGBA_S3TC_DXT1 (RGBA每个像素0.5个字节) GL_COMPRESSED_RGBA_S3TC_DXT3 (RGBA每个像素1个字节) GL_COMPRESSED_RGBA_S3TC_DXT5 (RGBA每个像素1个字节)

由此可见Mali系列GPU只支持ETC1格式的压缩纹理而且该纹理不支持透明通道有一定局限性。
以上压缩纹理格式每个像素大小相对A8R8G8B8格式的比例最高压缩比是16:1最低压缩比是4:1对于减小纹理的数据容量有明显作用相应在显存带宽上也有明显优势从而提高游戏的运行效率(此特性没有绝对数值,根据每个游戏的用法和瓶颈点不同而有差别)。
  1. OpenGL中相关API的使用

1 获得GPU的型号

glGetString(GL_RENDERER)

2 获得GPU的生产厂商

glGetString(GL_VENDOR);

3 获取GPU支持哪些压缩纹理

string extensions = (const char*)glGetString(GL_EXTENSIONS);


a. 判断是否支持ETC1格式的压缩纹理

return (extensions.find("GL_OES_compressed_ETC1_RGB8_texture")!= string::npos);


b. 判断是否支持DXT格式的压缩纹理

return (extensions.find("GL_EXT_texture_compression_dxt1")!= string::npos ||

        extensions.find("GL_EXT_texture_compression_s3tc")!= string::npos);


c. 判断是否支持PVRTC格式的压缩纹理

return (extensions.find("GL_IMG_texture_compression_pvrtc")!= string::npos);


d. 判断是否支持ATITC格式的压缩纹理

return (extensions.find("GL_AMD_compressed_ATC_texture")!= string::npos ||

        extensions.find("GL_ATI_texture_compression_atitc")!= string::npos);

4 填充压缩纹理数据

void glCompressedTexImage2D (

     GLenum target,

     GLint level,

     GLenum internalformat,

     GLsizei width,

     GLsizei height,

     GLint border,

     GLsizei imageSize,

     const GLvoid * data);

这里的参数不做详细解释其中internalformat即是压缩纹理格式的类型。