1.简介
前文中描述了OpenGL的图像格式,本文接着描述像素格式
图像格式可以理解为对GPU中数据的解释,那么对于CPU端(也就是内存中)的数据解释就是像素格式的内容。
像素数据一般会在CPU和GPU中进行传输,如果传输过程是从GPU到CPU一般称为压包(pack),从CPU到GPU的传输称为解包(unpack)
2. 像素传输的应用场景
在OpenGL中有许多函数会用到像素的传输,主要包括两类
1. 压包操作:
- 1
- 2
- 1
- 2
- 解包操作:
- 1
- 2
- 1
- 2
3. 像素传输的参数
所有上面列举的像素传输类函数,都包含了一下三个参数,用来定义像素的格式,这三个参数如下:
- 1
- 1
这三个参数中:
data:指向内存中数据的指针或者是缓冲区对象的偏移量(由GL_PIXEL_PACK_BUFFER、GL_PIXEL_UNNPACK_BUFFER是否有缓冲区对象绑定来决定data的含义是前者还是后者)
format和type:真正定义了在内存或者缓冲区中像素数据的格式
这两个参数在《OpenGL图像格式》中也有提到,只不过OpenGL图像格式把二者混合写在一起了。(例如GL_RGBA8I实际上通过解析它的format是RGBA,type是GL_SHORT)下面分别进行介绍。
3.1 像素格式 format
内存中的像素可以分为 颜色数据、深度数据、深度/模板数据、模板数据。颜色数据一般分为4个成分:R、G、B、A。深度和模板数据一般只有一个成分。深度/模板数据是混合了深度和模板的数据,包含两个成分。
format定义了一下的数据特性:
1. 像素中的数据类型(是颜色、深度、深度/模板、模板)
2. 每一个像素的成分顺序(是RGBA还是BGRA)
3. 对于颜色数据来说,是否需要转换为浮点类型传输
format的定义格式和它的描述
format | 描述 | 数据类型 |
---|---|---|
GL_DEPTH_COMPONENT | 深度数据 | 浮点型 |
GL_STENCIL_INDEX | 模板数据 | 浮点型 |
GL_DEPTH_STENCIL | 深度模板数据 | 浮点型 |
GL_RED GL_GREEN GL_BLUE GL_RG GL_RGB GL_BGR GL_RGBA GL_BGRA | 颜色数据 | 浮点型 |
默认上面的数据都是浮点类型的,如果对于内存中的整型数据使用了上述浮点类型的标签,那么这些内存中的整型数据会被解析为归一化的浮点类型。
如果真的想传输整型的数据,那么需要使用_INTEGER后缀。
3.2 像素数据类型 type
type定义了每一个成分所占用的字节数。有两种表示方式,一种是定义单一成分占用多少字节,另一种是定义所有成分占用总的字节数。
第一种方式
示例:
- 1
- 2
- 3
- 1
- 2
- 3
其他可用的枚举包括
type枚举值 | 占用的字节 |
---|---|
GL_(UNSIGNED_)BYTE | 1字节 |
GL_(UNSIGNED_)SHORT | 2字节 |
GL_(UNSIGNED_)INT | 4字节 |
GL_HALF_FLOAT | 2字节 |
GL_FLOAT | 4字节 |
第二种方式
格式如下,将所有成分打包在一起:
- 1
- 1
例如:
GL_UNSIGNED_SHORT_5_6_5 (GL_UNSIGNED_SHORT的大小必须容纳下后面的5+6+5 = 16位)
_REV是可选的,如果定义了,那么解析的方向按format中定义的方式反向解析。
- 1
- 2
- 1
- 2
4. 像素传输的控制
通过format和type定义了单一像素的数据格式,像素传输的是一整块的数据,因此数据的布局也非常重要,OpenGL通过glPixelStore定义了数据的布局格式,详细的内容可以参考另一篇文章的描述。OpenGL API 之 glPixelStore(2)
5. 格式转换
像素格式在传输中客户端(cpu内存中)的数据和OpenGL图像(纹理和帧缓冲区)中的数据必须保持一致。
一般来说客户端的数据可以是浮点类型(包含归一化的整型)或者整型。在客户端指定数据类型时,如果format指定的是_INTEGER,但是type指定的是浮点类型的值(如GL_FLOAT,GL_HALF_FLOAT),那么就会出现错误。同样如果客户端format指定的是_INTERGER,但是GPU端的图像格式指定的不是整型,那么传输也会失败。一般来说最好将两者指定的兼容,省去转换的麻烦。
参考文献: Pixel Transfer