[SOLVED]Need help with FrameBuffer for post processing

Started by bogieman9876, April 30, 2014, 18:28:53

Previous topic - Next topic

bogieman9876

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.


And here's without, I changed the background color, to make sure there is a change.


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

bogieman9876

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 :/

quew8

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. 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 ...

bogieman9876

That is right, GL_NO_ERROR.

Those debuggers seem a little bit complicated to set up lol

quew8

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.

bogieman9876

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)

matanui159

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
ALGORITHM
A word used by programmers when they do not want to explain what they did.

WEE :)

bogieman9876

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

quew8

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

bogieman9876

Thanks,

Any ideas on the framebuffer?
Could it be something to do with nVidia or something?

Hanksha

Is it possible to see the inner method of the frame buffer class?

quew8

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

bogieman9876

@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 :/

Hanksha

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)

bogieman9876

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 :/