pBuffer vs PBO vs FBO


since years I’m using the pBuffer for offscreen rendering.
Is this still a good choice?

Or is there a good reason to switch to PBO or FBO?

What are the pros and cons for all three extensions
(compatibility, speed, flexibility)?

Please enlighten me :slight_smile:

AFAIK, PBuffers are deprecated, which is a good enough reason not to use them. As times goes by, vendors will begin to drop support for PBuffers and their implementation will not be as efficient. FBOs are by far a more flexible (and perhaps faster) option.

PBOs, IIRC, have a different purpose from FBOs. They are primarily used for Render-To-Vertex Array implementations (though they have other uses). Even then, I have been told that Transform Feedback is a better option for that purpose. So that leaves you with just FBOs…

PBO is not for off-screen rendering. It’s just for asynchronous texture writes/reads.

FBO is a better choice then PBuffer. It doesn’t maintain separate GL context per instance, so switching is faster. I used both and now see no use of the latter.

Thanks guys, I’ll switch to FBO then.

I saw there is an older EXT_framebuffer_object
and an ARB_framebuffer_object extension string.

According to…


…the latter “Integrates multiple disjoint extensions
into a single ARB extension. These extensions are:

So I guess I should rather check for the ARB_ string
than for the EXT_, right?

FBOs are now core, so you don’t have to use ARB or EXT.

Just follow along this tutorial, and remove the “EXT” wherever you find it:

For example: glGenFramebuffersEXT would simply become glGenFramebuffers

For a more advanced tutorial, have a look at the second part:

So I guess I should rather check for the ARB_ string
than for the EXT_, right?

There are some differences between ARB_FBO and the combination of all of those EXT extensions. For example, ARB_FBO allows the user to add attachments that have different sizes; the total size of the renderable area is the intersection of all of the attached image sizes. EXT_FBO does not allow this.

Mhm on Windows I don’t have the lib and gl headers including
these functions. So I always have to bind the extension
functions with…

wglGetProcAddress( );

Or how do you do it on Windows?

Or how do you do it on Windows?

Usually, we use an extension loading library that does this for us.

I have a (hopefully) final question:

For FBO I guess I should replace

gluBuild2DMipmaps( ) with
glGenerateMipmapEXT( ).

So far so good, but can I still use…


…to auto generate the mipmaps if the base map is updated?
Or does this auto generation not work with FBO and I have
to call glGenerateMipmapEXT( ) manually on every base update?

Thanks again :slight_smile:

P.S. I ask this because here they say:
When GL_EXT_framebuffer_object is present, instead of using the GL_GENERATE_MIPMAP flag, you can use glGenerateMipmapEXT.

I don’t really understand that because I would say
GL_GENERATE_MIPMAP is for auto generation while
glGenerateMipmapEXT is for manual mipmap generation.
So the “instead of using…” does not make sense?

AFAIK, this means that GL_GENERATE_MIPMAP is going to be deprecated (and it is in 3.0 at least).
glGenerateMipmap can be used on any texture regardless of whether it’s attached to FBO or not. And yes, you have to call it each time the base level changes.

glGenerateMipmapEXT is for auto mipmap generation, done explicitely when asked.
The older method (GL_GENERATE_MIPMAP, GL_TRUE) is implicit, so regenerate the whole mipmap chain each time the texture is touched.
It depends on the usage, but you may get better performance by using glGenerateMipmapEXT only when needed. And it is more modern.

You can use GL_GENERATE_MIPMAP, but you shouldn’t. If the texture changes, you’ll know about it because you did it. So just

Also, GL_GENERATE_MIPMAP will do so when any change happens. So if you change it twice (two TexSubImage calls), it will generate mipmaps twice. If you did it explicitly, you’d know that you only needed to do it after the last change.

And of course, GL_GENERATE_MIPMAP was removed in GL 3.1 core, so you can’t use it unless you’ve got a compatibility context.

Ok thanks a lot!