OpenGL несколько кадровых буферов и последующая обработка

У меня есть три разных объекта framebuffer для трех разных шагов:

GLuint fbo1;   // Step1: draw initial scene
GLuint fbo2;   // Step2: apply lens effect shader
GLuint fbo3;   // Step3: final smoothing

Я хочу нарисовать мою начальную сцену как текстуру, прикрепленную к fbo1. Затем примените к нему объектив-шейдер и сохраните его как текстуру в fbo2. Затем примените сглаживающий шейдер к fbo2 и сохраните его в fbo3.

Код в моей основной функции рендеринга, использует несколько вспомогательных функций и выглядит следующим образом:

// Step1    
useFrameBuffer(fbo1, fbo1);   // src , dest
DrawInitialScene();

// Step2    
LensShader.use();             // a glsl shader program class 
useFrameBuffer(fbo1, fbo2);   // src , dest
drawQuadOnFbo(fbo2Texture);

// Step3    
SmoothingShader.use();         // a glsl shader program class
useFrameBuffer(fbo2, fbo3);    // src , dest
drawQuadOnFbo(fbo3Texture);

// Final Copy Step to OpenGL default FBO
int width = self.frame.size.width;
int height = self.frame.size.height;
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo3);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); //destination
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);

Вспомогательная функция useFrameBuffer(src, dest) просто устанавливает исходный фрейм-буфер для чтения и целевой фрейм-буфер записи:

void useFrameBuffer (GLuint fboSrc , GLuint fboDest)
{
    glBindFramebuffer(GL_READ_FRAMEBUFFER, fboSrc);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboDest);

    GLenum drawbufs[] = {GL_COLOR_ATTACHMENT0};
    glDrawBuffers(1, drawbufs);
    glReadBuffer(GL_COLOR_ATTACHMENT0);

    glViewport(0, 0, width, height);  // width, height are private to class
}

Чтобы применить шейдер на выходе fbo1 и fbo2, я рисую квад с текстурой, связанной с соответствующими буферами кадров:

void drawQuadOnFbo(GLuint fboTexture) {
    glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // We're not using stencil buffer now
    glBlendFunc(GL_ONE, GL_ONE);

    glBindVertexArray(quadVAO);
    glDisable(GL_DEPTH_TEST);
    glBindTexture(GL_TEXTURE_2D, fboTexture);
    glDrawArrays(GL_TRIANGLES, 0, 6);
    glBindVertexArray(0);
}

Эта проблема:

Проблема заключается в том, что выводом является комбинация только шагов 1 и 3. Похоже, что Step2 полностью пропущен. На последнем шаге копирования вы можете видеть, что я копирую содержимое fbo3 в конечный fbo OpenGL по умолчанию, используя:

glBindFramebuffer (GL_READ_FRAMEBUFFER, fbo3);

Если я изменю это на fbo2, то я вижу результаты применения Step2 (но тогда у меня нет Step3).

Таким образом, похоже, что и fbo2, и fbo3 подключены напрямую к выходу fbo1, но не связаны друг с другом.

Как я могу это исправить??

Другие вспомогательные функции:

Я инициализировал свои Framebuffers в начале приложения, вне основной функции рендеринга, используя метод ниже:

GLuint initFrameBuffer( int width, int height, GLenum textureTarget) {


    // 1. Create FBO
    GLuint fbo;
    glGenFramebuffers(1, &fbo);

    // 2. Bind it
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);

    // FrameBuffer Requirements
    //   (i). atleast 1 buffer (color, depth, stencil)
    //  (ii). atleast 1 color-attachment
    // (iii). all attachments should be complete
    //  (iv). same no. of samples for each buffer

    // 3. Texture Attachment
    GLuint quadTex;  // texture to be associated to this FBO
    glActiveTexture(textureTarget);
    glGenTextures(1, &quadTex);
    glBindTexture(GL_TEXTURE_2D, quadTex);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    // attach it as COLOR-ATTACHMENT 0
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, quadTex, 0);


    // 4. RenderBuffer attachement
    GLuint rbo;
    glGenRenderbuffers(1, &rbo);
    glBindRenderbuffer(GL_RENDERBUFFER, rbo);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
    glBindRenderbuffer(GL_RENDERBUFFER, 0);
    // attach it
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);


    // 5. Set Targets for fragment shader output
    GLenum drawbufs[] = {GL_COLOR_ATTACHMENT0};
    glDrawBuffers(1, drawbufs);

    // 6. Check that the FrameBuffer is complete
    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
        NSLog(@"ERROR::FRAMEBUFFER:: Framebuffer is not complete!");
        return fboObj;
    }

    // 7. revert to Default
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    return fbo;
}

0 ответов

Другие вопросы по тегам