• OpenGL ES 3.0之Fragment buffer objects(FBO)详解 (转)


    http://www.cnblogs.com/salam/p/4957250.html

    片段操作图

      

      这篇文章将介绍从写入帧缓冲和读取帧缓冲的方式。

      Buffers(缓冲)

      OpenGL ES支持三种缓冲:

      OpenGL ES

      •• Color buffer颜色缓冲

      •• Depth buffer深度缓冲

      •• Stencil buffer模板缓冲

      创建缓冲区

      OpenGL ES 是一个交互式的渲染系统,假设每帧的开始,你希望初始化所有缓冲区中数据的默认值。调用glClear 函数来清除缓冲区内容,参数mask 指定清除的缓冲区。

      

    你可能不要求清除每一个缓冲区,不在同时清除它们。但如果你想同时清除所有的缓冲区,只调用一次glClear 可以获得更好的性能。

      

      

      

     如果你的帧缓冲区中有多个绘制缓冲,你也可以清除指定的缓冲区,如下:

      

      为减少调用函数的次数,你可以同时清除深度和模板缓冲区内容,如下:

      

      使用掩码来控制写入缓冲区

      一般你可以控制对缓冲区的操作,哪部分可以写,哪部分不可写。在颜色缓冲区中,glColorMask 指定颜色缓冲区的组成里那部分可被更新。如果mask 被设为GL_FALSE,这个组成部分不能更新,默认值是GL_TRUE。对于深度同样

      

      

      

      

      读取和写入像素到帧缓冲区

      

      

      

      多渲染目标MRTs

      MRTs允许应用程序同时渲染多个颜色缓冲区。下面是流程

      1.创建帧缓冲对象framebuffer objects,使用

      glGenFramebuffers ( 1, &fbo );创建帧缓冲对象
      glBindFramebuffer ( GL_FRAMEBUFFER, fbo );绑定为当前使用的帧缓冲对象。

      

      2.创建纹理对象

      glGenTextures(4,textureId);创建

      glBindTexture ( GL_TEXTURE_2D, textureId );绑定
      glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGBA,
              textureWidth, textureHeight,
      0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
      // Set the filtering mode
      glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
      GL_NEAREST );
      glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
    GL_NEAREST );

      

      3.帧缓冲对象绑定相关的纹理。

      glFramebufferTexture2D ( GL_DRAW_FRAMEBUFFER,
                   GL_COLOR_ATTACHMENT0,
                   GL_TEXTURE_2D,
                   textureId, 0 );

      

       4.指定渲染的附加颜色

      glDrawBuffers(GLsizei n, const GLenum* bufs)

      

    例如你可以使用4种颜色输出建立一个FBO对象

      const GLenum attachments[4] = { GL_COLOR_ATTACHMENT0,

                        GL_COLOR_ATTACHMENT1,

                        GL_COLOR_ATTACHMENT2,

                        GL_COLOR_ATTACHMENT3 };

    glDrawBuffers ( 4, attachments );

     

    通过GL_MAX_COLOR_ATTACHMENTS你可以查询支持最多的颜色数,支持最小的数目是4.

    5.声明和使用着色器的输出

    layout(location = 0) out vec4 fragData0;
    layout(location = 1) out vec4 fragData1;
    layout(location = 2) out vec4 fragData2;
    layout(location = 3) out vec4 fragData3;

     

     

    完整代码  

     

     
    int InitFBO ( ESContext *esContext )
    {
       UserData *userData = esContext->userData;
       int i;
       GLint defaultFramebuffer = 0;
       const GLenum attachments[4] =
       {
          GL_COLOR_ATTACHMENT0,
          GL_COLOR_ATTACHMENT1,
          GL_COLOR_ATTACHMENT2,
          GL_COLOR_ATTACHMENT3
       };

       glGetIntegerv ( GL_FRAMEBUFFER_BINDING, &defaultFramebuffer );

       // Setup fbo
       glGenFramebuffers ( 1, &userData->fbo );
       glBindFramebuffer ( GL_FRAMEBUFFER, userData->fbo );

       // Setup four output buffers and attach to fbo
       userData->textureHeight = userData->textureWidth = 400;
       glGenTextures ( 4, &userData->colorTexId[0] );
       for (i = 0; i < 4; ++i)
       {
          glBindTexture ( GL_TEXTURE_2D, userData->colorTexId[i] );

          glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGBA,
                         userData->textureWidth, userData->textureHeight,
                         0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );

          // Set the filtering mode
          glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
          glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );

          glFramebufferTexture2D ( GL_DRAW_FRAMEBUFFER, attachments[i],
                                   GL_TEXTURE_2D, userData->colorTexId[i], 0 );
       }

       glDrawBuffers ( 4, attachments );

       if ( GL_FRAMEBUFFER_COMPLETE != glCheckFramebufferStatus ( GL_FRAMEBUFFER ) )
       {
          return FALSE;
       }

       // Restore the original framebuffer
       glBindFramebuffer ( GL_FRAMEBUFFER, defaultFramebuffer );

       return TRUE;
    }
     
    fsh代码
    #version 300 es
    precision mediump float;
    layout(location = 0) out vec4 fragData0;
    layout(location = 1) out vec4 fragData1;
    layout(location = 2) out vec4 fragData2;
    layout(location = 3) out vec4 fragData3;
    void main()
    {
        // first buffer will contain red color
        fragData0 = vec4 ( 1, 0, 0, 1 );
        // second buffer will contain green color
        fragData1 = vec4 ( 0, 1, 0, 1 );
        // third buffer will contain blue color
        fragData2 = vec4 ( 0, 0, 1, 1 );
        // fourth buffer will contain gray color
        fragData3 = vec4 ( 0.5, 0.5, 0.5, 1 );
    }
    我们可以使用帧缓冲对象来实现离屏渲染。帧缓冲对象支持下列操作

      1.只使用OpenGL ES 函数创建帧缓冲区对象。

      2.使用EGL context创建多个FBO。

      3.创建离屏颜色、深度、模板渲染缓冲区和纹理,把它们绑定到帧缓冲区对象上。

      4.通过多种缓冲区共享颜色、深度、模板缓冲区内容。

      5.把纹理作为颜色、深度直接关联到帧缓冲区,避免使用拷贝操作。

      6.FBO与无效FBO之间的复制。

      Framebuffer and Renderbuffer Objects帧缓冲对象与渲染缓冲对象

      渲染缓冲区对象是应用程序分配的2D图像缓冲区。渲染缓冲区被用来存储颜色、深度或模板值,能作为颜色、深度或模板关联到一个帧缓冲区对象。渲染缓冲区和操作系统提供的离屏的绘制窗口pbuffer 有很多相似的地方。渲染缓冲区不能直接被GL 作为纹理使用。

      FBO是一个颜色,深度和模板纹理或渲染目标的集合。各种2D 图像能被关联到帧缓冲区对象的颜色点上。

      

      创建FBO与RBO

       

      

      使用渲染缓冲区对象

      

    注意在使用glBindRenderbuffer 绑定缓冲区前,glGenRenderbuffers 不要求去分配渲染缓冲区对象名字。虽然调用glGenRenderbuffers 是一个好的习惯,那仍然有很多应用程序在编译时为它们的缓冲区指定常量。应用程序能指定一个不使用的渲染缓冲区对象名字去执行glBindRenderbuffer。我们建议使用glGenRenderbuffers 返回的名字替代应用程序自己指定缓冲区名字。

      一旦渲染缓冲区对象被绑定,我们能指定渲染缓冲区内的存储的图像的尺寸和格式

      

      使用FBO

      

      

     

     

     

  • 相关阅读:
    jenkins与gitlab集成,分支提交代码后自动构建任务(六)
    MySQL配置参数sync_binlog说明
    jenkins部署java项目(五)
    Mac OS X 中安装JDK 7
    centos 使用pip安装mysql-python
    CentOS6.4下安装TeamViewer8
    adb & adb shell 相关命令
    mac下限速
    mac 下 word 2011 使用笔记
    python twisted启动定时服务
  • 原文地址:https://www.cnblogs.com/mazhenyu/p/6549569.html
Copyright © 2020-2023  润新知