C++ OpenGL FBO,MRT写入后台缓冲区
我在Mac上的OpenGL3.3中遇到了一个令人困惑的情况。我已经创建了一个FBO,有五个连接点,每个连接点的大小为512x512。我构建了一个着色器,它可以写入gl_FragData[0-4],用于我的几何体的漫反射、法线、位置、镜面反射和发射。渲染场景时,后缓冲区和渲染目标将被更新,即使我只绑定了FBO 下面是一些代码:C++ OpenGL FBO,MRT写入后台缓冲区,c++,macos,opengl,fbo,C++,Macos,Opengl,Fbo,我在Mac上的OpenGL3.3中遇到了一个令人困惑的情况。我已经创建了一个FBO,有五个连接点,每个连接点的大小为512x512。我构建了一个着色器,它可以写入gl_FragData[0-4],用于我的几何体的漫反射、法线、位置、镜面反射和发射。渲染场景时,后缓冲区和渲染目标将被更新,即使我只绑定了FBO 下面是一些代码: void OpenGLESDriver::setFrameBufferAttachments( u32 nAttachments, const u32* aAtta
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();
}
因此,最终渲染代码如下所示:
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和FBO。我一定错过了什么,但不知道是什么。有人知道我做错了什么吗?经过一番摸索,我终于找到了答案。我的渲染器使用渲染期间填充的RenderNode对象向量。在我完成后期效果后,我没有清除那个向量。出于某种原因,未填充向量将与下一个FBO目标一起渲染,该目标将在第二个FBO中再次绘制所有第一批几何体。通过在渲染过程开始和结束时清除向量,我解决了这个问题。我仍在尝试跟踪是谁再次提交了所有渲染节点。希望我粘贴的代码能够帮助任何希望做FBO的人,因为它毕竟可以工作。:) 实际上,我有点困惑,为什么这
GLenum aBuffers[max]当max
不是常数时,code>编译。我假设USE\u MRT
是未定义的,它是setFrameBufferAttachments
中我们应该关注的第二个代码分支?在C++11中,max不需要是常量。诚然,它不是在VisualStudio下编译的,但这段代码是针对Android和OSX的。这没关系,因为我的Win32渲染器使用DirectX,而我的iOS渲染器使用Metal。Win32代码并没有采用这种技巧。
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();