Difference between revisions of "Framebuffer Object Extension Examples"

From OpenGL Wiki
Jump to: navigation, search
m (Quick example, render_to_texture (2D), mipmaps)
(Quick example, render_to_texture (2D Depth texture ONLY))
Line 218: Line 218:
  
 
=== Quick example, render_to_texture (2D Depth texture ONLY) ===
 
=== Quick example, render_to_texture (2D Depth texture ONLY) ===
//32 bit depth texture, 256x256
+
  //32 bit depth texture, 256x256
 
   glGenTextures(1, &depth_tex);
 
   glGenTextures(1, &depth_tex);
 
   glBindTexture(GL_TEXTURE_2D, depth_tex);
 
   glBindTexture(GL_TEXTURE_2D, depth_tex);
Line 270: Line 270:
 
   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
 
   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
 
   glDeleteFramebuffersEXT(1, &fb);
 
   glDeleteFramebuffersEXT(1, &fb);
 +
 +
=== Quick example, render_to_texture (2D), mipmaps, depth_stencil ===
 +
If GL_EXT_packed_depth_stencil is present, use it. Also called a D24S8 format.
 +
All common GPUs support this format.<br>
 +
http://www.opengl.org/registry/specs/EXT/packed_depth_stencil.txt<br>
 +
 +
  //RGBA8 2D texture, D24S8 depth/stencil texture, 256x256
 +
  glGenTextures(1, &color_tex);
 +
  glBindTexture(GL_TEXTURE_2D, color_tex);
 +
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
 +
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
 +
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 +
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
 +
  //NULL means reserve texture memory, but texels are undefined
 +
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
 +
  //You must reserve memory for other mipmaps levels as well either by making a series of calls to
 +
  //glTexImage2D or use glGenerateMipmapEXT(GL_TEXTURE_2D).
 +
  //Here, we'll use :
 +
  glGenerateMipmapEXT(GL_TEXTURE_2D);
 +
  //-------------------------
 +
  glGenFramebuffersEXT(1, &fb);
 +
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
 +
  //Attach 2D texture to this FBO
 +
  glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, color_tex, 0);
 +
  //-------------------------
 +
  glGenRenderbuffersEXT(1, &depth_stencil_rb);
 +
  glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_stencil_rb);
 +
  glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, 256, 256);
 +
  //-------------------------
 +
  //Attach depth buffer to FBO
 +
  glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_stencil_rb);
 +
  //Also attach as a stencil
 +
  glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_stencil_rb);
 +
  //-------------------------
 +
  //Does the GPU support current FBO configuration?
 +
  GLenum status;
 +
  status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
 +
  switch(status)
 +
  {
 +
    case GL_FRAMEBUFFER_COMPLETE_EXT:
 +
    cout<<"good";
 +
  default:
 +
    HANDLE_THE_ERROR;
 +
  }
 +
  //-------------------------
 +
  //and now you can render to GL_TEXTURE_2D
 +
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
 +
  glClearColor(0.0, 0.0, 0.0, 0.0);
 +
  //It's always a good idea to clear the stencil at the same time as the depth when the format is D24S8.
 +
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |  GL_STENCIL_BUFFER_BIT);
 +
  //-------------------------
 +
  glViewport(0, 0, 256, 256);
 +
  glMatrixMode(GL_PROJECTION);
 +
  glLoadIdentity();
 +
  glOrtho(0.0, 256.0, 0.0, 256.0, -1.0, 1.0);
 +
  glMatrixMode(GL_MODELVIEW);
 +
  glLoadIdentity();
 +
  //-------------------------
 +
  glDisable(GL_TEXTURE_2D);
 +
  glDisable(GL_BLEND);
 +
  glEnable(GL_DEPTH_TEST);
 +
  //-------------------------
 +
  //**************************
 +
  //RenderATriangle, {0.0, 0.0}, {256.0, 0.0}, {256.0, 256.0}
 +
  //Read http://www.opengl.org/wiki/VBO_-_just_examples
 +
  RenderATriangle();
 +
  //-------------------------
 +
  GLubyte pixels[4*4*4];
 +
  glReadPixels(0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
 +
  //pixels 0, 1, 2 should be white
 +
  //pixel 4 should be black
 +
  //----------------
 +
  //Bind 0, which means render to back buffer
 +
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
 +
 +
And in the end, cleanup
 +
 +
  //Delete resources
 +
  glDeleteTextures(1, &color_tex);
 +
  glDeleteRenderbuffersEXT(1, &depth_stencil_rb);
 +
  //Bind 0, which means render to back buffer, as a result, fb is unbound
 +
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
 +
  glDeleteFramebuffersEXT(1, &fb);

Revision as of 13:54, 6 August 2009

RTT = render_to_texture
This page shows a few examples on how to setup a RTT and how to cleanup.
The extension specification is at http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
Note that this extension became core in GL 3.0 and at the same time they released the ARB version of the extension
http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
GL_ARB_framebuffer_object brings together GL_EXT_framebuffer_object, GL_EXT_framebuffer_blit, GL_EXT_framebuffer_multisample, GL_EXT_packed_depth_stencil which are all folded into the core of GL 3.0.

Quick example, render_to_texture (2D)

  //RGBA8 2D texture, 24 bit depth texture, 256x256
  glGenTextures(1, &color_tex);
  glBindTexture(GL_TEXTURE_2D, color_tex);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  //NULL means reserve texture memory, but texels are undefined
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
  //-------------------------
  glGenFramebuffersEXT(1, &fb);
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
  //Attach 2D texture to this FBO
  glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, color_tex, 0);
  //-------------------------
  glGenRenderbuffersEXT(1, &depth_rb);
  glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_rb);
  glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, 256, 256);
  //-------------------------
  //Attach depth buffer to FBO
  glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_rb);
  //-------------------------
  //Does the GPU support current FBO configuration?
  GLenum status;
  status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
  switch(status)
  {
     case GL_FRAMEBUFFER_COMPLETE_EXT:
     cout<<"good";
  default:
     HANDLE_THE_ERROR;
  }
  //-------------------------
  //and now you can render to GL_TEXTURE_2D
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
  glClearColor(0.0, 0.0, 0.0, 0.0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  //-------------------------
  glViewport(0, 0, 256, 256);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0.0, 256.0, 0.0, 256.0, -1.0, 1.0); 
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  //-------------------------
  glDisable(GL_TEXTURE_2D);
  glDisable(GL_BLEND);
  glEnable(GL_DEPTH_TEST);
  //-------------------------
  //**************************
  //RenderATriangle, {0.0, 0.0}, {256.0, 0.0}, {256.0, 256.0}
  //Read http://www.opengl.org/wiki/VBO_-_just_examples
  RenderATriangle();
  //-------------------------
  GLubyte pixels[4*4*4];
  glReadPixels(0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
  //pixels 0, 1, 2 should be white
  //pixel 4 should be black
  //----------------
  //Bind 0, which means render to back buffer
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

And in the end, cleanup

  //Delete resources
  glDeleteTextures(1, &color_tex);
  glDeleteRenderbuffersEXT(1, &depth_rb);
  //Bind 0, which means render to back buffer, as a result, fb is unbound
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  glDeleteFramebuffersEXT(1, &fb);

Quick example, render_to_texture (2D), mipmaps

  //RGBA8 2D texture, 24 bit depth texture, 256x256
  glGenTextures(1, &color_tex);
  glBindTexture(GL_TEXTURE_2D, color_tex);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  //NULL means reserve texture memory, but texels are undefined
  //**** Tell OpenGL to reserve level 0
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
  //You must reserve memory for other mipmaps levels as well either by making a series of calls to
  //glTexImage2D or use glGenerateMipmapEXT(GL_TEXTURE_2D).
  //Here, we'll use :
  glGenerateMipmapEXT(GL_TEXTURE_2D)
  //-------------------------
  glGenFramebuffersEXT(1, &fb);
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
  //Attach 2D texture to this FBO
  glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, color_tex, 0);
  //-------------------------
  glGenRenderbuffersEXT(1, &depth_rb);
  glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_rb);
  glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, 256, 256);
  //-------------------------
  //Attach depth buffer to FBO
  glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_rb);
  //-------------------------
  //Does the GPU support current FBO configuration?
  GLenum status;
  status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
  switch(status)
  {
     case GL_FRAMEBUFFER_COMPLETE_EXT:
     cout<<"good";
  default:
     HANDLE_THE_ERROR;
  }
  //-------------------------
  //and now you can render to GL_TEXTURE_2D
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
  glClearColor(0.0, 0.0, 0.0, 0.0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  //-------------------------
  glViewport(0, 0, 256, 256);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0.0, 256.0, 0.0, 256.0, -1.0, 1.0); 
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  //-------------------------
  glDisable(GL_TEXTURE_2D);
  glDisable(GL_BLEND);
  glEnable(GL_DEPTH_TEST);
  //-------------------------
  //**************************
  //RenderATriangle, {0.0, 0.0}, {256.0, 0.0}, {256.0, 256.0}
  //Read http://www.opengl.org/wiki/VBO_-_just_examples
  RenderATriangle();
  //-------------------------
  GLubyte pixels[4*4*4];
  glReadPixels(0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
  //pixels 0, 1, 2 should be white
  //pixel 4 should be black
  //----------------
  //Bind 0, which means render to back buffer
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  //----------------
  //**** Now that we rendered to level 0 of the texture, we must generate the mipmaps.
  //This should be quick since it is done on the GPU.
  glBindTexture(GL_TEXTURE_2D, color_tex);
  glGenerateMipmapEXT(GL_TEXTURE_2D)

And in the end, cleanup

  //Delete resources
  glDeleteTextures(1, &color_tex);
  glDeleteRenderbuffersEXT(1, &depth_rb);
  //Bind 0, which means render to back buffer, as a result, fb is unbound
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  glDeleteFramebuffersEXT(1, &fb);

Quick example, render_to_texture (Cubemap)

//RGBA8 Cubemap texture, 24 bit depth texture, 256x256

 glGenTextures(1, &color_tex);
 glBindTexture(GL_TEXTURE_CUBE_MAP, color_tex);
 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 //NULL means reserve texture memory, but texels are undefined
 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+0, 0, GL_RGBA8, 256, 256, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+1, 0, GL_RGBA8, 256, 256, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+2, 0, GL_RGBA8, 256, 256, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+3, 0, GL_RGBA8, 256, 256, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+4, 0, GL_RGBA8, 256, 256, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+5, 0, GL_RGBA8, 256, 256, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
 //-------------------------
 glGenFramebuffersEXT(1, &fb);
 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
 //Attach one of the faces of the Cubemap texture to this FBO
 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X, color_tex, 0);
 //-------------------------
 glGenRenderbuffersEXT(1, &depth_rb);
 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_rb);
 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, 256, 256);
 //-------------------------
 //Attach depth buffer to FBO
 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_rb);
 //-------------------------
 //Does the GPU support current FBO configuration?
 GLenum status;
 status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
 switch(status)
 {
    case GL_FRAMEBUFFER_COMPLETE_EXT:
    cout<<"good";
 default:
    HANDLE_THE_ERROR;
 }
 //-------------------------
 //and now you can render to GL_TEXTURE_CUBE_MAP_POSITIVE_X
 //In order to render to the other faces, do this :
 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, color_tex, 0);
 //... now render
 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, color_tex, 0);
 //... now render
 //... and so on


And in the end, cleanup

  //Delete resources
  glDeleteTextures(1, &color_tex);
  glDeleteRenderbuffersEXT(1, &depth_rb);
  //Bind 0, which means render to back buffer, as a result, fb is unbound
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  glDeleteFramebuffersEXT(1, &fb);

Quick example, render_to_texture (2D Depth texture ONLY)

 //32 bit depth texture, 256x256
 glGenTextures(1, &depth_tex);
 glBindTexture(GL_TEXTURE_2D, depth_tex);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
 //NULL means reserve texture memory, but texels are undefined
 //You can also try GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24 for the internal format.
 //If GL_DEPTH24_STENCIL8_EXT, go ahead and use it (GL_EXT_packed_depth_stencil)
 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, 256, 256, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
 //-------------------------
 glGenFramebuffersEXT(1, &fb);
 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
 //Attach
 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, depth_tex, 0);
 //-------------------------
 //Does the GPU support current FBO configuration?
 //Before checking the configuration, you should call these 2 according to the spec.
 //At the very least, you need to call glDrawBuffer(GL_NONE)
 glDrawBuffer(GL_NONE);
 glReadBuffer(GL_NONE);
 GLenum status;
 status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
 switch(status)
 {
    case GL_FRAMEBUFFER_COMPLETE_EXT:
    cout<<"good";
 default:
    HANDLE_THE_ERROR;
 }
 //-------------------------
 //----and to render to it, don't forget to call
 //At the very least, you need to call glDrawBuffer(GL_NONE)
 glDrawBuffer(GL_NONE);
 glReadBuffer(GL_NONE);
 //-------------------------
 //If you want to render to the back buffer again, you must bind 0 AND THEN CALL glDrawBuffer(GL_BACK)
 //else GL_INVALID_OPERATION will be raised
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
 glDrawBuffer(GL_BACK);
 glReadBuffer(GL_BACK);

And in the end, cleanup

  //Delete resources
  glDeleteTextures(1, &depth_tex);
  //Bind 0, which means render to back buffer, as a result, fb is unbound
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  glDeleteFramebuffersEXT(1, &fb);

Quick example, render_to_texture (2D), mipmaps, depth_stencil

If GL_EXT_packed_depth_stencil is present, use it. Also called a D24S8 format. All common GPUs support this format.
http://www.opengl.org/registry/specs/EXT/packed_depth_stencil.txt

 //RGBA8 2D texture, D24S8 depth/stencil texture, 256x256
 glGenTextures(1, &color_tex);
 glBindTexture(GL_TEXTURE_2D, color_tex);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
 //NULL means reserve texture memory, but texels are undefined
 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
 //You must reserve memory for other mipmaps levels as well either by making a series of calls to
 //glTexImage2D or use glGenerateMipmapEXT(GL_TEXTURE_2D).
 //Here, we'll use :
 glGenerateMipmapEXT(GL_TEXTURE_2D);
 //-------------------------
 glGenFramebuffersEXT(1, &fb);
 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
 //Attach 2D texture to this FBO
 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, color_tex, 0);
 //-------------------------
 glGenRenderbuffersEXT(1, &depth_stencil_rb);
 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_stencil_rb);
 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, 256, 256);
 //-------------------------
 //Attach depth buffer to FBO
 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_stencil_rb);
 //Also attach as a stencil
 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_stencil_rb);
 //-------------------------
 //Does the GPU support current FBO configuration?
 GLenum status;
 status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
 switch(status)
 {
    case GL_FRAMEBUFFER_COMPLETE_EXT:
    cout<<"good";
 default:
    HANDLE_THE_ERROR;
 }
 //-------------------------
 //and now you can render to GL_TEXTURE_2D
 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
 glClearColor(0.0, 0.0, 0.0, 0.0);
 //It's always a good idea to clear the stencil at the same time as the depth when the format is D24S8.
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |  GL_STENCIL_BUFFER_BIT);
 //-------------------------
 glViewport(0, 0, 256, 256);
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 glOrtho(0.0, 256.0, 0.0, 256.0, -1.0, 1.0); 
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
 //-------------------------
 glDisable(GL_TEXTURE_2D);
 glDisable(GL_BLEND);
 glEnable(GL_DEPTH_TEST);
 //-------------------------
 //**************************
 //RenderATriangle, {0.0, 0.0}, {256.0, 0.0}, {256.0, 256.0}
 //Read http://www.opengl.org/wiki/VBO_-_just_examples
 RenderATriangle();
 //-------------------------
 GLubyte pixels[4*4*4];
 glReadPixels(0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
 //pixels 0, 1, 2 should be white
 //pixel 4 should be black
 //----------------
 //Bind 0, which means render to back buffer
 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

And in the end, cleanup

 //Delete resources
 glDeleteTextures(1, &color_tex);
 glDeleteRenderbuffersEXT(1, &depth_stencil_rb);
 //Bind 0, which means render to back buffer, as a result, fb is unbound
 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
 glDeleteFramebuffersEXT(1, &fb);