2015-02-05 122 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的人,因爲它畢竟工作。 :)