1

我是新来的,而且是 OpenGL ES 2.0 for 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 进行任何修改......相反,我得到了一个黑屏。我在绑定纹理时显然在这里做错了,但我不清楚纹理之间的乒乓球应该如何工作。我做了很多谷歌搜索,在任何地方都找不到任何明确的例子。因此,如果有人可以在这里帮助我,那就太好了,因为我已经为此烦恼了很长时间。谢谢。

顺便说一句,如果您需要更多详细信息,请告诉我。

4

1 回答 1

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。您需要确保glClear()在 FBO 绑定后您有电话。

  • 我认为这个调用首先需要一个纹理绑定。还要确保你有正确的活动纹理单元:

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

    您可能不想在每次重绘时从位图加载纹理。您应该能够在安装过程中加载一次。

  • generate()您在每次重绘时调用该方法。那里的大部分内容只需要在设置期间完成一次。

  • 不保证 ES 2.0 中的GL_REPEAT非二次幂纹理支持环绕模式。除非您的宽度和高度是 2 的幂,否则您可能希望使用GL_CLAMP_TO_EDGE它来确定它适用于所有设备。

于 2014-12-27T21:52:00.483 回答