学习新知识只有结合实际使用才能真正掌握,之前看过几遍OpenGL的离屏渲染机制,但都不得要领,直到最近因为实际工作需要边看边做笔记边运用才算掌握了。
本文以离屏渲染技术为基础,说明如何通过读取离屏渲染的像素绘制保存为图片。
OpenGL的离屏渲染,跟屏幕渲染相比,区别主要在于需要自己定义RenderBuffer和FrameBuffer,将RenderBuffer绑定到FrameBuffer上。
其他的绘图流程跟屏幕渲染流程是一样的。
以下为RenderBuffer和FrameBuffer的创建和初始化相关代码。
glViewport(0, 0, showWidth, showHeight);
GLuint fbo, rbo;
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB, showWidth, showHeight);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
在创建和初始化完RenderBuffer和FrameBuffer后,开始绘制和读取像素。绘制的方式跟屏幕渲染一样,主要是以下几个步骤。
1. 创建、加载、编译着色器。
2. 创建、绑定纹理。
3. 将纹理坐标和顶点坐标相绑定映射。
而离屏渲染像素的读取,可以通过glReadPixel来实现,这里需要注意的是读取出来的像素格式和纹理渲染时格式是一致的。
glColor3f(0.0, 1.0, 0.0);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
pDrawer->Draw(showWidth, showHeight, panorama, logo);//自定义实现的纹理绘制函数
glReadBuffer(GL_COLOR_ATTACHMENT0);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, showWidth, showHeight, GLenum(GL_BGR), GLenum(GL_UNSIGNED_BYTE), m_pBGRBuf);//将读出的像素保存在m_pBGRBuf中。
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
要将glReadPixels读取出来的像素保存为图片,可以通过QT的QImage来实现。将读出保存在m_pBGRBuf、showWidth、showHeight以及指定像素格式作为参数传递给QImage。
QImage image(m_pBGRBuf, showWidth, showHeight, QImage::Format_RGB888);
image.save("Capture.jpg", "JPG");
在学习OpenGL的过程中推荐以下网络资料,本文有参考。
http://www.songho.ca/opengl/gl_fbo.html
https://learnopengl.com/Advanced-OpenGL/Framebuffers