概念说明:
帧缓冲可以把渲染得到的数据附加在一个纹理或者是渲染缓冲中,由此可以更方便的做后期处理。 我认为“更方便后期处理”主要体现在下面两点:
- 帧缓冲把整个场景的渲染都附加到一个纹理上了,那么后期只需要对这一个纹理做就可以了,而不用对场景里所有的纹理都做一遍。并且我们可以获得“此时的渲染结果”,类似动态的场景截图,可以用来实现后视镜这种状态。
- 如果要对一个画面做多步的后期操作,帧缓冲被叫做“离屏渲染”的意义就体现出来了,它可以不在屏幕上显示后期处理的每一步过程,而直接给出结果。
代码说明
对应到代码里,为了将渲染结果附加到纹理中,我们首先要创建一个纹理:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 800, 600, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
我们给纹理的 data 参数传递了 NULL。说明对于这个纹理,我们仅仅分配了内存而没有填充它。填充这个纹理将会在我们渲染到帧缓冲之后来进行。
然后将这个纹理附加到帧缓冲上就可以了。
我们同样可以将深度测试和模板测试的缓冲作为附件添加到帧缓冲,有两种方法可以附上他们:
- 将它们视为纹理同样使用 glFramebufferTexture2D() 函数将它们附上帧缓冲,这其中根据传入类型的不同,我们可以附上深度缓冲、模板缓冲,或是在一个纹理中的前24位附上深度缓冲,后8位附上模板缓冲。
- 创建并绑定一个渲染缓冲对象 (Renderbuffer Object) ,并使用 glFramebufferRenderbuffer() 函数将它附加到帧缓冲
渲染过程
在控制渲染的主循环中,我们仅需要先绑定我们自定义的帧缓冲 framebuffer 再调用 Draw() 函数进行渲染就可以,openGL 会自动的将渲染的结果保存到我们刚才附上的纹理中
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
然后为了在主窗口绘制,我们需要绑定到默认的帧缓冲: glBindFramebuffer(GL_FRAMEBUFFER, 0) ,然后绑定相应的 VAO 和 (保存了帧缓冲渲染结果的)纹理,再 Draw 就可以了。
glBindVertexArray(quadVAO);
glBindTexture(GL_TEXTURE_2D, textureColorbuffer);
glDrawArrays(GL_TRIANGLES, 0, 6);