FBO Blitting is not working

半世苍凉 提交于 2019-12-21 12:57:20

问题


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.


回答1:


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.



来源:https://stackoverflow.com/questions/9248223/fbo-blitting-is-not-working

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!