OffScreen rendering with EXT_framebuffer_object

After having successfully used the PBuffers for offscreen rendering with LWJGL I would like to use the FrameBuffer Object for doing offscreen graphics.

The docs are unclear (at least for me) and I didn’t manage to have something working.
My aim is not to use render-to-texture, but only allocate an FBO, bind it to a ARGB 32bit Render Buffer Object and then read the pixels back from it.

My init code:


IntBuffer fbID = BufferUtils.createIntBuffer(1);
IntBuffer rbID = BufferUtils.createIntBuffer(1);

EXTFramebufferObject.glGenRenderbuffersEXT(rbID);
EXTFramebufferObject.glGenFramebuffersEXT(fbID);

EXTFramebufferObject.glRenderbufferStorageEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT,EXTBgra.GL_BGRA_EXT,getPhysicalWidth(), getPhysicalHeight());
EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT,fbID.get(0));
EXTFramebufferObject.glFramebufferRenderbufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, EXTFramebufferObject.GL_COLOR_ATTACHMENT0_EXT, EXTFramebufferObject.GL_RENDERBUFFER_EXT, fbID.get(0));
EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, fbID.get(0));

..
GL11.gl calls here.


checkError() signals an error when I call glRenderbufferStorageEXT().

What I’m missing ?

Help appreciated (Spasi, are you there ?).

Code to help you debugging:

   private final boolean isValidFramebuffer()
   {
      String message;

      int status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);

      switch (status)
      {
         case GL_FRAMEBUFFER_COMPLETE_EXT:
            return true;
         case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
            message = "format unsupported";
            break;
         case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
            message = "image-attachments have different internal formats";
            break;
         case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
            message = "image-attachments have different dimensions";
            break;
         case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
            message = "duplicate image-attachment";
            break;
         case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
            message = "missing an image-attachment";
            break;
         default:
            message = "unknown: " + status;
      }

      System.out.println("isValidFramebuffer(\"" + message + "\")");

      return false;
   }

Hope this helps.

[quote=“javazoid,post:1,topic:24451”]
In line 3 you try to bind the RenderBuffer to the FrameBuffer, but you pass the fbID instead of the rbID.
In line 2 and 4 you do the same, so line 4 is a no-op.

I don’t think BGRA is a valid internal format for render buffers.

[quote] must be RGB, RGBA, DEPTH_COMPONENT, STENCIL_INDEX, or one of the internal formats from table 3.16 or table 2.nnn that has a base internal format of RGB, RGBA, DEPTH_COMPONENT, or STENCIL_INDEX.
[/quote]
And what Riven said.

What’s unclear with the FBO is how to create it without a texture binding. I don’t need to render-to-texture: I only need to create an FBO with an ARGB pixel format (so, binded to a framebufferobject).

A piece of sample code is worth a thousand posts, so don’t be shy :wink:

Mik

Just use a standard RGBA format for the render buffer’s internal format.

Besides, why is it a problem to use a texture? You can still read back the pixels.

So you suggest me to read pixels from the texture using glGetTexImage() ? Do you know how it performs compared to glReadPixels() ?

The problem for me is a bit more complex: I use a hierarchy of classes that implement a gl graphics “context”. The context is abstract but it defines concrete methods for reading pixels. These methods use glReadPixels(); Ok, I could solve this issue by re-working the classes…

Anyway, I still have initialization problems. I’ll do further checks and test. Any help appreciated.

[quote=“javazoid,post:7,topic:24451”]
Yes, exactly. I would expect similar performance to ReadPixels, since a renderable texture would have a memory layout similar to any other renderable surface.

[quote=“javazoid,post:7,topic:24451”]
Could you post any errors you’re getting?

You can glReadBuffer directly from the FBO.

Whether or not it is backed by a texture or not is irrelevant.

At last I have the FBO working:

init


EXTFramebufferObject.glGenFramebuffersEXT(fbIDbuf);
EXTFramebufferObject.glGenRenderbuffersEXT(rbIDbuf);

EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, fbIDbuf.get(0));
EXTFramebufferObject.glBindRenderbufferEXT(EXTFramebufferObject.GL_RENDERBUFFER_EXT, rbIDbuf.get(0));

EXTFramebufferObject.glRenderbufferStorageEXT(EXTFramebufferObject.GL_RENDERBUFFER_EXT, GL11.GL_RGBA, getPhysicalWidth(), getPhysicalHeight());
EXTFramebufferObject.glFramebufferRenderbufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, EXTFramebufferObject.GL_COLOR_ATTACHMENT0_EXT, EXTFramebufferObject.GL_RENDERBUFFER_EXT, rbIDbuf.get(0));


make current:


EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, fbIDbuf.get(0));

dispose


EXTFramebufferObject.glDeleteRenderbuffersEXT(rbIDbuf);
EXTFramebufferObject.glDeleteFramebuffersEXT(fbIDbuf);
			
EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, 0);
EXTFramebufferObject.glBindRenderbufferEXT(EXTFramebufferObject.GL_RENDERBUFFER_EXT, 0);

For a “windowless” application I have to create a shared PBuffer first.
The strange thing is that I get a 1280 error after disposing the FBO and making the shared PBuffer current.

From the performance point of view, I get 1:1 against the PBuffers version, but the API is much simpler.

When you do frequent buffer-switches (a couple per frame), FBOs really shine (performance wise).

You can even make it faster by using the same FBO and only switching the RenderBuffer/Texture ‘behind’ it.

One question about the renderbuffer format: how can I specify stencil bits, depth, alpha bits, etc. ?


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

Don’t be afraid to read the FBO spec :stuck_out_tongue:

Thanks for the code. I already did that (by reading the specs :P).
I also tried to create an 8 bit stencil buffer by implementing similar code but even if it doesn’t give any error, it does not work.
I’ve double checked the source and it seems to be ok.
First I created the color buffer and attached it, then the depth buffer and last the stencil. All attached to the same FBO.

Stencil renderbuffers are not supported by any hardware right now. A new extension is planned that will provide a packed depth-stencil format, which should be available on most cards.

Many thanks Spasi. You saved me a lot of improductive testing.
FBO is indeed a nice feature but I suppose it’s still too much early stage. I read somewhere that FBOs cannot be created when Anisotropic Filtering is on. Also NVIDIA says they will support anti-aliasing in FBO in future drivers, but they do not say anything about AF.

Cheers,

Mik

Yes, a new extension (or an update of the current one) is planned for AA with FBO. That’s the most important feature missing right now. The AF limitation is probably a bug in current drivers.

I’m curious, why do you need to use a stencil buffer with FBO? I’m sure you could live without that, right?

I’ve implemented Java2D Shape clipping in my SGL engine through stencil buffers. That’s why I need stencils.
I hope to see FBO improvements/fixes very soon. By this time, LWJG Pbuffers work very well…

How can you be so well informed about the FBO status ? Have you got an account on developer.nvidia.com ?

FBO is the hottest OpenGL topic lately, so it’s natural that I’ve learned everything about it. :slight_smile:

Yes, I’m registered to both nvdeveloper and ATI developers relations. But there’s not much info there, they’re only useful for early access drivers/tools and if you want to contact them directly for specific issues and bug reports.

I get most information from forums, papers and presentations (GDC, Siggraph, etc). I have a 3 gig PDF collection and that’s for graphics only. :wink:

What you are working on lately ?