new to fbo's, two questions

i’m new to fbo’s, i was using glcopytexsubimage() before, so i have some questions.

  • i have the following code which sets up the fbo and the texture. it works, but is it also correct, i.e. is this the way it should be set up, or am i missing sth etc ?
// Setup reflection frame buffer
glGenFramebuffersEXT( 1, &m_uiReflectionBufferId );
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, m_uiReflectionBufferId );

// Setup reflection texture
glGenTextures( 1, &m_uiReflectionTextureId );
glBindTexture( GL_TEXTURE_2D, m_uiReflectionTextureId );
glTexImage2D( GL_TEXTURE_2D, 0, 3, SIZE, SIZE, 0, GL_RGB, GL_UNSIGNED_BYTE, 0 );
glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f );

glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_uiReflectionTextureId, 0 );

// Setup depth render buffer
unsigned int uiDepthBufferId;
glGenRenderbuffersEXT( 1, &uiDepthBufferId );
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, uiDepthBufferId );
glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, SIZE, SIZE );
glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, uiDepthBufferId );
  • ok so this renders color data to a texture, now i want to setup a 2nd fbo to save the depth of a scene. how do i have to setup the fbo and texture this time? and will i need a render buffer as well?

  • does it make sense to create mipmaps for dynamic textures?

thanks! :slight_smile:

Originally posted by Vexator:
[b]

  • does it make sense to create mipmaps for dynamic textures?[/b]
    It depends on what you are going to use it for, if you are using it as a texture on any 3d surface then it might be good to have mipmaps.
    But if you are just using it for a fullscreen renderbuffer that is never going to be rendered to anything but a fullscreen quad then the ansver is no.
    In any other case in between, you have to test what looks the best.

Here’s an example that I use for my post-process FBOs.

if( !glrimp.exts.EXT_framebuffer_object ) {
		return; 
	}

	glActiveTextureARB( GL_TEXTURE0 );
	
	if( regenerate ) 
	{
		common->RSafePrintf("Reparameterizing render target
");
		/*if( rt.fbo ) {

			glDeleteFramebuffersEXT(1, &rt.fbo->_handle);
			rt.fbo->_handle = 0;
		}*/

		const bool deleteTexturesOnResize = Renderer::kATI == Renderer::GetSingleton()->vendor ? true : false;

		if( deleteTexturesOnResize ) {
			if( rt.fb_colorTex2D ) {
				glDeleteTextures(1, &rt.fb_colorTex2D->_handle );
				rt.fb_colorTex2D->_handle = 0;
			}
			if( rt.fb_depthTex2D ) {
				glDeleteTextures(1, &rt.fb_depthTex2D->_handle );
				rt.fb_depthTex2D->_handle = 0;
			}
		}
		


		if( !rt.fbo || !rt.fbo->_handle ) {
			common->RSafePrintf(" Generating FBO
");
			rt.fbo = Renderer::GetSingleton()->GenFrameBufferObject();

		}
		if( !rt.fb_colorTex2D || !rt.fb_colorTex2D->_handle ) {
			common->RSafePrintf(" Generating FBO's color texture2D
");
			rt.fb_colorTex2D = Renderer::GetSingleton()->GenTexture();
		}
		if( !rt.fb_depthTex2D || !rt.fb_depthTex2D->_handle) {
			common->RSafePrintf(" Generating FBO's depth texture2D
");
			rt.fb_depthTex2D = Renderer::GetSingleton()->GenTexture();
		}
		
		if( !rt.fb_colorTexRect || !rt.fb_colorTexRect->_handle ) {
			common->RSafePrintf(" Generating FBO's color textureRect
");
			rt.fb_colorTexRect = Renderer::GetSingleton()->GenTexture();
		}
		if( !rt.fb_depthTexRect || !rt.fb_depthTexRect->_handle) {
			common->RSafePrintf(" Generating FBO's depth textureRect
");
			rt.fb_depthTexRect = Renderer::GetSingleton()->GenTexture();
		}
		
		if( cvarSystem->GetBool("r_postProcessUseNVRECT") ) {
			rt.textureTarget = GL_TEXTURE_RECTANGLE_NV;
			rt.fb_colorTex = rt.fb_colorTexRect;
			rt.fb_depthTex = rt.fb_depthTexRect;
		}
		else {
			rt.textureTarget = GL_TEXTURE_2D;
			rt.fb_colorTex = rt.fb_colorTex2D;
			rt.fb_depthTex = rt.fb_depthTex2D;
		}

		
	

		float samples = cvarSystem->GetFloat("r_postProcessSuperSamples");
		samples = NxMath::clamp( samples, 16.0f, 0.025f );
		common->RSafePrintf(" ...samples: %4.4f
", samples );

		const int reqBufferWidth  = static_cast< int >( float(g_appWindow.width)  * samples );
		// const int reqBufferHeight = static_cast< int >( float(g_appWindow.height) * samples );
		 const int reqBufferHeight = reqBufferWidth;
		if( cvarSystem->GetBool("r_postProcessAllowNPOT") ) {
			rt.width  = reqBufferWidth;
			rt.height = reqBufferHeight;
		}
		else if( cvarSystem->GetInteger("r_backBufferWidth") ) {
			rt.width  = cvarSystem->GetInteger("r_backBufferWidth");
			rt.height = cvarSystem->GetInteger("r_backBufferHeight");
		}
		else {
			rt.width  = PowerOf2Ceil( reqBufferWidth  );
			rt.height = PowerOf2Ceil( reqBufferHeight );
		}
		

		

		
		g_rgl->BindTexture( rt.textureTarget, rt.fb_colorTex->_handle );
		Renderer::GetSingleton()->UploadTextureData2D( rt.textureTarget, 0, GL_RGBA8, rt.width, rt.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
		glGenerateMipmapEXT( rt.textureTarget );
		

		// TODO: mess with magnifcation filtering for render target
		glTexParameteri(  rt.textureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
		bool mipmap = cvarSystem->GetBool("r_postProcessGenerateMipmaps");
		if( mipmap ) {
			glTexParameteri(  rt.textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
			common->RSafePrintf("Establishing mipmap chain for render texture
");
		}
		else {
			glTexParameteri(  rt.textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
		}
		g_rgl->BindTexture( rt.textureTarget, 0 );

		

		glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, rt.fbo->_handle );
		
		glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, rt.textureTarget, rt.fb_colorTex->_handle, 0 );
		
	

		// Detach renderBuffer (if there was one)
		glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0 );
		

		// Detach depth Texture if there was one
		glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, rt.textureTarget, 0, 0 );
		
	


		const int depthType = cvarSystem->GetInteger("r_postProcessDepthTexture") ;
		

		GLint internalDepthFormat = GL_DEPTH_COMPONENT24_ARB;
		if( Renderer::kATI == Renderer::GetSingleton()->vendor ) {
			internalDepthFormat = GL_DEPTH_COMPONENT16_ARB;
			common->RSafePrintf(" ...using GL_DEPTH_COMPONENT16_ARB
");
		}

		
		if( kTexture == depthType ) {
		
			g_rgl->BindTexture(  rt.textureTarget, rt.fb_depthTex->_handle );
			glTexImage2D( rt.textureTarget, 0, internalDepthFormat, rt.width, rt.height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL );
			glTexParameteri(  rt.textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
			glTexParameteri(  rt.textureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
			g_rgl->BindTexture( rt.textureTarget, 0);
			
			glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, rt.textureTarget, rt.fb_depthTex->_handle, 0 );
			
		}
		else if( kRenderBuffer == depthType ) {
			static GLuint depth_rb = 0;
			glGenRenderbuffersEXT( 1, &depth_rb );
			glGenRenderbuffersEXT(1, &depth_rb);// render buffer
			// initialize depth renderbuffer
			glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_rb);
			glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internalDepthFormat, rt.width, rt.height );
			// attach renderbuffer to framebufferdepth buffer
			glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_rb);
		}




		
		

		common->RSafePrintf( COM_GREEN("  RenderTexture( %d, %d )
"), rt.width, rt.height);
		if( depthType == kTexture ) {
			common->RSafePrintf( COM_GREEN("    with depth texture
") );
		}
		else if( depthType == kRenderBuffer ) {
			common->RSafePrintf( COM_GREEN("    with depth render buffer
") );
		}
		else {
			common->RSafePrintf( COM_GREEN("    with no depth information
") );
		}
	}

	//Set of state that can change on a framebuffer bind
	// – AUX_BUFFERS, MAX_DRAW_BUFFERS, STEREO, AUX_BUFFERS, MAX_DRAW_BUFFERS, STEREO,
	//	SAMPLES, X_BITS, DOUBLE_BUFFER and a few others
	glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, rt.fbo->_handle );
	CHECKGL;
	GL_CHECK_FRAMEBUFFER_STATUS();
}

thanks :slight_smile: