예제 #1
0
/*
==============
CaptureRenderToFile

==============
*/
void idRenderSystemLocal::CaptureRenderToFile( const char *fileName, bool fixAlpha ) {
	if ( !glConfig.isInitialized ) {
		return;
	}

	renderCrop_t *rc = &renderCrops[currentRenderCrop];

	guiModel->EmitFullScreen();
	guiModel->Clear();
	R_IssueRenderCommands();

	qglReadBuffer( GL_BACK );

	// include extra space for OpenGL padding to word boundaries
	int	c = ( rc->width + 3 ) * rc->height;
	byte *data = (byte *)R_StaticAlloc( c * 3 );
	
	qglReadPixels( rc->x, rc->y, rc->width, rc->height, GL_RGB, GL_UNSIGNED_BYTE, data ); 

	byte *data2 = (byte *)R_StaticAlloc( c * 4 );

	for ( int i = 0 ; i < c ; i++ ) {
		data2[ i * 4 ] = data[ i * 3 ];
		data2[ i * 4 + 1 ] = data[ i * 3 + 1 ];
		data2[ i * 4 + 2 ] = data[ i * 3 + 2 ];
		data2[ i * 4 + 3 ] = 0xff;
	}

	R_WriteTGA( fileName, data2, rc->width, rc->height, true );

	R_StaticFree( data );
	R_StaticFree( data2 );
}
예제 #2
0
/*
* RFB_AttachTextureToObject
*/
void RFB_AttachTextureToObject( int object, image_t *texture )
{
	r_fbo_t *fbo;
	int attachment;

	assert( object > 0 && object <= r_num_framebuffer_objects );
	if( object <= 0 || object > r_num_framebuffer_objects ) {
		return;
	}

	assert( texture != NULL );
	if( !texture ) {
		return;
	}

	fbo = r_framebuffer_objects + object - 1;
	qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fbo->objectID );

	if( texture->flags & IT_DEPTH ) {
		attachment = GL_DEPTH_ATTACHMENT_EXT;
		fbo->depthTexture = texture;
	} else {
		attachment = GL_COLOR_ATTACHMENT0_EXT;
		fbo->colorTexture = texture;
#ifndef GL_ES_VERSION_2_0
		qglDrawBuffer( GL_COLOR_ATTACHMENT0_EXT );
		qglReadBuffer( GL_COLOR_ATTACHMENT0_EXT );
#endif
	}
	texture->fbo = object;

	// attach texture
	qglFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, attachment, GL_TEXTURE_2D, texture->texnum, 0 );
	if( ( texture->flags & ( IT_DEPTH|IT_STENCIL ) ) == ( IT_DEPTH|IT_STENCIL ) ) {
		qglFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, texture->texnum, 0 );
	}

	qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, r_bound_framebuffer_objectID ? r_bound_framebuffer_object->objectID : 0 );
}
예제 #3
0
/*
==============
idRenderSystemLocal::CaptureRenderToFile
==============
*/
void idRenderSystemLocal::CaptureRenderToFile( const char* fileName, bool fixAlpha )
{
	if( !R_IsInitialized() )
	{
		return;
	}
	
	idScreenRect& rc = renderCrops[currentRenderCrop];
	
	guiModel->EmitFullScreen();
	guiModel->Clear();
	RenderCommandBuffers( frameData->cmdHead );
	
	qglReadBuffer( GL_BACK );
	
	// include extra space for OpenGL padding to word boundaries
	int	c = ( rc.GetWidth() + 3 ) * rc.GetHeight();
	byte* data = ( byte* )R_StaticAlloc( c * 3 );
	
	qglReadPixels( rc.x1, rc.y1, rc.GetWidth(), rc.GetHeight(), GL_RGB, GL_UNSIGNED_BYTE, data );
	
	byte* data2 = ( byte* )R_StaticAlloc( c * 4 );
	
	for( int i = 0 ; i < c ; i++ )
	{
		data2[ i * 4 ] = data[ i * 3 ];
		data2[ i * 4 + 1 ] = data[ i * 3 + 1 ];
		data2[ i * 4 + 2 ] = data[ i * 3 + 2 ];
		data2[ i * 4 + 3 ] = 0xff;
	}
	
	R_WriteTGA( fileName, data2, rc.GetWidth(), rc.GetHeight(), true );
	
	R_StaticFree( data );
	R_StaticFree( data2 );
}
예제 #4
0
/*
============
FBO_Init
============
*/
void FBO_Init(void)
{
	int             i;
	// int             width, height, hdrFormat, multisample;
	int             hdrFormat, multisample;

	ri.Printf(PRINT_ALL, "------- FBO_Init -------\n");

	if(!glRefConfig.framebufferObject)
		return;

	tr.numFBOs = 0;

	GL_CheckErrors();

	R_IssuePendingRenderCommands();

/*	if(glRefConfig.textureNonPowerOfTwo)
	{
		width = glConfig.vidWidth;
		height = glConfig.vidHeight;
	}
	else
	{
		width = NextPowerOfTwo(glConfig.vidWidth);
		height = NextPowerOfTwo(glConfig.vidHeight);
	} */

	hdrFormat = GL_RGBA8;
	if (r_hdr->integer && glRefConfig.framebufferObject && glRefConfig.textureFloat)
	{
		hdrFormat = GL_RGBA16F_ARB;
	}

	qglGetIntegerv(GL_MAX_SAMPLES_EXT, &multisample);

	if (r_ext_framebuffer_multisample->integer < multisample)
	{
		multisample = r_ext_framebuffer_multisample->integer;
	}

	if (multisample < 2 || !glRefConfig.framebufferBlit)
		multisample = 0;

	if (multisample != r_ext_framebuffer_multisample->integer)
	{
		ri.Cvar_SetValue("r_ext_framebuffer_multisample", (float)multisample);
	}
	
	// only create a render FBO if we need to resolve MSAA or do HDR
	// otherwise just render straight to the screen (tr.renderFbo = NULL)
	if (multisample && glRefConfig.framebufferMultisample)
	{
		tr.renderFbo = FBO_Create("_render", tr.renderDepthImage->width, tr.renderDepthImage->height);
		FBO_Bind(tr.renderFbo);

		FBO_CreateBuffer(tr.renderFbo, hdrFormat, 0, multisample);
		FBO_CreateBuffer(tr.renderFbo, GL_DEPTH_COMPONENT24_ARB, 0, multisample);

		R_CheckFBO(tr.renderFbo);


		tr.msaaResolveFbo = FBO_Create("_msaaResolve", tr.renderDepthImage->width, tr.renderDepthImage->height);
		FBO_Bind(tr.msaaResolveFbo);

		//FBO_CreateBuffer(tr.msaaResolveFbo, hdrFormat, 0, 0);
		FBO_AttachTextureImage(tr.renderImage, 0);

		//FBO_CreateBuffer(tr.msaaResolveFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0);
		R_AttachFBOTextureDepth(tr.renderDepthImage->texnum);

		R_CheckFBO(tr.msaaResolveFbo);
	}
	else if (r_hdr->integer)
	{
		tr.renderFbo = FBO_Create("_render", tr.renderDepthImage->width, tr.renderDepthImage->height);
		FBO_Bind(tr.renderFbo);

		//FBO_CreateBuffer(tr.renderFbo, hdrFormat, 0, 0);
		FBO_AttachTextureImage(tr.renderImage, 0);

		//FBO_CreateBuffer(tr.renderFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0);
		R_AttachFBOTextureDepth(tr.renderDepthImage->texnum);

		R_CheckFBO(tr.renderFbo);
	}

	// clear render buffer
	// this fixes the corrupt screen bug with r_hdr 1 on older hardware
	if (tr.renderFbo)
	{
		FBO_Bind(tr.renderFbo);
		qglClearColor( 1, 0, 0.5, 1 );
		qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
		FBO_Bind(NULL);
	}

	if (r_drawSunRays->integer)
	{
		tr.sunRaysFbo = FBO_Create("_sunRays", tr.renderDepthImage->width, tr.renderDepthImage->height);
		FBO_Bind(tr.sunRaysFbo);

		FBO_AttachTextureImage(tr.sunRaysImage, 0);

		R_AttachFBOTextureDepth(tr.renderDepthImage->texnum);

		R_CheckFBO(tr.sunRaysFbo);
	}

	// FIXME: Don't use separate color/depth buffers for a shadow buffer
	if (MAX_DRAWN_PSHADOWS && tr.pshadowMaps[0])
	{
		for( i = 0; i < MAX_DRAWN_PSHADOWS; i++)
		{
			tr.pshadowFbos[i] = FBO_Create(va("_shadowmap%d", i), tr.pshadowMaps[i]->width, tr.pshadowMaps[i]->height);
			FBO_Bind(tr.pshadowFbos[i]);

			//FBO_CreateBuffer(tr.pshadowFbos[i], GL_RGBA8, 0, 0);
			FBO_AttachTextureImage(tr.pshadowMaps[i], 0);

			FBO_CreateBuffer(tr.pshadowFbos[i], GL_DEPTH_COMPONENT24_ARB, 0, 0);
			//R_AttachFBOTextureDepth(tr.textureDepthImage->texnum);

			R_CheckFBO(tr.pshadowFbos[i]);
		}
	}

	if (tr.sunShadowDepthImage[0])
	{
		for ( i = 0; i < 4; i++)
		{
			tr.sunShadowFbo[i] = FBO_Create("_sunshadowmap", tr.sunShadowDepthImage[i]->width, tr.sunShadowDepthImage[i]->height);
			FBO_Bind(tr.sunShadowFbo[i]);

			//FBO_CreateBuffer(tr.sunShadowFbo[i], GL_RGBA8, 0, 0);
			//FBO_AttachTextureImage(tr.sunShadowImage, 0);
			qglDrawBuffer(GL_NONE);
			qglReadBuffer(GL_NONE);

			//FBO_CreateBuffer(tr.sunShadowFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0);
			R_AttachFBOTextureDepth(tr.sunShadowDepthImage[i]->texnum);

			R_CheckFBO(tr.sunShadowFbo[i]);

		}

		tr.screenShadowFbo = FBO_Create("_screenshadow", tr.screenShadowImage->width, tr.screenShadowImage->height);
		FBO_Bind(tr.screenShadowFbo);

		FBO_AttachTextureImage(tr.screenShadowImage, 0);

		R_CheckFBO(tr.screenShadowFbo);
	}

	for (i = 0; i < 2; i++)
	{
		tr.textureScratchFbo[i] = FBO_Create(va("_texturescratch%d", i), tr.textureScratchImage[i]->width, tr.textureScratchImage[i]->height);
		FBO_Bind(tr.textureScratchFbo[i]);

		//FBO_CreateBuffer(tr.textureScratchFbo[i], GL_RGBA8, 0, 0);
		FBO_AttachTextureImage(tr.textureScratchImage[i], 0);

		R_CheckFBO(tr.textureScratchFbo[i]);
	}

	{
		tr.calcLevelsFbo = FBO_Create("_calclevels", tr.calcLevelsImage->width, tr.calcLevelsImage->height);
		FBO_Bind(tr.calcLevelsFbo);

		//FBO_CreateBuffer(tr.calcLevelsFbo, hdrFormat, 0, 0);
		FBO_AttachTextureImage(tr.calcLevelsImage, 0);

		R_CheckFBO(tr.calcLevelsFbo);
	}

	{
		tr.targetLevelsFbo = FBO_Create("_targetlevels", tr.targetLevelsImage->width, tr.targetLevelsImage->height);
		FBO_Bind(tr.targetLevelsFbo);

		//FBO_CreateBuffer(tr.targetLevelsFbo, hdrFormat, 0, 0);
		FBO_AttachTextureImage(tr.targetLevelsImage, 0);

		R_CheckFBO(tr.targetLevelsFbo);
	}

	for (i = 0; i < 2; i++)
	{
		tr.quarterFbo[i] = FBO_Create(va("_quarter%d", i), tr.quarterImage[i]->width, tr.quarterImage[i]->height);
		FBO_Bind(tr.quarterFbo[i]);

		//FBO_CreateBuffer(tr.quarterFbo[i], hdrFormat, 0, 0);
		FBO_AttachTextureImage(tr.quarterImage[i], 0);

		R_CheckFBO(tr.quarterFbo[i]);
	}

	if (r_ssao->integer)
	{
		tr.hdrDepthFbo = FBO_Create("_hdrDepth", tr.hdrDepthImage->width, tr.hdrDepthImage->height);
		FBO_Bind(tr.hdrDepthFbo);

		FBO_AttachTextureImage(tr.hdrDepthImage, 0);

		R_CheckFBO(tr.hdrDepthFbo);

		tr.screenSsaoFbo = FBO_Create("_screenssao", tr.screenSsaoImage->width, tr.screenSsaoImage->height);
		FBO_Bind(tr.screenSsaoFbo);
		
		FBO_AttachTextureImage(tr.screenSsaoImage, 0);

		R_CheckFBO(tr.screenSsaoFbo);
	}

	if (tr.renderCubeImage)
	{
		tr.renderCubeFbo = FBO_Create("_renderCubeFbo", tr.renderCubeImage->width, tr.renderCubeImage->height);
		FBO_Bind(tr.renderCubeFbo);
		
		//FBO_AttachTextureImage(tr.renderCubeImage, 0);
		R_AttachFBOTexture2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, tr.renderCubeImage->texnum, 0);
		glState.currentFBO->colorImage[0] = tr.renderCubeImage;

		FBO_CreateBuffer(tr.renderCubeFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0);

		R_CheckFBO(tr.renderCubeFbo);
	}

	GL_CheckErrors();

	FBO_Bind(NULL);
}
예제 #5
0
/*
* RFB_RegisterObject
*/
int RFB_RegisterObject( int width, int height, bool builtin, bool depthRB, bool stencilRB,
						bool colorRB, int samples, bool useFloat, bool sRGB ) {
	int i;
	int format;
	GLuint fbID;
	GLuint rbID = 0;
	r_fbo_t *fbo = NULL;

	if( !r_frambuffer_objects_initialized ) {
		return 0;
	}

#ifdef GL_ES_VERSION_2_0
	if( samples ) {
		return 0;
	}
#else
	if( samples && !glConfig.ext.framebuffer_multisample ) {
		return 0;
	}
#endif

	for( i = 0, fbo = r_framebuffer_objects; i < r_num_framebuffer_objects; i++, fbo++ ) {
		if( !fbo->objectID ) {
			// free slot
			goto found;
		}
	}

	if( i == MAX_FRAMEBUFFER_OBJECTS ) {
		Com_Printf( S_COLOR_YELLOW "RFB_RegisterObject: framebuffer objects limit exceeded\n" );
		return 0;
	}

	clamp_high( samples, glConfig.maxFramebufferSamples );

	i = r_num_framebuffer_objects++;
	fbo = r_framebuffer_objects + i;

found:
	qglGenFramebuffersEXT( 1, &fbID );
	memset( fbo, 0, sizeof( *fbo ) );
	fbo->objectID = fbID;
	if( builtin ) {
		fbo->registrationSequence = -1;
	} else {
		fbo->registrationSequence = rsh.registrationSequence;
	}
	fbo->width = width;
	fbo->height = height;
	fbo->samples = samples;
	fbo->sRGB = sRGB;

	qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fbo->objectID );

	if( colorRB ) {
		format = glConfig.forceRGBAFramebuffers ? GL_RGBA : GL_RGB;
		if( useFloat ) {
			format = glConfig.forceRGBAFramebuffers ? GL_RGBA16F_ARB : GL_RGB16F_ARB;
		}

		qglGenRenderbuffersEXT( 1, &rbID );
		fbo->colorRenderBuffer = rbID;
		qglBindRenderbufferEXT( GL_RENDERBUFFER_EXT, rbID );

#ifndef GL_ES_VERSION_2_0
		if( samples ) {
			qglRenderbufferStorageMultisampleEXT( GL_RENDERBUFFER_EXT, samples, format, width, height );
		} else
#endif
		qglRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, format, width, height );
	}
#ifndef GL_ES_VERSION_2_0
	else {
		// until a color texture is attached, don't enable drawing to the buffer
		qglDrawBuffer( GL_NONE );
		qglReadBuffer( GL_NONE );
	}
#endif

	if( depthRB ) {
		qglGenRenderbuffersEXT( 1, &rbID );
		fbo->depthRenderBuffer = rbID;
		qglBindRenderbufferEXT( GL_RENDERBUFFER_EXT, rbID );

		if( stencilRB ) {
			format = GL_DEPTH24_STENCIL8_EXT;
		} else if( glConfig.ext.depth24 ) {
			format = GL_DEPTH_COMPONENT24;
		} else if( glConfig.ext.depth_nonlinear ) {
			format = GL_DEPTH_COMPONENT16_NONLINEAR_NV;
		} else {
			format = GL_DEPTH_COMPONENT16;
		}

#ifndef GL_ES_VERSION_2_0
		if( samples ) {
			qglRenderbufferStorageMultisampleEXT( GL_RENDERBUFFER_EXT, samples, format, width, height );
		} else
#endif
		qglRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, format, width, height );

		if( stencilRB ) {
			fbo->stencilRenderBuffer = rbID;
		}
	}

	if( rbID ) {
		qglBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );
	}

	if( fbo->colorRenderBuffer ) {
		qglFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, fbo->colorRenderBuffer );
	}
	if( fbo->depthRenderBuffer ) {
		qglFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->depthRenderBuffer );
	}
	if( fbo->stencilRenderBuffer ) {
		qglFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->stencilRenderBuffer );
	}

	if( colorRB && depthRB ) {
		if( !RFB_CheckObjectStatus() ) {
			goto fail;
		}
	}

	if( r_bound_framebuffer_objectID ) {
		qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, r_bound_framebuffer_object->objectID );
	} else {
		qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
	}

	return i + 1;

fail:
	RFB_DeleteObject( fbo );
	qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
	return 0;
}
예제 #6
0
/*
* RFB_BlitObject
*
* The target FBO must be equal or greater in both dimentions than
* the currently bound FBO!
*/
void RFB_BlitObject( int src, int dest, int bitMask, int mode, int filter, int readAtt, int drawAtt ) {
	int bits;
	int destObj;
	int dx, dy, dw, dh;
	r_fbo_t scrfbo;
	r_fbo_t *fbo;
	r_fbo_t *destfbo;

	if( !glConfig.ext.framebuffer_blit ) {
		return;
	}

	assert( src >= 0 && src <= r_num_framebuffer_objects );
	if( src < 0 || src > r_num_framebuffer_objects ) {
		return;
	}

	if( src == 0 ) {
		fbo = &scrfbo;
	} else {
		fbo = r_framebuffer_objects + src - 1;
	}

	assert( dest >= 0 && dest <= r_num_framebuffer_objects );
	if( dest < 0 || dest > r_num_framebuffer_objects ) {
		return;
	}

	if( dest ) {
		destfbo = r_framebuffer_objects + dest - 1;
	} else {
		destfbo = NULL;
	}

	bits = bitMask;
	if( !bits ) {
		return;
	}

	RB_ApplyScissor();

	if( src == 0 ) {
		memset( fbo, 0, sizeof( *fbo ) );
		fbo->width = glConfig.width;
		fbo->height = glConfig.height;
	}

	if( destfbo ) {
		dw = destfbo->width;
		dh = destfbo->height;
		destObj = destfbo->objectID;
	} else {
		dw = glConfig.width;
		dh = glConfig.height;
		destObj = 0;
	}

	switch( mode ) {
		case FBO_COPY_CENTREPOS:
			dx = ( dw - fbo->width ) / 2;
			dy = ( dh - fbo->height ) / 2;
			dw = fbo->width;
			dh = fbo->height;
			break;
		case FBO_COPY_INVERT_Y:
			dx = 0;
			dy = dh - fbo->height;
			dw = fbo->width;
			dh = fbo->height;
			break;
		case FBO_COPY_NORMAL_DST_SIZE:
			dx = 0;
			dy = 0;
			//dw = dw;
			//dh = dh;
			break;
		default:
			dx = 0;
			dy = 0;
			dw = fbo->width;
			dh = fbo->height;
			break;
	}

	qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
	qglBindFramebufferEXT( GL_READ_FRAMEBUFFER_EXT, fbo->objectID );
	qglBindFramebufferEXT( GL_DRAW_FRAMEBUFFER_EXT, destObj );

#ifndef GL_ES_VERSION_2_0
	if( src == 0 ) {
		qglReadBuffer( GL_BACK );
		qglDrawBuffer( GL_COLOR_ATTACHMENT0_EXT + drawAtt );
	} else {
		qglReadBuffer( GL_COLOR_ATTACHMENT0_EXT + readAtt );
		qglDrawBuffer( GL_COLOR_ATTACHMENT0_EXT + drawAtt );
	}
#endif

	qglBlitFramebufferEXT( 0, 0, fbo->width, fbo->height, dx, dy, dx + dw, dy + dh, bits, filter );
	qglBindFramebufferEXT( GL_READ_FRAMEBUFFER_EXT, 0 );
	qglBindFramebufferEXT( GL_DRAW_FRAMEBUFFER_EXT, 0 );
	qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fbo->objectID );

#ifndef GL_ES_VERSION_2_0
	if( src == 0 ) {
		qglReadBuffer( GL_BACK );
		qglDrawBuffer( GL_BACK );
	} else {
		qglReadBuffer( GL_COLOR_ATTACHMENT0_EXT );
		qglDrawBuffer( GL_COLOR_ATTACHMENT0_EXT );
	}
#endif

	assert( qglGetError() == GL_NO_ERROR );
}
예제 #7
0
/*
* RFB_AttachTextureToObject
*/
bool RFB_AttachTextureToObject( int object, bool depth, int target, image_t *texture ) {
	r_fbo_t *fbo;
	int attachment;
	GLuint texnum = 0;

	assert( object > 0 && object <= r_num_framebuffer_objects );
	if( object <= 0 || object > r_num_framebuffer_objects ) {
		return false;
	}

	if( target < 0 || target >= MAX_FRAMEBUFFER_COLOR_ATTACHMENTS ) {
		return false;
	}
	if( target > 0 && !glConfig.ext.draw_buffers ) {
		return false;
	}

	fbo = r_framebuffer_objects + object - 1;
	qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fbo->objectID );

bind:
	if( depth ) {
		attachment = GL_DEPTH_ATTACHMENT_EXT;

		if( texture ) {
			assert( texture->flags & IT_DEPTH );
			texnum = texture->texnum;
			texture->fbo = object;
		}
	} else {
#ifndef GL_ES_VERSION_2_0
		const GLenum fboBuffers[8] = {
			GL_COLOR_ATTACHMENT0_EXT,
			GL_COLOR_ATTACHMENT1_EXT,
			GL_COLOR_ATTACHMENT2_EXT,
			GL_COLOR_ATTACHMENT3_EXT,
			GL_COLOR_ATTACHMENT4_EXT,
			GL_COLOR_ATTACHMENT5_EXT,
			GL_COLOR_ATTACHMENT6_EXT,
			GL_COLOR_ATTACHMENT7_EXT,
		};
#endif

		attachment = GL_COLOR_ATTACHMENT0_EXT + target;

#ifndef GL_ES_VERSION_2_0
		if( target > 0 && texture ) {
			qglDrawBuffersARB( target + 1, fboBuffers );
		} else {
			if( glConfig.ext.draw_buffers ) {
				qglDrawBuffersARB( 0, fboBuffers );
			}
			qglDrawBuffer( GL_COLOR_ATTACHMENT0_EXT );
			qglReadBuffer( GL_COLOR_ATTACHMENT0_EXT );
		}
#endif

		if( texture ) {
			assert( !( texture->flags & IT_DEPTH ) );
			texnum = texture->texnum;
			texture->fbo = object;
		}
	}

	// attach texture
	qglFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, attachment, GL_TEXTURE_2D, texnum, 0 );
	if( texture ) {
		if( ( texture->flags & ( IT_DEPTH | IT_STENCIL ) ) == ( IT_DEPTH | IT_STENCIL ) ) {
			qglFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, texnum, 0 );
		}
	}
	else {
		if( depth ) {
			qglFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, texnum, 0 );
		}
	}
	qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, r_bound_framebuffer_objectID ? r_bound_framebuffer_object->objectID : 0 );

	// check framebuffer status and unbind if failed
	if( !RFB_CheckObjectStatus() ) {
		if( texture ) {
			texture = NULL;
			goto bind;
		}
		return false;
	}

	if( depth ) {
		fbo->depthTexture = texture;
	} else {
		fbo->colorTexture[target] = texture;
	}
	return true;
}
예제 #8
0
/*
* RFB_RegisterObject
*/
int RFB_RegisterObject( int width, int height, bool builtin, bool depthRB, bool stencilRB )
{
	int i;
	GLuint fbID;
	GLuint rbID;
	r_fbo_t *fbo;

	if( !r_frambuffer_objects_initialized )
		return 0;

	for( i = 0, fbo = r_framebuffer_objects; i < r_num_framebuffer_objects; i++, fbo++ ) {
		if( !fbo->objectID ) {
			// free slot
			goto found;
		}
	}

	if( i == MAX_FRAMEBUFFER_OBJECTS )
	{
		Com_Printf( S_COLOR_YELLOW "RFB_RegisterObject: framebuffer objects limit exceeded\n" );
		return 0;
	}

	i = r_num_framebuffer_objects++;
	fbo = r_framebuffer_objects + i;

found:
	qglGenFramebuffersEXT( 1, &fbID );
	memset( fbo, 0, sizeof( *fbo ) );
	fbo->objectID = fbID;
	if( builtin )
		fbo->registrationSequence = -1;
	else
		fbo->registrationSequence = rsh.registrationSequence;
	fbo->width = width;
	fbo->height = height;

	qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fbo->objectID );

#ifndef GL_ES_VERSION_2_0
	// until a color texture is attached, don't enable drawing to the buffer
	qglDrawBuffer( GL_NONE );
	qglReadBuffer( GL_NONE );
#endif

	if( depthRB )
	{
		int format;

		qglGenRenderbuffersEXT( 1, &rbID );
		fbo->depthRenderBuffer = rbID;
		qglBindRenderbufferEXT( GL_RENDERBUFFER_EXT, rbID );

		if( stencilRB )
			format = GL_DEPTH24_STENCIL8_EXT;
		else if( glConfig.ext.depth24 )
			format = GL_DEPTH_COMPONENT24;
		else if( glConfig.ext.depth_nonlinear )
			format = GL_DEPTH_COMPONENT16_NONLINEAR_NV;
		else
			format = GL_DEPTH_COMPONENT16;
		qglRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, format, width, height );

		qglFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rbID );
		if( stencilRB )
			qglFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rbID );

		qglBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );	
	}

	if( r_bound_framebuffer_objectID )
		qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, r_bound_framebuffer_object->objectID );
	else
		qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );

	return i+1;
}