OpenGL API 之 glTexImage2D
Posted csxiaoshui
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenGL API 之 glTexImage2D相关的知识,希望对你有一定的参考价值。
-
简介
glTexImage2D在OpenGL中主要用来指定二维纹理和立方体纹理,函数原型如下(OpenGL 2.1):
void glTexImage2D(
GLenum target,
GLint level,
GLint internalFormat,
GLsizei width,
GLsizei height,
GLint border,
GLenum format,
GLenum type,
const GLvoid * data
);
-
1
参数:
target :指定纹理单元的类型是哪一种,必须指定为 GL_TEXTURE_2D
, GL_PROXY_TEXTURE_2D
, GL_TEXTURE_CUBE_MAP_POSITIVE_X
, GL_TEXTURE_CUBE_MAP_NEGATIVE_X
, GL_TEXTURE_CUBE_MAP_POSITIVE_Y
, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
, GL_TEXTURE_CUBE_MAP_POSITIVE_Z
, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
, or GL_PROXY_TEXTURE_CUBE_MAP
中的一个。二维纹理需要指定为GL_TEXTURE_2D
level:指定纹理单元的层次,非mipmap纹理level设置为0,mipmap纹理设置为纹理的层级
internalFormat:指定OpenGL是如何管理纹理单元中数据格式的。网络上很多解释说这个参数必须和后面的format参数一样,这个说法是不正确的
width:指定纹理单元的宽度
height:指定纹理单元的高度
border:指定纹理单元的边框,如果包含边框取值为1,不包含边框取值为0
format:指定data所指向的数据的格式
type:指定data所指向的数据的类型
data:实际指向的数据是什么,这个参数有两种解释
下面对这些参数作更详细的解释,记录下来备忘。
target:由于目前只用到了二维纹理的部分,因此这个参数必须指定为GL_TEXTURE_2D
level:目前只用在非mipmap纹理方式下,因此这个参数必须设置为0
internalFormat:对于这个参数需要重点解释一下,以前的使用中一般也是参考网络上的解释将它和后面的format参数设置为一样的,但是具体是什么原因并不清楚。查阅一些资料后,对这个参数有了更好的理解。
以下是stackoverflow 中的一段解释:
The format and type parameters describe the data you are passing to OpenGL as part of a pixel transfer operation. The internalforamt describes the format of the texture. You're telling OpenGL that you're giving it takes that looks like X, and OpenGL is to store it in a texture where the data is Y. Theinternalformat is "Y".
从描述中我们知道:internalFormat用来指定OpenGL中纹理单元中的格式是什么样的,而参数中的后三个(format 、type、 data)是用来指定用来传输到OpenGL中纹理单元数据的格式是怎么样的。回忆一下我们是如何加载一张图片作为纹理的,一般过程如下:
- 读取一张图片到内存中的某处(假设到pBytes指向的内存中)
- 生成一个绑定纹理ID(假设为texID),并绑定纹理ID到一个纹理单元(glGenTexture和glBindTexture)
- 使用glTexImage2D将内存中的数据拷贝到OpenGL纹理单元中
- 设置纹理单元的过滤方式、插值方式等(一般是使用glTexParameter)
- 绑定纹理(texID)并使用纹理
上面的internalForamt参数指定的就是texID对应纹理单元中的数据格式(An Image Format describes the way that the images in Textures and renderbuffers store their data. They define the meaning of the image's data.),它是对OpenGL硬件驱动的一种很强的提示,告诉驱动它里面的数据是怎么组织的。
因此如果我们将internalForamt中的格式指定的和format中格式一致就可以更快地进行传输,而不需要在二者之间进行转换。
format、type、data指定的是pBytes中数据是怎么样组织的(A Pixel Transfer operation is the act of taking pixel data from an unformatted memory buffer and copying it in OpenGL-owned storag)
参数format和type指定了pBytes中的像素数据该如何解译:
其中format指定了每一个像素所包含的成分以及这些成分的顺序是怎么样的,比如:GL_RGBA指定了每个像素包含RGBA四个部分,顺序是R、G、B、A 而如果我们指定GL_BGRA则说明每个像素包含四个部分,但是顺序却不一样;
type则指定每一个成分需要几个字节来表示,比如我们指定GL_UNSIGNED_BYTE在说明每个成分需要一个unsigned byte来表示也就是一个字节,type的取值还包括:
- GL_(UNSIGNED_)BYTE: 1 byte
- GL_(UNSIGNED_)SHORT: 2 bytes
- GL_(UNSIGNED_)INT: 4 bytes
- GL_HALF_FLOAT: 2 bytes
- GL_FLOAT: 4 bytes
参数data在上文中说有两种解释:
1.当有缓冲区绑定到 GL_PIXEL_PACK/UNPACK_BUFFER 时,这时候使用了PBO(Pixel Buffer Object),此时的data是一个指向缓冲区对象数据的偏移量
2.当没有缓冲区绑定到GL_PIXEL_PACK/UNPACK_BUFFER 时,这是data是指向内存中的指针(上文中提到的pBytes)
这两者之间的转换过程:(将Memory中的格式转换为纹理中的格式的过程):
包括如下两个阶段:
先将Memory转换为RGBA的方式(中间过程),转换方式:
Memory RGBA (中间过程)
----------------------------------------------------------------
RED R001
----------------------------------------------------------------
GREEN 0G01
----------------------------------------------------------------
BLUE 00B1
----------------------------------------------------------------
ALPHA 000A
----------------------------------------------------------------
RGB RGB1
----------------------------------------------------------------
RGBA RGBA
----------------------------------------------------------------
LUMINANCE LLL1
----------------------------------------------------------------
LUMINANCE_ALPHA LLLA
----------------------------------------------------------------
之后再从中间过程的RGBA转换到internalFormat指定的格式(转换的方式按下面的公式进行)
INTENSITY = R
LUMINANCE = R
R = R
G = G
B = B
A = A
举例说明:如果你指定format是GL_RGB,但是你指定internalFormat是GL_LUMINANCE ,那么转换过程是这样的
1.现将GL_RGB转为GL_RGBA其中A都是1
2.将GL_RGBA中的R成分给解释为LUMINANCE
另外一种情况,如果你将一个GL_RGB的format指定为GL_ALPHA的internalFormat,那么得到的值全都是0
以上是关于OpenGL API 之 glTexImage2D的主要内容,如果未能解决你的问题,请参考以下文章
glTexImage2D与glDeleteTextures 求助