2014-12-27 38 views
1

我在這裏是新手,並且對於android也是OpenGL ES 2.0的新手。我試圖做一些非常簡單的事情,但由於某些原因,我無法實現它的工作。 基本上我試圖使用一個幀緩衝區在片段着色器中做一些後處理工作,然後將其顯示在屏幕上。下面是我的片段着色器的簡化版本:OpenGL ES 2.0 - Android上的多通道/後處理器

precision mediump float; 

uniform sampler2D u_Texture0; 
uniform sampler2D u_Texture1; 
uniform float u_FirstPass; 
varying vec3 v_texCoord; 

float mytexture2D(sampler2D text0, vec2 coord) 
{ 
    vec4 pixelColor=texture2D(text0, coord.xy); 
    return pixelColor.r * 0.299 + pixelColor.g * 0.587 + pixelColor.b * 0.114; 
} 

void main() 
{  
    if(u_FirstPass==1.0) 
    { 
     gl_FragColor = vec4(0.0,0.0,mytexture2D(u_Texture0, v_texCoord.st),1.0); 
    } 
    else 
    { 
     gl_FragColor = texture2D(u_Texture1, v_texCoord.st); 
    } 
} 

我使用的FrameBufferObject類是:

package com.my.cameratesting; 

import android.opengl.GLES20; 

public class FrameBufferObject { 
    public int colorTexture; 
    private int frameBuffer; 
    private int depthRenderBuffer; 

    public FrameBufferObject(){ 

    } 

    public void generate(int w, int h){ 
      //Generate color texture 
      //------------------------- 
      int [] id = new int[1]; 
      GLES20.glGenTextures(1, id, 0); 
      colorTexture = id[0]; 
      GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, colorTexture); 
      GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT); 
      GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT); 
      GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); 
      GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); 
      GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, w, h, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null); 
      //------------------------- 

      // Generate frame buffer; 
      //------------------------- 
      GLES20.glGenFramebuffers(1, id, 0); 
      frameBuffer = id[0]; 
      GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBuffer); 
      //Attach 2D texture to this FBO 
      GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, colorTexture, 0); 
      //------------------------- 

      // Generate depth render buffer 
      //------------------------- 
      GLES20.glGenRenderbuffers(1, id, 0); 
      depthRenderBuffer = id[0]; 
      GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthRenderBuffer); 
      GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, w, h); 
      //------------------------- 

      //Attach depth buffer to FBO 
      GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER, depthRenderBuffer); 
      //------------------------- 
      //and now you can render to GL_TEXTURE_2D 
      //GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBuffer); 

      //GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 
    } 

    public void unbind(){ 
     GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 
    } 

    public void bind(){ 
     GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBuffer); 
    } 

    public int getTextureId(){ 
     return colorTexture; 
    } 

} 

最後:

@Override 
public void onDrawFrame(GL10 gl) { 

    GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1f); 
    GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT); 

    GLES20.glUseProgram(mProgramHandle); 
    GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);  

    GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 
    //fbo0 is properly instanciated in my onSurfaceCreated function 
    fbo0.generate(mWidth, mHeight); 
    fbo0.bind(); 

    GLES20.glUniform1i(mTextureUniformHandle0, 0); 
    GLES20.glUniform1f(mFirstPassUniformHandle,1); 
    checkFBOError(); 

    objects[0].draw(mProgramShader,mMVPMatrix); 

    fbo0.unbind(); 

    //***** THIS IS THE BIT THAT DOESNT WORK AS I WOULD LIKE IT TO*******/ 

    GLES20.glActiveTexture(GLES20.GL_TEXTURE1); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,fbo0.colorTexture); 
    GLES20.glUniform1i(mTextureUniformHandle1, 0); 
    GLES20.glUniform1f(mFirstPassUniformHandle,0); 

    objects[0].draw(mProgramShader,mMVPMatrix); 
} 

,所以我希望以後我的照片第一次傳球以藍色顯示 - 當我不使用任何幀緩衝器並且不打算第二次傳球時,這種傳球效果很好。現在,當我運行第二遍時,我期待着相同的輸出,因爲我沒有對我的u_Texture1做任何修改......相反,我得到一個黑屏。 我很明顯在綁定紋理時在這裏做了一些錯誤,但我不清楚這個紋理之間的乒乓球應該如何工作。我做了很多搜索,並且找不到任何明確的例子。所以如果有人能夠幫助我,這將是非常棒的,因爲我現在一直在用這個頭撞了很久。 THKS。

順便說一句,請讓我知道,如果你需要更多的細節。

+0

您確定您正確複製了代碼嗎?該着色器不會按照它的方式進行編譯。 – 2014-12-27 18:26:43

+0

感謝Reto Koradi,對不起,我的壞!第一遍應該調用mytexture2D,而第二遍應該調用texture2D ... 2次傳球后的最終結果應該是(或者至少這是我想要做的),與第一次傳球后相同,即:我的藍色的圖片。 我修正了着色器,因此對於那些熱衷於幫助我的人來說,它更加清晰。 – RogerLePatissier 2014-12-27 20:57:00

回答

0

它看起來像你不使用你第一遍所產生的紋理渲染時的第二關:

GLES20.glActiveTexture(GLES20.GL_TEXTURE1); 
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,fbo0.colorTexture); 
GLES20.glUniform1i(mTextureUniformHandle1, 0); 
GLES20.glUniform1f(mFirstPassUniformHandle,0); 

這結合了質感紋理單元1,但然後設置均勻,從而從紋理單元0。如果你想使用紋理單元1着色器樣品,設置統一的呼叫必須是:

GLES20.glUniform1i(mTextureUniformHandle1, 1); 

但是也有一些可能涉及一些事情:

  • 至少在這裏顯示的代碼中,你永遠不會清除FBO。在綁定FBO後,您需要確保您撥打glClear()

  • 我認爲這個調用需要首先綁定紋理。另外請確保您擁有正確的主動紋理單元:

    GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);  
    

    您可能不希望在每次重繪時從位圖加載紋理。您應該能夠在安裝過程中加載一次。

  • 您在每個重繪中調用generate()方法。在安裝過程中,大部分內容只需要完成一次。

  • GL_REPEAT換行模式不保證支持ES 2.0中非冪次冪紋理。除非你的寬度和高度是2的冪,否則你可能想要使用GL_CLAMP_TO_EDGE來確定它可以在所有設備上工作。

+0

感謝Reto Koradi。我已經改變了所有建議,並且在進行2次傳球時似乎有效。但現在我試圖做n通,它似乎並沒有工作?我已經在線程頂部相應地更新了初始代碼。任何與此有關的幫助將非常感謝,因爲我還沒有得知這裏可能有什麼錯誤的線索? – RogerLePatissier 2015-01-02 03:05:22

+0

請不要編輯問題以包含答案。這不是這個網站的工作原理。堆棧溢出不是一個論壇,它是問題和答案的存儲庫。如果你對這個問題做出重大修改,答案就會失效,從而破壞目的。 – 2015-01-02 03:13:15

+0

對不起,謝謝你爲我回滾。我想我必須創建另一個問題來揭露我現在的問題是什麼... – RogerLePatissier 2015-01-02 03:46:00