天天看点

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

   片段操作图

  

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

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

  Buffers(缓冲)

  OpenGL ES支持三种缓冲:

  OpenGL ES

  •• Color buffer颜色缓冲

  •• Depth buffer深度缓冲

  •• Stencil buffer模板缓冲

  创建缓冲区

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

OpenGL ES 3.0之Fragment buffer objects(FBO)详解(一)
你可能不要求清除每一个缓冲区,不在同时清除它们。但如果你想同时清除所有的缓冲区,只调用一次glClear 可以获得更好的性能。
OpenGL ES 3.0之Fragment buffer objects(FBO)详解(一)
OpenGL ES 3.0之Fragment buffer objects(FBO)详解(一)
OpenGL ES 3.0之Fragment buffer objects(FBO)详解(一)
 如果你的帧缓冲区中有多个绘制缓冲,你也可以清除指定的缓冲区,如下:
OpenGL ES 3.0之Fragment buffer objects(FBO)详解(一)
  为减少调用函数的次数,你可以同时清除深度和模板缓冲区内容,如下:
OpenGL ES 3.0之Fragment buffer objects(FBO)详解(一)

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

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

OpenGL ES 3.0之Fragment buffer objects(FBO)详解(一)
OpenGL ES 3.0之Fragment buffer objects(FBO)详解(一)
OpenGL ES 3.0之Fragment buffer objects(FBO)详解(一)
  读取和写入像素到帧缓冲区
OpenGL ES 3.0之Fragment buffer objects(FBO)详解(一)
OpenGL ES 3.0之Fragment buffer objects(FBO)详解(一)

  多渲染目标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)

OpenGL ES 3.0之Fragment buffer objects(FBO)详解(一)
例如你可以使用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 );
}      

继续阅读