zoukankan      html  css  js  c++  java
  • OpenGL中FBO的概念及其应用 [转]

     http://www.cppblog.com/kongque/archive/2010/08/26/124754.html

    FBO一个最常见的应用就是:渲染到纹理(render to texture),通过这项技术可以实现发光效果,环境映射,阴影映射等很炫的效果。

    OpenGL中的Frame Buffer Object(FBO)扩展,被推荐用于把数据渲染到纹理对像。相对于其它同类技术,如数据拷贝或交换缓冲区等,使用FBO技术会更高效并且更容易实现。

    在 OpenGL渲染管线中,几何数据和纹理最终都是以2d像素绘制到屏幕上。最后一步的渲染目标在OpenGL渲染管线中被称为帧缓存(frame buffer)。帧缓存是颜色缓存、深度缓存、模板缓存、累积缓存的集合。默认情况下, OpenGL使用的帧缓存是由窗体系统创建和管理的。

    在 OpenGL扩展中,GL_EXT_framebuffer_object扩展提供了一个创建额外帧缓存对象(FBO)的接口。这个帧缓存的创建和控制完 全是由OpenGL完成的,有别于窗体系统创建的默认的帧缓存。与系统默认的帧缓存类似,一个FBO也是颜色缓存、深度缓存、模板缓存的集合(FBO不包 括累积缓存),然后OpenGL程序就可以把渲染重定向到FBO中。

    这里有一个新的概念需要注意,那就是renderbuffer object。这个对象是通过GL_EXT_framebuffer_object扩展创建。它被用来在渲染过程中为一个2D图像提供渲染目标。

    下 图展示了FBO和renderbuffer object与texture object之间的关系。从图中我们可以看出:多个renderbuffer object和texture object可以通过挂接点挂接到FBO上。需要主要的是FBO并没有实际存储数据的地方,它只是一个数据的壳,它只有挂接点。



    一 个FBO对象包含多个颜色挂接点和一个深度挂接点以及一个模板挂接点。不同的显卡支持的颜色挂接点的数目是不同的,可以通过查询 GL_MAX_COLOR_ATTACHMENTS_EXT获取支持的最大的挂接点的数目。支持多个颜色挂接点的原因是FBO可以在同一时间内将颜色缓存 渲染到多个目标中去,这种能力被称为MRT(multiple render targets)。通过GL_ARB_draw_buffers扩展可以实现该功能。

    帧缓冲提供了一种有效的切换机制,使得挂接和卸载一 个可挂接的图像非常之迅速。FBO使用glFramebufferTexture2DEXT()来进行texturebuffer对象的切换,使用 glFramebufferRenderbufferEXT()来进行renderbuffer对象的切换。

    让我们看一下其使用过程:
    1.FBO对象的创建与销毁
    void glGenFramebuffersEXT(GLsizei n, GLuint* ids);
    void glDeleteFramebuffersEXT(GLsizei n, const GLuint* ids);
    第一个参数是要创建的FBO的个数,第二个保存创建的FBO的ID。

    2.一旦FBO对象创建完毕,即要进行绑定
    void glBindFramebufferEXT(GLenum target, GLuint id);
    第一个参数必须是GL_FRAMEBUFFER_EXT
    第二个参数是第一步创建FBO对象中获取的id号,该id号是一个非0值,因为系统默认的FBO的id号是0,所以如果你想取消FBO的绑定,将id等于0作为id参数传递给该函数即可。

    3.创建Renderbuffer Object
    void glGenRenderbuffersEXT(GLsizei n, GLuint* ids);
    void glDeleteRenderbuffersEXT(GLsizei n, const GLuint* ids);

    4.同样的,Renderbuffer Object创建好之后,要记得绑定。
    void glBindRenderbufferEXT(GLenum target, GLuint id)

    5.确定Renderbuffer Object的数据格式和尺寸。
      这一步很重要,因为我们只是创建了Renderbuffer Object,还没有为它提供一个存储数据的地方,也没有指定其存储数据的地方存储什么格式的数据,所以接下来就要做这个事情了。
    void glRenderbufferStorageEXT(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height);
    第一个参数必须是GL_RENDERBUFFER_EXT
    第二个参数可以是可渲染的颜色格式,如(GL_RGB, GL_RGBA, etc.),可渲染的深度格式(GL_DEPTH_COMPONENT)或者是可渲染的模板格式(GL_STENCIL_INDEX)。
    最后两个参数就是以像素为单位指定数据所要占用内存的大小。

    这里需要注意两点:
    1。 指定的内存区域的宽和高应该都小于GL_MAX_RENDERBUFFER_SIZE_EXT,否则将产生GL_INVALID_VALUE错误。
    2。 所有的texture object也好,renderbuffer object也好,其宽和高都是严格一致的。

    6.指定挂接的对象
    glFramebufferTexture2DEXT函数挂接一个texture图像到FBO
    glFramebufferRenderbufferEXT函数挂接一个Renderbuffer图像到FBO

    7.检测FBO状态
    该挂接的对象都挂接好了,在使用FBO之前,必须要检查FBO的状态是否处于完成状态。如果FBO处于未完成状态,那么绘制操作就会失败。如何获取FBO的完成状态呢?使用
    glCheckFramebufferStatusEXT函数。

    至此,关于FBO的概念及其使用就算告一段落了。下面给出一个完整的例子,该例子是从国外一个网站上找到的,代码写得简单而漂亮,对FBO的演示也很完善。

    FBO Demo

  • 相关阅读:
    基于requirejs和oclazyloadjs的实际按需加载的angular项目
    vue源码解析data与watcher
    video标签播放数据调整
    ngnix搭建前端服务
    面试总结篇(一)
    mongodb的安装、配置、启动、数据库密码的配置;
    今天随手写个发布订阅的 event.js
    Mac OS系统使用的链接,以及关于前端软件的安装(持续更新)
    bind 以及原型 1px边框的实现(面试后内容整理)
    flexbox的学习,display:flex display:box 淘宝触屏版、饿了么网布局分析分析
  • 原文地址:https://www.cnblogs.com/mazhenyu/p/5048157.html
Copyright © 2011-2022 走看看