OpenGL Frame Buffer管理

OpenGL应用程序进行图形渲染都是以pipeline的方式进行处理,在其中的每一个步骤都有输入和输出,渲染的最后一步是将渲染的结果绘制到屏幕上。在绘制这一步的输出是屏幕专用的存储,输入则是Frame buffer。由于OpenGL并没有窗口处理函数,所以与窗口相关的处理都需要外部的扩展来实现,因此相应的窗口处理函数会在初始化的时候分配相应的Frame buffer,同时OpenGL会将最终渲染的结果给写到系统分配管理的Frame buffer中。由于这部分Frame Buffer是由系统管理的,所以程序员不能够直接的操作这部分存储。为了更好的与Frame buffer进行交互,OpenGL提供了对应的扩展接口——Frame Buffer Object,也就是说OpenGL提供了一种程序员可以操作的Frame Buffer。这就使得渲染与最终绘制到窗口的操作可以分开来处理,从而在某些应用场景中有效的提高显示效率。

在渲染的过程的中间步骤,需要用到两个比较重要的缓存,一个叫做texture buffer,另一个是render buffer。在某些时候render buffer也可以用作texture buffer,然而需要注意的是texture buffer指作为输入缓存,用于存储常规的纹理信息。然而render buffer则是作为输出缓存,用于存储逻辑缓存,仅仅包含一些与纹理格式无关的一些信息,比如说模板、深度信息之类的。不过texture buffer和render buffer都可以作为frame buffer最终的输出存储来接收渲染到frame buffer中的数据,从而有效的实现离屏渲染。

frame buffer的创建和其他的缓存一样,同样遵循三步走规则,第一步通过相应的生成函数分配frame buffer的ID号,第二步通过bind函数将ID号和对应的frame buffer的对象绑定到一起,第三步通过指定的函数为frame buffer提供存储空间。需要注意的是OGL中,分配存储空间有两种形式,第一种是为当前的缓存对象分配独占的存储空间,第二种则是以共享的方式在不同的buffer对象之间进行存储共享,这样共享的好处是只需要将输出缓存对象和输入缓存对象之间的存储空间进行共享就可以有效的在pipeline中进行存储的传递,不过需要注意的是,共享也需要遵循pipeline的顺序进行。在Frame buffer object的管理中,生成ID号码可以通过glGenFramebuffers函数实现,这个函数的操作和其他的函数是类似的,绑定是通过glBindFramebuffer函数实现的。为Frame buffer提供存储有两种方式,第一种是和texture buffer对象进行内存共享,第二种是和render buffer对象进行内存共享。与render buffer对象进行绑定操作是利用下列函数实现的。

void glFramebufferRenderbuffer(GLenum target,
                               GLenum attachmentPoint,
                               GLenum renderbufferTarget,
                               GLuint renderbufferId)

而与texture buffer绑定则是通过glRenderbufferStorage函数实现的。

glFramebufferTexture2D(GLenum target,
                       GLenum attachmentPoint,
                       GLenum textureTarget,
                       GLuint textureId,
                       GLint  level)
通过这两个函数render object和texture object与frame buffer object粘合到了一起,粘合的点由attachmentPoint指定。frame buffer object管理的存储空间类似于一个数组,而attachmentPoint则类似于数组中对应的索引。这主要是由于frame buffer中包含了很多的信息,比如模板,深度,颜色等等。level参数则是用于指定当前提交的纹理是mipmap纹理的第几层,粘合之后的示意图如下所示。
OpenGL Frame Buffer管理_第1张图片

Render Buffer Object

Render Buffer和其他的缓存的管理一样,包括创建、绑定、存储分配与删除,除此之外还可以向当前的OGL得到当前的render buffer的相关的参数。需要注意的是,在为render buffer分配存储空间时,internalformat只能够是可渲染的颜色的格式比如说GL_RGB、GL_RGBA等等,或者是可渲染的深度格式GL_DEPTH_COMPONEN以及可渲染的模板格式GL_STENCIL_INDEX。

void glGenRenderbuffers(GLsizei n, GLuint* ids)
void glBindRenderbuffer(GLenum target, GLuint id)
void glDeleteRenderbuffers(GLsizei n, const Gluint* ids)
void glRenderbufferStorage(GLenum  target,
                           GLenum  internalFormat,
                           GLsizei width,
                           GLsizei height)
由于render buffer是一个输出存储区,因此在使用的时候可以通过复制的方式将已经渲染好的数据从render buffer中拷贝到另一个frame buffer,这样的操作主要是通过glBlitFrameBuffer函数实现的,该函数通过将当前的read frame buffer给复制到draw frame buffer。在下面是glBlitFramebuffer函数的定义。倒数第二个参数mask用于指定复制read frame buffer中的哪一部分缓存到draw frame buffer中,最后一个参数filter用于指定当两者大小不一致时,以什么样的方式进行图像的压缩或者是扩展。

void glBlitFramebuffer(	GLint srcX0,
 	GLint srcY0,
 	GLint srcX1,
 	GLint srcY1,
 	GLint dstX0,
 	GLint dstY0,
 	GLint dstX1,
 	GLint dstY1,
 	GLbitfield mask,
 	GLenum filter);
Texture buffer object

texture buffer粘合到frame buffer和render buffer的处理流程大致相同,唯一的差异是由于texture buffer是输入缓存,所以在使用的时候可以不用复制,而只需要通过将当前的texture buffer通过glBindTexture函数给绑定激活就可以了,在稍后的处理就会基于最近一次通过glBindTexture函数绑定的texture buffer。
OpenGL Frame Buffer管理_第2张图片

你可能感兴趣的:(C++)