Help with FBOs: Incomplete attachments

Hi.

I’m just starting with the FBOs thing, and right from the start I’m getting some unexpected problems.
Basically what I want to do is the classic render-to-texture but I can’t figure out how to set up the FBO correctly.
Here’s my code (I’m doing this in the init() method of my listener):


		// create the FBOs, texture objects and renderbuffers
		System.out.println("Setting up framebuffer objects...");
		fbos = new int[layers.length];
		gl.glGenFramebuffersEXT(layers.length, fbos, 0);
		textures = new int[layers.length];
		gl.glGenTextures(layers.length, textures, 0);

		// now for each layer
		int i,status;
		for (i=0; i<layers.length; i++)
		{
			// bind the corresponding FBO
			gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, fbos[i]);
			// initialize texture image
			gl.glBindTexture(GL.GL_TEXTURE_2D, textures[i]);
			gl.glTexImage2D(GL.GL_TEXTURE_2D, 0,
							GL.GL_RGBA, 512, 512, 0,
							GL.GL_RGBA, GL.GL_INT, null);
	
			// attach texture to framebuffer color buffer #0
			gl.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT,
										 GL.GL_COLOR_ATTACHMENT0_EXT,
										 GL.GL_TEXTURE_2D, textures[i], 0);

			// check framebuffer completeness
			status = gl.glCheckFramebufferStatusEXT(GL.GL_FRAMEBUFFER_EXT);
			if (status != GL.GL_FRAMEBUFFER_COMPLETE_EXT)
			{
				String str = "Framebuffer initialization error! ("+status+")\n";
				throw new RuntimeException(str);
			}
		}

Really simple. Just generate the identifiers, bind the FBO, generate a texture image and bind it to the FBO’s color buffer.
So… what’s wrong? The ‘status’ variable returns with a value of 36054, which seems to be GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENTS_EXT. What’s missing in this code? Any help would be really appreciated.

Btw, if I do this afterwards:


		    if ((err = gl.glGetError()) != GL.GL_NO_ERROR) {
		        System.err.println ("ERROR [OpenGL] " + new GLU().gluErrorString(err));
		    }

I get a ‘null’ string from gluErrorString(). Is this expected behavior?
Thanks for any help.

Just a guess but you may need a depth buffer attachment as well.

gluErrorString only works for errors reported from GLU, such as the quadric routines, tessellators, etc.

No, the depth-buffer is optional. Better read the FBO spec chopsuey, if you really want to be sure what’s going on.

This is my LWJGL FBO code, shouldn’t be too hard to port to JOGL/JSR-231:


   private final IntBuffer setupFramebuffer(boolean depth)
   {
      // init pixel-buffer
      frameBufferHandle = BufferUtils.createIntBuffer(1);
      glGenFramebuffersEXT(frameBufferHandle);
      glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBufferHandle.get(0));
      glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, backing.id(), 0);

      if (depth)
      {
         int depthComponent;

         if (true)
            depthComponent = GL_DEPTH_COMPONENT;
         else
            depthComponent = ARBDepthTexture.GL_DEPTH_COMPONENT24_ARB;

         // init depth-buffer
         depthBufferHandle = BufferUtils.createIntBuffer(1);
         glGenRenderbuffersEXT(depthBufferHandle);
         glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBufferHandle.get(0));
         glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, depthComponent, dim, dim);
         glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthBufferHandle.get(0));
      }

      // validate (destroy everything if not valid)
      if (!this.isValidFramebuffer())
      {
         // release pixel-buffer and depth-buffer
         glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, 0, 0);
         if (depth)
            glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0);

         // unbind framebuffer
         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

         // delete framebuffer
         glDeleteFramebuffersEXT(frameBufferHandle);

         // means: no framebuffer
         return null;
      }

      // unbind framebuffer
      glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

      // return framebuffer
      return frameBufferHandle;
   }

I recall having this problem when I first experimented with FBOs. It took me a few hours to realize that I’d get INCOMPLETE_FRAMEBUFFER if I forgot to set the texture mag/min filter after creating the texture object:
glTexImage2D(…);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

Hope this helps.
Chris
Java 2D Team

Thank you so much, Campbell, and the others as well.

The glTexParameteri made the trick. Actually, only the GL_TEXTURE_MIN_FILTER is needed. Otherwise the texture seems to be incompletely specified. This is strange, but if I recall correctly, I already encountered this issue back when dealing with textures for the first time. If you didn’t specify the filter, the texture was drawn white.

I think this really ought to be noted somewhere. I’ve read once and again the opengl spec, as well as the FBO spec, and I can’t find any reference to this fact.

Well, life goes on… thanks again.
See ya.