有两种类型的“帧缓存关联图像”:纹理图像(texture images)和渲染缓存图像(renderbuffer images)。如果纹理对象的图像数据关联到帧缓存,OpenGL执行的是“渲染到纹理”(render to texture)操作。如果渲染缓存的图像数据关联到帧缓存,OpenGL执行的是离线渲染(offscreen rendering)
void glGenframebuffers(GLsizei n, GLuint * ids);
第一个是要创建的帧缓存的数目,第二个是指向存储一个或者多个ID的变量或数组的指针。它返回未使用的FBO的ID。ID为0表示默认帧缓存,即window系统提供的帧缓存。当创建成功的时候,会在第二个参数 framebuffer 中生成 n 个之前没有使用过的 framebuffer objects 的 name。然后这些 name 会被标记为已使用。只创建FBO的name,bind之后才真正创建FBO
void glBindframebuffer(GLenum target, GLuint id);
第一个参数target应该是GL_frameBUFFER,第二个参数是FBO的ID号即framebuffer objects 的 name。id为0即默认的window提供的帧缓存,即解绑当前FBO。
新创建的 framebuffer object 是一个空间为 0,且初始状态为默认值的 framebuffer object,一个FBO有一个color attachment挂载点、一个depth attachment挂载点、一个stencil attachment挂载点。
同一时间一个 thread 的一 个 context 中只能有一个 framebuffer被使用,因此之后关于 framebuffer 的操作会直接操作
FBO可以通过调用glDeleteframebuffers()来删除GL_frameBUFFER ,而不会在使用 framebuffer object name 了
系统帧缓存和FBO区别为:FBO的attachment可以修改,FBO的buffer无法像framebuffer那样可以被swap到屏幕上,要先弄到framebuffer再swap,
渲染缓存对象(Renderbuffer Object)
另外,渲染缓存是为离线渲染而新引进的。它允许将一个场景直接渲染到一个渲染缓存对象中,而不是渲染到纹理对象中。渲染缓存对象是用于存储单幅图像的数据存储区域。该图像按照一种可渲染的内部格式存储。它用于存储没有相关纹理格式的OpenGL逻辑缓存,比如模板缓存或者深度缓存。
void glGenRenderbuffers(GLsizei n, GLuint * ids//renderbuffers);void glDeleteRenderbuffers(GLsizei n, const Gluint* ids//renderbuffers)
renderbuffer就是FBO上关联的一块buffer或texture
void glBindRenderbuffer(GLenum target, GLuint renderbuffer);
target参数应该是GL_RENDERBUFFER
新创建的 renderbuffer object 是一个空间为 0,格式为GL_RGBA4,red, green, blue, alpha, depth, and stencil的像素位均为0,且初始状态为默认值的 renderbuffer object,作为当前GPU使用的RBO
void glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
渲染缓存被创建,没有任何数据存储区域,用该函数分配空间
第一个参数必须是GL_RENDERBUFFER。第二个参数可以是用于颜色的(GL_RGB,GL_RGBA,etc.),用于深度的(GL_DEPTH_COMPONENT),或者是用于模板的格式(GL_STENCIL_INDEX)。因为RBO是将作为FBO的color/depth/stencil attachment。第三四个参数Width和height是渲染缓存图像的像素维度,即RBO的尺寸。width和height必须比GL_MAX_RENDERBUFFER_SIZE_EXT小
FBO本身没有图像存储区,必须帧缓存关联图像(纹理或渲染对象)关联到FBO。(一个纹理可以被关联到多个FBO上,图像存储区可以被多个FBO共享。)FBO的buffer可以是RBO,还可以是texture
void glframebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
把一幅纹理图像(texture)关联到一个FBO。
第一个参数一定是GL_frameBUFFER_,第二个参数是关联纹理图像的关联点,FBO的3个挂载点之一。一个帧缓冲区对象可以有多个颜色关联点(GL_COLOR_ATTACHMENT0, …, GL_COLOR_ATTACHMENTn),L_DEPTH_ATTACHMENT, 和GL_STENCIL_ATTACHMENT。第三个参数textureTarget在多数情况下是GL_TEXTURE_2D。第四个参数是纹理对象的ID号,(textureId被设置为0,那么纹理图像将会被从FBO分离)。最后一个参数是要被关联的纹理的mipmap等级
如果纹理对象在依然关联在FBO上时被删除,那么纹理对象将会自动从当前绑定FBO上分离。然而,如果它被关联到多个FBO上然后被删除,那么它将只被从绑定的FBO上分离,而不会被从其他非绑定的FBO上分离。
void glframebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
把渲染缓存对象关联到FBO
前两个参数和glframebufferTexture2D()一样。第三个参数只能是GL_RENDERBUFFER,最后一个参数是渲染缓存对象的ID号
GLenum glCheckframebufferStatus(GLenum target);
一旦关联图像(纹理和渲染缓存)被关联到FBO上,在执行FBO的操作前必须检查FBO的状态:完整或不完整。如果帧缓冲区状态是不完整的,那么任何绘制命令(glBegin(),glCopyTexImage2D()等等)都会失败
FBO完整性准则有:
(1)帧缓存关联图像的宽度和高度必须非零。
(2)如果一幅图像被关联到一个颜色关联点,那么这幅图像必须有颜色可渲染的内部格式(GL_RGBA, GL_DEPTH_COMPONENT, GL_LUMINANCE, etc)。
(3)如果一幅被图像关联到GL_DEPTH_ATTACHMENT,那么这幅图像必须有深度可渲染的内部格式(GL_DEPTH_COMPONENT,GL_DEPTH_COMPONENT24, etc)。
(4)如果一幅被图像关联到GL_STENCIL_ATTACHMENT,那么这幅图像必须有模板可渲染的内部格式(GL_STENCIL_INDEX,GL_STENCIL_INDEX8, etc)。
(5)FBO至少有一幅图像关联。
(6)被关联到FBO的缩影图像必须有相同的宽度和高度。
(7)被关联到颜色关联点上的所有图像必须有相同的内部格式。