songho——OpenGL的帧缓冲

http://www.songho.ca/opengl/gl_fbo.html

纵览:
在OpengL的渲染管线中,几何数据和纹理被变换,被传送到几个不同的测试,最终作为2D像素渲染到屏幕上。最后一个渲染目的地是OpenGL管线,它称为帧缓冲。帧缓冲一个一组2D数组、或者是存储空间的集合。颜色缓冲、深度缓冲、模板缓冲,还有累计缓冲。默认情况下,OpenGL使用帧缓冲作为最终的渲染目的地,这个目的地,是通过窗口系统来创建、管理。这个默认的帧缓冲叫做窗口-系统提供的帧缓冲。

OpenGL的扩展,GL_ARB_framebuffer_object提供一个接口,来创建额外的未展示的帧缓冲对象。这个帧缓冲对象叫做应用-创建的帧缓冲,它区别于默认的窗口-系统-提供的帧缓冲。通过使用帧缓冲对象,OpengL应用可以重定向渲染输出到应用创建的帧缓冲对象,而不是传统的窗口-系统提供的帧缓冲,这个完全由OpengL控制。

和窗口-系统-提供的帧缓冲一样,FBO对象是渲染目标:颜色、深度、末班缓冲的集合。注意到累计缓冲不在FBO中定义。这写FBO中逻辑的缓冲叫做帧缓冲——附件图片,它们是被关联到帧缓冲对象的2D数组的像素。

这里有两个类型的帧缓冲-附件图片:纹理图片和渲染缓冲对象。如果纹理对象的图片附加到帧缓冲,OpenGL执行的是渲染到纹理。如果是渲染缓冲对象的图片关联到帧缓冲,OpenGL执行的是离屏渲染。

顺便说一句,渲染缓冲对象是新类型的存储对象,通过GL_ARB_framebuffer_object扩展定义。这个被用于简单的2D图片的渲染目标。

下面一张图展示帧缓冲对象、纹理对象和渲染缓冲对象的联系。多个纹理对象和渲染缓冲对象可以被附加到帧缓冲对象,通过附件点进行附件。

在这里插入图片描述

这里有多个颜色附着点:
GL_COLOR_ATTACHMENT0,…, GL_COLOR_ATTACHMENTn)
一个深度附着点GL_DEPTH_ATTACHMENT,一个模板缓冲附着点GL_STENCIL_ATTACHMENT,在帧缓冲对象中。

颜色附着点的个数和实现是独立的,但是每个FBO都至少有一个颜色附着点。你可以查看附着点的个数GL_MAX_COLOR_ATTACHMENTS,这个是图形显卡支持的。FBO有多个颜色附着点,是允许渲染颜色缓冲同时渲染到多个目标。这个就是多重渲染目标(MRT),他可以通过GL_ARB_draw_buffers实现。注意帧缓冲对象本身没有任何的图片存储空间,它只有多个附件附着点。、

帧缓冲对象提供有效的切换机制。从前一个帧缓冲附着图片,附加到新的帧缓冲附着点的图片。在帧缓冲附着的图片之间做切换比在帧缓冲对象之间切换要快。FBO提供glFramebufferTexture2D在2D纹理对象之间做切换,glFramebufferRenderbuffer在渲染对象之间做切换。

创建一个帧缓冲对象
创建一个帧缓冲对象和创建顶点缓冲对象类似:

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

glGenFramebuffers需要两个参数:第一个是帧缓冲的个数,dirge参数是指向2D存储空间的ID,或者是多个ID数组。它的返回是未使用的帧缓冲对象的IDs。ID=0是默认的帧缓冲,这个是窗口-系统提供的帧缓冲。

同时,FBO可以通过glDeleteFramebuffers删除。

一旦FBO被创建,它必须在使用之前绑定。

void glBindFramebuffer(GLenum target, GLuint id)

第一个参数是目标,应该是`GL_FRAMEBUFFER,第二个是帧缓冲对象的ID。一旦FBO被绑定,所有的OpenGL操作会影响到当前绑定到的帧缓冲对象。ID=0的对象,是窗口-系统提供的预留的帧缓冲。因此,为了解绑当前的帧缓冲,使用ID为0,作为参数:glBindFramebuffer。

渲染缓冲对象
除此之外,渲染缓冲对象是被新引入的离屏渲染。它允许直接渲染场景到渲染缓冲对象,而不是渲染到纹理贴图对象。渲染缓冲对象是一个简单的存储数据的对象,包含一个简单的图片,里面有内部的格式。它用于OpengL存储逻辑缓冲,没有对应的纹理格式件,比如模板和深度缓冲:

glGenRenderbuffers()
void glGenRenderbuffers(GLsizei n, GLuint* ids)
void glDeleteRenderbuffers(GLsizei n, const Gluint* ids)

一旦渲染缓冲被创建,它的返回时非零的整数。ID=0,是OpengL预留的。

glBindRenderbuffer()
void glBindRenderbuffer(GLenum target, GLuint id)

和OpengL其他对象一样,你需要使用它之前,把它绑定的到当前的渲染缓冲对象。目标应该是GL_RENDERBUFFER,它是针对渲染缓冲对象的。

glRenderbufferStorage()
void glRenderbufferStorage(GLenum  target,
                           GLenum  internalFormat,
                           GLsizei width,
                           GLsizei height)

当渲染缓冲对象呗创建,它没有任何的数据存储,所以我们需要分配一个内存空间给它。这个可以通过
glRenderbufferStorage指定。第一个参数是GL_RENDERBUFFER。第二个参数是颜色渲染值,如GL_RGB, GL_RGBA等,或者是GL_DEPTH_COMPONENT,或者是模板渲染格式GL_STENCIL_INDEX。渲染缓冲对象图片的像素宽度和高度。

宽度和高度需要小于GL_MAX_RENDERBUFFER_SIZE,否则会产生GL_INVALID_VALUE错误。

glGetRenderbufferParameteriv()
void glGetRenderbufferParameteriv(GLenum target,
                                  GLenum param,
                                  GLint* value)

你对于当前绑定的渲染缓冲对象,还需要多个参数。目标应该是GL_RENDERBUFFER。第二个参数是参数的名字。最后一个指向返回值的整数指针。第二个参数的参数名字可以为:

GL_RENDERBUFFER_WIDTH
GL_RENDERBUFFER_HEIGHT
GL_RENDERBUFFER_INTERNAL_FORMAT
GL_RENDERBUFFER_RED_SIZE
GL_RENDERBUFFER_GREEN_SIZE
GL_RENDERBUFFER_BLUE_SIZE
GL_RENDERBUFFER_ALPHA_SIZE
GL_RENDERBUFFER_DEPTH_SIZE
GL_RENDERBUFFER_STENCIL_SIZE

绑定图片到FBO
FBO本身没有图片存储空间。反之,我们必须绑定帧缓冲-附件图片(纹理或者是渲染缓冲对象)到FBO。这个机制允许FBO可以在切换之间(绑定和解绑),解绑图片做到迅速切换。切换帧缓冲-附着图片比切换FBO要迅速的多。这个也避免了不必要的数据拷贝和内存浪费。比如,一个纹理可以附加到多个帧缓冲对象,它的图片图片存储可以被多个FBO共享。

Attaching a 2D texture image to FBO
glFramebufferTexture2D(GLenum target,
                       GLenum attachmentPoint,
                       GLenum textureTarget,
                       GLuint textureId,
                       GLint  level)

glFramebufferTexture2D把2D纹理绑定到FBO。第一个参数是GL_FRAMEBUFFER,第二个参数是附着点,它连接了纹理图片。一个帧缓冲对象有多个附着点,(GL_COLOR_ATTACHMENT0, …, GL_COLOR_ATTACHMENTn),
GL_DEPTH_ATTACHMENT和GL_STENCIL_ATTACHMENT。第三个参数,纹理目标,他多数情况是GL_TEXTURE_2D。第四个参数是纹理对象的标识符。最后一个是纹理对象的mipmap等级。

如果textureID参数被设置为0,接着,纹理图片从FBO解绑。如果纹理对象被删除了,它依然绑定到FBO。结合,纹理图片将会自动从当前绑定的FBO解绑。但是,如果它被附加到多个FBO,如果被删除了,则只会从绑定的FBO解除,但是不会从其他的未绑定的FBO对象解绑。

Attaching a Renderbuffer image to FBO
void glFramebufferRenderbuffer(GLenum target,
                               GLenum attachmentPoint,
                               GLenum renderbufferTarget,
                               GLuint renderbufferId)

一个渲染缓冲对象可以通过glFramebufferRenderbuffer来附加。第一个参数和第二个参数和glFramebufferTexture2D一样。第三个参数必须是GL_RENDERBUFFER,最后一个参数是渲染缓冲对象的ID。

如果渲染缓冲id设置为0,这个渲染缓冲对象从FBO的附着点上解绑。如果渲染缓冲对象从附加到FBO上删除,它就不自动从FBO上解绑。但是,他不会从其他的未绑定的FBO上解绑。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值