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 multisample. 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
- glGenFramebuffer***T(1, &fboID);
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID);
- //----------------------
- //Now make a multisample color buffer
- glGenRenderbuffer***T(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
- glGenRenderbuffer***T(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=glCheckFramebufferStatu***T(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
glDeleteRenderbuffer***T(1, &ColorBufferID);
glDeleteRenderbuffer***T(1, &DepthBufferID);
//Bind 0, which means render to back buffer, as a result, fb is unbound
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glDeleteFramebuffer***T(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);
阅读(2320) | 评论(0) | 转发(0) |