OpenGL学习脚印: 帧缓冲对象(Frame Buffer Object)

本文介绍了OpenGL中的帧缓冲对象(FBO),包括FBO的概念、创建过程、如何附加纹理和RenderBuffer,以及利用FBO实现离屏渲染和后处理效果。FBO允许自定义帧缓冲区,实现镜面、离屏渲染和各种视觉特效,如颜色反转、模糊和边缘检测。文章还探讨了附加纹理和RenderBuffer的选择,以及使用FBO时可能遇到的颜色和深度渲染问题。
摘要由CSDN通过智能技术生成

写在前面
一直以来,我们在使用OpenGL渲染时,最终的目的地是默认的帧缓冲区,实际上OpenGL也允许我们创建自定义的帧缓冲区。使用自定义的帧缓冲区,可以实现镜面,离屏渲染,以及很酷的后处理效果。本节将学习帧缓存的使用,文中示例代码均可以在我的github下载

本节内容整理自
1.OpenGL Frame Buffer Object (FBO)
2.www.learnopengl.com Framebuffers

FBO概念

在OpenGL中,渲染管线中的顶点、纹理等经过一系列处理后,最终显示在2D屏幕设备上,渲染管线的最终目的地就是帧缓冲区。帧缓冲包括OpenGL使用的颜色缓冲区(color buffer)、深度缓冲区(depth buffer)、模板缓冲区(stencil buffer)等缓冲区。默认的帧缓冲区由窗口系统创建,例如我们一直使用的GLFW库来完成这项任务。这个默认的帧缓冲区,就是目前我们一直使用的绘图命令的作用对象,称之为窗口系统提供的帧缓冲区(window-system-provided framebuffer)。

OpenGL也允许我们手动创建一个帧缓冲区,并将渲染结果重定向到这个缓冲区。在创建时允许我们自定义帧缓冲区的一些特性,这个自定义的帧缓冲区,称之为应用程序帧缓冲区(application-created framebuffer object )。

同默认的帧缓冲区一样,自定义的帧缓冲区也包含颜色缓冲区、深度和模板缓冲区,这些逻辑上的缓冲区(logical buffers)在FBO中称之为可附加的图像(framebuffer-attachable images),他们是可以附加到FBO的二维像素数组(2D arrays of pixels )。

FBO中包含两种类型的附加图像(framebuffer-attachable): 纹理图像和RenderBuffer图像(texture images and renderbuffer images)。附加纹理时OpenGL渲染到这个纹理图像,在着色器中可以访问到这个纹理对象;附加RenderBuffer时,OpenGL执行离屏渲染(offscreen rendering)。

之所以用附加这个词,表达的是FBO可以附加多个缓冲区,而且可以灵活地在缓冲区中切换,一个重要的概念是附加点(attachment points)。FBO中包含一个以上的颜色附加点,但只有一个深度和模板附加点,如下图所示(来自songho FBO):

FBO attachment point

一个FBO可以有
(GL_COLOR_ATTACHMENT0,…, GL_COLOR_ATTACHMENTn)
多个附加点,最多的附加点可以通过查询GL_MAX_COLOR_ATTACHMENTS变量获取。

值得注意的是:从上面的图中我们可以看到,FBO本身并不包含任何缓冲对象,实际上是通过附加点指向实际的缓冲对象的。这样FBO可以快速地切换缓冲对象。

创建FBO

同OpenGL中创建其他缓冲对象一样,创建和销毁FBO的步骤也很简单:

void glGenFramebuffers(GLsizei n, GLuint* ids)
void glDeleteFramebuffers(GLsizei n, const GLuint* ids)

创建之后,我们需要将FBO绑定到目标对象:

    void glBindFramebuffer(GLenum target, GLuint id) 

这里的target一般可以填写GL_FRAMEBUFFER,这个缓冲区将会用来进行读和写操作;如果需要绑定到读操作的缓冲区使用GL_READ_FRAMEBUFFER,支持 glReadPixels这类读操作;如果需要绑定到写操作的缓冲区使用GL_DRAW_FRAMEBUFFER,支持渲染、清除等操作。

OpenGL要求,一个完整的FBO需要满足以下条件(来自FrameBufffer):

  • 至少附加一个缓冲区(颜色、深度或者模板)
  • 至少有一个颜色附加
  • 所有的附加必须完整(预分配了内存)
  • 每个缓冲区的采样数需要一致

关于采样,后面会学习,暂时不做讨论。判断一个FBO是否完整,可以如下:

   if(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)

如果FBO不完整将不能正常工作。
那么我们需要按照上述要求构建一个完整的FBO。

创建纹理附加图像

创建FBO的附加纹理如同平常使用纹理一样,不同的是,这里只是为纹理预分配空间,而不需要真正的加载纹理,因为当使用FBO渲染时渲染结果将会写入到我们创建的这个纹理上去。附加纹理使用函数glFramebufferTexture2D

API void glFramebufferTexture2D( GLenum target,
GLenum attachment,
GLenum textarget,GLuint texture,GLint level);
1.target表示绑定目标,参数可选为GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER, or GL_FRAMEBUFFER。
2.attechment表示附加点,可选值为GL_COLOR_ATTACHMENTi, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT or GL_DEPTH_STENCIL_ATTACHMMENT。
3. textTarget表示纹理的绑定目标,我们使用二维纹理填写GL_TEXTURE_2D即可。
4. texture表示实际的纹理对象。
5. level表示 mipmap级别,我们填写0即可。

这里的texture是我们实际创建的纹理对象,在创建纹理对象时使用代码:

GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 800, 600, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);  

这里需

  • 6
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值