1. 位图
像素数据由位图(一系列表示像素值开启和关闭0,1)来表示的。每个内存中存储的位图数据和像素开启和关闭是一一对应的。
2. 像素包装
像素数据的字节以特定方式与地址对齐的方式。比如说很多计算机CPU每四个字节从缓冲区读取数据,而以每四个字节与地址对齐的方式,可以提高其读写效率。
3. 像素图
像素图属于位图,像素图的位数比较多,一般为8位,16位和32位,可以显示的颜色为2的位数次方,此外像素图还有一个附加位,用来表示屏幕的两度或者颜色值的强度。OpenGL中无法将像素数据写入到颜色缓冲区,但是可以指定颜色缓冲区内容,也就是我们用一种形式表示图像数据,通过直接读取颜色缓冲区的数据而间接的提取出相关的像素数据。比如说可以通过这个函数进行提取。
void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
x, y为矩形窗口在窗口左下角坐标,width和height为矩形宽和高,矩形为对应图像数据的区域。pixels指针为图像数据在内存中的地址。format为pixels指向的颜色缓冲区存取数据元素的颜色布局。type为pixels指向颜色缓冲区存取的数据类型。
需要注意的,glReadPixelds从图形硬件中复制数据,通常通过总线传输到内存,这种情况下应用程序会被阻塞,直到内存传输完成,而且指定一个与本地图形硬件不同的像素布局,也会带来额外的开销.
4. 包装的像素格式
如果一个字节等于8位,通常我们用八位表示三原色的一个分量,那么显示一种颜色需要三个字节,但是经过包装后,比如说我们可以用八位就可以表示一种颜色,比如说从高位到低位,没三位表示三原色的一种分量,后一位表示一种三原色的分量,这样对图像数据进行包装,可以节省大量的内存的空间.或者更快的进行操作.
5. 载入纹理
将纹理数据载入到内存中,在OpenGL一般我们通过下面三个函数
void glTexImage1d(GLenum target, GLint level, GLint internalformat , GLseizei width, GLint border , GLenum format, GLenum type, void *data)
void glTexImage2d(GLenum target, GLint level, GLint internalformat , GLseizei width, GLseizei height, GLint border , GLenum format, GLenum type, void *data)
void glTexImage3d(GLenum target, GLint level, GLint internalformat , GLseizei width, GLseizei height, GLseizei depth, GLint border , GLenum format, GLenum type, void *data)
target参数为载入纹理单元的模式,level为mip的层次,internalformat为每个纹理单元存储的颜色成分,如果指定颜色组成的特定方式,也可作为压缩纹理数据的参数,width,height,depth指定了被加载纹理数据的范围, border为每个纹理单元额外的边界。format为纹理数据的颜色布局,type为存储到内存中的纹理数据类型,data为纹理数据对应的地址指针。
6.从颜色颜色缓存区读取纹理数据
可以使用下面两个函数
void glCopyTexImage1d(GLenum target, GLint level, GLint internalformat , GLint x, GLseizei width, GLint border)
void glCopyTexImage2d(GLenum target, GLint level, GLint internalformat , GLint x, GLint y, GLseizei width, GLseizei height, GLint border)
其中x,y为指定内存中要加载纹理的位置,需要注意的是颜色缓冲区没有深度的概念,故不能加载三维的纹理数据。
7. 更新纹理
频繁的载入纹理数据,实际上是对内存的写操作,内存的写操作是很耗性能的,当我们不在需要这段纹理时,这时候我们可以在这段纹理的内存上进行纹理的替换或者部分替换,而避免再次重新写入新的纹理数据。下面几个函数可以完成纹理更新
void glTexSubImage1d(GLenum target, GLint level, GLint xOffset, GLseizei width, GLint border , GLenum format, GLenum type, void *data )
void glTexSubImage2d(GLenum target, GLint level, GLint xOffset, GLint yOffset, GLseizei width, GLseizei height, GLint border , GLenum format, GLenum type, void *data)
oid glTexSubImage3d(GLenum target, GLint level , GLint xOffset, GLint yOffset, GLint zOffset, GLseizei width, GLseizei height, GLint border , GLenum format, GLenum type, void *data)
其中xOffset,yOffset,zOffset,为需要更新的纹理在原纹理的坐标偏移量。
8.在颜色颜色缓存区更新纹理
void glCopyTexSubImage1d(GLenum target, GLint level, GLint xOffset, GLint x, GLint y, GLseizei width )
void glCopyTexSubImage2d(GLenum target, GLint level, GLint xOffset, GLint yOffset, GLint x, GLint y, GLseizei width, GLseizei height)
oid glCopyTexSubImage3d(GLenum target, GLint level , GLint xOffset, GLint yOffset, GLint zOffset, GLint x, GLint y, GLseizei width, GLseizei height)
需要注意的地方从颜色缓存区读取纹理数据是没有glCopyTexImage3d函数的,这是因为颜色缓冲区是没有深度概念的,只可以将2D彩色图片设置成2D纹理,但是我们更新颜色缓冲区的纹理是可以使用glCopyTexSubImage3d函数的,因为纹理有深度的概念,我们可以用纹理单元平面来设置一个二维的纹理。
9.纹理对象
当载入纹理数据后,这时候我们是需要管理这些纹理的,如果用到哪个纹理状态就加载哪个纹理数据或者更新哪个纹理的话,这样显然是很耗费性能的,纹理对象允许一次加载多个纹理,通过一段特定的无符号整形数据一个指针指向这段纹理内存,这样我们通过纹理对象可以方便的进行多个纹理的管理。
首先使用下面这个函数进行纹理对象的分配
void glGenTextures(GLSizei n, GLint * textures)
n为纹理对象的个数, textures为纹理对象集合的指针
通过下面的函数进行纹理与纹理对象的绑定
void glBindTexture(GLEnum target, GLint *texture)
target为纹理数据的坐标形式,teture为指向纹理内存的指针。
可以使用下面的函数进行纹理对象的删除
void glDeleteTextures(GLSizei n, GLint * textures)
n为要删除的纹理个数,textures为要删除的纹理集合
可以使用下面的函数判断纹理对象是否有绑定纹理状态
GLboolean GLIsTexture(GLint teure)
teure为要判读是否存在的纹理对象