Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics
[Home] [Tutorials] [All Classes] [Grouped Classes]

X:/dropbox/visualizationlibrary/src/vlGraphics/FramebufferObject.cpp

Go to the documentation of this file.
00001 /**************************************************************************************/
00002 /*                                                                                    */
00003 /*  Visualization Library                                                             */
00004 /*  http://www.visualizationlibrary.org                                               */
00005 /*                                                                                    */
00006 /*  Copyright (c) 2005-2011, Michele Bosi                                             */
00007 /*  All rights reserved.                                                              */
00008 /*                                                                                    */
00009 /*  Redistribution and use in source and binary forms, with or without modification,  */
00010 /*  are permitted provided that the following conditions are met:                     */
00011 /*                                                                                    */
00012 /*  - Redistributions of source code must retain the above copyright notice, this     */
00013 /*  list of conditions and the following disclaimer.                                  */
00014 /*                                                                                    */
00015 /*  - Redistributions in binary form must reproduce the above copyright notice, this  */
00016 /*  list of conditions and the following disclaimer in the documentation and/or       */
00017 /*  other materials provided with the distribution.                                   */
00018 /*                                                                                    */
00019 /*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
00020 /*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
00021 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
00022 /*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
00023 /*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
00024 /*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
00025 /*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
00026 /*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
00027 /*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
00028 /*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
00029 /*                                                                                    */
00030 /**************************************************************************************/
00031 
00032 #include <vlCore/VisualizationLibrary.hpp>
00033 #include <vlGraphics/FramebufferObject.hpp>
00034 #include <vlGraphics/OpenGLContext.hpp>
00035 #include <vlCore/GlobalSettings.hpp>
00036 #include <vlCore/Say.hpp>
00037 #include <vlCore/Log.hpp>
00038 
00039 using namespace vl;
00040 
00041 namespace
00042 {
00043   class ScopedFBOBinding
00044   {
00045     GLint mPrevFBO;
00046   public:
00047     ScopedFBOBinding( FramebufferObject* fbo )
00048     {
00049       VL_CHECK( fbo );
00050       VL_CHECK( fbo->handle() );
00051       /*if ( !fbo->handle() )
00052         fbo->create();*/
00053 
00054       // saves current FBO
00055       mPrevFBO = 0;
00056       glGetIntegerv( GL_FRAMEBUFFER_BINDING, &mPrevFBO ); VL_CHECK_OGL()
00057 
00058       // binds this FBO
00059       VL_glBindFramebuffer( GL_FRAMEBUFFER, fbo->handle() ); VL_CHECK_OGL()
00060     }
00061 
00062     ~ScopedFBOBinding()
00063     {
00064       // restore the FBO
00065       VL_glBindFramebuffer( GL_FRAMEBUFFER, mPrevFBO ); VL_CHECK_OGL()
00066     }
00067   };
00068 }
00069 //-----------------------------------------------------------------------------
00070 // FramebufferObject
00071 //-----------------------------------------------------------------------------
00072 void FramebufferObject::createFBO()
00073 {
00074   VL_CHECK_OGL();
00075   VL_CHECK(openglContext());
00076   openglContext()->makeCurrent(); VL_CHECK_OGL();
00077 
00078   if ( !mHandle )
00079   {
00080     VL_glGenFramebuffers( 1, ( unsigned int* )&mHandle ); VL_CHECK_OGL();
00081   }
00082   VL_CHECK( mHandle )
00083 }
00084 //-----------------------------------------------------------------------------
00085 void FramebufferObject::deleteFBO()
00086 {
00087   VL_CHECK_OGL();
00088   VL_CHECK(openglContext());
00089   openglContext()->makeCurrent(); VL_CHECK_OGL();
00090 
00091   removeAllAttachments();
00092   if ( handle() )
00093   {
00094     VL_glBindFramebuffer( GL_FRAMEBUFFER, 0 ); VL_CHECK_OGL();
00095     VL_glDeleteFramebuffers( 1, &mHandle ); VL_CHECK_OGL();
00096     mHandle = 0;
00097   }
00098   setWidth( 0 );
00099   setHeight( 0 );
00100 }
00101 //-----------------------------------------------------------------------------
00102 void FramebufferObject::bindFramebuffer( EFramebufferBind target )
00103 {
00104   VL_CHECK_OGL();
00105   VL_CHECK(openglContext());
00106   openglContext()->makeCurrent(); VL_CHECK_OGL();
00107 
00108   if ( !Has_FBO )
00109   {
00110     Log::error( "FramebufferObject::bindFramebuffer(): framebuffer object not supported.\n" );
00111     return;
00112   }
00113 
00114   if ( width() <= 0 || height() <= 0 )
00115   {
00116     Log::error( Say( "FramebufferObject::bindFramebuffer() called with illegal dimensions: width = %n, height = %n\n" ) << width() << height() );
00117     VL_TRAP()
00118   }
00119 
00120   if ( mFBOAttachments.empty() )
00121   {
00122     Log::error( "FramebufferObject::bindFramebuffer() called with no attachment points!\n" );
00123     VL_TRAP()
00124   }
00125 
00126   if ( !handle() )
00127   {
00128     Log::error( "FramebufferObject::bindFramebuffer() called but handle() == NULL!\n" );
00129     VL_TRAP()
00130   }
00131 
00132   VL_glBindFramebuffer( target, handle() ); VL_CHECK_OGL()
00133 
00134 #if defined(VL_OPENGL)
00135   // bind draw buffers
00136   if (target == FBB_FRAMEBUFFER || target == FBB_DRAW_FRAMEBUFFER)
00137     bindDrawBuffers();
00138 
00139   // bind read buffer
00140   if (target == FBB_FRAMEBUFFER || target == FBB_READ_FRAMEBUFFER)
00141     bindReadBuffer();
00142 #endif
00143 
00144   #ifndef NDEBUG
00145     GLenum status = VL_glCheckFramebufferStatus( GL_FRAMEBUFFER ); VL_CHECK_OGL()
00146     if ( status != GL_FRAMEBUFFER_COMPLETE )
00147     {
00148       VL_glBindFramebuffer( GL_FRAMEBUFFER, 0 ); VL_CHECK_OGL()
00149     }
00150     printFramebufferError( status );
00151   #endif
00152 }
00153 //-----------------------------------------------------------------------------
00155 GLenum FramebufferObject::checkFramebufferStatus()
00156 {
00157   VL_CHECK_OGL();
00158   VL_CHECK(openglContext());
00159   openglContext()->makeCurrent(); VL_CHECK_OGL();
00160 
00161   if ( !Has_FBO )
00162   {
00163     Log::error( "FramebufferObject::checkFramebufferStatus(): framebuffer object not supported.\n" );
00164     return 0;
00165   }
00166 
00167   if ( width() <= 0 || height() <= 0 )
00168   {
00169     Log::error( Say( "FramebufferObject::checkFramebufferStatus() called with illegal dimensions: width = %n, height = %n\n" ) << width() << height() );
00170     return 0;
00171   }
00172 
00173   if ( mFBOAttachments.empty() )
00174   {
00175     Log::error( "FramebufferObject::checkFramebufferStatus() called with no attachment points!\n" );
00176     return 0;
00177   }
00178 
00179   if ( !handle() )
00180   {
00181     Log::error( "FramebufferObject::checkFramebufferStatus() called but handle() == NULL!\n" );
00182     return 0;
00183   }
00184 
00185   // binds the FBO for this function call
00186   ScopedFBOBinding fbo_bind( this );
00187 
00188   // checks error
00189   GLenum status = VL_glCheckFramebufferStatus( GL_FRAMEBUFFER ); VL_CHECK_OGL()
00190 
00191   // restore the FBO
00192   if ( globalSettings()->verbosityLevel() >= vl::VEL_VERBOSITY_NORMAL )
00193     printFramebufferError( status );
00194 
00195   VL_CHECK( status == GL_FRAMEBUFFER_COMPLETE )
00196 
00197   return status;
00198 }
00199 //-----------------------------------------------------------------------------
00200 void FramebufferObject::printFramebufferError( GLenum status ) const
00201 {
00202   switch( status )
00203   {
00204   case GL_FRAMEBUFFER_COMPLETE:
00205     break;
00206   case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
00207     Log::bug( "FramebufferObject::activate(): GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT\n" ); VL_TRAP()
00208     break;
00209   case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
00210     Log::bug( "FramebufferObject::activate(): GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT\n" ); VL_TRAP()
00211     break;
00212   case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
00213     Log::bug( "FramebufferObject::activate(): GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT\n" ); VL_TRAP()
00214     break;
00215   case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
00216     Log::bug( "FramebufferObject::activate(): GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT\n" ); VL_TRAP()
00217     break;
00218   case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
00219     Log::bug( "FramebufferObject::activate(): GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER\n" ); VL_TRAP()
00220     break;
00221   case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
00222     Log::bug( "FramebufferObject::activate(): GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER\n" ); VL_TRAP()
00223     break;
00224   case GL_FRAMEBUFFER_UNSUPPORTED:
00225     Log::bug( "FramebufferObject::activate(): GL_FRAMEBUFFER_UNSUPPORTED\n" ); VL_TRAP()
00226     break;
00227   case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB:
00228     Log::bug( "FramebufferObject::activate(): GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB\n" ); VL_TRAP()
00229     break;
00230   case GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB:
00231     Log::bug( "FramebufferObject::activate(): GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB\n" ); VL_TRAP()
00232     break;
00233   case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
00234     Log::bug( "FramebufferObject::activate(): GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE\n" ); VL_TRAP()
00235     break;
00236   }
00237 }
00238 //-----------------------------------------------------------------------------
00239 void FramebufferObject::addColorAttachment( EAttachmentPoint attach_point, FBOColorBufferAttachment* attachment )
00240 {
00241   VL_CHECK( attach_point >= AP_COLOR_ATTACHMENT0 && attach_point <= AP_COLOR_ATTACHMENT15 );
00242   VL_CHECK( Has_FBO )
00243   if( !Has_FBO )
00244     return;
00245   removeAttachment( attach_point );
00246   mFBOAttachments[attach_point] = attachment;
00247   attachment->mFramebufferObjects.insert( this );
00248   attachment->bindAttachment( this, attach_point );
00249 }
00250 //-----------------------------------------------------------------------------
00251 void FramebufferObject::addTextureAttachment( EAttachmentPoint attach_point, FBOAbstractTextureAttachment* attachment )
00252 {
00253   VL_CHECK( attach_point >= AP_COLOR_ATTACHMENT0 && attach_point <= AP_COLOR_ATTACHMENT15 ||
00254             attach_point == AP_DEPTH_ATTACHMENT ||
00255             attach_point == AP_STENCIL_ATTACHMENT ||
00256             attach_point == AP_DEPTH_STENCIL_ATTACHMENT);   // Texture attachment can be depth or stencil too (see glFrameBufferTexture documentation)
00257   VL_CHECK( Has_FBO )
00258   if( !Has_FBO )
00259     return;
00260   removeAttachment( attach_point );
00261   mFBOAttachments[attach_point] = attachment;
00262   attachment->mFramebufferObjects.insert( this );
00263   attachment->bindAttachment( this, attach_point );
00264 }
00265 //-----------------------------------------------------------------------------
00266 void FramebufferObject::addDepthAttachment( FBOAbstractAttachment* attachment )
00267 {
00268   VL_CHECK( Has_FBO )
00269   if( !Has_FBO )
00270     return;
00271   removeAttachment( AP_DEPTH_ATTACHMENT );
00272   mFBOAttachments[AP_DEPTH_ATTACHMENT] = attachment;
00273   attachment->mFramebufferObjects.insert( this );
00274   attachment->bindAttachment( this, AP_DEPTH_ATTACHMENT );
00275 }
00276 //-----------------------------------------------------------------------------
00277 void FramebufferObject::addStencilAttachment( FBOAbstractAttachment* attachment )
00278 {
00279   VL_CHECK( Has_FBO )
00280   if( !Has_FBO )
00281     return;
00282   removeAttachment( AP_STENCIL_ATTACHMENT );
00283   mFBOAttachments[AP_STENCIL_ATTACHMENT] = attachment;
00284   attachment->mFramebufferObjects.insert( this );
00285   attachment->bindAttachment( this, AP_STENCIL_ATTACHMENT );
00286 }
00287 //-----------------------------------------------------------------------------
00288 void FramebufferObject::addDepthStencilAttachment( FBOAbstractAttachment* attachment )
00289 {
00290   VL_CHECK( Has_FBO )
00291   if( !Has_FBO )
00292     return;
00293   removeAttachment( AP_DEPTH_STENCIL_ATTACHMENT );
00294   mFBOAttachments[AP_DEPTH_STENCIL_ATTACHMENT] = attachment;
00295   attachment->mFramebufferObjects.insert( this );
00296   attachment->bindAttachment( this, AP_DEPTH_STENCIL_ATTACHMENT );
00297 }
00298 //-----------------------------------------------------------------------------
00299 void FramebufferObject::removeAttachment( FBOAbstractAttachment* attachment )
00300 {
00301   VL_CHECK( Has_FBO )
00302   if( !Has_FBO )
00303     return;
00304   // collect for all the attachment points
00305   std::vector<EAttachmentPoint> attachment_points;
00306   std::map< EAttachmentPoint, ref<FBOAbstractAttachment> >::iterator it = mFBOAttachments.begin();
00307   for( ; it != mFBOAttachments.end(); ++it )
00308     if ( it->second == attachment )
00309       attachment_points.push_back( it->first );
00310 
00311   // remove it from all the attachment points
00312   for( unsigned i=0; i<attachment_points.size(); ++i )
00313     removeAttachment( attachment_points[i] );
00314 }
00315 //-----------------------------------------------------------------------------
00316 void FramebufferObject::removeAttachment( EAttachmentPoint attach_point )
00317 {
00318   VL_CHECK( vl::VisualizationLibrary::isGraphicsInitialized() )
00319 
00320   VL_CHECK_OGL();
00321   VL_CHECK(openglContext());
00322   openglContext()->makeCurrent(); VL_CHECK_OGL();
00323 
00324   VL_CHECK( Has_FBO )
00325   if( !Has_FBO )
00326     return;
00327   if ( handle() )
00328   {
00329     // save current fbo
00330     int fbo = -1;
00331     glGetIntegerv( GL_FRAMEBUFFER_BINDING, &fbo ); VL_CHECK_OGL()
00332     // bind this fbo
00333     VL_glBindFramebuffer( GL_FRAMEBUFFER, handle() ); VL_CHECK_OGL()
00334     // detach should work for any kind of buffer and texture
00335     VL_glFramebufferRenderbuffer( GL_FRAMEBUFFER, attach_point, GL_RENDERBUFFER, 0 ); VL_CHECK_OGL()
00336     // restore fbo
00337     VL_glBindFramebuffer( GL_FRAMEBUFFER, fbo ); VL_CHECK_OGL()
00338   }
00339   // remove FramebufferObject from FBOAbstractAttachment
00340   FBOAbstractAttachment* fbo_attachment = /* mFBOAttachments.find( attachment ) != mFBOAttachments.end() ? */ mFBOAttachments[attach_point].get() /* : NULL */;
00341   if ( fbo_attachment )
00342     fbo_attachment->mFramebufferObjects.erase( this );
00343   mFBOAttachments.erase( attach_point );
00344 }
00345 //-----------------------------------------------------------------------------
00346 void FramebufferObject::removeAllAttachments()
00347 {
00348   VL_CHECK( Has_FBO )
00349   if( !Has_FBO )
00350     return;
00351   // look for all the attachment points
00352   std::vector<EAttachmentPoint> attachment_points;
00353   std::map< EAttachmentPoint, ref<FBOAbstractAttachment> >::iterator it = mFBOAttachments.begin();
00354   for( ; it != mFBOAttachments.end(); ++it )
00355     attachment_points.push_back( it->first );
00356 
00357   // remove attachment points
00358   for( unsigned i=0; i<attachment_points.size(); ++i )
00359     removeAttachment( attachment_points[i] );
00360 }
00361 //-----------------------------------------------------------------------------
00362 void FBOTexture1DAttachment::bindAttachment( FramebufferObject* fbo, EAttachmentPoint attach_point )
00363 {
00364   VL_CHECK_OGL()
00365   VL_CHECK( Has_FBO )
00366   if( !Has_FBO )
00367     return;
00368   VL_CHECK( texture() )
00369   VL_CHECK( texture()->handle() )
00370   VL_CHECK( texture()->dimension() == GL_TEXTURE_1D )
00371   VL_CHECK( fbo->width() == texture()->width()  );
00372 
00373   // binds the FBO for this function call
00374   ScopedFBOBinding fbo_bind( fbo );
00375 
00376   VL_glFramebufferTexture1D( GL_FRAMEBUFFER, attach_point, GL_TEXTURE_1D, texture()->handle(), mipmapLevel() ); VL_CHECK_OGL()
00377 
00378   // needed to make non-mipmapped textures work with FBO, see framebuffer_object.txt line 442
00379   glBindTexture( texture()->dimension(), texture()->handle() ); VL_CHECK_OGL()
00380   glTexParameteri( texture()->dimension(), GL_TEXTURE_MIN_FILTER, GL_LINEAR ); VL_CHECK_OGL()
00381   glBindTexture( texture()->dimension(), 0 ); VL_CHECK_OGL()
00382 }
00383 //-----------------------------------------------------------------------------
00384 void FBOTexture2DAttachment::bindAttachment( FramebufferObject* fbo, EAttachmentPoint attach_point )
00385 {
00386   VL_CHECK_OGL()
00387   VL_CHECK( Has_FBO )
00388   if( !Has_FBO )
00389     return;
00390   VL_CHECK( texture() )
00391   VL_CHECK( texture()->handle() )
00392   // VL_CHECK( texture()->dimension() == GL_TEXTURE_2D )
00393   VL_CHECK( fbo->width()  <= texture()->width()  );
00394   VL_CHECK( fbo->height() <= texture()->height() );
00395 
00396   // binds the FBO for this function call
00397   ScopedFBOBinding fbo_bind( fbo );
00398 
00399   int target = texture()->dimension() == TD_TEXTURE_CUBE_MAP ? ( int )textureTarget() : texture()->dimension();
00400   #ifndef NDEBUG
00401     if( !( texture()->dimension() == TD_TEXTURE_CUBE_MAP || ( int )textureTarget() == ( int )texture()->dimension() ) )
00402     {
00403       Log::bug( "FBOTexture2DAttachment::init(): textureTarget() doens't match texture()->dimension().\n" );
00404     }
00405   #endif
00406 
00407   VL_glFramebufferTexture2D( GL_FRAMEBUFFER, attach_point, target, texture()->handle(), mipmapLevel() ); VL_CHECK_OGL()
00408 
00409   // needed to make non-mipmapped textures work with FBO, see framebuffer_object.txt line 442
00410   if ( texture()->dimension() != TD_TEXTURE_2D_MULTISAMPLE )
00411   {
00412     glBindTexture( texture()->dimension(), texture()->handle() ); VL_CHECK_OGL()
00413     glTexParameteri( texture()->dimension(), GL_TEXTURE_MIN_FILTER, GL_LINEAR ); VL_CHECK_OGL()
00414     glBindTexture( texture()->dimension(), 0 ); VL_CHECK_OGL()
00415   }
00416 }
00417 //-----------------------------------------------------------------------------
00418 void FBOTextureAttachment::bindAttachment( FramebufferObject* fbo, EAttachmentPoint attach_point )
00419 {
00420   VL_CHECK_OGL()
00421   VL_CHECK( Has_GL_NV_geometry_shader4||Has_GL_EXT_geometry_shader4||Has_GL_ARB_geometry_shader4||Has_GL_Version_3_2||Has_GL_Version_4_0 )
00422   VL_CHECK( texture() )
00423   VL_CHECK( texture()->handle() )
00424 
00425   // binds the FBO for this function call
00426   ScopedFBOBinding fbo_bind( fbo );
00427 
00428   VL_glFramebufferTexture( GL_FRAMEBUFFER, attach_point, texture()->handle(), mipmapLevel() ); VL_CHECK_OGL()
00429 
00430   // needed to make non-mipmapped textures work with FBO, see framebuffer_object.txt line 442
00431   if ( texture()->dimension() != TD_TEXTURE_2D_MULTISAMPLE )
00432   {
00433     glBindTexture( texture()->dimension(), texture()->handle() ); VL_CHECK_OGL()
00434     glTexParameteri( texture()->dimension(), GL_TEXTURE_MIN_FILTER, GL_LINEAR ); VL_CHECK_OGL()
00435     glBindTexture( texture()->dimension(), 0 ); VL_CHECK_OGL()
00436   }
00437 }
00438 //-----------------------------------------------------------------------------
00439 void FBOTexture3DAttachment::bindAttachment( FramebufferObject* fbo, EAttachmentPoint attach_point )
00440 {
00441   VL_CHECK_OGL()
00442   VL_CHECK( Has_FBO )
00443   if( !Has_FBO )
00444     return;
00445   VL_CHECK( texture() )
00446   VL_CHECK( texture()->handle() )
00447   VL_CHECK( fbo->width()  <= texture()->width()  );
00448   VL_CHECK( fbo->height() <= texture()->height() );
00449   VL_CHECK( layer() <= texture()->depth() );
00450   VL_CHECK( texture()->dimension() == GL_TEXTURE_3D )
00451 
00452   // binds the FBO for this function call
00453   ScopedFBOBinding fbo_bind( fbo );
00454 
00455   VL_glFramebufferTexture3D( GL_FRAMEBUFFER, attach_point, texture()->dimension(), texture()->handle(), mipmapLevel(), layer() ); VL_CHECK_OGL()
00456 
00457   // needed to make non-mipmapped textures work with FBO, see framebuffer_object.txt line 442
00458   if ( texture()->dimension() != TD_TEXTURE_2D_MULTISAMPLE_ARRAY )
00459   {
00460     glBindTexture( texture()->dimension(), texture()->handle() ); VL_CHECK_OGL()
00461     glTexParameteri( texture()->dimension(), GL_TEXTURE_MIN_FILTER, GL_LINEAR ); VL_CHECK_OGL()
00462     glBindTexture( texture()->dimension(), 0 ); VL_CHECK_OGL()
00463   }
00464 }
00465 //-----------------------------------------------------------------------------
00466 void FBOTextureLayerAttachment::bindAttachment( FramebufferObject* fbo, EAttachmentPoint attach_point )
00467 {
00468   VL_CHECK_OGL()
00469   VL_CHECK( Has_FBO )
00470   VL_CHECK( Has_GL_EXT_texture_array||Has_GL_NV_geometry_shader4||Has_GL_ARB_geometry_shader4||Has_GL_EXT_geometry_shader4||Has_GL_Version_3_2||Has_GL_Version_4_0 )
00471   if( !Has_FBO )
00472     return;
00473   if( !( Has_GL_EXT_texture_array||Has_GL_NV_geometry_shader4||Has_GL_ARB_geometry_shader4||Has_GL_EXT_geometry_shader4||Has_GL_Version_3_2||Has_GL_Version_4_0 ) )
00474     return;
00475   VL_CHECK( texture() )
00476   VL_CHECK( texture()->handle() )
00477   VL_CHECK( texture()->dimension() == GL_TEXTURE_2D_ARRAY || texture()->dimension() == GL_TEXTURE_1D_ARRAY )
00478   VL_CHECK( fbo->width()  <= texture()->width()  );
00479   VL_CHECK( fbo->height() <= texture()->height() );
00480   // VL_CHECK( layer() <= texture()->depth() );
00481 
00482   // binds the FBO for this function call
00483   ScopedFBOBinding fbo_bind( fbo );
00484 
00485   VL_glFramebufferTextureLayer( GL_FRAMEBUFFER, attach_point, texture()->handle(), mipmapLevel(), layer() ); VL_CHECK_OGL()
00486 
00487   // needed to make non-mipmapped textures work with FBO, see framebuffer_object.txt line 442
00488   if ( texture()->dimension() != TD_TEXTURE_2D_MULTISAMPLE_ARRAY )
00489   {
00490     glBindTexture( texture()->dimension(), texture()->handle() ); VL_CHECK_OGL()
00491     glTexParameteri( texture()->dimension(), GL_TEXTURE_MIN_FILTER, GL_LINEAR ); VL_CHECK_OGL()
00492     glBindTexture( texture()->dimension(), 0 ); VL_CHECK_OGL()
00493   }
00494 }
00495 //-----------------------------------------------------------------------------
00496 void FBOAbstractAttachment::unbindFromAllFBO()
00497 {
00498   std::set< ref<FramebufferObject> > fbos = fboFramebuffers();
00499   for( std::set< ref<FramebufferObject> >::iterator it = fbos.begin(); it != fbos.end(); ++it )
00500     it->get_writable()->removeAttachment( this );
00501 }
00502 //-----------------------------------------------------------------------------
00503 void FBORenderbufferAttachment::createRenderBuffer()
00504 {
00505   VL_CHECK_OGL()
00506   VL_CHECK( Has_FBO )
00507   if( !Has_FBO )
00508     return;
00509   if ( !mHandle )
00510   {
00511     VL_glGenRenderbuffers( 1, &mHandle ); VL_CHECK_OGL()
00512     mReallocateRenderbuffer = true;
00513   }
00514   VL_CHECK( mHandle )
00515 }
00516 //-----------------------------------------------------------------------------
00517 void FBORenderbufferAttachment::deleteRenderBuffer()
00518 {
00519   VL_CHECK_OGL()
00520   VL_CHECK( Has_FBO )
00521   if( !Has_FBO )
00522     return;
00523 
00524   unbindFromAllFBO();
00525 
00526   mWidth  = 0;
00527   mHeight = 0;
00528   if ( mHandle )
00529   {
00530     VL_glDeleteRenderbuffers( 1, &mHandle ); VL_CHECK_OGL()
00531     mHandle = 0;
00532     mReallocateRenderbuffer = true;
00533   }
00534 }
00535 //-----------------------------------------------------------------------------
00536 void FBORenderbufferAttachment::initStorage( int w, int h, int samp )
00537 {
00538   VL_CHECK_OGL()
00539   VL_CHECK( handle() );
00540   VL_CHECK( w>0 && h>0 );
00541   VL_CHECK( Has_FBO )
00542   if( !Has_FBO )
00543     return;
00544 
00545   if ( w != width() || h != height() || samp != samples() || mReallocateRenderbuffer )
00546   {
00547     mWidth  = w;
00548     mHeight = h;
00549     mSamples = samp;
00550     VL_glBindRenderbuffer( GL_RENDERBUFFER, handle() ); VL_CHECK_OGL()
00551     if ( Has_FBO_Multisample && samples() != 0)
00552     {
00553       VL_glRenderbufferStorageMultisample( GL_RENDERBUFFER, samples(), internalType(), width(), height() ); VL_CHECK_OGL()
00554     }
00555     else
00556     {
00557       VL_CHECK(samples() == 0)
00558       if (samples())
00559         Log::error("FBORenderbufferAttachment::initStorage() requesting multisampling storage but current OpenGL implementation does not support it!\n");
00560       VL_glRenderbufferStorage( GL_RENDERBUFFER, internalType(), width(), height() ); VL_CHECK_OGL()
00561     }
00562     VL_glBindRenderbuffer( GL_RENDERBUFFER, 0 ); VL_CHECK_OGL()
00563     mReallocateRenderbuffer = false;
00564   }
00565 }
00566 //-----------------------------------------------------------------------------
00567 void FBORenderbufferAttachment::bindAttachment( FramebufferObject* fbo, EAttachmentPoint attach_point )
00568 {
00569   VL_CHECK_OGL()
00570   VL_CHECK( Has_FBO )
00571   if( !Has_FBO )
00572     return;
00573 
00574   if (!handle())
00575     createRenderBuffer();
00576 
00577   // binds the FBO for this function call
00578   ScopedFBOBinding fbo_bind( fbo );
00579 
00580   // choose the maximum dimension
00581   int actual_w = width()  == 0 ? fbo->width()  : width();
00582   int actual_h = height() == 0 ? fbo->height() : height();
00583   VL_CHECK( actual_w >= fbo->width() );
00584   VL_CHECK( actual_h >= fbo->height() );
00585   initStorage( actual_w, actual_h, samples() );
00586 
00587   // attach the renderbuffer to the framebuffer's attachment point
00588   VL_glFramebufferRenderbuffer( GL_FRAMEBUFFER, attach_point, GL_RENDERBUFFER, handle() ); VL_CHECK_OGL()
00589 }
00590 //-----------------------------------------------------------------------------

Visualization Library 2011.09.1160 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 2 2013 13:40:37.
Permission is granted to use this page to write and publish articles regarding Visualization Library.