1

私はここが初めてで、Android用のOpenGL ES 2.0もかなり初心者です。私は非常に単純なことをしようとしていますが、何らかの理由でそれを機能させることができません。基本的に、フレームバッファを使用してフラグメントシェーダで後処理作業を行い、それを画面に表示しようとしています。以下は、私のフラグメント シェーダーの簡略化されたバージョンです。

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);
}

したがって、最初のパスの後に写真が青で表示されることを期待していました-これは、フレームバッファーを使用せず、2番目のパスを実行するつもりがない場合にうまく機能します。2番目のパスを実行すると、u_Texture1に変更を加えていないため、同じ出力が期待されていました...代わりに、黒い画面が表示されます。テクスチャをバインドしている間、ここで明らかに何か間違ったことをしていますが、テクスチャ間のこのピンポンがどのように機能するかは明確ではありません。私は多くのグーグルを行いましたが、明示的な例はどこにも見つかりませんでした。ここで誰かが私を助けてくれたら、それは素晴らしいことです。私はこれでかなり長い間頭を悩ませてきました。ありがとう。

ところで、追加の詳細が必要な場合はお知らせください。

4

1 に答える 1

0

2 番目のパスをレンダリングするときに、最初のパスで作成したテクスチャを使用していないようです。

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()再描画のたびにメソッドを呼び出します。そこにあるもののほとんどは、セットアップ中に一度だけ実行する必要があります。

  • ラップ モードは、GL_REPEATES 2.0 の 2 の累乗でないテクスチャに対してサポートされる保証はありません。幅と高さが 2 のべき乗でない限り、GL_CLAMP_TO_EDGEすべてのデバイスで確実に動作するように使用することをお勧めします。

于 2014-12-27T21:52:00.483 に答える