1

FBO にレンダリングしてから OpenGL / LWJGL でスクリーンしようとしていますが、奇妙な結果が得られます。

フレームバッファに直接レンダリングされた場合、私のシーンは問題なく動作し、次のようになります。

1

しかし、FBO にレンダリングしてから、デフォルトのフレームバッファのクワッドにレンダリングすると、次のようになります。

2

画像内のすべての色が単一の色で平均化され、画面がその色でクリアされたように見えます。

私の推測では、クワッドのテクスチャのサンプリングに何か問題があると思いますが、それを理解することはできません。

glPolymode - GL_LINEでエッジを見ると、クワッドは明らかにそこにあります。また、ゲーム内カメラを動かすとクワッドの単一の色が変化し、どういうわけか画面上で最も目立つ色も反映されます. おそらく明白な解決策を教えていただけますか?この投稿の最後に、関連すると思われるコードをいくつか入れます。


これが、分隊の頂点と UV 座標を設定する方法です。キューブに同じメソッドと親クラスを使用しているので、これが機能することがわかります。

    vertices[0] = new Vertex(-1.0f,-1.0f,0.0f);
    vertices[0].setTexCoords(0.0f,0.0f);

    vertices[1] = new Vertex(-1.0f,1.0f,0.0f);
    vertices[1].setTexCoords(0.0f,1.0f);

    vertices[2] = new Vertex(1.0f,1.0f,0.0f);
    vertices[2].setTexCoords(1.0f,1.0f);

    vertices[3] = new Vertex(1.0f,-1.0f,0.0f);
    vertices[3].setTexCoords(1.0f,0.0f);

これは私がそれらをvbosにバインドする方法です:

    vaoID = GL30.glGenVertexArrays();
    GL30.glBindVertexArray(vaoID);
        //POSITION - LOCATION 0
        int vboID = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboID);

        FloatBuffer buffer = BufferUtils.createFloatBuffer(vertices.length*3);
        buffer.put(getPositions());
        buffer.flip();

        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
        GL20.glVertexAttribPointer(0,  3,  GL11.GL_FLOAT, false, 0,0);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);

        buffer.clear();

       //... some code for color and normal, going into VBO location 1 and 2


        //TEX COORDS - LOCATION 3
        vboID = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboID);

        buffer = BufferUtils.createFloatBuffer(vertices.length*2);
        buffer.put(getTexCoords());
        buffer.flip();

        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
        GL20.glVertexAttribPointer(3, 2,  GL11.GL_FLOAT, false, 0,0);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);

        buffer.clear();

これは、クワッドのシェーダーで属性の場所をバインドする方法です。

    protected void bindAttributes(){
       GL20.glBindAttribLocation(id, 0, "vertex_position");
       GL20.glBindAttribLocation(id, 3, "vertex_texCoord");
    }

これは私がスクリーンクワッドをレンダリングする方法です:

GL20.glUseProgram(presentShader.getProgramID());
    GL30.glBindVertexArray(screenQuad.getMesh(0).getVaoID());
    GL20.glEnableVertexAttribArray(0);
    GL20.glEnableVertexAttribArray(3);

    GL13.glActiveTexture(GL13.GL_TEXTURE0);
    //GL11.glBindTexture(GL11.GL_TEXTURE_2D, frameBufferTextureID);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, frameBufferTextureID);
    GL11.glDrawElements(GL11.GL_TRIANGLES, screenQuad.getMesh(0).getIndexCount(), GL11.GL_UNSIGNED_INT, 0);

    GL20.glDisableVertexAttribArray(3);
    GL20.glDisableVertexAttribArray(0);
    GL30.glBindVertexArray(0);
GL20.glUseProgram(0);

これは私の頂点とフラグメント シェーダーです: 頂点:

#version 400 core

in vec2 vertex_position;
in vec2 vertex_texCoords;

out vec2 pass_texCoords;

void main(){

    gl_Position =  vec4(vertex_position.x, vertex_position.y, 0.0f, 1.0f);
    pass_texCoords = vertex_texCoords;
}

断片:

#version 400 core

in vec2 pass_texCoords;

out vec4 fragment_color;

uniform sampler2D screenTexture;

void main(){
    fragment_color = texture(screenTexture, pass_texCoords);
    //fragment_color  = vec4(0.3,0.3,0.3,1.0);

}

最後に、これが私のレンダリング プロシージャです。drawScene(); 現在();

これらの機能を使用すると:

public void prepare(){
        //FBO aktivieren, alles danach wird auf FBO-Textur gerendert
        GL11.glClearColor(0.0f,0.0f,0.0f, 1.0f); 
        GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBufferID);
        GL11.glEnable(GL11.GL_DEPTH_TEST);
        GL11.glEnable(GL11.GL_STENCIL_TEST);
        GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE); 
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT |  GL11.GL_STENCIL_BUFFER_BIT);
    }

    public void present(){
        //Standard Framebuffer aktivieren
        GL11.glClearColor(1.0f,1.0f,1.0f, 1.0f);
        GL11.glDisable(GL11.GL_DEPTH_TEST);
        GL11.glDisable(GL11.GL_STENCIL_TEST);
        GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);


        GL20.glUseProgram(presentShader.getProgramID());
        GL30.glBindVertexArray(screenQuad.getMesh(0).getVaoID());
        GL20.glEnableVertexAttribArray(0);
        GL20.glEnableVertexAttribArray(3);

        GL13.glActiveTexture(GL13.GL_TEXTURE0);
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, frameBufferTextureID);
        GL11.glDrawElements(GL11.GL_TRIANGLES, screenQuad.getMesh(0).getIndexCount(), GL11.GL_UNSIGNED_INT, 0);

        GL20.glDisableVertexAttribArray(3);
        GL20.glDisableVertexAttribArray(0);
        GL30.glBindVertexArray(0);

        GL20.glUseProgram(0);
    }

編集:FBOの設定方法を追加する必要があるかもしれません:

private void linitializeFrameBuffer(int viewportWidth, int viewportHeight){
    //COLOR TEXTURE
    frameBufferID = GL30.glGenFramebuffers();
    GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBufferID); // GL_READ_FRAMEBUFFER, GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER

    frameBufferTextureID = GL11.glGenTextures();
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, frameBufferTextureID);   //GL_TEXTURE_1D, GL_TEXTURE2D, GL_TEXTURE3D
    FloatBuffer pixelBuffer;
    pixelBuffer = BufferUtils.createFloatBuffer(viewportWidth*viewportHeight*3);
    pixelBuffer.clear();
    GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, viewportWidth, viewportHeight, 0, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, (java.nio.ByteBuffer) null);     
    GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR );
    GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR );
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);

    //Attach the new Texture to the framebuffer
    GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, GL11.GL_TEXTURE_2D, frameBufferTextureID, 0);

    //DEPTH BUFFER
    depthBufferID = GL30.glGenRenderbuffers();
    GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, depthBufferID);
    GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL30.GL_DEPTH24_STENCIL8, viewportWidth, viewportHeight);
    GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, 0);

    //Attach the new renderbuffer to the framebuffer
    GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_STENCIL_ATTACHMENT, GL30.GL_RENDERBUFFER, depthBufferID);


    if(GL30.glCheckFramebufferStatus(GL30.GL_FRAMEBUFFER) != GL30.GL_FRAMEBUFFER_COMPLETE){
        System.out.println("ERROR::FRAMEBUFFER:: Framebuffer is not complete!");
    }
    GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0); 
}
4

2 に答える 2

1

初め、

GL30.glBindVertexArray(screenQuad.getMesh(0).getVaoID());
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(3);

enableVertexAttribArray は、レンダリング ループ中ではなく、VAO を初期化する関数内にある必要があります;)。その通り、disableVertexAttribArray は「役に立たない」。

第 2 に、状態への直接アクセスは OpenGL コアの一部であるため、「バインドして作業する」ことにはあまり便利ではありません。しかし、2 つの最終的な警告が表示されます (よくわからない場合でも)。

「内部フォーマット」GL_RGBをglTexImage2Dに与えています。私があなたなら、GL_RGB8を使用します。(glTexStorage を使用すると GL_RGB が正しくないことはわかっていますが、GLTexImage2D で使用することは可能かもしれません。arb デバッグ出力を有効にして、エラーがあるかどうかを確認してください)。

テクスチャを frameBuffer に送信する前にバインドを解除します (ドキュメントを読んだ後は問題ありません)。

使用されていない「pixelBuffer」を作成しています。

最後に、Depth および Stencil バッファを使用すると、特に renderBuffer を使用するときに多くの問題が発生しました。renderBuffer の代わりにテクスチャに切り替え、ステンシルなしで depthTexture のみを使用してプログラムの「デバッグ」を開始することをお勧めします。

EDIT:Djindjidjが書いたように、シェーダーでvec2 / vec3を尊重しませんでした

于 2016-09-06T12:05:52.280 に答える
1

解決策を得ました。シェーダのテクスチャ座標が呼び出されますin vec2 vertex_texCoords;

私はそれらを次のように参照しましたGL20.glBindAttribLocation(id, 3, "vertex_texCoord");

それを変更しGL20.glBindAttribLocation(id, 3, "vertex_texCoords"); て仕事をしました。

于 2016-09-06T12:08:29.660 に答える