天天看點

Android OpenGL ES 幀緩沖FBO

平時我們都是渲染到的預設的螢幕緩沖,通過swapbuffer來渲染到螢幕上,相對的我們可以同樣建立一個離屏的幀緩沖來渲染到紋理。

建立一個fbo
glGenFramebuffers(,&frame);
    glBindFramebuffer(GL_FRAMEBUFFER,frame);
           

fbo需要我們為他準備一個至少一個緩沖(顔色、深度或模闆緩沖),我們通常使用的是紋理附件

glGenTextures(,&textureFrame);
    glBindTexture(GL_TEXTURE_2D,textureFrame);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexImage2D(GL_TEXTURE_2D, , GL_RGBA, width, width, , GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,textureFrame,);
           

這裡我們選擇的是顔色緩沖,通過生成一個隻配置設定了控件的紋理對象,并沒有填充資料。

我們同樣可以為fbo添加渲染緩沖附件,這個緩沖是隻寫的,如果需要從緩沖中讀取資料,還是需要使用紋理。我們這裡使用渲染緩沖來作為fbo深度緩沖的附加。

glGenRenderbuffers(,&render);

    glBindRenderbuffer(GL_RENDERBUFFER,render);

    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, width);

   glBindFramebuffer(GL_FRAMEBUFFER,frame);
   glFramebufferRenderbuffer(GL_FRAMEBUFFER,
   GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,render);

           

以上的代碼需要注意,需要和紋理附加的緩沖寬高一緻。

使用fbo繪制到紋理

建立好了fbo之後的繪制流程就比較正常了

  1. 綁定fbo
  2. 正常繪制
  3. 解綁fbo
  4. 繪制fob綁定的紋理
//綁定生成的fbo
     picPreviewTexture->bindFrameBuffer();


    glViewport(_backingLeft, _backingTop, _backingWidth, _backingHeight);

    //設定一個顔色狀态
    glClearColor(, , , );
    //使能顔色狀态的值來清屏
    glClear(GL_COLOR_BUFFER_BIT);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glUseProgram(program);
    static const GLfloat _vertices[] = {-, ,//左上
                                        -, -,//左下
                                        , ,//右上
                                        , -//右下
    };
    //stride設定為0自動決定步長
    //設定定點緩存指針
    glVertexAttribPointer(ATTRIBUTE_VERTEX, , GL_FLOAT, GL_FALSE, , _vertices);
    glEnableVertexAttribArray(ATTRIBUTE_VERTEX);
    //注意位置颠倒
    static const GLfloat texCoords[] = {, , , , , , , };
    //設定紋理緩存指針,varying變量會被插值傳入片元着色器
    glVertexAttribPointer(ATTRIBUTE_TEXCOORD, , GL_FLOAT, , , texCoords);
    glEnableVertexAttribArray(ATTRIBUTE_TEXCOORD);
    //綁定紋理
    picPreviewTexture->bindTexture(uniformSampler);
    glDrawArrays(GL_TRIANGLE_STRIP, , );
    //切換回螢幕緩沖并繪制fbo之前綁定的空紋理
    glBindFramebuffer(GL_FRAMEBUFFER,);
    glClearColor(, , , ); // set clear color to white (not really necessery actually, since we won't be able to see behind the quad anyways)
    glClear(GL_COLOR_BUFFER_BIT);
    picPreviewTexture->bindTextureFrame(uniformSampler);
    glDrawArrays(GL_TRIANGLE_STRIP, , );
           

幀緩沖就說到這裡了,主要的作用可以從紋理中擷取對應的資料來進行後期處理,總的來說使用還是非常簡單。

源碼位址