您的位置:首页 > 运维架构

如何将OpenGL渲染的图片保存到本地(正常渲染和离屏渲染)

2017-07-17 21:00 816 查看

关于如何将OpenGL渲染的图片保存到本地

标签(空格分隔):CG opengl

转载请说明出处:http://blog.csdn.net/hust_sheng/article/details/75268056

主要就是使用函数
glReadPixels()


#define BMP_Header_Length 54

void saveFrameBuff(const char* fileName)
{
FILE* pDummyFile;
FILE* pWritingFile;
GLubyte* pPixelData;
GLubyte BMP_Header[BMP_Header_Length];
GLint i, j;
GLint PixelDataLength;

// 因为是窗口渲染,此处设置读取的数据来源于“前端窗口”(也可以是后端,详细见http://blog.csdn.net/hust_sheng/article/details/75268410)
//glReadBuffer(GL_BACK);
glReadBuffer(GL_FRONT);

// 计算像素数据的实际长度
// 默认是3通道
i = width * 3;      // 得到每一行的像素数据长度
while (i % 4 != 0)  // 补充数据,直到 i 是的倍数
++i;

PixelDataLength = i * height;

// 但这里仅追求直观,对速度没有太高要求PixelDataLength = i * WindowHeight;
// 分配内存和打开文件
pPixelData = (GLubyte*)malloc(PixelDataLength);
if (pPixelData == 0)
exit(0);

pDummyFile = fopen("ground.bmp", "rb");
if (pDummyFile == 0)
exit(0);

pWritingFile = fopen(fileName, "wb");
if (pWritingFile == 0)
exit(0);

// 读取像素
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glReadPixels(0, 0, width, height, GL_BGR_EXT, GL_UNSIGNED_BYTE, pPixelData);

// 把 dummy.bmp 的文件头复制为新文件的文件头
fread(BMP_Header, sizeof(BMP_Header), 1, pDummyFile);
fwrite(BMP_Header, sizeof(BMP_Header), 1, pWritingFile);
fseek(pWritingFile, 0x0012, SEEK_SET);
i = width;
j = height;
fwrite(&i, sizeof(i), 1, pWritingFile);
fwrite(&j, sizeof(j), 1, pWritingFile);

// 写入像素数据
fseek(pWritingFile, 0, SEEK_END);
fwrite(pPixelData, PixelDataLength, 1, pWritingFile);

// 释放内存和关闭文件
fclose(pDummyFile);
fclose(pWritingFile);
free(pPixelData);
}


#define BMP_Header_Length 54

static void saveFrameBuff1(const int outImageNo)
{
// 因为是离屏渲染,此处设置读取的数据来源于我们自己设置的m_FboID对应的FBO
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_FboID);

// GPU -> CPU 数据读取异步操作,详细见:http://blog.csdn.net/hust_sheng/article/details/75268410
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboIds[0]);
glReadPixels(0, 0, width, height * 30, GL_BGR_EXT, GL_UNSIGNED_BYTE, 0);
GLubyte* image_src = (GLubyte*)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB);

if (image_src){
glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
}

FILE* pDummyFile;
FILE* pWritingFile;
GLubyte BMP_Header[BMP_Header_Length];

//GLubyte* pPixelData;
GLint i, j, k;
GLint PixelDataLength;

// 计算像素数据的实际长度
i = width * 3; // 得到每一行的像素数据长度
while (i % 4 != 0) // 补充数据,直到 i 是的倍数
++i;

PixelDataLength = i * height;

// 同时渲染以及传输多张图片
for (k = 0; k < 30; k++){
char outFileStr[OUTIMAGE_FILENAME_LEN];

sprintf_s(outFileStr, 20, "outView_GL%d_x.bmp", outImageNo + 1 - OPENGL_FBO_PARALLELNUM + k);
pWritingFile = fopen(outFileStr, "wb");
if (pWritingFile == 0)
exit(0);

pDummyFile = fopen("ground.bmp", "rb");
if (pDummyFile == 0)
exit(0);

// 把 dummy.bmp 的文件头复制为新文件的文件头
fread(BMP_Header, sizeof(BMP_Header), 1, pDummyFile);
fwrite(BMP_Header, sizeof(BMP_Header), 1, pWritingFile);
fseek(pWritingFile, 0x0012, SEEK_SET);
i = width;
j = height;
fwrite(&i, sizeof(i), 1, pWritingFile);
fwrite(&j, sizeof(j), 1, pWritingFile);

// 写入像素数据
fseek(pWritingFile, 0, SEEK_END);

fwrite(image_src + width*height * 3 * k, PixelDataLength, 1, pWritingFile);

// 释放内存和关闭文件
fclose(pDummyFile);
fclose(pWritingFile);
}
}


上述两段代码,前者是一般的过程,也是窗口渲染的过程,后者是离屏渲染且加上了异步优化。基本的思路都是先读取GPU图片数据,再读取本地的*.bmp文件的头部54个byte的信息,将两者拼接得到新的bmp文件,保存在本地。贴图渲染和异步优化见链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: