opengles2.0 帧缓存对象(FBO)

来源:互联网 发布:金点子炒股软件下载 编辑:程序博客网 时间:2024/06/05 08:46

帧缓存对象(fbo)主要是用于做渲染到纹理。


opengles2.0渲染到纹理的方法有三种:

    第一,使用glCopyTexImage2D或者glCopyTexSubImage2D,这两个函数,复制framebuffer中的

        像素到纹理缓存里面,但这两个函数性能比较低下,并且要求纹理的尺寸必须小于等于

        framebuffer的尺寸。

    第二,使用一个附加到纹理的pbuffer,来执行渲染到纹理的操作。我们知道,窗口系统为我们提供

        的surface必须添加到一个渲染环境里面,但是,在某些平台上要求每个pbuffer和窗口系统提供

        的surface都需要一个单独的context,所以如果要渲染到pbuffer里面的话,就会发生context的切换,

        这种切换操作时很耗时的。


    第三,使用fbo,rbo等,这种是最高效的。




Framebuffer和Renderbuffer Object(fbo和rbo):

    
    rbo是一块2D图像缓存,能够用于存储color,depth,stencil值,也就是可以作为

    fbo的color或depth或stencil attachment。但是这个rbo不能直接作为纹理使用。


    fbo是一个容器,他有三个attachment 点:颜色缓存,深度缓存,和模板缓存的attachment 点。
    
    还保存着,添加到这些attachment点上的颜色缓存,深度缓存,模板缓存的大小、格式等属性,

    以及添加进来的纹理和rbo的名字等等。

    颜色缓存attachment点,可以添加纹理或rbo。

    深度缓存attachment点,可以添加纹理或rbo。

    模板缓存attachment点,只能添加rbo。


    GL_OES_texture_3D 这个扩展允许3D纹理的2D切添加到attachment点。

    GL_OES_depth_texture 这个扩展允许2D深度纹理,和立方体深度纹理。

    GL_OES_packed_depth_stencil 这个扩展允许packed depth stencil texture。

    fbo还有一个:Framebuffer completeness status,这个状态表明本fbo是否可以用来接受渲染结果。


    注意:添加到一个fbo中attachment点的各个rbo或纹理才尺寸必须一致。


    rbo的创建:

    glGenRenderbuffers    //得到一堆没有使用的rbo的名字
    glDeleteRenderbuffers    //删除rbo

    glBindRenderbuffer    //生成rbo,可以不调用glGenRenderbuffers生成未使用的rbo名字,
                //但不推荐这么做。

    glRenderbufferStorage(GLenum target,GLenum internalformat,
        GLsizei width, GLsizei height)
        //指定rbo的格式,申请存储空间。
        //可以在rbo添加到fbo的绑定点之前或者之后调用这个函数
        //但必须在使用fbo接受渲染结果之前调用这个函数。

    GLint maxRenderbufferSize;
    glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &maxRenderbufferSize);//得到可以的最大的rbo大小。

    fbo创建:

    glGenFramebuffers
    glDeleteFramebuffers

    glBindFrameBuffer     一绑定fbo,这个fbo就作为渲染环境的当前 fbo来使用了,也就是    
                会渲染到这个fbo了。

    glFramebufferRenderbuffer();
    glFramebufferTexture2D();

    如果一张纹理被添加到fbo,但在渲染的时候,这个纹理又被某个模型使用,

    这样是会导致glDrawElement,glDrawArray失败。所以要注意避免这种情况。

    检测fbo的完整性:

        GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
        返回值:
            GL_FRAMEBUFFER_COMPLETE

            GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 某个必要的attachment点绑定了无效的纹理或rbo

            GL_FRAMEBUFFER_MISSING_ATTACHMENT  所有的attachment point都是0

            GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 各个attachment之间的尺寸不匹配

            GL_FRAMEBUFFER_INCOMPLETE_FORMATS  某个attachment的Internal format不能用于渲染。

            GL_FRAMEBUFFER_UNSUPPORTED  三个attachment的组合的结果internal formats是不可渲染的。


    窗口系统的surface可以支持多重采样,可以有多重采样缓存。fbo不支持多重采样缓存attachment。




关于提升渲染性能的建议:

    频繁的在自己创建的fbo和窗口系统创建的vbo之间切换,比较影响性能。

    不要在每一帧都去创建,销毁fbo,vbo对象。要一次创建多次使用。

    如果一个纹理attach到一个fbo的attachment point,就要尽量避免调用glTexImage2D或glTexSubImage2D
    
        glCopyTexImage2D等去修改纹理的值。

   
0 1