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