glCompressedTexImage2D 压缩纹理

来源:互联网 发布:淘宝图片水印设置 编辑:程序博客网 时间:2024/05/28 11:51

Name

glCompressedTexImage2D — 指明一个二维的压缩纹理图像

C Specification

void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid * data);
 

Parameters

target

指定活动纹理单元的目标纹理,必须为GL_TEXTURE_2DGL_TEXTURE_CUBE_MAP_POSITIVE_X,

GL_TEXTURE_CUBE_MAP_NEGATIVE_XGL_TEXTURE_CUBE_MAP_POSITIVE_Y

GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,GL_TEXTURE_CUBE_MAP_POSITIVE_Z,

 或者GL_TEXTURE_CUBE_MAP_NEGATIVE_Z.

level

指定细节级别数,0级表示基本图像级别,n级表示第n级mipmap缩小图。

internalformat

指定data压缩图像数据的存储格式

width

指明纹理图像的宽度,所有OpenGL实现支持的2D纹理图像都至少为64纹素(texel)宽,立方体映射纹理图像都至少为16纹素宽。

height

指明纹理图像的高度,所有OpenGL实现支持的2D纹理图像都至少为64纹素(texel)高,立方体映射纹理图像都至少为16纹素高。

border

指定边框宽度,必须为零(梦维:没错,你必须传入0,因为这是OpenGL ES)。

imageSize

指定data压缩纹理图像的大小,单位为byte

data

指定一个指向压缩图像数据内存的指针。

Description

纹理映射一个指定的纹理图像的一部分到每个开启了纹理映射的图元上。在当前段着色器或顶点着色器使用内建纹理搜索函数时,贴图被启用。

glCompressedTexImage2D定义了二维纹理图像或者立方体映射纹理图像,图像数据是压缩的并存储在客户端内存中。纹理图形根据internalformat指定的格式来解码。OpenGL ES并没有指定压缩纹理格式,但是它提供一个机制:获取这些由扩展名指定的格式所对应的OpenGL符号常量。所支持压缩纹理格式数量可以查询GL_NUM_COMPRESSED_TEXTURE_FORMATS值来获取。所支持的压缩格式列表可以查询GL_COMPRESSED_TEXTURE_FORMATS值来获取。

 

Notes

GL实现可能会选择任何内部分辨率来存储纹理数组

glCompressedTexImage2D为由glActiveTexture指定的当前纹理单元指定一个二维或立方体映射纹理

Errors

如果target不是

GL_TEXTURE_2DGL_TEXTURE_CUBE_MAP_POSITIVE_X

GL_TEXTURE_CUBE_MAP_NEGATIVE_X,GL_TEXTURE_CUBE_MAP_POSITIVE_Y,

 GL_TEXTURE_CUBE_MAP_NEGATIVE_YGL_TEXTURE_CUBE_MAP_POSITIVE_Z,

GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,将会产生GL_INVALID_ENUM错误。

如果internalformat 不是一个被支持的格式(这些格式由GL_COMPRESSED_TEXTURE_FORMATS查询返回),则产生GL_COMPRESSED_TEXTURE_FORMATS错误。

如果level小于0则产生GL_INVALID_VALUE错误。

如果level大于log2maxtarget为GL_TEXTURE_2D时,max为GL_MAX_TEXTURE_SIZE查询的返回值;target不为GL_TEXTURE_2D时,max为GL_MAX_CUBE_MAP_TEXTURE_SIZE)。则可能会产生GL_INVALID_VALUE错误。

width 或 height小于0,或target为GL_TEXTURE_2D时大于GL_MAX_TEXTURE_SIZE,target不为GL_TEXTURE_2D时大于GL_MAX_CUBE_MAP_TEXTURE_SIZE,会产生GL_INVALID_VALUE错误。

如果border不是0则产生GL_INVALID_VALUE错误。

如果imageSize不符合压缩图像数据的格式、尺寸和内容,则产生GL_INVALID_VALUE错误值。

如果参数组合不被指定的内部压缩格式(由纹理压缩格式指定)支持,则产生GL_INVALID_OPERATION错误。

如果data 并未以扩展名指定的内部压缩格式合理地编码,将会导致不可预料的结果,包括程序崩溃。


使用纹理的缺陷是纹理需要大量的内存来存储和处理。在早期我们会把纹理压缩成JPG的格式,然后在加载之前(调用glTexImage之前)对其进行解压。这样仅仅是节省了磁盘的空间以及加快了在网络上传输纹理的速度,但并没有减少对显存(加载到显存中还是原格式那么大)。

在OpenGL1.3后,OpenGL原生支持了纹理压缩的特性。在更低的版本中,通过扩展来支持,你可以通过GL_ARB_texture_compression来检查是否支持这个扩展。OpenGL对纹理的压缩不仅仅是加载压缩的纹理,而且在显卡内存中也是保存着压缩的纹理。这可以减少加载纹理时使用的内存以及提升处理纹理的性能(减少了移动纹理和切换纹理的时间,因为要操作的内存空间变小了)。

你可以通过下表的一个常量作为glTexImage函数中internalFormat参数的值,来达到压缩纹理的目的。当纹理无法被压缩时,将使用对应的基本内部格式。

压缩格式基本内部格式GL_COMPRESSED_ALPHAGL_ALPHAGL_COMPRESSED_LUMINANCEGL_LUMINANCEGL_COMPRESSED_LUMINANCE_ALPHAGL_LUMINANCE_ALPHAGL_COMPRESSED_RGBGL_RGBGL_COMPRESSED_RGBAGL_RGBAGL_COMPRESSED_INTENSITYGL_INTENSITY

在这种方式下,加载压缩的图像会多耗一点时间,但却提升了处理纹理内存的速度。但你使用这种方式压缩了纹理之后,你可以通过glGetTexLevelParameteriv参数为GL_TEXTURE_COMPRESSED来检查纹理是否压缩成功。

GLint compFlag;

glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED, &compFlag);

此函数接受的参数如下表:

参数返回值GL_TEXTURE_COMPRESSED返回1代表压缩成功,0代表失败GL_TEXTURE_COMPRESSED_IMAGE_SIZE返回压缩后纹理的大小(字节为单位)GL_TEXTURE_INTERNAL_FORMAT使用的压缩格式GL_NUM_COMPRESSED_TEXTURE_FORMATS支持的压缩格式的数量GL_COMPRESSED_TEXTURE_FORMATS返回一个保存每一个被支持的压缩格式的数组常量GL_TEXTURE_COMPRESSION_HINT纹理压缩的提示值

我们还可以通过glHint函数来告诉OpenGL我们要用的是最快的压缩算法还是最高质量的压缩算法。通过使用GL_NUM_COMPRESSED_TEXTURE_FORMATS和GL_COMPRESSED_TEXTURE_FORMATS来获得被支持的压缩格式的列表。几乎所有的OpenGl实现都支持GL_EXT_texture_compression_s3tc纹理压缩格式,如果这个扩展被支持那下面表格的所有格式都是支持的(仅适用于2维纹理)

格式描述GL_COMPRESSED_RGB_S3TC_DXT1RGB数据被压缩。alpha为1.0GL_COMPRESSED_RGBA_S3TC_DXT1RGB数据被压缩。alpha值为1.0或0.0GL_COMPRESSED_RGBA_S3TC_DXT3RGB数据被压缩。alpha值用4位存储GL_COMPRESSED_RGBA_S3TC_DXT5RGB数据被压缩。alpha为一些8位值的加权平均值

加载压缩的纹理

在前面我们已经介绍了,如何压缩纹理数据。然后我们可以通过glGetCompressedTexImage(与glGetTexImage获取未压缩数据一样)来获取被压缩的数据,并把它存到硬盘上。在随后的加载中,直接加载已经压缩过的纹理数据会更快。此技术完全依赖于硬件的实现。

加载已经预先压缩过的纹理数据,可以调用下面的函数:

void glCompressedTexImage1D(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLint border, GLsizei imageSize, void *data);

void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, void *data);

void glCompressedTexImage3D(GLenum target, GLint level, GLenum internalFormat, GLint width, GLint height, GLint depth, GLint border, GLint imageSize, void *data);

这个方法与glTexImage几乎是一样的,不一样的是其internalFormat必须是压缩的格式。如果实现支持GL_EXT_texture_compression_s3tc扩展,那么其参数值就可以是上面的表格列出的值。当然也有glCompressedTexSubImage函数来更新部分已加载的压缩过的纹理数据,就像glTexSubImage一样。

纹理压缩时非常流行的特性。更小的纹理意味着更快的加载速度,更快地在网上传输,更快地拷贝到显卡中,可以加载更多的纹理。


不压缩和压缩后的图片大小的对比,压缩前是196kb左右,压缩后只有32kb了:

GLint flag; 
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED, &flag); 
printf("compress flag : %d\n", flag); 
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &flag); 
printf("compress size : %d\n", flag);

3. 常见的压缩纹理格式
基于OpenGL ES的压缩纹理有常见的如下几种实现:
1)ETC1(Ericsson texture compression)
2)PVRTC (PowerVR texture compression)
3)ATITC (ATI texture compression)
4)S3TC (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,对于减小纹理的数据容量有明显作用,相应在显存带宽上也有明显优势,从而提高游戏的运行效率(此特性没有绝对数值,根据每个游戏的用法和瓶颈点不同而有差别)。

4. 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);



1 0
原创粉丝点击