LWJGL Forum

Programming => OpenGL => Topic started by: bogieman9876 on April 30, 2014, 18:28:53

Title: [SOLVED]Need help with FrameBuffer for post processing
Post by: bogieman9876 on April 30, 2014, 18:28:53
Hi, like the subject says, I need help with the FrameBuffer for post processing.

What happens is, everything runs, nothing renders, and then after updating the display it crashes.
No errors from glGetError, no errors from the shaders either.
I have a FrameBuffer class where it get's set up, I check for errors using glCheckFramebufferStatus, returns, no error.
I have a class called BufferQuad, basically the quadrilateral that the framebuffer texture get's rendered to. I'm pretty sure it's ok.
Ok, so part of the problem may have been caused by the BufferQuad, I instead loaded in a quad, same as how I load the game objects, no crash, now nothing renders.
The screen is just the background color.

So it must be in how I've tried to implement it.

Here's the main part of the render class:
Note: I'm using instancing as there will be a lot of objects, eventually, any criticisms on the code itself is appreciated.

public void update2(GameObject[] gameObject) {
              // Game Object includes location to vertex, texture data as well as matrix for location.
updateMatrices();

GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, getFrameBuffer().getFBO());

GL30.glClearBuffer(GL11.GL_COLOR, 0, getClColBuffer());
GL30.glClearBuffer(GL11.GL_DEPTH, 0, getClDepthBuffer());

GL20.glUseProgram(getShader().getShaderProgram());

// Projection Matrix
getProjectionMatrix().store(getMatrixBuffer());
getMatrixBuffer().flip();
GL20.glUniformMatrix4(getShader().getUniform(Uniform.PROJECTION).getLocation(), false, getMatrixBuffer());

// View Matrix
getViewMatrix().store(getMatrixBuffer());
getMatrixBuffer().flip();
GL20.glUniformMatrix4(getShader().getUniform(Uniform.VIEW).getLocation(), false, getMatrixBuffer());

for(int i = 0; i < gameObject.length; i++) {
// Model matrix
for(int j = 0; j < gameObject[i].getNumOf(); j++) {
gameObject[i].getModelMatrix()[j].store(getMatrixBuffer());
}
getMatrixBuffer().flip();
GL20.glUniformMatrix4(getShader().getUniform(Uniform.MODEL).getLocation(), false, getMatrixBuffer());

GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, gameObject[i].getMaterial().getVboT());

GL30.glBindVertexArray(gameObject[i].getModel().getVao());
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(1);
GL20.glEnableVertexAttribArray(2);

GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, gameObject[i].getModel().getVboI());

GL31.glDrawElementsInstanced(GL11.GL_TRIANGLES, gameObject[i].getModel().getNumOfIndeces(),
GL11.GL_UNSIGNED_INT, 0, gameObject[i].getNumOf());
}

               // Do I have to disable all this ^ stuff before doing this part??
               // It's the first time implementing more than one shader program.

// Render frame buffer
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);

GL30.glClearBuffer(GL11.GL_COLOR, 0, getClColBuffer());
GL30.glClearBuffer(GL11.GL_DEPTH, 0, getClDepthBuffer());

GL11.glBindTexture(GL11.GL_TEXTURE_2D, getFrameBuffer().getTexture());

GL20.glUseProgram(getPost().getShaderProgram());

// Draw square
GL30.glBindVertexArray(getBufferQuad().getVao());
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(1);

GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, getBufferQuad().getVboI());

GL11.glDrawElements(GL11.GL_TRIANGLES, getBufferQuad().getIndecesCount(), GL11.GL_UNSIGNED_BYTE, 0);

GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
GL20.glDisableVertexAttribArray(0);
GL20.glDisableVertexAttribArray(1);
GL20.glDisableVertexAttribArray(2);
GL30.glBindVertexArray(0);

GL20.glUseProgram(0);

getCamera().reset();

if(getIfSync()) {
Display.sync(getFps());
}
Display.update();

ErrorCheck.checkForGLError(" * Render.java * ");
}


FrameBuffer Class:

private void init(int width, int height, int[] buffers) {
setFBO(GL30.glGenFramebuffers());
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, getFBO());

// Texture for color
setTexture(GL11.glGenTextures());
GL11.glBindTexture(GL11.GL_TEXTURE_2D, getTexture());
GL42.glTexStorage2D(GL11.GL_TEXTURE_2D, 1, GL11.GL_RGBA8, width, height);

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

// Texture for depth
setDepth(GL11.glGenTextures());
GL11.glBindTexture(GL11.GL_TEXTURE_2D, getDepth());
GL42.glTexStorage2D(GL11.GL_TEXTURE_2D, 1 , GL30.GL_DEPTH_COMPONENT32F, width, height);

GL32.glFramebufferTexture(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, getTexture(), 0);
GL32.glFramebufferTexture(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, getDepth(), 0);

IntBuffer drawBuffers = BufferUtils.createIntBuffer(buffers.length);
for(int i = 0; i < buffers.length; i++) {
drawBuffers.put(buffers[i]);
}
drawBuffers.flip();
               // Draw Buffers will inlcude the GL_COLOR_ATTACHMENT0, changed it for now
GL20.glDrawBuffers(GL30.GL_COLOR_ATTACHMENT0);

errorCheck();
}


Edit:
Perhaps these may help.
Here's when not using the frame buffer.
(http://i.imgur.com/KNWCgfKl.png)

And here's without, I changed the background color, to make sure there is a change.
(http://i.imgur.com/YrxxNx0l.png)

Shaders:

Main Vertex
#version 430 core

layout(location = 0) in vec4 in_Position;
layout(location = 1) in vec2 in_TextureCoord;

out VS_OUT {
vec2 pass_TextureCoord;
vec4 pass_Color;
} vs_out;

uniform mat4 proj_matrix;
uniform mat4 view_matrix;
uniform mat4 model_matrix;

void main(void) {
gl_Position = in_Position;
gl_Position = proj_matrix * view_matrix * model_matrix * in_Position;

vs_out.pass_Color = vec4(1.0, 1.0, 1.0, 1.0);
vs_out.pass_TextureCoord = in_TextureCoord;
}


Main Fragment
#version 430 core

uniform sampler2D diffuse_Tex;

in VS_OUT {
vec2 pass_TextureCoord;
vec4 pass_Color;
} fs_in;

out vec4 out_Color;

void main(void) {
out_Color = texture(diffuse_Tex, fs_in.pass_TextureCoord);
}


Post Vertex
#version 430 core

layout(location = 0) in vec4 in_Position;
layout(location = 1) in vec2 in_TexCoord;

out vec2 pass_TexCoord;

void main(void) {
gl_Position = in_Position;
pass_TexCoord = in_TexCoord;
}


Post Fragment
#version 430 core

uniform sampler2D fbo_texture;
uniform sampler2D fbo_depth;

in vec2 pass_TextureCoord;

out vec4 out_Color;

void main(void) {
out_Color = texture2D(fbo_texture, pass_TextureCoord);
}


That's all I can really think of, that's needed to be shown, if other code is needed just let me know.

It works perfectly fine without trying to implement the frame buffer.

Thanks
Title: Re: Need help with FrameBuffer for post processing
Post by: bogieman9876 on May 03, 2014, 12:17:58
Anyone?

Should I ask else where as well?
To increase the chances of some-one who sees this knowing what's wrong.

Edit: Thought I may have found the reason, but I can't see anything in the code that would cause the issue :/
Title: Re: Need help with FrameBuffer for post processing
Post by: quew8 on May 03, 2014, 22:41:55
Hey two things.

1) Just a little note, you say you check the framebuffer for errors with glCheckFrameBufferStatus() and that it returns no error. Probably you mean that there is no error rather than GL_NO_ERROR but, just in case, it should be returning GL_FRAMEBUFFER_COMPLETE.

2) To help you localize your problem a little more, I recommend using an OpenGL debugging program as listed here: http://www.opengl.org/wiki/Debugging_Tools (http://www.opengl.org/wiki/Debugging_Tools). Take your pick. Specifically BuGLe (and maybe some of the others) will let you examine the contents of textures. So what you can do is see if the texture bound to your framebuffer has what you expect in it. If it does then your problem is in rendering that texture if not ...
Title: Re: Need help with FrameBuffer for post processing
Post by: bogieman9876 on May 03, 2014, 23:06:57
That is right, GL_NO_ERROR.

Those debuggers seem a little bit complicated to set up lol
Title: Re: Need help with FrameBuffer for post processing
Post by: quew8 on May 03, 2014, 23:42:41
Yeah it would be nice to have a little IDE integration, but to my knowledge there is none.

The best one I've found is the GLTracer that comes with the Android SDK. It's built right into the Eclipse plugin. Great except that the one time I tried to use it, my app crashed whenever I tried to use GLTracer and that is on a Nexus 7 (not even a year old - certainly got the latest "stable" Android and I was using the latest SDK too). After spending about 5 minutes trying to figure out the problem I gave up on it and just did things the hard way, and have done so ever since.

So I agree. They are not simple. But sometimes, just sometimes, they are invaluable and once it's set up that's it. It should (read "if you're lucky") always work.
Title: Re: Need help with FrameBuffer for post processing
Post by: bogieman9876 on May 04, 2014, 21:20:47
Ok, made a little bit of progress in regards to getting errors.

Whilst I didn't set up any proper debugging, I did splash glGetError everywhere, found that I had an invalid enum when checking the framebuffer status.
After fixing that, the framebuffer status now reports it being completed.

I don't know if this is important in regards to the framebuffer, but I do notice a weird bug of sorts, when switching the rendering type from GL_TRIANGLES to GL_LINES

GL_TRIANGLES, everything looks fine

(Removed Image)

GL_LINES, the geometry is messed up, If this is how it really is, I would have thought that it would show in
GL_TRIANGLES mode

(Removed Image)
Title: Re: Need help with FrameBuffer for post processing
Post by: matanui159 on May 07, 2014, 00:26:33
Im not sure why the framebuffer isnt working
But I can tell you why GL_LINES is messing it up
GL_TRIANGLES works with 3 points (three corners)
But GL_LINES works with 2 (start and end)

So if you had a square (2 triangles) with six points and changed it to GL_LINES it will get 3 lines

Im not sure how to properly do it... try GL_LINE_STRIP, it may work
Title: Re: Need help with FrameBuffer for post processing
Post by: bogieman9876 on May 07, 2014, 17:39:16
Ah that makes sense, I thought that it wouldn't matter, that it just rendered the lines of the triangle instead of the triangle itself.

Thanks :D
Title: Re: Need help with FrameBuffer for post processing
Post by: quew8 on May 08, 2014, 19:12:02
To do it properly, you need to use the polygon mode:


glPolygonMode(GL_FRONT, GL_LINE);


and to go back to full face rendering:


glPolygonMode(GL_FRONT, GL_FILL);


For further info, the docs: http://www.opengl.org/sdk/docs/man2/xhtml/glPolygonMode.xml (http://www.opengl.org/sdk/docs/man2/xhtml/glPolygonMode.xml)
Title: Re: Need help with FrameBuffer for post processing
Post by: bogieman9876 on May 09, 2014, 17:20:31
Thanks,

Any ideas on the framebuffer?
Could it be something to do with nVidia or something?
Title: Re: Need help with FrameBuffer for post processing
Post by: Hanksha on May 09, 2014, 23:58:49
Is it possible to see the inner method of the frame buffer class?
Title: Re: Need help with FrameBuffer for post processing
Post by: quew8 on May 10, 2014, 10:39:17
I have looked through your code and I can't see anything wrong with it. But I have some advice for finding the bug.

Take a look at the example code here: http://lwjgl.org/wiki/index.php?title=Render_to_Texture_with_Frame_Buffer_Objects_(FBO) (http://lwjgl.org/wiki/index.php?title=Render_to_Texture_with_Frame_Buffer_Objects_(FBO)). If that doesn't work then you might have a problem with your drivers but that is extremely unlikely unless you haven't been updating them or are using a beta driver. So if that code (that exact code - some people I tell to do this and they just copy a bit of it and paste that into their code) doesn't work, then get back to us.

If it does work then try incrementally changing bits until it looks more and more like your code. When it breaks you know you've found your problem. I know it's a long process to find a bug but the alternative is just start over from the ground up and if it actually something you don't know about FBOs (as opposed to a typo or something) then you would just make the same mistake again.
Title: Re: Need help with FrameBuffer for post processing
Post by: bogieman9876 on May 10, 2014, 19:45:59
@Hanksha Here's the Framebuffer class in it's entirety.
public class FrameBuffer {
private int fbo;
private int texture;
private int depth;

public int getFBO() {return fbo;}
public int getTexture() {return texture;}
public int getDepth() {return depth;}

public void setFBO(int fbo) {this.fbo = fbo;}
public void setTexture(int texture) {this.texture = texture;}
public void setDepth(int depth) {this.depth = depth;}

public FrameBuffer(int width, int height, int[] buffers) {
init(width, height, buffers);
}

private void init(int width, int height, int[] buffers) {
// This is here just in case it fails some where,
// and to make it look pretty than a simple log in the console.
System.out.println("Initiating Framebuffer" + "\n -----------------------------");

setFBO(GL30.glGenFramebuffers());
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, getFBO());

// Texture for color
setTexture(GL11.glGenTextures());
GL11.glBindTexture(GL11.GL_TEXTURE_2D, getTexture());
GL42.glTexStorage2D(GL11.GL_TEXTURE_2D, 1, GL30.GL_RGBA32F, width, height);

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

// Texture for depth
setDepth(GL11.glGenTextures());
GL11.glBindTexture(GL11.GL_TEXTURE_2D, getDepth());
GL42.glTexStorage2D(GL11.GL_TEXTURE_2D, 1 , GL30.GL_DEPTH_COMPONENT32F, width, height);

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

GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, GL11.GL_TEXTURE_2D, getTexture(), 0);
GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, GL11.GL_TEXTURE_2D, getDepth(), 0);

GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);

// The buffers given would contain things like GL30.GL_COLOR_ATTACHMENT0 inside an int array where here
// it's converted a buffer
IntBuffer drawBuffers = BufferUtils.createIntBuffer(buffers.length);
for(int i = 0; i < buffers.length; i++) {
drawBuffers.put(buffers[i]);
}
drawBuffers.flip();
GL20.glDrawBuffers(drawBuffers);

errorCheck();
System.out.println("Framebuffer Initiated" + "\n -----------------------------");
}

private void errorCheck() {
int val = GL30.glCheckFramebufferStatus(GL30.GL_FRAMEBUFFER);

System.out.println("Error Val: " + Integer.toString(val));
System.out.println("Error Message: " + GLU.gluErrorString(val));

if(val != GL30.GL_FRAMEBUFFER_COMPLETE) {
GL30.glDeleteFramebuffers(getFBO());
System.out.println("Framebuffer Initiation Failed" + "\n -----------------------------");
ErrorCheck.stopOnError();
}
}

public void destroy() {
GL11.glDeleteTextures(getTexture());
GL11.glDeleteTextures(getDepth());
GL30.glDeleteFramebuffers(getFBO());
}
}


@quew8 Ok I'll try that, and report back.

Edit: Well at least that piece of code works, now to slowly change it :/
Title: Re: Need help with FrameBuffer for post processing
Post by: Hanksha on May 10, 2014, 21:56:09
Here is my frame buffer class (but I used EXT), if it can be helpful:
import static org.lwjgl.opengl.EXTFramebufferObject.*;
import static org.lwjgl.opengl.GL11.*;

public class FrameBufferObject {

private int frameBufferID;
private int colorTextureID;
private int depthRenderBufferID;

//dimensions
private int FRAME_WIDTH;
private int FRAME_HEIGHT;

public FrameBufferObject(int width, int height){
FRAME_WIDTH = width;
FRAME_HEIGHT = height;

frameBufferID = glGenFramebuffersEXT();
colorTextureID = glGenTextures();
depthRenderBufferID = glGenRenderbuffersEXT();

//frame buffer object
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBufferID);

//color texture
glBindTexture(GL_TEXTURE_2D, colorTextureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, FRAME_WIDTH, FRAME_HEIGHT, 0, GL_RGBA, GL_INT, (java.nio.ByteBuffer)null);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, colorTextureID, 0);

//depth buffer
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthRenderBufferID);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, FRAME_WIDTH, FRAME_HEIGHT);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthRenderBufferID);


//check completeness
if(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT){
System.out.println("Frame buffer created sucessfully.");
}
else
System.out.println("An error occured creating the frame buffer.");

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}

public void Begin(int width, int height){
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, height, 0, 1, -1);
glMatrixMode(GL_MODELVIEW);
glViewport(0, 0, FRAME_WIDTH, FRAME_HEIGHT);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBufferID);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

public void End(){
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}

public int getTexture(){
return colorTextureID;
}
}


(Some part in the Begin() method can be remove, it was just for a special purpose)
Title: Re: Need help with FrameBuffer for post processing
Post by: bogieman9876 on May 10, 2014, 22:20:08
After messing around further, I found that the problem may be lying with the square used during the standard rending operation.

After changing the current method, to using a hard coded square that's rendered using "glDrawArrays()".
I actually get a square, now I need to set up the texture coords and that should be the problem sorted.

Why the square loaded in wasn't working right is beyond me. Especially when it seems everything else loaded in works right.

Edit: Also, what's the difference between FramebuffersEXT and the method I'm using?

Edit2: Ok, so I'm getting color change and such, however, now I'm getting it where just one color fills the square :/
Title: Re: Need help with FrameBuffer for post processing
Post by: quew8 on May 10, 2014, 23:04:23
Well at least you know where to look now. The ARB is an extension introduced before FBOs became core in 3.0. That's how most features are introduced into OpernGl, first as an extension then if there is popular support then it is added into the core profile.

The vast majority of the extension is exactly the same as the core just with ARB added on the end of names. A few things have different names but do the same thing. And a tiny few are added \removed.
Title: Re: Need help with FrameBuffer for post processing
Post by: bogieman9876 on May 11, 2014, 19:24:46
Yay, I got it working :D

So all in all, the problem was with the square used to render the texture to.

Thanks for the help guys :D