繁体   English   中英

带有MRT的OpenGL FBO向后缓冲区写入

[英]OpenGL FBO with MRT writing to back buffer

在Mac上的OpenGL 3.3中,我有一个令人困惑的情况。 我创建了一个FBO,其中包含五个固定点,每个固定点的大小为512x512。 我构造了一个着色器,该着色器写入gl_FragData [0-4]以获取几何体的漫反射,法线,位置,镜面反射和发射。 当我渲染场景时,即使我只绑定了FBO,后台缓冲区和渲染目标也会被更新!

这是一些代码:

    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也被渲染。 我一定想念一些东西,但是什么都不知道。 谁能看到我在做什么错?

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM