FBO Rendering Issue

Started by 222464, February 11, 2012, 21:44:31

Previous topic - Next topic

222464

Hello,

I have create a frame buffer object with the following code. However, when I bind it, I cannot draw to the texture at all (not even change the color with glClear). Absolutely nothing happens. What am I missing?

Here is how I generate the FBO:

                // Generate the fbo
		int fbo = EXTFramebufferObject.glGenFramebuffersEXT();
		
		GLErrorCheck();
		
		// Attach a texture to render to
		int texture = GL11.glGenTextures();
		GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
		
		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR_MIPMAP_LINEAR); 
		
		// The null at the end must be cast to tell javac which overload to use,
		// even though the last parameter (for the different overloads) isn't even used
		GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, width, height, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, (ByteBuffer)null);
		
		// Unbind texture
		GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
		
		GLErrorCheck();
		
		// Bind the fbo for use
		EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, fbo);
		
		EXTFramebufferObject.glFramebufferTexture2DEXT(
				EXTFramebufferObject.GL_FRAMEBUFFER_EXT,
				EXTFramebufferObject.GL_COLOR_ATTACHMENT0_EXT,
				GL11.GL_TEXTURE_2D, texture, 0); // The 0 is for mip map levels, we aren't using any
		
		GLErrorCheck();
		
		// Attach a depth buffer render buffer if desired
		if(depthBuffer)
		{
			int depthRenBuff = EXTFramebufferObject.glGenRenderbuffersEXT();
			
			// Bind it so we can set it up
			EXTFramebufferObject.glBindRenderbufferEXT(EXTFramebufferObject.GL_RENDERBUFFER_EXT, depthRenBuff);
			
			// Set up the depth buffer
			EXTFramebufferObject.glRenderbufferStorageEXT(EXTFramebufferObject.GL_RENDERBUFFER_EXT, GL11.GL_DEPTH_COMPONENT, width, height);
		
			// Attach the dpeth buffer
			EXTFramebufferObject.glFramebufferRenderbufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, EXTFramebufferObject.GL_DEPTH_ATTACHMENT_EXT, EXTFramebufferObject.GL_RENDERBUFFER_EXT, depthRenBuff);
		
			GLErrorCheck();
		}
		
		// Check
		if(EXTFramebufferObject.glCheckFramebufferStatusEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT) != EXTFramebufferObject.GL_FRAMEBUFFER_COMPLETE_EXT)
			throw new Error("Could not create FBO!");
		
		// An fbo has its own viewport, so lets set it
		GL11.glViewport(0, 0, width, height);
		
		// Unbind
		EXTFramebufferObject.glBindRenderbufferEXT(EXTFramebufferObject.GL_RENDERBUFFER_EXT, 0);
		EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, 0);
		
		GLErrorCheck();


Binding it:

                // Unbind textures
		GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
		
		EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, fbo);
		
		// Save view port information, since this will in almost all cases change (states are shared with main context)
		GL11.glPushAttrib(GL11.GL_VIEWPORT_BIT | GL11.GL_COLOR_BUFFER_BIT);


Unbinding:

                // Finish all operations so can use texture
		GL11.glFlush();
		
		// Restore saved information for main rendering context
		GL11.glPopAttrib();
		
		// Unbind
		EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, 0);


After the FBO is bound I do the following:

                // Create the view port for this render texture
		GL11.glViewport(0, 0, m_width, m_height);
                GL11.glClearColor(0.5f, 0.2f, 0.8f, 1.0f);
		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);


After unbinding the FBO, I bind the texture that went with it and draw a quad, but it is plain white every time.

Fool Running

Without all of your code, it's hard to tell what the problem is, but I don't see that you are enabling texturing (which would explain why everything appears white). Make sure you call GL11.glEnable(GL11.GL_TEXTURE_2D).
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

222464

Here is a complete and minimal code example that produces this problem:

public static void main(String[] args)
	{
		try
		{
		    Display.setDisplayMode(new DisplayMode(800, 600));
		    Display.create();
		    Display.setVSyncEnabled(true);
		}
		catch(LWJGLException e)
		{
		    e.printStackTrace();
		    System.exit(0);
		}
		
		// Requirements
		if(!GLContext.getCapabilities().GL_EXT_framebuffer_object)
			throw new Error("FBOs not supported! Get a better computer!");
		
		// Defaults
		GL11.glEnable(GL11.GL_TEXTURE_2D);
		
		GL11.glEnable(GL11.GL_BLEND);	
		GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
		
		GL11.glDisable(GL11.GL_DEPTH_BUFFER_BIT);
		
		// Set up orthographic projection for 2D
		GL11.glMatrixMode(GL11.GL_PROJECTION);
		GL11.glLoadIdentity();
		GL11.glOrtho(0, 800, 0, 600, -100, 100);
		GL11.glMatrixMode(GL11.GL_MODELVIEW);
		
		// Create a FBO
		// Generate the fbo
		int fbo = EXTFramebufferObject.glGenFramebuffersEXT();
		
		// Attach a texture to render to
		int texture = GL11.glGenTextures();
		GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
		
		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR_MIPMAP_LINEAR); 
		
		// The null at the end must be cast to tell javac which overload to use,
		// even though the last parameter (for the different overloads) isn't even used
		GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, 800, 600, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, (ByteBuffer)null);
		
		// Unbind texture
		GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
		
		// Bind the fbo for use
		EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, fbo);
		
		EXTFramebufferObject.glFramebufferTexture2DEXT(
				EXTFramebufferObject.GL_FRAMEBUFFER_EXT,
				EXTFramebufferObject.GL_COLOR_ATTACHMENT0_EXT,
				GL11.GL_TEXTURE_2D, texture, 0); // The 0 is for mip map levels, we aren't using any
		
		// Check
		if(EXTFramebufferObject.glCheckFramebufferStatusEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT) != EXTFramebufferObject.GL_FRAMEBUFFER_COMPLETE_EXT)
			throw new Error("Could not create FBO!");
		
		// An fbo has its own viewport, so lets set it
		GL11.glViewport(0, 0, 800, 600);
		
		// Unbind
		EXTFramebufferObject.glBindRenderbufferEXT(EXTFramebufferObject.GL_RENDERBUFFER_EXT, 0);
		EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, 0);
		
		// Game loop
		while(!Keyboard.isKeyDown(Keyboard.KEY_ESCAPE))
		{
			GL11.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
			GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
			
			// --------------------- Render to the FBO ----------------------
			
			// Unbind textures
			GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
			
			EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, fbo);
			
			// Save view port information
			GL11.glPushAttrib(GL11.GL_VIEWPORT_BIT);
			
			// Clear the FBO to a color
			GL11.glClearColor(0.5f, 0.3f, 0.3f, 1.0f);
			GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
			
			// Finish all operations so can use texture
			GL11.glFlush();
			
			// Restore saved information for main rendering context
			GL11.glPopAttrib();
			
			// Unbind the FBO
			EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, 0);
			
			// ------------------ Render FBO to the screen -----------------------
			
			// Draw a quad with the FBO on it
			GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
			
			GL11.glBegin(GL11.GL_QUADS);
			
			GL11.glTexCoord2f(0.0f, 0.0f); GL11.glVertex2f(200.0f, 200.0f);
			GL11.glTexCoord2f(1.0f, 0.0f); GL11.glVertex2f(600.0f, 200.0f);
			GL11.glTexCoord2f(1.0f, 1.0f); GL11.glVertex2f(600.0f, 600.0f);
			GL11.glTexCoord2f(0.0f, 1.0f); GL11.glVertex2f(200.0f, 600.0f);
			
			GL11.glEnd();
			
			Display.update();
		}
	}


The FBO does not change from a plain white texture, so I assume it is never really rendering to it.



spasi

GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR_MIPMAP_LINEAR);


You need to set GL_TEXTURE_MIN_FILTER to GL_LINEAR instead of GL_LINEAR_MIPMAP_LINEAR. You're only defining a single mip map level in the texture.

GL11.glDisable(GL11.GL_DEPTH_BUFFER_BIT);


Unrelated to your problem, but this line causes a GL error. You probably meant GL_DEPTH_TEST. There are a few options to catch errors like these while developing your app:

- Always put a Util.checkGLError(); in your main loop. That's the simplest solution, but it won't give you the error source.
- Use LWJGL's debug jar, which performs an error check after every GL call. This will give you the exact error source, but it will affect performance.
- Use the ARB_debug_output extension (or AMD_debug_output). This is the preferred way and it's very simple to enable:

Display.create(new PixelFormat(), new ContextAttribs(4, 2).withProfileCompatibility(true).withDebug(true));
...
if ( GLContext.getCapabilities().GL_ARB_debug_output )
	ARBDebugOutput.glDebugMessageCallbackARB(new ARBDebugOutputCallback());
else if ( GLContext.getCapabilities().GL_AMD_debug_output )
	AMDDebugOutput.glDebugMessageCallbackAMD(new AMDDebugOutputCallback());

222464

Thank you very much! It was indeed the mipmap setting. Thanks for the advice on debugging!