1.使用glReadPixels()函数,需要从显存传递数据到内存,耗时长
glPixelStorei(GL_PACK_ALIGNMENT, 4);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)pixel);
2.使用glGetTexImage()函数,需要从显存传递数据到内存,耗时长
glGetTexImage(GL_TEXTURE_2D,0,GL_RGBA,GL_UNSIGNED_BYTE,(GLvoid *)pixel);
3.使用PBO的方式,速度快
opengl2.0之后才有的,PBO设计的目的就是快速地向显卡传输数据,或者从显卡读取数据,我们可以使用它更加高效的读取屏幕数据。
单个PBO读取屏幕数据效率大概和 glReadPixels() 差不多,双PBO交换读取效率会很高。原因是使用PBO时,屏幕上的数据不是读取到内存,而是从显卡读到PBO中,或者如果内部机制是读取到内存中,但这也是由DMA 控制器来完成的,而不是cpu指令来做的,再加上两个PBO交换使用,所以读取效率很高。
还可以使用PBO 高效读取内存数据(比如纹理)到显存中。代码如下:
glGenBuffers(2, pboBuffer); //创建两个个pboBuffer 存储屏幕数据 创建一个pboBuffer时在内存和显存都有一份 共两份(一个PBO)
glBindBuffer(GL_PIXEL_PACK_BUFFER, pboBuffer[0]); //绑定
glBufferData(GL_PIXEL_PACK_BUFFER, WIDTH * HEIGHT * 4, 0, GL_STREAM_READ); //分配显存空间 ... // DMA
if ( swap_pbo )
{
int seq = index % 2;
glBindBuffer(GL_PIXEL_PACK_BUFFER, pboBuffer[seq]);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
seq = (index +1 ) % 2;
glBindBuffer(GL_PIXEL_PACK_BUFFER, pboBuffer[seq]);
} else {
glBindBuffer(GL_PIXEL_PACK_BUFFER, pboBuffer[0]);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
}
void *data = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_WRITE);
memcpy(pixel, data, width * height * 4); //这个很重要,把PBO里面的数据copy到内存中
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
index++;
附上opengl保存图片的代码:
int bmp_write(unsigned char* image, int imageWidth, int imageHeight, char* filename)
{
unsigned char header[54] = {
0x42, 0x4d, 0, 0, 0, 0, 0, 0, 0, 0,
54, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 32, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0
};
//for (int i = 1000; i < 1100; i++)
//{
// printf("ddd = %d", image[i]);
//}
long file_size = (long)imageWidth * (long)imageHeight * 4 + 54;
header[2] = (unsigned char)(file_size & 0x000000ff);
header[3] = (file_size >> 8) & 0x000000ff;
header[4] = (file_size >> 16) & 0x000000ff;
header[5] = (file_size >> 24) & 0x000000ff;
long width = imageWidth;
header[18] = width & 0x000000ff;
header[19] = (width >> 8) & 0x000000ff;
header[20] = (width >> 16) & 0x000000ff;
header[21] = (width >> 24) & 0x000000ff;
long height = imageHeight;
header[22] = height & 0x000000ff;
header[23] = (height >> 8) & 0x000000ff;
header[24] = (height >> 16) & 0x000000ff;
header[25] = (height >> 24) & 0x000000ff;
char fname_bmp[128];
sprintf(fname_bmp, "%s", filename);
FILE* fp;
if (!(fp = fopen(fname_bmp, "wb")))
return -1;
fwrite(header, sizeof(unsigned char), 54, fp);
fwrite(image, sizeof(unsigned char), (size_t)(long)imageWidth * imageHeight * 4, fp);
fclose(fp);
return 0;
}