Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://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 VL_CHECK( Has_FBO ) 00255 if( !Has_FBO ) 00256 return; 00257 removeAttachment( attach_point ); 00258 mFBOAttachments[attach_point] = attachment; 00259 attachment->mFramebufferObjects.insert( this ); 00260 attachment->bindAttachment( this, attach_point ); 00261 } 00262 //----------------------------------------------------------------------------- 00263 void FramebufferObject::addDepthAttachment( FBOAbstractAttachment* attachment ) 00264 { 00265 VL_CHECK( Has_FBO ) 00266 if( !Has_FBO ) 00267 return; 00268 removeAttachment( AP_DEPTH_ATTACHMENT ); 00269 mFBOAttachments[AP_DEPTH_ATTACHMENT] = attachment; 00270 attachment->mFramebufferObjects.insert( this ); 00271 attachment->bindAttachment( this, AP_DEPTH_ATTACHMENT ); 00272 } 00273 //----------------------------------------------------------------------------- 00274 void FramebufferObject::addStencilAttachment( FBOAbstractAttachment* attachment ) 00275 { 00276 VL_CHECK( Has_FBO ) 00277 if( !Has_FBO ) 00278 return; 00279 removeAttachment( AP_STENCIL_ATTACHMENT ); 00280 mFBOAttachments[AP_STENCIL_ATTACHMENT] = attachment; 00281 attachment->mFramebufferObjects.insert( this ); 00282 attachment->bindAttachment( this, AP_STENCIL_ATTACHMENT ); 00283 } 00284 //----------------------------------------------------------------------------- 00285 void FramebufferObject::addDepthStencilAttachment( FBOAbstractAttachment* attachment ) 00286 { 00287 VL_CHECK( Has_FBO ) 00288 if( !Has_FBO ) 00289 return; 00290 removeAttachment( AP_DEPTH_STENCIL_ATTACHMENT ); 00291 mFBOAttachments[AP_DEPTH_STENCIL_ATTACHMENT] = attachment; 00292 attachment->mFramebufferObjects.insert( this ); 00293 attachment->bindAttachment( this, AP_DEPTH_STENCIL_ATTACHMENT ); 00294 } 00295 //----------------------------------------------------------------------------- 00296 void FramebufferObject::removeAttachment( FBOAbstractAttachment* attachment ) 00297 { 00298 VL_CHECK( Has_FBO ) 00299 if( !Has_FBO ) 00300 return; 00301 // collect for all the attachment points 00302 std::vector<EAttachmentPoint> attachment_points; 00303 std::map< EAttachmentPoint, ref<FBOAbstractAttachment> >::iterator it = mFBOAttachments.begin(); 00304 for( ; it != mFBOAttachments.end(); ++it ) 00305 if ( it->second == attachment ) 00306 attachment_points.push_back( it->first ); 00307 00308 // remove it from all the attachment points 00309 for( unsigned i=0; i<attachment_points.size(); ++i ) 00310 removeAttachment( attachment_points[i] ); 00311 } 00312 //----------------------------------------------------------------------------- 00313 void FramebufferObject::removeAttachment( EAttachmentPoint attach_point ) 00314 { 00315 VL_CHECK( vl::VisualizationLibrary::isGraphicsInitialized() ) 00316 00317 VL_CHECK_OGL(); 00318 VL_CHECK(openglContext()); 00319 openglContext()->makeCurrent(); VL_CHECK_OGL(); 00320 00321 VL_CHECK( Has_FBO ) 00322 if( !Has_FBO ) 00323 return; 00324 if ( handle() ) 00325 { 00326 // save current fbo 00327 int fbo = -1; 00328 glGetIntegerv( GL_FRAMEBUFFER_BINDING, &fbo ); VL_CHECK_OGL() 00329 // bind this fbo 00330 VL_glBindFramebuffer( GL_FRAMEBUFFER, handle() ); VL_CHECK_OGL() 00331 // detach should work for any kind of buffer and texture 00332 VL_glFramebufferRenderbuffer( GL_FRAMEBUFFER, attach_point, GL_RENDERBUFFER, 0 ); VL_CHECK_OGL() 00333 // restore fbo 00334 VL_glBindFramebuffer( GL_FRAMEBUFFER, fbo ); VL_CHECK_OGL() 00335 } 00336 // remove FramebufferObject from FBOAbstractAttachment 00337 FBOAbstractAttachment* fbo_attachment = /* mFBOAttachments.find( attachment ) != mFBOAttachments.end() ? */ mFBOAttachments[attach_point].get() /* : NULL */; 00338 if ( fbo_attachment ) 00339 fbo_attachment->mFramebufferObjects.erase( this ); 00340 mFBOAttachments.erase( attach_point ); 00341 } 00342 //----------------------------------------------------------------------------- 00343 void FramebufferObject::removeAllAttachments() 00344 { 00345 VL_CHECK( Has_FBO ) 00346 if( !Has_FBO ) 00347 return; 00348 // look for all the attachment points 00349 std::vector<EAttachmentPoint> attachment_points; 00350 std::map< EAttachmentPoint, ref<FBOAbstractAttachment> >::iterator it = mFBOAttachments.begin(); 00351 for( ; it != mFBOAttachments.end(); ++it ) 00352 attachment_points.push_back( it->first ); 00353 00354 // remove attachment points 00355 for( unsigned i=0; i<attachment_points.size(); ++i ) 00356 removeAttachment( attachment_points[i] ); 00357 } 00358 //----------------------------------------------------------------------------- 00359 void FBOTexture1DAttachment::bindAttachment( FramebufferObject* fbo, EAttachmentPoint attach_point ) 00360 { 00361 VL_CHECK_OGL() 00362 VL_CHECK( Has_FBO ) 00363 if( !Has_FBO ) 00364 return; 00365 VL_CHECK( texture() ) 00366 VL_CHECK( texture()->handle() ) 00367 VL_CHECK( texture()->dimension() == GL_TEXTURE_1D ) 00368 VL_CHECK( fbo->width() == texture()->width() ); 00369 00370 // binds the FBO for this function call 00371 ScopedFBOBinding fbo_bind( fbo ); 00372 00373 VL_glFramebufferTexture1D( GL_FRAMEBUFFER, attach_point, GL_TEXTURE_1D, texture()->handle(), mipmapLevel() ); VL_CHECK_OGL() 00374 00375 // needed to make non-mipmapped textures work with FBO, see framebuffer_object.txt line 442 00376 glBindTexture( texture()->dimension(), texture()->handle() ); VL_CHECK_OGL() 00377 glTexParameteri( texture()->dimension(), GL_TEXTURE_MIN_FILTER, GL_LINEAR ); VL_CHECK_OGL() 00378 glBindTexture( texture()->dimension(), 0 ); VL_CHECK_OGL() 00379 } 00380 //----------------------------------------------------------------------------- 00381 void FBOTexture2DAttachment::bindAttachment( FramebufferObject* fbo, EAttachmentPoint attach_point ) 00382 { 00383 VL_CHECK_OGL() 00384 VL_CHECK( Has_FBO ) 00385 if( !Has_FBO ) 00386 return; 00387 VL_CHECK( texture() ) 00388 VL_CHECK( texture()->handle() ) 00389 // VL_CHECK( texture()->dimension() == GL_TEXTURE_2D ) 00390 VL_CHECK( fbo->width() <= texture()->width() ); 00391 VL_CHECK( fbo->height() <= texture()->height() ); 00392 00393 // binds the FBO for this function call 00394 ScopedFBOBinding fbo_bind( fbo ); 00395 00396 int target = texture()->dimension() == TD_TEXTURE_CUBE_MAP ? ( int )textureTarget() : texture()->dimension(); 00397 #ifndef NDEBUG 00398 if( !( texture()->dimension() == TD_TEXTURE_CUBE_MAP || ( int )textureTarget() == ( int )texture()->dimension() ) ) 00399 { 00400 Log::bug( "FBOTexture2DAttachment::init(): textureTarget() doens't match texture()->dimension().\n" ); 00401 } 00402 #endif 00403 00404 VL_glFramebufferTexture2D( GL_FRAMEBUFFER, attach_point, target, texture()->handle(), mipmapLevel() ); VL_CHECK_OGL() 00405 00406 // needed to make non-mipmapped textures work with FBO, see framebuffer_object.txt line 442 00407 if ( texture()->dimension() != TD_TEXTURE_2D_MULTISAMPLE ) 00408 { 00409 glBindTexture( texture()->dimension(), texture()->handle() ); VL_CHECK_OGL() 00410 glTexParameteri( texture()->dimension(), GL_TEXTURE_MIN_FILTER, GL_LINEAR ); VL_CHECK_OGL() 00411 glBindTexture( texture()->dimension(), 0 ); VL_CHECK_OGL() 00412 } 00413 } 00414 //----------------------------------------------------------------------------- 00415 void FBOTextureAttachment::bindAttachment( FramebufferObject* fbo, EAttachmentPoint attach_point ) 00416 { 00417 VL_CHECK_OGL() 00418 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 ) 00419 VL_CHECK( texture() ) 00420 VL_CHECK( texture()->handle() ) 00421 00422 // binds the FBO for this function call 00423 ScopedFBOBinding fbo_bind( fbo ); 00424 00425 VL_glFramebufferTexture( GL_FRAMEBUFFER, attach_point, texture()->handle(), mipmapLevel() ); VL_CHECK_OGL() 00426 00427 // needed to make non-mipmapped textures work with FBO, see framebuffer_object.txt line 442 00428 if ( texture()->dimension() != TD_TEXTURE_2D_MULTISAMPLE ) 00429 { 00430 glBindTexture( texture()->dimension(), texture()->handle() ); VL_CHECK_OGL() 00431 glTexParameteri( texture()->dimension(), GL_TEXTURE_MIN_FILTER, GL_LINEAR ); VL_CHECK_OGL() 00432 glBindTexture( texture()->dimension(), 0 ); VL_CHECK_OGL() 00433 } 00434 } 00435 //----------------------------------------------------------------------------- 00436 void FBOTexture3DAttachment::bindAttachment( FramebufferObject* fbo, EAttachmentPoint attach_point ) 00437 { 00438 VL_CHECK_OGL() 00439 VL_CHECK( Has_FBO ) 00440 if( !Has_FBO ) 00441 return; 00442 VL_CHECK( texture() ) 00443 VL_CHECK( texture()->handle() ) 00444 VL_CHECK( fbo->width() <= texture()->width() ); 00445 VL_CHECK( fbo->height() <= texture()->height() ); 00446 VL_CHECK( layer() <= texture()->depth() ); 00447 VL_CHECK( texture()->dimension() == GL_TEXTURE_3D ) 00448 00449 // binds the FBO for this function call 00450 ScopedFBOBinding fbo_bind( fbo ); 00451 00452 VL_glFramebufferTexture3D( GL_FRAMEBUFFER, attach_point, texture()->dimension(), texture()->handle(), mipmapLevel(), layer() ); VL_CHECK_OGL() 00453 00454 // needed to make non-mipmapped textures work with FBO, see framebuffer_object.txt line 442 00455 if ( texture()->dimension() != TD_TEXTURE_2D_MULTISAMPLE_ARRAY ) 00456 { 00457 glBindTexture( texture()->dimension(), texture()->handle() ); VL_CHECK_OGL() 00458 glTexParameteri( texture()->dimension(), GL_TEXTURE_MIN_FILTER, GL_LINEAR ); VL_CHECK_OGL() 00459 glBindTexture( texture()->dimension(), 0 ); VL_CHECK_OGL() 00460 } 00461 } 00462 //----------------------------------------------------------------------------- 00463 void FBOTextureLayerAttachment::bindAttachment( FramebufferObject* fbo, EAttachmentPoint attach_point ) 00464 { 00465 VL_CHECK_OGL() 00466 VL_CHECK( Has_FBO ) 00467 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 ) 00468 if( !Has_FBO ) 00469 return; 00470 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 ) ) 00471 return; 00472 VL_CHECK( texture() ) 00473 VL_CHECK( texture()->handle() ) 00474 VL_CHECK( texture()->dimension() == GL_TEXTURE_2D_ARRAY || texture()->dimension() == GL_TEXTURE_1D_ARRAY ) 00475 VL_CHECK( fbo->width() <= texture()->width() ); 00476 VL_CHECK( fbo->height() <= texture()->height() ); 00477 // VL_CHECK( layer() <= texture()->depth() ); 00478 00479 // binds the FBO for this function call 00480 ScopedFBOBinding fbo_bind( fbo ); 00481 00482 VL_glFramebufferTextureLayer( GL_FRAMEBUFFER, attach_point, texture()->handle(), mipmapLevel(), layer() ); VL_CHECK_OGL() 00483 00484 // needed to make non-mipmapped textures work with FBO, see framebuffer_object.txt line 442 00485 if ( texture()->dimension() != TD_TEXTURE_2D_MULTISAMPLE_ARRAY ) 00486 { 00487 glBindTexture( texture()->dimension(), texture()->handle() ); VL_CHECK_OGL() 00488 glTexParameteri( texture()->dimension(), GL_TEXTURE_MIN_FILTER, GL_LINEAR ); VL_CHECK_OGL() 00489 glBindTexture( texture()->dimension(), 0 ); VL_CHECK_OGL() 00490 } 00491 } 00492 //----------------------------------------------------------------------------- 00493 void FBOAbstractAttachment::unbindFromAllFBO() 00494 { 00495 std::set< ref<FramebufferObject> > fbos = fboFramebuffers(); 00496 for( std::set< ref<FramebufferObject> >::iterator it = fbos.begin(); it != fbos.end(); ++it ) 00497 it->get_writable()->removeAttachment( this ); 00498 } 00499 //----------------------------------------------------------------------------- 00500 void FBORenderbufferAttachment::createRenderBuffer() 00501 { 00502 VL_CHECK_OGL() 00503 VL_CHECK( Has_FBO ) 00504 if( !Has_FBO ) 00505 return; 00506 if ( !mHandle ) 00507 { 00508 VL_glGenRenderbuffers( 1, &mHandle ); VL_CHECK_OGL() 00509 mReallocateRenderbuffer = true; 00510 } 00511 VL_CHECK( mHandle ) 00512 } 00513 //----------------------------------------------------------------------------- 00514 void FBORenderbufferAttachment::deleteRenderBuffer() 00515 { 00516 VL_CHECK_OGL() 00517 VL_CHECK( Has_FBO ) 00518 if( !Has_FBO ) 00519 return; 00520 00521 unbindFromAllFBO(); 00522 00523 mWidth = 0; 00524 mHeight = 0; 00525 if ( mHandle ) 00526 { 00527 VL_glDeleteRenderbuffers( 1, &mHandle ); VL_CHECK_OGL() 00528 mHandle = 0; 00529 mReallocateRenderbuffer = true; 00530 } 00531 } 00532 //----------------------------------------------------------------------------- 00533 void FBORenderbufferAttachment::initStorage( int w, int h, int samp ) 00534 { 00535 VL_CHECK_OGL() 00536 VL_CHECK( handle() ); 00537 VL_CHECK( w>0 && h>0 ); 00538 VL_CHECK( Has_FBO ) 00539 if( !Has_FBO ) 00540 return; 00541 00542 if ( w != width() || h != height() || samp != samples() || mReallocateRenderbuffer ) 00543 { 00544 mWidth = w; 00545 mHeight = h; 00546 mSamples = samp; 00547 VL_glBindRenderbuffer( GL_RENDERBUFFER, handle() ); VL_CHECK_OGL() 00548 if ( Has_FBO_Multisample ) 00549 { 00550 VL_glRenderbufferStorageMultisample( GL_RENDERBUFFER, samples(), internalType(), width(), height() ); VL_CHECK_OGL() 00551 } 00552 else 00553 { 00554 VL_CHECK(samples() == 0) 00555 if (samples()) 00556 Log::error("FBORenderbufferAttachment::initStorage() requesting multisampling storage but current OpenGL implementation does not support it!\n"); 00557 VL_glRenderbufferStorage( GL_RENDERBUFFER, internalType(), width(), height() ); VL_CHECK_OGL() 00558 } 00559 VL_glBindRenderbuffer( GL_RENDERBUFFER, 0 ); VL_CHECK_OGL() 00560 mReallocateRenderbuffer = false; 00561 } 00562 } 00563 //----------------------------------------------------------------------------- 00564 void FBORenderbufferAttachment::bindAttachment( FramebufferObject* fbo, EAttachmentPoint attach_point ) 00565 { 00566 VL_CHECK_OGL() 00567 VL_CHECK( Has_FBO ) 00568 if( !Has_FBO ) 00569 return; 00570 00571 if (!handle()) 00572 createRenderBuffer(); 00573 00574 // binds the FBO for this function call 00575 ScopedFBOBinding fbo_bind( fbo ); 00576 00577 // choose the maximum dimension 00578 int actual_w = width() == 0 ? fbo->width() : width(); 00579 int actual_h = height() == 0 ? fbo->height() : height(); 00580 VL_CHECK( actual_w >= fbo->width() ); 00581 VL_CHECK( actual_h >= fbo->height() ); 00582 initStorage( actual_w, actual_h, samples() ); 00583 00584 // attach the renderbuffer to the framebuffer's attachment point 00585 VL_glFramebufferRenderbuffer( GL_FRAMEBUFFER, attach_point, GL_RENDERBUFFER, handle() ); VL_CHECK_OGL() 00586 } 00587 //-----------------------------------------------------------------------------