FBO Blitting не работает - PullRequest
       54

FBO Blitting не работает

6 голосов
/ 12 февраля 2012

Я пытаюсь отобразить мультисэмплированную сцену в текстуру, вот код, который я использую. У меня черный экран. Я проверяю полноту fbo в конце init, и они сообщают, что оба fbo завершены.

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);
}

Можете ли вы заметить что-нибудь, что я пропустил? Я думаю, что проблема может быть с вызовом glFramebufferRenderbuffer. Я попытался переключить первый аргумент на GL_READ_FRAMEBUFFER, но это не помогло.

Я проверяю glGetError и ошибок нет. Если я настрою что-то не так, конечно, что-то не получится и даст мне INVALID_ENUM или INVALID_OPERATION, чтобы помочь мне сузить проблему.

Способ, которым я использую этот код, заключается в том, что для включения мультисэмплинга все, что мне нужно изменить, - это связать multi_fbo при рисовании, а затем вызвать функцию разрешения, которая будет связывать и мигать. После этого моя текстура fbo (которая отлично работает, когда я рендерим прямо на нее) теперь должна содержать мультисэмплерный рендер. Но это просто черный. Я также позвонил glEnable(GL_MULTISAMPLE) в другой части кода инициализации.

Теперь я попытаюсь переместить не мультисэмплированную текстуру в другую, чтобы убедиться, что она работает. Надеюсь, это поможет мне сузиться там, где я облажался.

Обновление: получается, что при копировании обычного FBO в другое идентичное FBO (к обоим прикреплены текстуры с цветным вложением 0) получается такой же черный экран. Блит просто не работает.

Что также странно, так это то, что, как только я пытаюсь сделать блиц, а затем нарисую текстуру SOBCE fbo, она все еще остается черной. Это все равно что пытаться заморозить, просто все разрушает.

Кто-нибудь знает или имеет какой-либо блит-код FBO? Я не могу найти ни одного, но я знаю, что люди получили работу FBO с несколькими выборками.

Вот как вы можете помочь: Если у вас есть код, который вызывает glBlitFramebuffer в любой момент, я хотел бы увидеть другие вызовы для настройки этой операции. Кажется, я не могу получить ничего, кроме черных буферов и текстур, как только я его вызову.

Обновление: Blit to backbuffer работает, даже с мультисэмплингом! Это, конечно, не требует абсолютно никакой настройки, так как я просто связываю кадровый буфер 0. Так что проблема, похоже, заключается в моей настройке FBO, у которого есть текстурное вложение, которое должно быть скрыто.

1 Ответ

4 голосов
/ 12 февраля 2012

Оказывается, я не сделал ничего плохого, кроме сброса привязки кадрового буфера.

В конце void resolve_multisample_FBO() Мне просто понадобился glBindFramebuffer(GL_FRAMEBUFFER, 0);

Ужасный способ потратить 3 часа, уверяю вас.Но мультисэмплинг выглядит великолепно и более чем компенсирует это.

...