Frame buffer objects is something new to openGL, it didn’t make it in time to 2.0 but it will probably be in 2.1 so it’s likely that it will change a little, but this tut should still remain valid for the most part.
Now if you don’t know what frame buffer objects are then i will tell you, the frame buffer is where you do all of your rendering, it is the memory area where the actual pixel data is stored, now previously you had only one (4 actually, but the other ones are rarely used) and if you wanted more then you had to use p-buffers, but p-buffers are something that is definitely problematic, I’m not gonna go into details but my advice it to stay as far away from them as possible.
This is where Frame Buffer Objects come into the picture, an FBO is a custom memory area in where you could render stuff to and provide a quick and easy render to texture solution where you could render directly to a depth texture or use odd formats and sizes.
FBO’s also makes High Dynamic Rendering (HDR) practical as you only have to create a texture that uses this format witch is as easy as typing GL_RGBA16F_ARB.
Now on to the cody bits.
The stuff i am gonna ignore this tutorial is the drawBox() func, the IsExtensionSupported() func, the checkfbo() func and all the extension init code, they are pretty much self explanatory and dull as dry bread, if you want to know what’s in it then you have to download the code and take a look.
So the first thing we have to do is to initialize the frame buffer and the associated textures and render buffers then binding the frame buffer so that we can work with it.
fb, color_tex and depth_rb are just unsigned ints, nothing complicated.
// generate namespace for the frame buffer, colorbuffer and depthbuffer
glGenFramebuffersEXT(1, &fb);
glGenTextures(1, &color_tex);
glGenRenderbuffersEXT(1, &depth_rb);
//switch to our fbo so we can bind stuff to it
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
Then bind and create the texture color_tex, the same way as with regular texturing but with a NULL or 0 instead of the data
//create the colorbuffer texture and attach it to the frame buffer
glBindTexture(GL_TEXTURE_2D, color_tex);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 512, 512, 0,
GL_RGBA, GL_INT, NULL)
Now attach the texture to the frame buffer to the first color attachment, if you need to in conjunction with MRT it’s possible to have more than one color buffer
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, color_tex, 0);
Do the same thing with the render buffer and bind it to the depth attachment.
A render buffer is basically the same as the texture above except that it cant be used anywhere else so it’s primarily used as throwaway depth buffer.
// create a render buffer as our depth buffer and attach it
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_rb);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
GL_DEPTH_COMPONENT24,512, 512);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, depth_rb);
// Go back to regular frame buffer rendering
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
And thats it, use the checkfbo() function to see if you where successfull in creating the FBO, if it passes you can now start using it.
So we have now managed to create it, but in order for you to be able to render to this frame buffer you need to do two things, first make sure the color buffer texture or any other texture bound to the fbo is not bound at the moment and then switch to FBO rendering.
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
Simple, and to render the texture you do the reverse.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glBindTexture(GL_TEXTURE_2D, color_tex);
And thats all there is to it, naturally the render loop is a bit more complicated and i am gonna include the tutorials full draw func just to show you how it’s done, note that you have to call glClear two times, this is because the clear only works on the currently bound frame buffer and not all of them at once, you also need to set the viewport to the size of the current framebuffer or things will look odd.
// FBO render pass
glViewport (0, 0, 512, 512);
// set The Current Viewport to the fbo size glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
glClearColor (1.0f, 0.0f, 0.0f, 0.5f);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity ();
glTranslatef (0.0f, 0.0f, -6.0f);
glRotatef(angle,0.0f,1.0f,0.0f);
glRotatef(angle,1.0f,0.0f,0.0f);
glRotatef(angle,0.0f,0.0f,1.0f);
glColor3f(1,1,0);
drawBox()
// Framebuffer render pass
glEnable(GL_TEXTURE_2D);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glBindTexture(GL_TEXTURE_2D, color_tex);
glClearColor (0.0f, 0.0f, 0.0f, 0.5f);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport (0, 0, (GLsizei)(g_window->init.width), (GLsizei)(g_window->init.height));
glLoadIdentity ();
glTranslatef (0.0f, 0.0f, -6.0f);
glRotatef(angle,0.0f,1.0f,0.0f);
glRotatef(angle,1.0f,0.0f,0.0f);
glRotatef(angle,0.0f,0.0f,1.0f)
glColor3f(1,1,1);
drawBox();
glDisable(GL_TEXTURE_2D);
glFlush ();
That’s all for this time make sure you download the tutorial and look at the code to understand the context a bit better.
Download this tutorial for MSVCPP 6.0