I am getting a weird OpenGL error when running my application on my HD4000 (Windows 64bit, driver version 15.28.20.64.3347).
I boiled it down to a few OpenGL calls to reproduce it:
Create two framebuffer objects.
Create a texture and bind it as GL_COLOR_ATTACHMENT0 to both FBOs.
Call glTexImage2D a second time on the texture
Bind the first FBO and call glCheckFramebufferStatus (returns GL_FRAMEBUFFER_COMPLETE).
Bind the second FBO and call glClear. The glClear gives an GL_INVALID_FRAMEBUFFER_OPERATION.
Step 3 and 4 are required to reproduce the error, which I find especially disturbing for the glCheckFramebufferStatus call. The problem also does not occur on other graphics cards (including the Nvidia card on the same machine).
If you call glCheckFramebufferStatus on the second FBO, it also returns GL_FRAMEBUFFER_COMPLETE. However, when inspecting the internal OpenGL state with apitrace, it says that the second FBO has now a color attachment with object name zero.
Re-binding the texture to the second FBO after the glCheckFramebufferStatus call resolves the error. This is working as a workaround for now, but I suppose that binding textures to various FBOs each frame is not a good idea.
Here is the C++ code that reproduces the error:
// Create a texture and bind it to two FBOs
GLuint textureName;
glGenTextures(1, &textureName);
glBindTexture(GL_TEXTURE_RECTANGLE, textureName);
glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
GLuint fboNames[2];
glGenFramebuffers(2, fboNames);
glBindFramebuffer(GL_FRAMEBUFFER, fboNames[0]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, textureName, 0);
glBindFramebuffer(GL_FRAMEBUFFER, fboNames[1]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, textureName, 0);
glBindTexture(GL_TEXTURE_RECTANGLE, textureName);
glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindFramebuffer(GL_FRAMEBUFFER, fboNames[0]);
// Removing this line resolves the error
glCheckFramebufferStatus(GL_FRAMEBUFFER); // Returns GL_FRAMEBUFFER_COMPLETE
glBindFramebuffer(GL_FRAMEBUFFER, fboNames[1]);
GLenum bufferTarget = GL_COLOR_ATTACHMENT0;
glDrawBuffers(1, &bufferTarget);
// Adding this line resolves the error
// glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_RECTANGLE, 1, 0);
glCheckFramebufferStatus(GL_FRAMEBUFFER); // Returns GL_FRAMEBUFFER_COMPLETE
//This call causes a GL_INVALID_FRAMEBUFFER_OPERATION error.
glClear(GL_COLOR_BUFFER_BIT);
Here is a minimal Visual Studio 2013 Project to reproduce it: https://www.dropbox.com/s/5142j26d839gkp9/HD4000Error.zip
Now, my question is: Am I doing something illegal with OpenGL here or is this simply a driver bug?
We reported this issue to Intel and it seems that it was in fact a bug. It is fixed in the current driver version.
Related
I'm trying to copy one GL_TEXTURE_2D into a chosen slice of a GL_TEXTURE_2D_ARRAY Texture.
I try to bind the usual Texture_2D to one framebuffer and only a slice of the Texture_2D_Array to another framebuffer (both have the same size (width, height, GL_RGB, GL_UNSIGNED_BYTE)).
Afterwards I thought to glBlitFramebuffer would copy that texture into this one slice... but I think I misunderstand the glFramebufferTexture3D command.
BTW: the GL_TEXTURE_2D is loaded correctly and I also printed it out (works)
Here my code:
//Create 2 FBOs for copying textures
glGenFramebuffers(1, &nFrameBufferRead); //FBO for texture2D
glGenFramebuffers(1, &nFrameBufferWrite); //FBO for one slice of the texture2d_array
CBasics::GetOpenGLError();
//generate the GL_TEXTURE_2D_ARRAY with given values (glgentextures is already called for this texture)
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, nWidth, nHeight, countSlices, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
CBasics::GetOpenGLError();
//Bind the Texture2D to the readFramebuffer
glBindFramebuffer(GL_READ_FRAMEBUFFER, nFrameBufferRead);
glFramebufferTexture(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture2D_ID, 0);
CBasics::GetOpenGLError();
//try to bind the Texture2D_Array to the drawFramebuffer
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, nFrameBufferWrite);
CBasics::GetOpenGLError(); //till here everything works (no glerror)
glFramebufferTexture3D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_ARRAY, texture2D_Array_ID, 0, slicenumber); // here the error appears
CBasics::GetOpenGLError();
//because of the error one step earlier here will be the next error...
glBlitFramebuffer(0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
CBasics::GetOpenGLError();
at glFramebufferTexture3D the error appears: GL_INVALID_VALUE
I think it is because of
GL_INVALID_VALUE is generated if texture is not zero or the name of an
existing texture object.
1st: Is this way to copy textures into arrayslices correctly? Or is there a better way to do that?
2nd: Is it possible to bind only one slice of a GL_TEXTURE_2D_ARRAY?
3rd: Do I need the glFramebufferTexture3D command or the glFramebufferTexture2D command for GL_TEXTURE_2D_ARRAYs?
Assuming that "Here's my code" actually does contain all of your code, it doesn't work because you didn't bind the 2D array texture before calling glTexImage3D to allocate storage for it.
However, you don't have to render or blit to copy texture data. You can copy texture data by... copying texture data. The glCopyImageSubData function can copy layers between textures with different array layer counts. In your case:
glCopyImageSubData(
texture2D_ID, GL_TEXTURE_2D, 0, 0, 0, 0,
texture2D_Array_ID, GL_TEXTURE_2D_ARRAY, 0, 0, 0, slicenumber,
nWidth, nHeight, 1);
This requires OpenGL 4.3 or better, or one of the ARB/NV_copy_image extensions. The NVIDIA extension is actually quite widely implemented.
But you still need to use glTexImage3D correctly.
An OpenGL FBO is created and bind color buffer and stencil buffer to it .
glCheck(glBindFramebuffer(GL_FRAMEBUFFER, fbo));
// Delete old framebuffers if ever created.
if ( clrRbo != 0)
glDeleteRenderbuffers(1, & clrRbo);
if ( stencilRbo != 0)
glDeleteRenderbuffers(1, & stencilRbo);
// Create new framebuffers with new size.
int maxSize; glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &maxSize);
glCheck(glGenRenderbuffers(1,&clrRbo));
glCheck(glBindRenderbuffer(GL_RENDERBUFFER,clrRbo));
glCheck(glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, (std::min)(maxSize,m_localvp.pix_width),(std::min)(maxSize, m_localvp.pix_height)))
glCheck(glGenRenderbuffers(1,&stencilRbo));
glCheck(glBindRenderbuffer(GL_RENDERBUFFER,stencilRbo));
glCheck(glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX, (std::min)(maxSize,m_localvp.pix_width),(std::min)(maxSize, m_localvp.pix_height)))
// Bind new framebuffers to FBO;
glCheck(glBindFramebuffer(GL_FRAMEBUFFER, fbo));
glCheck(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, clrRbo));
glCheck(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencilRbo));
Problem that bothers me lies at :
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, (std::min)(maxSize,m_localvp.pix_width),(std::min)(maxSize, m_localvp.pix_height))
This call fails (get GL_INVALID_OPERATION error ) when different internal formats are used, which caused the failed creation of FBO. Some machine works fine with GL_RGBA and some works with GL_RGBA8, and some works with both. What's the difference between GL_RGBA8 and GL_RGBA. How could I figure out which format is supported on current machine?
How can I attach a depth-buffer to my framebufferobject when I use GL_TEXTURE_2D_MULTISAMPLE. glCheckFramebufferStatus(msaa_fbo) from the code below returns 0. From the documentation this seems to mean that msaa_fba is not a framebuffer, but it is created from glGenFramebuffers(1, &msaa_fbo);.
Additionally, if an error occurs, zero is returned.
GL_INVALID_ENUM is generated if target is not GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER or GL_FRAMEBUFFER.
The error is 1280, which I think means GL_INVALID_ENUM.
If i remove the depth buffer attachment the program runs and renders (although without depth testing). The error is still present when it runs then. With the depth attachment included there is an error (1286) after every frame, which is INVALID_FRAMEBUFFER. I don't know how to continue from here. Some examples I've looked at do somewhat the same but seem to work.
glGenTextures(1, &render_target_texture);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, render_target_texture);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, NUM_SAMPLES, GL_RGBA8, width, height, false);
glGenFramebuffers(1, &msaa_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, msaa_fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, render_target_texture, 0);
glGenRenderbuffers(1, &depth_render_buffer);
glBindRenderbuffer(GL_RENDERBUFFER, depth_render_buffer);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, NUM_SAMPLES, GL_DEPTH_COMPONENT24, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_render_buffer);
GLenum status = glCheckFramebufferStatus(msaa_fbo);
Most of the code is from this.
EDIT
The status check was wrong, it should've been GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);. Now there is no error when I don't include the depth. When I include depth I get this error now: GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE.
EDIT 2
Documentation claims that this happens when GL_TEXTURE_SAMPLES and GL_RENDERBUFFER:SAMPLES don't match.
GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE is returned if the value of GL_RENDERBUFFER_SAMPLES is not the same for all attached renderbuffers; if the value of GL_TEXTURE_SAMPLES is the not same for all attached textures; or, if the attached images are a mix of renderbuffers and textures, the value of GL_RENDERBUFFER_SAMPLES does not match the value of GL_TEXTURE_SAMPLES.
But they do!
I've tested them like this:
std::cout << "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE" << std::endl;
GLsizei gts, grs;
glGetTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_SAMPLES, >s);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &grs);
std::cout << "GL_TEXTURE_SAMPLES: " << gts << std::endl;
std::cout << "GL_RENDERBUFFER_SAMPLES: " << grs << std::endl;
Output is:
GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE
GL_TEXTURE_SAMPLES: 8
GL_RENDERBUFFER_SAMPLES: 8
EDIT 3
Worked around this by using two textures instead of a texture and a renderbuffer like this:
glGenFramebuffers(1, &msaa_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, msaa_fbo);
glGenTextures(1, &render_texture);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, render_texture);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, NUM_SAMPLES, GL_RGBA8, width, height, false);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, render_texture, 0);
glGenTextures(1, &depth_texture);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, depth_texture);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, NUM_SAMPLES, GL_DEPTH_COMPONENT, width, height, false);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, depth_texture, 0);
I'm am still interested in what was wrong with the original implementation, so question is still standing.
You need to used fixed sample locations for the texture if you mix it with renderbuffers. From the spec, in section "Framebuffer Completeness":
The value of TEXTURE_FIXED_SAMPLE_LOCATIONS is the same for all attached textures; and, if the attached images are a mix of renderbuffers and textures, the value of TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
{FRAMEBUFFER_INCOMPLETE_MULTISAMPLE}
To avoid this error condition, you the call for setting up the texture storage needs to be changed to:
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,
NUM_SAMPLES, GL_RGBA8, width, height, GL_TRUE);
I'm trying to implement color picking with FBO. I have multisampled FBO (fbo[0]) which I use to render the scene and I have non multisampled FBO (fbo[1]) which I use for color picking.
The problem is: when I try to read pixel data from fbo[1] everything goes well until glReadPixels call which sets GL_INVALID_OPERATION flag. I've checked the manual and can't find the reason why.
The code to create FBO:
glBindRenderbuffer(GL_RENDERBUFFER, rbo[0]);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL_RGBA8, resolution[0], resolution[1]);
glBindRenderbuffer(GL_RENDERBUFFER, rbo[1]);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL_DEPTH24_STENCIL8, resolution[0], resolution[1]);
glBindRenderbuffer(GL_RENDERBUFFER, rbo[2]);
glRenderbufferStorage(GL_RENDERBUFFER, GL_R32UI, resolution[0], resolution[1]);
glBindRenderbuffer(GL_RENDERBUFFER, rbo[3]);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, resolution[0], resolution[1]);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo[1]);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo[3]);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo[2]);
OGLChecker::checkFBO(GL_DRAW_FRAMEBUFFER);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo[0]);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo[1]);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo[0]);
OGLChecker::checkFBO(GL_DRAW_FRAMEBUFFER);
My checker stays silent so the FBOs are complete. Next the picking code
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo[1]);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// bla, bla, bla
// do the rendering
unsigned int result;
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo[1]);
int sb;
glReadBuffer(GL_COLOR_ATTACHMENT0);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
glGetIntegerv(GL_SAMPLE_BUFFERS, &sb);
// glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
OGLChecker::getGlError();
std::cerr << "Sample buffers " << sb << std::endl;
glReadPixels(pos.x(), resolution.y() - pos.y(), 1, 1, GL_RED, GL_UNSIGNED_INT, &result);
OGLChecker::getGlError();
return result;
the output:
Sample buffers 0
OpenGL Error : Invalid Operation
The interesting fact that if I uncomment glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); then no error happens and pixels are read from screen (but I don't need this).
What may be wrong here?
Your problem is the format parameter. For a texture that has a one-channel integer internal format the correct parameter isn't GL_RED, but GL_RED_INTEGER:
glReadPixels(pos.x(), resolution.y() - pos.y(), 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &result);
Look at the OpenGL documentation wiki (emphasis mine):
...
format
Specifies the format of the pixel data. For transfers of depth, stencil, or depth/stencil data, you must use GL_DEPTH_COMPONENT, GL_STENCIL_INDEX, or GL_DEPTH_STENCIL, where appropriate. For transfers of normalized integer or floating-point color image data, you must use one of the following: GL_RED, GL_GREEN, GL_BLUE, GL_RG, GL_RGB, GL_BGR, GL_RGBA, and GL_BGRA. For transfers of non-normalized integer data, you must use one of the following: GL_RED_INTEGER, GL_GREEN_INTEGER, GL_BLUE_INTEGER, GL_RG_INTEGER, GL_RGB_INTEGER, GL_BGR_INTEGER, GL_RGBA_INTEGER, and GL_BGRA_INTEGER. Even if no actual pixel transfer is made (data is NULL and no buffer is bound to GL_PIXEL_UNPACK_BUFFER), you must set this parameter correctly for the internal format of the destination image.
...
Note: the official reference page is incomplete/wrong.
Given that it's "fixed" if you uncomment that line of code, I wonder if your driver is lying to you about GL_SAMPLE_BUFFERS being 0. From http://www.opengl.org/sdk/docs/man/xhtml/glReadPixels.xml:
GL_INVALID_OPERATION is generated if GL_READ_FRAMEBUFFER_BINDING is non-zero, the read framebuffer is complete, and the value of GL_SAMPLE_BUFFERS for the read framebuffer is greater than zero.
If you're using NVIDIA's binary driver on Linux and have switched to a non-graphical virtual console (e.g. CTRL+ALT+F1) then any attempt to glReadPixels() will return GL_INVALID_OPERATION (0x502).
Solution: Switch back to the graphical console (usually CTRL+ALT+F7).
I'm trying to render a multisampled scene to texture, here is the code I'm using. I'm getting a black screen. I check the fbo completeness at the end of init, and they report that both fbo's are complete.
void init_rendered_FBO() {
glGenFramebuffers(1,&fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glGenTextures(1,&fbo_tex);
glBindTexture(GL_TEXTURE_2D, fbo_tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width_screen, height_screen, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width_screen, height_screen);
glBindTexture (GL_TEXTURE_2D, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo_tex, 0);
int objectType;
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,&objectType);
ASSERT(objectType == GL_TEXTURE);
int objectName;
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,&objectName);
ASSERT(glIsTexture(objectName) == GL_TRUE);
int wid, hei, fmt;
glBindTexture(GL_TEXTURE_2D, objectName);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &wid);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &hei);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT,
&fmt);
glBindTexture(GL_TEXTURE_2D, 0);
std::string format = convertInternalFormatToString(fmt);
std::cout << "Color attachment 0: " << objectName << " " << wid << "x" << hei << ", " << format << std::endl;
ASSERT(checkFramebufferStatus());
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
// this is the init function that gets called.
void init_rendered_multisample_FBO() {
init_rendered_FBO();
// now I'm going to set up the additional component necessary to perform multisampling which is a new fbo
// that has a multisampled color buffer attached. I won't need a multisample depth buffer.
glGenFramebuffers(1,&multi_fbo);
glBindFramebuffer(GL_FRAMEBUFFER,multi_fbo);
glGenRenderbuffers(1,&renderbuffer_multi);
glBindRenderbuffer(GL_RENDERBUFFER,renderbuffer_multi);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA, width_screen,height_screen);
glBindRenderbuffer(GL_RENDERBUFFER,0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer_multi);
int objectType;
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,&objectType);
ASSERT(objectType == GL_RENDERBUFFER);
int objectName;
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,&objectName);
ASSERT(glIsRenderbuffer(objectName) == GL_TRUE);
glBindRenderbuffer(GL_RENDERBUFFER,objectName);
int wid,hei,fmt,sam;
glGetRenderbufferParameteriv(GL_RENDERBUFFER,GL_RENDERBUFFER_WIDTH,&wid);
glGetRenderbufferParameteriv(GL_RENDERBUFFER,GL_RENDERBUFFER_HEIGHT,&hei);
glGetRenderbufferParameteriv(GL_RENDERBUFFER,GL_RENDERBUFFER_INTERNAL_FORMAT,&fmt);
glGetRenderbufferParameteriv(GL_RENDERBUFFER,GL_RENDERBUFFER_SAMPLES,&sam);
glBindRenderbuffer(GL_RENDERBUFFER,0);
printf("Renderbuffer: %dx%d, fmt=%d, samples=%d\n",wid,hei,fmt,sam);
ASSERT(checkFramebufferStatus());
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
// this is called after rendering to multi_fbo
void resolve_multisample_FBO() {
glBindFramebuffer(GL_READ_FRAMEBUFFER, multi_fbo);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
GLenum drawbuf = GL_COLOR_ATTACHMENT0;
glDrawBuffers(1,&drawbuf);
glBlitFramebuffer(0,0,width_screen,height_screen,0,0,width_screen,height_screen,GL_COLOR_BUFFER_BIT,GL_NEAREST);
}
Can you spot anything I left out? I think the issue may be with the glFramebufferRenderbuffer call. I tried switching the first arg to GL_READ_FRAMEBUFFER but it did not fix.
I check glGetError and there are no errors. If I setup something wrong, surely something will fail and give me INVALID_ENUM or INVALID_OPERATION to help me narrow down the issue.
The way I use this code is that in order to enable multisampling all I have to change is to bind multi_fbo when drawing, and then call the resolve function which will bind and blit. After that, my fbo texture (which works fine when I render directly to it) should now contain the multisampled render. But it's just black. I also did call glEnable(GL_MULTISAMPLE) in another part of initialization code.
I'm now going to attempt to blit a non multisampled texture to another texture to make sure that works. Hopefully that will help me narrow down where I screwed up.
Update: So it turns out copying a regular FBO to another identical FBO (both have textures attached to color attachment 0) produces the same black screen. The blit simply doesn't work.
What is also strange is that once I attempt to blit, then draw the texture of the SOURCE fbo, it's still all black. It's like attempting to blit just ruins everything.
Does anybody know of or have any FBO blitting code? I can't find any but I know people have gotten multisampled FBO's working.
Here's how you can help: If you have code which calls glBlitFramebuffer at any point, I would like to see the other calls for setting that operation up. I can't seem to get anything but black buffers and textures once I invoke it.
Update: Blit to backbuffer works, even with multisampling! This of course requires absolutely no setup since I just bind the framebuffer 0. So the problem seems to be my setting up of the FBO which has a texture attachment which is supposed to be blitted to.
Well turns out I didn't do anything wrong other than fail to reset the framebuffer binding.
At the end of void resolve_multisample_FBO() I simply needed a glBindFramebuffer(GL_FRAMEBUFFER, 0);
A terrible way to waste 3 hours, I assure you. But multisampling looks great and more than makes up for it.