OpenGL系列教程之十:OpenGL帧缓冲区对象(FBO)
来源:互联网 发布:软件管家 编辑:程序博客网 时间:2024/05/17 16:44
相关主题:像素缓冲区对象(PBO)
下载: fbo.zip, fboDepth.zip, fboStencil.zip
- 概述
- 创建FBO
- 渲染缓冲区对象
- 附加镜像到FBO
- 检查FBO的状态
- 例子:渲染到纹理
glGenFramebuffers()
void glGenFramebuffers(GLsizei n, GLuint* ids)void glDeleteFramebuffers(GLsizei n, const GLuint* ids)
glBindFramebuffer()
void glBindFramebuffer(GLenum target, GLuint id)
void glGenRenderbuffers(GLsizei n, GLuint* ids)void glDeleteRenderbuffers(GLsizei n, const Gluint* ids)
void glRenderbufferStorage(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height)
当一个渲染缓冲区对象被创建以后,它不包含任何的数据存储区,因此我们必须为它分配空间。这可以使用glRenderbufferStorage()来实现。第一个参数必须是GL_RENDERBUFFER。第二个参数可以是渲染颜色(GL_RGB,GL_RGBA,等),渲染深度(GL_DEPTH_COMPONENT),或者渲染模板格式(GL_STENCIL_INDEX)。width和height是渲染缓冲区镜像的尺寸(以像素为单位)。
void glGetRenderbufferParameteriv(GLenum target, GLenum param, GLint* value)
GL_RENDERBUFFER_WIDTHGL_RENDERBUFFER_HEIGHTGL_RENDERBUFFER_INTERNAL_FORMATGL_RENDERBUFFER_RED_SIZEGL_RENDERBUFFER_GREEN_SIZEGL_RENDERBUFFER_BLUE_SIZEGL_RENDERBUFFER_ALPHA_SIZEGL_RENDERBUFFER_DEPTH_SIZEGL_RENDERBUFFER_STENCIL_SIZE
附加镜像到FBO
glFramebufferTexture2D(GLenum target, GLenum attachmentPoint, GLenum textureTarget, GLuint textureId, GLint level)
void glFramebufferRenderbuffer(GLenum target, GLenum attachmentPoint, GLenum renderbufferTarget, GLuint renderbufferId)
GLenum glCheckFramebufferStatus(GLenum target)
glCheckFramebufferStatus()检查附加到当前被绑定的FBO的镜像和帧缓冲的参数。并且这个函数不能在glBegin()和glEnd()之间。target参数必须是GL_FRAMEBUFFER。检查完FBO后会返回一个非零的值。如果所有的条件和规则都满足,会返回GL_FRAMEBUFFER_COMPLETE。否则,它返回一个有关的错误值,这个错误值会告诉违反了那条规则。
- 附加到帧缓冲区镜像的width和height必须是非零的。
- 如果一个镜像被附加到颜色附加点,那么这个镜像必须有一个可渲染颜色(color-renderable)的内部格式。(GL_RGBA,GL_DEPTH_COMPONENT,GL_LUMINANCE等)
- 如果一个镜像被附加到GL_DEPTH_ATTACHMENT,那么这个镜像必须有可渲染深度(depth-renderable)的内部格式。(GL_DEPTH_COMONENT,GL_DEPTH_COPONENT24等)
- 如果一个镜像被附加到GL_STENCIL_ATTACHMENT,那么这个镜像必须有可渲染模板(stencil-renderable)的内部格式。(GL_STENCIL_INDEX,GL_STENCIL_INDEX8等)
- FBO必须至少有一个附加的镜像。
- 所有附加到FBO的镜像必须有相同的宽体和高度。
- 所有附加到颜色附加点的镜像必须有相同的内部格式。
注意即使上面所有的条件都满足,你的OpenGL驱动(GPU)可能不支持某些内部的格式或参数。如果某个特殊的实现不被OpenGL驱动支持,那么glCheckFramebufferStatus()会返回GL_FRAMEBUFFER_UNSUPPORTED。
sample code提供了一些工具函数来显示当前FBO的信息:printFramebufferInfo()和checkFramebufferStatus()。
例子:渲染到纹理
下载源文件和可执行文件:fbo.zip(更新:2012-07-08)
附加:
-只渲染到深度缓冲区: fboDepth.zip
-使用模板缓冲区渲染物体的轮廓: fboStencil.zip
-使用glBlitFramebuffer()在两个FBO中传输:fboBlit.zip
有时,你需要生成动态的纹理。最普遍的例子是生成镜像/反射的效果,动态的立方体/环境映射和阴影映射。动态的纹理可以使用渲染场景到纹理中来生成。一个传统的渲染到纹理的方法是按照正常的步骤绘制一个场景到帧缓冲区中,然后使用glCopyTexSubImage2D()将帧缓冲区中的镜像复制到纹理中。
使用FBO,我们可以直接将一个场景渲染到纹理中,因此我们完全不需要使用”窗口系统提供的“帧缓冲区。除此之外,我们还可以减少额外的数据复制(从帧缓冲区到纹理)。
这个例子程序使用用FBO和不用FBO两种方式执行了渲染到纹理的操作,并比较了它们的性能差异。除了性能方面的区别外,FBO还有另外一个优点,在传统的渲染到纹理的模式中如果纹理的分辨率比渲染窗口大,那么纹理中窗口区域之外的部分会被裁剪掉,然后使用FBO不会产生这种裁剪的问题。你可以创建一个比显示窗口大的可渲染的帧缓冲区镜像。
下面的代码在渲染操作开始之前设置了一个FBO和附加到帧缓冲区的镜像。注意不仅纹理镜像可以附加到FBO中,渲染缓冲区镜像(深度缓冲,模板缓冲)也可以被附加到FBO。我们不会实际使用深度缓冲,然而FBO需要它进行深度测试。如果我们不将深度缓冲附加到FBO中,那么渲染输出的结果会被破坏因为缺少了深度测试。如果在FBO渲染时需要模板测试,那么额外的模板缓冲需要附加到GL_STENCIL_ATTACHMENT附加点。
...// 创建一个纹理对象GLuint textureId;glGenTextures(1, &textureId);glBindTexture(GL_TEXTURE_2D, textureId);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // 自动贴图glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);glBindTexture(GL_TEXTURE_2D, 0);// 创建一个渲染缓冲区对象来存储深度信息GLuint rboId;glGenRenderbuffers(1, &rboId);glBindRenderbuffer(GL_RENDERBUFFER, rboId);glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, TEXTURE_WIDTH, TEXTURE_HEIGHT);glBindRenderbuffer(GL_RENDERBUFFER, 0);// 创建一个帧缓冲区对象GLuint fboId;glGenFramebuffers(1, &fboId);glBindFramebuffer(GL_FRAMEBUFFER, fboId);// 将纹理对象附加到FBO的颜色附加点上glFramebufferTexture2D(GL_FRAMEBUFFER, // 1. fbo target: GL_FRAMEBUFFER GL_COLOR_ATTACHMENT0, // 2. attachment point GL_TEXTURE_2D, // 3. tex target: GL_TEXTURE_2D textureId, // 4. tex ID 0); // 5. mipmap level: 0(base)// 将渲染缓冲区对象附加到FBO的深度附加点上glFramebufferRenderbuffer(GL_FRAMEBUFFER, // 1. fbo target: GL_FRAMEBUFFER GL_DEPTH_ATTACHMENT, // 2. attachment point GL_RENDERBUFFER, // 3. rbo target: GL_RENDERBUFFER rboId); // 4. rbo ID// 检查FBO的状态GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);if(status != GL_FRAMEBUFFER_COMPLETE) fboUsed = false;// 切换到窗口系统提供的帧缓冲区中glBindFramebuffer(GL_FRAMEBUFFER, 0);...
...// 设置FBO为渲染的目的地glBindFramebuffer(GL_FRAMEBUFFER, fboId);// 清除缓冲区glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// 直接绘制一个场景到纹理中draw();// 解除FBO的绑定glBindFramebuffer(GL_FRAMEBUFFER, 0);// 贴图生成// 注意:如果GL_GENERATE_MIPMAP被设置成 GL_TRUE, 那么glCopyTexSubImage2D()//会自动生成贴图. 然而, 附加到FBO的纹理需要使用glGenerateMipmap()来生成贴图glBindTexture(GL_TEXTURE_2D, textureId);glGenerateMipmap(GL_TEXTURE_2D);glBindTexture(GL_TEXTURE_2D, 0);...
注意为了在修改纹理镜像的基础级别后显示地生成贴图glGenerateMipmap()也被当做FBO的扩展。如果GL_GENERATE_MIPMAP被设置为GL_TRUE,那么glTex{Sub}Image2D()和glCopyTex{Sub}Image2D()会自动触发生成贴图(在OpenGL 1.4版本或更高的版本中)。然而,FBO当它的基础纹理被更改后不会自动生成它的贴图这是因为FBO不会调用glCopyTex{Sub}Image2D()来修改纹理。因此,glGenerateMipmap()必须被显示地调用。
如果你需要快速地出来纹理,可以联合像素缓冲区对象(PBO)一起修改纹理。
- OpenGL系列教程之十:OpenGL帧缓冲区对象(FBO)
- OpenGL系列教程之十:OpenGL帧缓冲区对象(FBO)
- OpenGL系列教程之十:OpenGL帧缓冲区对象(FBO)
- OpenGL缓冲区对象之FBO
- OpenGL缓冲区对象之FBO
- 【OpenGL ES】帧缓冲区对象FBO
- OpenGL系列教程之八:OpenGL顶点缓冲区对象(VBO)
- OpenGL系列教程之九:OpenGL像素缓冲区对象(PBO)
- OpenGL系列教程之八:OpenGL顶点缓冲区对象(VBO)
- OpenGL系列教程之九:OpenGL像素缓冲区对象(PBO)
- OpenGL ES 学习教程(十四) 帧缓冲区对象(FBO) 实现渲染到纹理(Render To Texture/RTT)
- WebGL之旅(二十) 帧缓冲区对象FBO
- OpenGL FBO 对象
- OpenGL FBO 对象
- Opengl中的FBO对象
- OpenGL帧缓存对象(FBO)
- OpenGL帧缓冲区多线(FBO)基本概念
- [OpenGL 超级宝典][笔记] 8.2 帧缓冲区(FBO)
- OpenGL系列教程之六:OpenGL顶点数组
- OpenGL系列教程之七:OpenGL显示列表
- 安装zencart出现curl问题的终极解决方法
- OpenGL系列教程之八:OpenGL顶点缓冲区对象(VBO)
- OpenGL系列教程之九:OpenGL像素缓冲区对象(PBO)
- OpenGL系列教程之十:OpenGL帧缓冲区对象(FBO)
- 【代码】php yaf和PEAR代码命名规范
- OpenGL系列教程之十一:OpenGL网格化
- OpenGL系列教程之十二:OpenGL Windows图形界面应用程序
- JS只能输入数字,数字和字母等的正则表达式
- 解决xmlSpy破解后,联网问题
- 分享:VS2005附加到进程后无法调试,找不到符号的终极解决办法
- adobe安装时计算机挂起解决办法
- E-R图转换为关系模式