OpenGL在图元rasterazation之后,得到的是fragment,fragment不是最后的像素数据,但和像素对应;fragment需要经过一写了的处理,blend,texture,lighting...,才会得到最后的像素。用来缓存fragment数据的缓冲区,就是frame buffer。
fragment相关的数据有color,stencil,depth等等,因此frame buffer可以说包含color buffer,stencil buffer,depth buffer等若干buffer。只有color buffer用于最后的像素显示,其他的都是用来辅助fragment的处理。
1、各种Buffer及其用途
具体的OpenGL实现决定了哪些buffer可用,每个buffer的bit深度。可以调用glGetIntegerv()来查询bit数。
ColorBuffers
支持立体视觉的OpenGL有left color buffer和right color buffer,否则的话只有left color buffer。支持double-buffer的时候,前面的两个buffer又会分出front buffer和back buffer,否则是有front buffer。OpenGL还有一些不用于显示的color buffer,叫做auxiliary color buffer,这些buffer的作用OpenGL并没有指定,而是由用户决定,比如可以用来存储一副反复使用的图像。
Depth Buffer
Depth Buffer存储fragment的深度,即离视点的距离。Depth Buffer也叫Z buffer。
Stencil Buffer
stencil buffer可以将绘图限制到屏幕的规定部分,比如透过窗户的场景。
Accumulation Buffer
Accumulation Buffer存储的也是颜色值,这个buffer累积一些列的图像,得到一个最终图像,可用于super sampling antialiasing。
2、Buffer 操作
清除buffer
可以通过下面的api来设置各buffer的清除值:void glClearColor,void glClearDepth(GLclampd depth),void glClearStencil(GLint s),void glClearAccum(GLfloat red, GLfloat green, GLfloat blue,GLfloat alpha);可以通过glClear来一次清除一个或多个buffer。
选择读写的目标color buffer
从上节可以,color buffer包括若干个buffer,通过glDrawBuffer()和glReadBuffer()可以选择目标buffer,
buffer遮罩
可以给buffer设置一个遮罩,数据被写入buffer前,会与遮罩做bit-wise AND计算。
glColorMask(),glDepthMask(),glStencilMask(),glStencilMaskSeparate()。
3、fragment测试与计算
当OpenGl对一个图元进行各类变换、光栅化得到fragment之后,还需要一些列的计算才能决定fragment是否需要、如何进入到frame buffer。
首先要经过一些列的测试:
Scissor Test
Scissor定义窗口中一块矩形区域,绘图被限制在这个矩形区域内。glScissor(GLint x, GLint y, GLsizei width, GLsizei height)。
scissor可以说是简化版的stencil,速度更加快。
Alpha Test
alpha测试基于fragment的alpha值来决定是否抛弃fragment,这个测试具体来说是通过与一个特定的值进行比较,比较操作和参考值由api glAlphaFunc(GLenum func, GLclampf ref)指定。
Stencil Test
将stencil buffer中的值与一个参考值进行比较,依据比较结果来决定是否接受fragment,同是决定是否修改stencil buffer的值。
Depth Test
比较fragment的深度和当前depth buffer里面的值,如果大于则fragment被抛弃,否则depth buffer里面的值被替换。可以通过glDepthFunc(GLenum func)来设定比较函数。
Blending, Dithering, and Logical 运算
blending操作依据输入fragment的alhpa值和frame buffer中对应fragment的alpha来进行混合。
logical元算对输framgment和frame buffer中的值进行一次逻辑元素结合,glLogicOp()可以指定运算类型。
4、frame buffer object
除了使用窗口系统固有的frame buffer外,可以创建frame buffer object,用于off-screen rendering。frame buffer object类似一种特殊的buffer object。
通过glGenFramebuffers来生成object 名字,glBindFramebuffer绑定FBO,并初始化,glDeleteFramebuffers删除FBO。
glBindFramebuffer(GLenum target, GLuint framebuffer); target=GL_DRAW_FRAMEBUFFER指定写入用途FBO,GL_READ_FRAMEBUFFER指定读取用途FBO,GL_FRAMEBUFFER指定两者。
FBO创建后,还不能绘图,必须为FBO提供绘图的目标buffer,也即Render Buffer Object。
Renderbuffer包含具体的图像数据,glGenRenderbuffers产生object名字,glBindRenderbuffer绑定名字到RenderBuffer,glRenderbufferStorage为rander buffer分配存储空间。
现在讲RenderBuffer attach到FBO上,glFramebufferRenderbuffer(GLenum target, GLenum attachment,GLenum renderbuffertarget, GLuint renderbuffer);target与glBindFramebuffer一致,attachment=GL_COLOR_ATTACHMENTi, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT, or GL_DEPTH_STENCIL_
ATTACHMENT,renderbuffertarget=GL_RENDERBUFFER,renderbuffer=RenderBuffer名字。
利用FBO可以创建出动态的texture,glFramebufferTexture*D可以绑定texture到FBO。
FBO配置完成以后,有可能是不可用的,glCheckFramebufferStatus检测FBO并给出错误建议。