2015-02-05 116 views
0

我在Mac上的OpenGL 3.3有一个令人困惑的情况。我创建了一个具有五个连接点的FBO,大小为512x512。我构建了一个着色器,用于为我的几何体写入gl_FragData [0-4]以获得漫反射,法线,位置,镜面反射和发射。当我渲染场景后缓冲区和渲染目标正在更新,即使我只绑定了FBO!OpenGL FBO与MRT写回缓冲区

下面是一些代码:

void OpenGLESDriver::setFrameBufferAttachments(u32 nAttachments, const u32* aAttachments){ 
     pushText("setFrameBufferAttachments"); 
     #if USE_MRT 
      GLint max; 
      glGetIntegerv(GL_MAX_DRAW_BUFFERS, &max); 
      GLenum aBuffers[max]; 
      if(nAttachments > max){ 
      nAttachments = max; 
      } 
      for(u32 i=0; i<nAttachments; ++i){ 
      aBuffers[i] = GL_COLOR_ATTACHMENT0+aAttachments[i]; 
      } 
      for(u32 i=nAttachments; i<max; ++i){ 
      aBuffers[i] = GL_NONE; 
      } 
      glDrawBuffers(max, aBuffers); 
      glAssert(); 
     #else 
      glDrawBuffer(GL_COLOR_ATTACHMENT0+aAttachments[0]); 
      glAssert(); 
     #endif 
     popText(); 
    } 

而且FBO粘结剂:

bool OpenGLESDriver::setFrameBuffer(const FrameBuffer::handle& hFrameBuffer){ 
     if(hFrameBuffer){ 
     pushText("setFrameBuffer"); 
      glBindFramebuffer(GL_FRAMEBUFFER, hFrameBuffer->toFBO()); 
      glAssert(); 
      if(!hFrameBuffer->toColorTargets().empty()){ 
      u32 nAttachments = hFrameBuffer->toColorTargets().size(); 
      u32 aAttachments[nAttachments]; 
      for(u32 i=0; i<nAttachments; ++i){ 
       aAttachments[i] = i; 
      } 
      setFrameBufferAttachments(nAttachments, aAttachments); 
      }else{ 
      setFrameBufferAttachments(0, 0); 
      } 
      int w = hFrameBuffer->toDepthTexture()->toWidth(); 
      int h = hFrameBuffer->toDepthTexture()->toHeight(); 
      glViewport(0, 0, w, h); 
      glAssert(); 
      //clear out all texture stages because we don't want a left over 
      //frame buffer texture being bound to the shader. 
      for(u32 i=0; i<Material::kMaxSamplers; ++i){ 
      setTextureStage(i, 0); 
      } 
     popText(); 
     return true; 
     } 
     return false; 
    } 

我创建FBO有:

FrameBuffer::handle OpenGLESDriver::createFrameBuffer(const FrameBuffer::ColorTargets& vColorTargets, const DepthTarget::handle& hDT){ 

     //-------------------------------------------------------------------- 
     // Save off default FBO. 
     //-------------------------------------------------------------------- 

     if(s_iFBOMaster < 0){ 
     glGetIntegerv(GL_FRAMEBUFFER_BINDING, &s_iFBOMaster); 
     glAssert(); 
     } 

     //-------------------------------------------------------------------- 
     // Generate frame buffer object. 
     //-------------------------------------------------------------------- 

     GLuint fbo; 
     glGenFramebuffers(1, &fbo); 
     glAssert(); 
     glBindFramebuffer(GL_FRAMEBUFFER, fbo); 
     glAssert(); 

     //-------------------------------------------------------------------- 
     // Attach color RBO. 
     //-------------------------------------------------------------------- 

     FrameBuffer::ColorTargets::const_iterator itCT = vColorTargets.getIterator(); 
     u32 mrtIndex = 0; 
     while(itCT){ 
     const ColorTarget::handle& hCT = itCT++; 
     if(!hCT){ 
      continue; 
     } 
     if(hCT->toTexID()){ 
      glFramebufferTexture2D(
       GL_FRAMEBUFFER, 
       GL_COLOR_ATTACHMENT0+mrtIndex, 
       GL_TEXTURE_2D, 
       hCT->toTexID(), 
       0); 
     }else if(hCT->toRBO()){ 
      glFramebufferRenderbuffer(
       GL_FRAMEBUFFER, 
       GL_COLOR_ATTACHMENT0+mrtIndex, 
       GL_RENDERBUFFER, 
       hCT->toRBO()); 
     }else{ 
      DEBUG_ASSERT_ALWAYS("No color texture or RBO to attach!"); 
     } 
     glAssert(); 
     ++mrtIndex; 
     if(!checkFBStatus()){ 
      e_log("GL", "Couldn't create color attachment!"); 
      hCT.as<ColorTarget>()->toFlags()->bFailed = true; 
     } 
     } 

     //-------------------------------------------------------------------- 
     // Attach depth RBO. 
     //-------------------------------------------------------------------- 

     if(hDT){ 
     if(hDT->toTexID()){ 
      glFramebufferTexture2D(
       GL_FRAMEBUFFER, 
       GL_DEPTH_ATTACHMENT, 
       GL_TEXTURE_2D, 
       hDT->toTexID(), 
       0); 
     }else if(hDT->toRBO()){ 
      glFramebufferRenderbuffer(
       GL_FRAMEBUFFER, 
       GL_DEPTH_ATTACHMENT, 
       GL_RENDERBUFFER, 
       hDT->toRBO()); 
     }else{ 
      DEBUG_ASSERT_ALWAYS("No depth texture or RBO to attach!"); 
     } 
     glAssert(); 
     if(!checkFBStatus()){ 
      e_log("GL", "Couldn't create depth attachment!"); 
      hDT.as<DepthTarget>()->toFlags()->bFailed = true; 
     } 
     } 

     //-------------------------------------------------------------------- 
     // New handle. 
     //-------------------------------------------------------------------- 

     glBindFramebuffer(GL_FRAMEBUFFER, 0); 
     glAssert(); 

     FrameBuffer::handle hFrameBuffer = e_new(FrameBuffer); 
     hFrameBuffer->setColorTargets(vColorTargets); 
     hFrameBuffer->setDepthTarget(hDT); 
     hFrameBuffer->setFBO(u32(fbo)); 
     return hFrameBuffer; 
    } 

我回去与后台缓冲区:

void OpenGLESDriver::setDefaultTarget(){ 
     pushText("setDefaultTarget"); 
     glBindFramebuffer(GL_FRAMEBUFFER, 0);//s_iFBOMaster); 
     glAssert(); 
     glViewport(0, 0, IEngine::cxView(), IEngine::cyView()); 
     glAssert(); 
     popText(); 
    } 

所以最终的渲染代码如下所示:

 pushText("Render MRT pass"); 
      if(setFrameBuffer(m_tPostFx.buffers[0])){ 
      setColorMask(true, true, true, true); 
      clearZ(); 
      enableZBuffer(false); 
      setColor(color); 
      clearMRT(m_tPostFx.clearMRTShader); 
      enableZBuffer(true); 
      drawMRTPass(); 
      } 
     popText(); 

,由于某种原因后缓冲器被渲染到还有FBO。我一定错过了一些东西,但没有弄清楚什么。任何人都可以看到我做错了什么?

+0

我实际上有点困惑,为什么_this_' GLenum aBuffers [max];'编译'max'不是一个常量。我假设'USE_MRT'是未定义的,它是'setFrameBufferAttachments'中我们应该关注的第二个代码分支? – 2015-02-05 20:29:53

+0

在C++ 11 max中不需要是常量。诚然,它不在Visual Studio下编译,但是这个代码适用于Android和OSX。没关系,因为我的Win32渲染器使用DirectX,而我的iOS使用的是Metal。 Win32代码不会诉诸于这种欺骗。 – toymaker 2015-02-09 15:55:40

回答

0

经过一番摸索,我终于找到答案。我的渲染器使用渲染过程中填满的RenderNode对象的向量。在完成我的后效后,我没有清除那个向量。由于某些原因,未填充的矢量正在使用下一个FBO目标进行渲染,该目标在第二个FBO中再次绘制了第一批几何图形。通过在渲染过程的开始处清除矢量,并在最后我摆脱了这个问题。我仍然试图追查谁再次提交所有渲染节点。希望我粘贴的代码将帮助任何想要做FBO的人,因为它毕竟工作。 :)