GL EXT framebuffer multisample

From OpenGL Wiki
Revision as of 18:21, 12 December 2008 by V-man (talk | contribs)
Jump to navigation Jump to search

Examples :


When GL_EXT_framebuffer_multisample is supported, GL_EXT_framebuffer_object and GL_EXT_framebuffer_blit are also supported.

  uint fboID, ColorBufferID, DepthBufferID;
  sint samples;
  schar ErrorMessage[1024];
  //We need to find out what the maximum supported samples is
  glGetIntegerv(GL_MAX_SAMPLES_EXT, &samples);
  //----------------------
  //If for example, 16 is returned, then you can attempt to make a FBO with samples=0 to 16
  //0 means no multiple. This is like using glFramebufferRenderbufferEXT instead of glRenderbufferStorageMultisampleEXT
  //You can attempt to make sample from 1 to 16, but some of them might fail
  //Now, let's make a FBO
  glGenFramebuffersEXT(1, &fboID);
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID);
  //----------------------
  //Now make a multisample color buffer
  glGenRenderbuffersEXT(1, &ColorBufferID);
  glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, ColorBufferID);
  //samples=4, format=GL_RGBA8, width=256, height=256
  glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, 4, GL_RGBA8, 256, 256);
  //----------------------
  //Make a depth multisample depth buffer
  //You must give it the same samples as the color RB, same width and height as well
  //else you will either get a GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT or some other error
  glGenRenderbuffersEXT(1, &DepthBufferID);
  glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, DepthBufferID);
  //samples=4, format=GL_DEPTH_COMPONENT24, width=256, height=256
  glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, 4, GL_DEPTH_COMPONENT24, 256, 256);
  //----------------------
  //It's time to attach the RBs to the FBO
  glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, ColorBufferID);
  glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, DepthBufferID);
  //----------------------
  //Make sure FBO status is good
  value=glExtCheckFramebufferStatus(ErrorMessage);
  sint glExtCheckFramebufferStatus(schar *errorMessage)
  {
  GLenum status;
  status=glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
  switch(status)
  {
  case GL_FRAMEBUFFER_COMPLETE_EXT:
  break;
  case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
  //Choose different formats
  strcpy(errorMessage, "Framebuffer object format is unsupported by the video hardware. (GL_FRAMEBUFFER_UNSUPPORTED_EXT)(FBO - 820)");
  return -1;
  case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
  strcpy(errorMessage, "Incomplete attachment. (GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT)(FBO - 820)");
  return -1;
  case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
  strcpy(errorMessage, "Incomplete missing attachment. (GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT)(FBO - 820)");
  return -1;
  case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
  strcpy(errorMessage, "Incomplete dimensions. (GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT)(FBO - 820)");
  return -1;
  case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
  strcpy(errorMessage, "Incomplete formats. (GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT)(FBO - 820)");
  return -1;
  case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
  strcpy(errorMessage, "Incomplete draw buffer. (GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT)(FBO - 820)");
  return -1;
  case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
  strcpy(errorMessage, "Incomplete read buffer. (GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT)(FBO - 820)");
  return -1;
  case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT:
  strcpy(errorMessage, "Incomplete multisample buffer. (GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT)(FBO - 820)");
  return -1;
  default:
  //Programming error; will fail on all hardware
  strcpy(errorMessage, "Some video driver error or programming error occured. Framebuffer object status is invalid. (FBO - 823)");
  return -2;
  }
  return 1;
  }

And in the end, cleanup

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

More info ...

Since you can't read the multisample buffer directly with glReadPixels since it would raise an error flag (GL_INVALID_OPERATION), what should you do?
You need to blit to another surface so that the GPU can do a downsample. You could blit to the backbuffer, but there is the problem of the "pixel owner ship test". It is best to make another FBO.
Let's assume you made another FBO and now you want blit.
This requires GL_EXT_framebuffer_blit. Typically, when your driver supports GL_EXT_framebuffer_multisample, it also supports GL_EXT_framebuffer_blit, for example the nVidia Geforce 8 series.

 //Bind the MS FBO
 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, multisample_fboID);
 //Bind the standard FBO
 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fboID);
 //Let's say I want to copy the entire surface
 //Let's say I only want to copy the color buffer only
 //Let's say I don't need the GPU to do filtering since both surfaces have the same dimension
 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
 //--------------------
 //Bind the standard FBO for reading
 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID);
 glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, pixels);