Reputation: 133
I am trying to render to FBO and then to screen in OpenGL / LWJGL and I get weird results.
My scene if rendered directly to the framebuffer works just fine and looks like this:
But when I render to the FBO and then to that one to a quad on the default framebuffer, I get this:
Looks like all the colors in the image got averaged in a single color and as if the screen was cleared with that one.
My guess is, that there's something wrong with the sampling of the texture on the quad but I cannot figure it out.
The quad obviously IS there as I see the edges with glPolymode - GL_LINE. Also, the single color on the quad changes when I move the ingame camera and somehow also reflects the most prominent color on screen. So maybe you can point me to the probably obvious solution? I will put some code that i think is relevant at the end of this post.
This is how I set up my squad's vertices and uv coordinates. I use the same method and parent classes for the cubes, so i know this works:
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);
This is how i bind those to the 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();
This is how i bind the attribute locations in the shader for the quad:
protected void bindAttributes(){
GL20.glBindAttribLocation(id, 0, "vertex_position");
GL20.glBindAttribLocation(id, 3, "vertex_texCoord");
}
This is how i render the screen quad:
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);
This is my vertex and fragment shader: Vertex:
#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;
}
Fragment:
#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);
}
Finally, this is my rendering procedure: prepare(); drawScene(); present();
With those functions:
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);
}
Edit: Maybe i should add how i set up the 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);
}
Upvotes: 1
Views: 420
Reputation: 133
Got the solution.
The texture coordinates in the shader are called in vec2 vertex_texCoords;
I referenced them as GL20.glBindAttribLocation(id, 3, "vertex_texCoord");
Changing that to GL20.glBindAttribLocation(id, 3, "vertex_texCoords");
did the job.
Upvotes: 1
Reputation: 4078
First,
GL30.glBindVertexArray(screenQuad.getMesh(0).getVaoID());
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(3);
enableVertexAttribArray should be in the function which initialize the VAO, and not during the rendering loop ;). Going that way, disableVertexAttribArray is "useless".
Secondly, I am not really convenient with "binding to work" since direct state access is a part of OpenGL core. But, I can see 2 eventuals caveat (even if I am not pretty sure about it)
You are giving the "internal format" GL_RGB to glTexImage2D, if I were you I would use GL_RGB8. (I know GL_RGB is not correct using glTexStorage, but maybe it is possible to use it with GLTexImage2D, enable arb debug output to know if there is an error or not).
You unbind the texture before sending it to frameBuffer (after reading the doc, it should be ok).
You are creating "pixelBuffer" which is never used.
Finally, I had a lot of issues using Depth and Stencil buffer, especially when I was using renderBuffer. I advice you to switch to texture instead of renderBuffer and begin to "debug" your program using only a depthTexture without stencil.
EDIT : As Djindjidj wrote, you did not respect vec2 / vec3 in your shader
Upvotes: 1