I need to share the color/depth/stencil buffers between two OpenGL contexts. 2D textures are attached to framebuffer object for the buffers. The code looks like below:
// === Start of context 1
//
Create _hDC1, _hRC1;
wglMakeCurrent(hDC1, hRC1);
glGenFramebuffers(1, &_FBO1);
glBindFramebuffer(GL_FRAMEBUFFER, _FBO1);
// color buffer
glGenTextures(1, &_color1);
glBindTexture(GL_TEXTURE2D, _color1);
glTexParameteri(GL_TEXTURE_2D, ..., ); // GL_TEXTURE_WRAP_S, ..., etc.
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA16F, 512, 512);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _color1, 0);
// depth buffer
glGenTextures(1, &_depth1);
glBindTexture(GL_TEXTURE2D, _depth1);
glTexParameteri(GL_TEXTURE_2D, ..., ); // GL_TEXTURE_WRAP_S, ..., etc.
glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, 512, 512);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _depth1, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, _depth1, 0);
// check completeness
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
assert(status == GL_FRAMEBUFFER_COMPLETE); // *pass fine here*
// detach _FBO1
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
glReadBuffer(GL_NONE);
glDrawBuffer(GL_NONE);
//
// === End of context 1
// === Start of context 2
//
Create _hDC2, _hRC2; // pixel format is same as _hDC1
wglShareLists(_hRC2, hRC1); // share objects between _hRC1 and _hRC2
wglMakeCurrent(_hDC2, _hRC2);
// Create another frame buffer, since it is not sharable
glGenFramebuffers(1, &_FBO2);
glBindFramebuffer(GL_FRAMEBUFFER, _FBO2);
// Use the shared textures for color/depth/stencil buffers
glBindTexture(GL_TEXTURE2D, _color1);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _color1, 0);
glBindTexture(GL_TEXTURE2D, _depth1);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _depth1, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, _depth1, 0);
// check completeness
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
assert(status == GL_FRAMEBUFFER_COMPLETE); // *fail here, status is GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT*
//
// === End of context 2
The second completeness check always fails.
Tried move the second completeness check right after attaching the color buffer, and I got the same failure.
Also tried to unbind _color and _depth before creating the second context, but, it did not help.
glGetError() was put after each OpenGL call and no error was detected.
From https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCheckFramebufferStatus.xml
Not all framebuffer attachment points are framebuffer attachment complete. This means that at least one attachment point with a renderbuffer or texture attached has its attached object no longer in existence or has an attached image with a width or height of zero, or the color attachment point has a non-color-renderable image attached, or the depth attachment point has a non-depth-renderable image attached, or the stencil attachment point has a non-stencil-renderable image attached.
Can not figure out what's get missed. Checked several posts online, but none of them is the same use case as mine.
Aha, I messed up with the arguments order when calling wglShareLists(), which should be:
wglShareLists(_hRC1, hRC2);
Everything works now. I should have put an error check around it.
Related
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 am trying to initialize a texture with all zeros, using DRAW framebuffer as suggested by this post. However, I'm quite puzzled that my DRAW framebuffer is only cleared when I attached it to GL_COLOR_ATTACHMENT0:
int levels = 2;
int potW = 2; int potH = 2;
GLuint _potTextureName;
glGenTextures(1, &_potTextureName);
glBindTexture(GL_TEXTURE_2D, _potTextureName);
glTexStorage2D(GL_TEXTURE_2D, levels, GL_RGBA32F, potW, potH);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _potTextureName, 0);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
GLuint clearColor[4] = {0,0,0,0};
glClearBufferuiv(GL_COLOR, 0, clearColor);
Modifying the snippet to use GL_COLOR_ATTACHMENT1, retaining everything else, will NOT clear the framebuffer:
int levels = 2;
int potW = 2; int potH = 2;
GLuint _potTextureName;
glGenTextures(1, &_potTextureName);
glBindTexture(GL_TEXTURE_2D, _potTextureName);
glTexStorage2D(GL_TEXTURE_2D, levels, GL_RGBA32F, potW, potH);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, _potTextureName, 0);
glDrawBuffer(GL_COLOR_ATTACHMENT1);
GLuint clearColor[4] = {0,0,0,0};
glClearBufferuiv(GL_COLOR, 0, clearColor);
I tried using glDrawBuffers instead as suggested here, and I also tried using glClearColor and glClear, but they all behave the same way. What am I missing here?
It turns out that it has todo with what I previously bind to GL_COLOR_ATTACHMENT0.
In the second case, GL_COLOR_ATTACHMENT0 was already bound to a texture of smaller size. There is a note related to Framebuffer Completeness Rules that although there is no restriction on the texture size, the effective size of the FBO is the intersection of the sizes of all bound images. Therefore, in my second case, if the texture (1) bound to GL_COLOR_ATTACHMENT1 is bigger than what I bound to GL_COLOR_ATTACHMENT0, then the texture (1) will only be cleared partially, no matter what clear operation I used (glClear or glClearBuffer*).
The first case turns out to work for me since I only have one texture bound to the FBO, in GL_COLOR_ATTACHMENT0.
I'm trying to do texture rendering using cocos2d and openGL.
After I called
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBufffer)
I checked the status, using:
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
and turned out the status was GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
I also checked the error using
GLenum error = glGetError();
and the result was GL_INVALID_OPERATION
According to the documentation the cause of GL_INVALID_OPERATION is because:
the default framebuffer object name 0 is bound.
or
if renderbuffer is neither 0 nor the name of an existing renderbuffer object
I checked the framebuffer and renderbuffer, neither of them are 0, but I am not sure wheather there is any other rederbuffer object has the same name.
Does any one know how to fix this issue?
The detailed code I was using:
.....
GLint oldRBO;
glGetIntegerv(GL_RENDERBUFFER_BINDING, &oldRBO);
// generate FBO
glGenFramebuffers(1, &_FBO);
glBindFramebuffer(GL_FRAMEBUFFER, _FBO);
// associate texture with FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture.name, 0);
if (depthStencilFormat != 0) {
glGenRenderbuffers(1, &_depthRenderBufffer);
glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderBufffer);
glRenderbufferStorage(GL_RENDERBUFFER, depthStencilFormat, (GLsizei)powW, (GLsizei)powH);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBufffer);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); // the status here will result in GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
GLenum error = glGetError (); // the error here will be GL_INVALID_OPERATION
// I checked the value of _FBO, which was 1, and the value of _depthRenderBufffer was 2
.....
}
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.