void Fbo::init() { gl::SaveFramebufferBinding bindingSaver; #if defined( CINDER_MSW ) static bool csaaSupported = ( GLEE_NV_framebuffer_multisample_coverage != 0 ); #else static bool csaaSupported = false; #endif bool useCSAA = csaaSupported && ( mObj->mFormat.mCoverageSamples > mObj->mFormat.mSamples ); bool useMSAA = ( mObj->mFormat.mCoverageSamples > 0 ) || ( mObj->mFormat.mSamples > 0 ); if( useCSAA ) useMSAA = false; // allocate the framebuffer itself GL_SUFFIX(glGenFramebuffers)( 1, &mObj->mId ); GL_SUFFIX(glBindFramebuffer)( GL_SUFFIX(GL_FRAMEBUFFER_), mObj->mId ); Texture::Format textureFormat; textureFormat.setTarget( getTarget() ); textureFormat.setInternalFormat( getFormat().getColorInternalFormat() ); textureFormat.setWrap( mObj->mFormat.mWrapS, mObj->mFormat.mWrapT ); textureFormat.setMinFilter( mObj->mFormat.mMinFilter ); textureFormat.setMagFilter( mObj->mFormat.mMagFilter ); textureFormat.enableMipmapping( getFormat().hasMipMapping() ); // allocate the color buffers for( int c = 0; c < mObj->mFormat.mNumColorBuffers; ++c ) { mObj->mColorTextures.push_back( Texture( mObj->mWidth, mObj->mHeight, textureFormat ) ); } #if ! defined( CINDER_GLES ) if( mObj->mFormat.mNumColorBuffers == 0 ) { // no color glDrawBuffer( GL_NONE ); glReadBuffer( GL_NONE ); } #endif if( ( ( ! useCSAA ) && ( ! useMSAA ) ) || ( ! initMultisample( useCSAA ) ) ) { // if we don't need any variety of multisampling or it failed to initialize // attach all the textures to the framebuffer vector<GLenum> drawBuffers; for( size_t c = 0; c < mObj->mColorTextures.size(); ++c ) { GL_SUFFIX(glFramebufferTexture2D)( GL_SUFFIX(GL_FRAMEBUFFER_), GL_SUFFIX(GL_COLOR_ATTACHMENT0_) + c, getTarget(), mObj->mColorTextures[c].getId(), 0 ); drawBuffers.push_back( GL_SUFFIX(GL_COLOR_ATTACHMENT0_) + c ); } #if ! defined( CINDER_GLES ) if( ! drawBuffers.empty() ) glDrawBuffers( drawBuffers.size(), &drawBuffers[0] ); #endif // allocate and attach depth texture if( mObj->mFormat.mDepthBuffer ) { if( mObj->mFormat.mDepthBufferAsTexture ) { #if ! defined( CINDER_GLES ) GLuint depthTextureId; glGenTextures( 1, &depthTextureId ); glBindTexture( getTarget(), depthTextureId ); glTexImage2D( getTarget(), 0, getFormat().getDepthInternalFormat(), mObj->mWidth, mObj->mHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL ); glTexParameteri( getTarget(), GL_TEXTURE_MIN_FILTER, mObj->mFormat.mMinFilter ); glTexParameteri( getTarget(), GL_TEXTURE_MAG_FILTER, mObj->mFormat.mMagFilter ); glTexParameteri( getTarget(), GL_TEXTURE_WRAP_S, mObj->mFormat.mWrapS ); glTexParameteri( getTarget(), GL_TEXTURE_WRAP_T, mObj->mFormat.mWrapT ); glTexParameteri( getTarget(), GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE ); mObj->mDepthTexture = Texture( getTarget(), depthTextureId, mObj->mWidth, mObj->mHeight, true ); glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, getTarget(), mObj->mDepthTexture.getId(), 0 ); //glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, getTarget(), mObj->mDepthTexture.getId(), 0 ); #else throw; // this should never fire in OpenGL ES #endif } else if( mObj->mFormat.mDepthBuffer ) { // implement depth buffer as RenderBuffer mObj->mDepthRenderbuffer = Renderbuffer( mObj->mWidth, mObj->mHeight, mObj->mFormat.getDepthInternalFormat() ); GL_SUFFIX(glFramebufferRenderbuffer)( GL_SUFFIX(GL_FRAMEBUFFER_), GL_SUFFIX(GL_DEPTH_ATTACHMENT_), GL_SUFFIX(GL_RENDERBUFFER_), mObj->mDepthRenderbuffer.getId() ); } } FboExceptionInvalidSpecification exc; if( ! checkStatus( &exc ) ) { // failed creation; throw throw exc; } } mObj->mNeedsResolve = false; mObj->mNeedsMipmapUpdate = false; }