2016-09-06 81 views
1

我想呈现给FBO,然后在OpenGL/LWJGL中进行屏幕显示,并得到奇怪的结果。渲染到FBO,采样失败

如果直接渲染到帧缓冲区我的现场工作得很好,看起来像这样:

1

但是当我渲染到FBO,然后到一到四的默认帧缓冲区,我得到这个:

2

貌似所有的图像中的颜色以单一颜色取平均值,就好像屏幕已被清除。

我的猜测是,quad上的纹理采样有问题,但我无法弄清楚。

显然,四分之四是因为我看到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); 

我这是怎么绑定那些由维也纳:

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(); present();

有了这些功能:

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

至少有一个错误发生在 #version 400核心 in vec2 vertex_position; 实际上是一个vec3。改变这个想法并没有改善结果。 – Djindjidj

回答

1

得到了解决。 着色器中的纹理坐标被称为in vec2 vertex_texCoords;

我引用他们作为GL20.glBindAttribLocation(id, 3, "vertex_texCoord");

更改,要GL20.glBindAttribLocation(id, 3, "vertex_texCoords");做的工作。

+1

只是一个小提示,以减少发生此错误的可能性,如果您有[显式位置](https://www.opengl.org/registry/specs/ARB/explicit_attrib_location.txt),只需声明'layout(location = TEX_COORD)在vec2 vertex_texCoords;'中。在顶部写上'#define TEX_COORD 3'并在你的java代码中使用'final int TEX_COORD 2'来引用 – elect

1

首先,

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

enableVertexAttribArray应该在功能初始化VAO,而不是在渲染循环过程中)。按照这种方式,disableVertexAttribArray是“无用的”。其次,由于直接状态访问是OpenGL核心的一部分,所以对于“绑定到工作”我并不方便。 但是,我可以看到2个最终警告(即使我对此不太确定)

您将“内部格式”GL_RGB给予glTexImage2D,如果我是你,我会使用GL_RGB8。 (我知道使用glTexStorage时GL_RGB不正确,但也许可以将它与GLTexImage2D一起使用,启用arb调试输出以了解是否有错误)。

您在将纹理发送到frameBuffer之前解除绑定(阅读文档后,应该可以)。

您正在创建从未使用的“pixelBuffer”。

最后,我有很多使用深度和模板缓冲区的问题,特别是当我使用renderBuffer时。 我建议你切换到纹理而不是renderBuffer,并开始使用没有模板的depthTexture来“调试”你的程序。

编辑:由于Djindjidj写道,你不尊重VEC 2/VEC3在你的shader

+0

感谢您花时间。我解决了这个问题。 你还提到了一些我想问的问题: 你的意思是“enableVertexAttribArray应该在初始化VAO的函数中,而不是在渲染过程中”。 我认为你必须绑定vao,然后在渲染期间启用vao的vbos?如果我有不同数量的vbos vaos,那我该如何处理呢? – Djindjidj

+0

我还没有真正进入opengl的自定义纹理初始化。我实际上是从教程中复制粘贴了该部分。到现在为止,我使用了光滑的TextureLoader。我计划在解决这个问题后进入自定义纹理处理阶段,然后我一定会检查你提到的有关GL_RGB和GL_RGB8的内容。 – Djindjidj

+0

Aaand我已经删除了这些pixelBuffer行。我用它们来初始化texture2d对象,因为我不能用“null”来做到这一点,直到我发现我必须转换为特定的缓冲区类型。 – Djindjidj