GL EXT framebuffer multisample
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);