OpenGL取渲染后的图片数据

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;

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容