/*
================
idRenderSystemLocal::CaptureRenderToImage
================
*/
void idRenderSystemLocal::CaptureRenderToImage( const char *imageName, bool clearColorAfterCopy ) {
	if ( !R_IsInitialized() ) {
		return;
	}
	guiModel->EmitFullScreen();
	guiModel->Clear();

	if ( common->WriteDemo() ) {
		common->WriteDemo()->WriteInt( DS_RENDER );
		common->WriteDemo()->WriteInt( DC_CAPTURE_RENDER );
		common->WriteDemo()->WriteHashString( imageName );

		if ( r_showDemo.GetBool() ) {
			common->Printf( "write DC_CAPTURE_RENDER: %s\n", imageName );
		}
	}
	idImage	* image = globalImages->GetImage( imageName );
	if ( image == NULL ) {
		image = globalImages->AllocImage( imageName );
	}

	idScreenRect & rc = renderCrops[currentRenderCrop];

	copyRenderCommand_t *cmd = (copyRenderCommand_t *)R_GetCommandBuffer( sizeof( *cmd ) );
	cmd->commandId = RC_COPY_RENDER;
	cmd->x = rc.x1;
	cmd->y = rc.y1;
	cmd->imageWidth = rc.GetWidth();
	cmd->imageHeight = rc.GetHeight();
	cmd->image = image;
	cmd->clearColorAfterCopy = clearColorAfterCopy;

	guiModel->Clear();
}
/*
================
idRenderSystemLocal::UnCrop
================
*/
void idRenderSystemLocal::UnCrop()
{
	if( !R_IsInitialized() )
	{
		return;
	}
	
	if( currentRenderCrop < 1 )
	{
		common->Error( "idRenderSystemLocal::UnCrop: currentRenderCrop < 1" );
	}
	
	// close any gui drawing
	guiModel->EmitFullScreen();
	guiModel->Clear();
	
	currentRenderCrop--;
	
	if( common->WriteDemo() )
	{
		common->WriteDemo()->WriteInt( DS_RENDER );
		common->WriteDemo()->WriteInt( DC_UNCROP_RENDER );
		
		if( r_showDemo.GetBool() )
		{
			common->Printf( "write DC_UNCROP\n" );
		}
	}
}
/*
=====================
idRenderSystemLocal::SwapCommandBuffers_FinishRendering
=====================
*/
void idRenderSystemLocal::SwapCommandBuffers_FinishRendering( 
												uint64 * frontEndMicroSec,
												uint64 * backEndMicroSec,
												uint64 * shadowMicroSec,
												uint64 * gpuMicroSec )  {
	SCOPED_PROFILE_EVENT( "SwapCommandBuffers" );

	if ( gpuMicroSec != NULL ) {
		*gpuMicroSec = 0;		// until shown otherwise
	}

	if ( !R_IsInitialized() ) {
		return;
	}


	// After coming back from an autoswap, we won't have anything to render
	if ( frameData->cmdHead->next != NULL ) {
		// wait for our fence to hit, which means the swap has actually happened
		// We must do this before clearing any resources the GPU may be using
		void GL_BlockingSwapBuffers();
		GL_BlockingSwapBuffers();
	}

	// read back the start and end timer queries from the previous frame
	if ( glConfig.timerQueryAvailable ) {
		uint64 drawingTimeNanoseconds = 0;
		if ( tr.timerQueryId != 0 ) {
			qglGetQueryObjectui64vEXT( tr.timerQueryId, GL_QUERY_RESULT, &drawingTimeNanoseconds );
		}
		if ( gpuMicroSec != NULL ) {
			*gpuMicroSec = drawingTimeNanoseconds / 1000;
		}
	}

	//------------------------------

	// save out timing information
	if ( frontEndMicroSec != NULL ) {
		*frontEndMicroSec = pc.frontEndMicroSec;
	}
	if ( backEndMicroSec != NULL ) {
		*backEndMicroSec = backEnd.pc.totalMicroSec;
	}
	if ( shadowMicroSec != NULL ) {
		*shadowMicroSec = backEnd.pc.shadowMicroSec;
	}

	// print any other statistics and clear all of them
	R_PerformanceCounters();

	// check for dynamic changes that require some initialization
	R_CheckCvars();

    // check for errors
	GL_CheckErrors();
}
void idRenderSystemLocal::DrawStretchPic( const idVec4& topLeft, const idVec4& topRight, const idVec4& bottomRight, const idVec4& bottomLeft, const idMaterial* material )
{
	if( !R_IsInitialized() )
	{
		return;
	}
	if( material == NULL )
	{
		return;
	}
	
	idDrawVert* verts = guiModel->AllocTris( 4, quadPicIndexes, 6, material, currentGLState, STEREO_DEPTH_TYPE_NONE );
	if( verts == NULL )
	{
		return;
	}
	
	ALIGNTYPE16 idDrawVert localVerts[4];
	
	localVerts[0].Clear();
	localVerts[0].xyz[0] = topLeft.x;
	localVerts[0].xyz[1] = topLeft.y;
	localVerts[0].SetTexCoord( topLeft.z, topLeft.w );
	localVerts[0].SetNativeOrderColor( currentColorNativeBytesOrder );
	localVerts[0].ClearColor2();
	
	localVerts[1].Clear();
	localVerts[1].xyz[0] = topRight.x;
	localVerts[1].xyz[1] = topRight.y;
	localVerts[1].SetTexCoord( topRight.z, topRight.w );
	localVerts[1].SetNativeOrderColor( currentColorNativeBytesOrder );
	localVerts[1].ClearColor2();
	
	localVerts[2].Clear();
	localVerts[2].xyz[0] = bottomRight.x;
	localVerts[2].xyz[1] = bottomRight.y;
	localVerts[2].SetTexCoord( bottomRight.z, bottomRight.w );
	localVerts[2].SetNativeOrderColor( currentColorNativeBytesOrder );
	localVerts[2].ClearColor2();
	
	localVerts[3].Clear();
	localVerts[3].xyz[0] = bottomLeft.x;
	localVerts[3].xyz[1] = bottomLeft.y;
	localVerts[3].SetTexCoord( bottomLeft.z, bottomLeft.w );
	localVerts[3].SetNativeOrderColor( currentColorNativeBytesOrder );
	localVerts[3].ClearColor2();
	
	WriteDrawVerts16( verts, localVerts, 4 );
}
/*
=============
idRenderSystemLocal::DrawStretchTri
=============
*/
void idRenderSystemLocal::DrawStretchTri( const idVec2& p1, const idVec2& p2, const idVec2& p3, const idVec2& t1, const idVec2& t2, const idVec2& t3, const idMaterial* material )
{
	if( !R_IsInitialized() )
	{
		return;
	}
	if( material == NULL )
	{
		return;
	}
	
	triIndex_t tempIndexes[3] = { 1, 0, 2 };
	
	idDrawVert* verts = guiModel->AllocTris( 3, tempIndexes, 3, material, currentGLState, STEREO_DEPTH_TYPE_NONE );
	if( verts == NULL )
	{
		return;
	}
	
	ALIGNTYPE16 idDrawVert localVerts[3];
	
	localVerts[0].Clear();
	localVerts[0].xyz[0] = p1.x;
	localVerts[0].xyz[1] = p1.y;
	localVerts[0].SetTexCoord( t1 );
	localVerts[0].SetNativeOrderColor( currentColorNativeBytesOrder );
	localVerts[0].ClearColor2();
	
	localVerts[1].Clear();
	localVerts[1].xyz[0] = p2.x;
	localVerts[1].xyz[1] = p2.y;
	localVerts[1].SetTexCoord( t2 );
	localVerts[1].SetNativeOrderColor( currentColorNativeBytesOrder );
	localVerts[1].ClearColor2();
	
	localVerts[2].Clear();
	localVerts[2].xyz[0] = p3.x;
	localVerts[2].xyz[1] = p3.y;
	localVerts[2].SetTexCoord( t3 );
	localVerts[2].SetNativeOrderColor( currentColorNativeBytesOrder );
	localVerts[2].ClearColor2();
	
	WriteDrawVerts16( verts, localVerts, 3 );
}
Exemple #6
0
/*
=============
SetColor
=============
*/
void idGuiModel::SetColor( float r, float g, float b, float a ) {
	if ( !R_IsInitialized() ) {
		return;
	}
	if ( r == surf->color[0] && g == surf->color[1]
		&& b == surf->color[2] && a == surf->color[3] ) {
		return;	// no change
	}

	if ( surf->numVerts ) {
		AdvanceSurf();
	}

	// change the parms
	surf->color[0] = r;
	surf->color[1] = g;
	surf->color[2] = b;
	surf->color[3] = a;
}
/*
================
idRenderSystemLocal::CropRenderSize
================
*/
void idRenderSystemLocal::CropRenderSize( int width, int height )
{
	if( !R_IsInitialized() )
	{
		return;
	}
	
	// close any gui drawing before changing the size
	guiModel->EmitFullScreen();
	guiModel->Clear();
	
	
	if( width < 1 || height < 1 )
	{
		common->Error( "CropRenderSize: bad sizes" );
	}
	
	if( common->WriteDemo() )
	{
		common->WriteDemo()->WriteInt( DS_RENDER );
		common->WriteDemo()->WriteInt( DC_CROP_RENDER );
		common->WriteDemo()->WriteInt( width );
		common->WriteDemo()->WriteInt( height );
		
		if( r_showDemo.GetBool() )
		{
			common->Printf( "write DC_CROP_RENDER\n" );
		}
	}
	
	idScreenRect& previous = renderCrops[currentRenderCrop];
	
	currentRenderCrop++;
	
	idScreenRect& current = renderCrops[currentRenderCrop];
	
	current.x1 = previous.x1;
	current.x2 = previous.x1 + width - 1;
	current.y1 = previous.y2 - height + 1;
	current.y2 = previous.y2;
}
/*
==============
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 );


	if ( !vr->useFBO ) // koz
	{
		glReadBuffer( 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 );
}
Exemple #9
0
/*
========================
idImage::AllocImage

Every image will pass through this function. Allocates all the necessary MipMap levels for the 
Image, but doesn't put anything in them.

This should not be done during normal game-play, if you can avoid it.
========================
*/
void idImage::AllocImage() {
	GL_CheckErrors();
	PurgeImage();

	switch ( opts.format ) {
	case FMT_RGBA8:
		internalFormat = GL_RGBA8;
		dataFormat = GL_RGBA;
		dataType = GL_UNSIGNED_BYTE;
		break;
	case FMT_XRGB8:
		internalFormat = GL_RGB;
		dataFormat = GL_RGBA;
		dataType = GL_UNSIGNED_BYTE;
		break;
	case FMT_RGB565:
		internalFormat = GL_RGB;
		dataFormat = GL_RGB;
		dataType = GL_UNSIGNED_SHORT_5_6_5;
		break;
	case FMT_ALPHA:
#if defined( USE_CORE_PROFILE )
		internalFormat = GL_R8;
		dataFormat = GL_RED;
#else
		internalFormat = GL_ALPHA8;
		dataFormat = GL_ALPHA;
#endif
		dataType = GL_UNSIGNED_BYTE;
		break;
	case FMT_L8A8:
#if defined( USE_CORE_PROFILE )
		internalFormat = GL_RG8;
		dataFormat = GL_RG;
#else
		internalFormat = GL_LUMINANCE8_ALPHA8;
		dataFormat = GL_LUMINANCE_ALPHA;
#endif
		dataType = GL_UNSIGNED_BYTE;
		break;
	case FMT_LUM8:
#if defined( USE_CORE_PROFILE )
		internalFormat = GL_R8;
		dataFormat = GL_RED;
#else
		internalFormat = GL_LUMINANCE8;
		dataFormat = GL_LUMINANCE;
#endif
		dataType = GL_UNSIGNED_BYTE;
		break;
	case FMT_INT8:
#if defined( USE_CORE_PROFILE )
		internalFormat = GL_R8;
		dataFormat = GL_RED;
#else
		internalFormat = GL_INTENSITY8;
		dataFormat = GL_LUMINANCE;
#endif
		dataType = GL_UNSIGNED_BYTE;
		break;
	case FMT_DXT1:
		internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
		dataFormat = GL_RGBA;
		dataType = GL_UNSIGNED_BYTE;
		break;
	case FMT_DXT5:
		internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
		dataFormat = GL_RGBA;
		dataType = GL_UNSIGNED_BYTE;
		break;
	case FMT_DEPTH:
		internalFormat = GL_DEPTH_COMPONENT;
		dataFormat = GL_DEPTH_COMPONENT;
		dataType = GL_UNSIGNED_BYTE;
		break;
	case FMT_X16:
		internalFormat = GL_INTENSITY16;
		dataFormat = GL_LUMINANCE;
		dataType = GL_UNSIGNED_SHORT;
		break;
	case FMT_Y16_X16:
		internalFormat = GL_LUMINANCE16_ALPHA16;
		dataFormat = GL_LUMINANCE_ALPHA;
		dataType = GL_UNSIGNED_SHORT;
		break;
	default:
		idLib::Error( "Unhandled image format %d in %s\n", opts.format, GetName() );
	}

	// if we don't have a rendering context, just return after we
	// have filled in the parms.  We must have the values set, or
	// an image match from a shader before OpenGL starts would miss
	// the generated texture
	if ( !R_IsInitialized() ) {
		return;
	}

	// generate the texture number
	qglGenTextures( 1, (GLuint *)&texnum );
	assert( texnum != TEXTURE_NOT_LOADED );

	//----------------------------------------------------
	// allocate all the mip levels with NULL data
	//----------------------------------------------------

	int numSides;
	int target;
	int uploadTarget;
	if ( opts.textureType == TT_2D ) {
		target = uploadTarget = GL_TEXTURE_2D;
		numSides = 1;
	} else if ( opts.textureType == TT_CUBIC ) {
		target = GL_TEXTURE_CUBE_MAP_EXT;
		uploadTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT;
		numSides = 6;
	} else {
		assert( !"opts.textureType" );
		target = uploadTarget = GL_TEXTURE_2D;
		numSides = 1;
	}

	qglBindTexture( target, texnum );

	for ( int side = 0; side < numSides; side++ ) {
		int w = opts.width;
		int h = opts.height;
		if ( opts.textureType == TT_CUBIC ) {
			h = w;
		}
		for ( int level = 0; level < opts.numLevels; level++ ) {

			// clear out any previous error
			GL_CheckErrors();

			if ( IsCompressed() ) {
				int compressedSize = ( ((w+3)/4) * ((h+3)/4) * int64( 16 ) * BitsForFormat( opts.format ) ) / 8;

				// Even though the OpenGL specification allows the 'data' pointer to be NULL, for some
				// drivers we actually need to upload data to get it to allocate the texture.
				// However, on 32-bit systems we may fail to allocate a large block of memory for large
				// textures. We handle this case by using HeapAlloc directly and allowing the allocation
				// to fail in which case we simply pass down NULL to glCompressedTexImage2D and hope for the best.
				// As of 2011-10-6 using NVIDIA hardware and drivers we have to allocate the memory with HeapAlloc
				// with the exact size otherwise large image allocation (for instance for physical page textures)
				// may fail on Vista 32-bit.
				void * data = HeapAlloc( GetProcessHeap(), 0, compressedSize );
				qglCompressedTexImage2DARB( uploadTarget+side, level, internalFormat, w, h, 0, compressedSize, data );
				if ( data != NULL ) {
					HeapFree( GetProcessHeap(), 0, data );
				}
			} else {
				qglTexImage2D( uploadTarget + side, level, internalFormat, w, h, 0, dataFormat, dataType, NULL );
			}

			GL_CheckErrors();

			w = Max( 1, w >> 1 );
			h = Max( 1, h >> 1 );
		}
	}

	qglTexParameteri( target, GL_TEXTURE_MAX_LEVEL, opts.numLevels - 1 );

	// see if we messed anything up
	GL_CheckErrors();

	SetTexParameters();

	GL_CheckErrors();
}
/*
=====================
idRenderSystemLocal::SwapCommandBuffers_FinishCommandBuffers
=====================
*/
const emptyCommand_t* idRenderSystemLocal::SwapCommandBuffers_FinishCommandBuffers()
{
	if( !R_IsInitialized() )
	{
		return NULL;
	}
	
	// close any gui drawing
	guiModel->EmitFullScreen();
	guiModel->Clear();
	
	// unmap the buffer objects so they can be used by the GPU
	vertexCache.BeginBackEnd();
	
	// save off this command buffer
	const emptyCommand_t* commandBufferHead = frameData->cmdHead;
	
	// copy the code-used drawsurfs that were
	// allocated at the start of the buffer memory to the backEnd referenced locations
	backEnd.unitSquareSurface = tr.unitSquareSurface_;
	backEnd.zeroOneCubeSurface = tr.zeroOneCubeSurface_;
	backEnd.testImageSurface = tr.testImageSurface_;
	
	// use the other buffers next frame, because another CPU
	// may still be rendering into the current buffers
	R_ToggleSmpFrame();
	
	// possibly change the stereo3D mode
	// PC
	if( glConfig.nativeScreenWidth == 1280 && glConfig.nativeScreenHeight == 1470 )
	{
		glConfig.stereo3Dmode = STEREO3D_HDMI_720;
	}
	else
	{
		glConfig.stereo3Dmode = GetStereoScopicRenderingMode();
	}
	
	// prepare the new command buffer
	guiModel->BeginFrame();
	
	//------------------------------
	// Make sure that geometry used by code is present in the buffer cache.
	// These use frame buffer cache (not static) because they may be used during
	// map loads.
	//
	// It is important to do this first, so if the buffers overflow during
	// scene generation, the basic surfaces needed for drawing the buffers will
	// always be present.
	//------------------------------
	R_InitDrawSurfFromTri( tr.unitSquareSurface_, *tr.unitSquareTriangles );
	R_InitDrawSurfFromTri( tr.zeroOneCubeSurface_, *tr.zeroOneCubeTriangles );
	R_InitDrawSurfFromTri( tr.testImageSurface_, *tr.testImageTriangles );
	
	// Reset render crop to be the full screen
	renderCrops[0].x1 = 0;
	renderCrops[0].y1 = 0;
	renderCrops[0].x2 = GetWidth() - 1;
	renderCrops[0].y2 = GetHeight() - 1;
	currentRenderCrop = 0;
	
	// this is the ONLY place this is modified
	frameCount++;
	
	// just in case we did a common->Error while this
	// was set
	guiRecursionLevel = 0;
	
	// the first rendering will be used for commands like
	// screenshot, rather than a possible subsequent remote
	// or mirror render
//	primaryWorld = NULL;

	// set the time for shader effects in 2D rendering
	frameShaderTime = Sys_Milliseconds() * 0.001;
	
	setBufferCommand_t* cmd2 = ( setBufferCommand_t* )R_GetCommandBuffer( sizeof( *cmd2 ) );
	cmd2->commandId = RC_SET_BUFFER;
	cmd2->buffer = ( int )GL_BACK;
	
	// the old command buffer can now be rendered, while the new one can
	// be built in parallel
	return commandBufferHead;
}
Exemple #11
0
/*
=============
DrawStretchTri

x/y/w/h are in the 0,0 to 640,480 range
=============
*/
void idGuiModel::DrawStretchTri( idVec2 p1, idVec2 p2, idVec2 p3, idVec2 t1, idVec2 t2, idVec2 t3, const idMaterial *material ) {
	idDrawVert tempVerts[3];
	glIndex_t tempIndexes[3];
	int vertCount = 3;
	int indexCount = 3;

	if ( !R_IsInitialized() ) {
		return;
	}
	if ( !material ) {
		return;
	}

	tempIndexes[0] = 1;
	tempIndexes[1] = 0;
	tempIndexes[2] = 2;
	tempVerts[0].xyz[0] = p1.x;
	tempVerts[0].xyz[1] = p1.y;
	tempVerts[0].xyz[2] = 0;
	tempVerts[0].st[0] = t1.x;
	tempVerts[0].st[1] = t1.y;
	tempVerts[0].normal[0] = 0;
	tempVerts[0].normal[1] = 0;
	tempVerts[0].normal[2] = 1;
	tempVerts[0].tangents[0][0] = 1;
	tempVerts[0].tangents[0][1] = 0;
	tempVerts[0].tangents[0][2] = 0;
	tempVerts[0].tangents[1][0] = 0;
	tempVerts[0].tangents[1][1] = 1;
	tempVerts[0].tangents[1][2] = 0;
	tempVerts[1].xyz[0] = p2.x;
	tempVerts[1].xyz[1] = p2.y;
	tempVerts[1].xyz[2] = 0;
	tempVerts[1].st[0] = t2.x;
	tempVerts[1].st[1] = t2.y;
	tempVerts[1].normal[0] = 0;
	tempVerts[1].normal[1] = 0;
	tempVerts[1].normal[2] = 1;
	tempVerts[1].tangents[0][0] = 1;
	tempVerts[1].tangents[0][1] = 0;
	tempVerts[1].tangents[0][2] = 0;
	tempVerts[1].tangents[1][0] = 0;
	tempVerts[1].tangents[1][1] = 1;
	tempVerts[1].tangents[1][2] = 0;
	tempVerts[2].xyz[0] = p3.x;
	tempVerts[2].xyz[1] = p3.y;
	tempVerts[2].xyz[2] = 0;
	tempVerts[2].st[0] = t3.x;
	tempVerts[2].st[1] = t3.y;
	tempVerts[2].normal[0] = 0;
	tempVerts[2].normal[1] = 0;
	tempVerts[2].normal[2] = 1;
	tempVerts[2].tangents[0][0] = 1;
	tempVerts[2].tangents[0][1] = 0;
	tempVerts[2].tangents[0][2] = 0;
	tempVerts[2].tangents[1][0] = 0;
	tempVerts[2].tangents[1][1] = 1;
	tempVerts[2].tangents[1][2] = 0;

	// break the current surface if we are changing to a new material
	if ( material != surf->material ) {
		if ( surf->numVerts ) {
			AdvanceSurf();
		}
		const_cast<idMaterial *>(material)->EnsureNotPurged();	// in case it was a gui item started before a level change
		surf->material = material;
	}


	int numVerts = verts.Num();
	int numIndexes = indexes.Num();

	verts.AssureSize( numVerts + vertCount );
	indexes.AssureSize( numIndexes + indexCount );

	surf->numVerts += vertCount;
	surf->numIndexes += indexCount;

	for ( int i = 0; i < indexCount; i++ ) {
		indexes[numIndexes + i] = numVerts + tempIndexes[i] - surf->firstVert;
	}

	memcpy( &verts[numVerts], tempVerts, vertCount * sizeof( verts[0] ) );
}
Exemple #12
0
/*
=============
DrawStretchPic

x/y/w/h are in the 0,0 to 640,480 range
=============
*/
void idGuiModel::DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, const idMaterial *hShader ) {
	idDrawVert verts[4];
	glIndex_t indexes[6];

	if ( !R_IsInitialized() ) {
		return;
	}
	if ( !hShader ) {
		return;
	}

	// clip to edges, because the pic may be going into a guiShader
	// instead of full screen
	if ( x < 0 ) {
		s1 += ( s2 - s1 ) * -x / w;
		w += x;
		x = 0;
	}
	if ( y < 0 ) {
		t1 += ( t2 - t1 ) * -y / h;
		h += y;
		y = 0;
	}
	if ( x + w > 640 ) {
		s2 -= ( s2 - s1 ) * ( x + w - 640 ) / w;
		w = 640 - x;
	}
	if ( y + h > 480 ) {
		t2 -= ( t2 - t1 ) * ( y + h - 480 ) / h;
		h = 480 - y;
	}

	if ( w <= 0 || h <= 0 ) {
		return;		// completely clipped away
	}

	indexes[0] = 3;
	indexes[1] = 0;
	indexes[2] = 2;
	indexes[3] = 2;
	indexes[4] = 0;
	indexes[5] = 1;
	verts[0].xyz[0] = x;
	verts[0].xyz[1] = y;
	verts[0].xyz[2] = 0;
	verts[0].st[0] = s1;
	verts[0].st[1] = t1;
	verts[0].normal[0] = 0;
	verts[0].normal[1] = 0;
	verts[0].normal[2] = 1;
	verts[0].tangents[0][0] = 1;
	verts[0].tangents[0][1] = 0;
	verts[0].tangents[0][2] = 0;
	verts[0].tangents[1][0] = 0;
	verts[0].tangents[1][1] = 1;
	verts[0].tangents[1][2] = 0;
	verts[1].xyz[0] = x + w;
	verts[1].xyz[1] = y;
	verts[1].xyz[2] = 0;
	verts[1].st[0] = s2;
	verts[1].st[1] = t1;
	verts[1].normal[0] = 0;
	verts[1].normal[1] = 0;
	verts[1].normal[2] = 1;
	verts[1].tangents[0][0] = 1;
	verts[1].tangents[0][1] = 0;
	verts[1].tangents[0][2] = 0;
	verts[1].tangents[1][0] = 0;
	verts[1].tangents[1][1] = 1;
	verts[1].tangents[1][2] = 0;
	verts[2].xyz[0] = x + w;
	verts[2].xyz[1] = y + h;
	verts[2].xyz[2] = 0;
	verts[2].st[0] = s2;
	verts[2].st[1] = t2;
	verts[2].normal[0] = 0;
	verts[2].normal[1] = 0;
	verts[2].normal[2] = 1;
	verts[2].tangents[0][0] = 1;
	verts[2].tangents[0][1] = 0;
	verts[2].tangents[0][2] = 0;
	verts[2].tangents[1][0] = 0;
	verts[2].tangents[1][1] = 1;
	verts[2].tangents[1][2] = 0;
	verts[3].xyz[0] = x;
	verts[3].xyz[1] = y + h;
	verts[3].xyz[2] = 0;
	verts[3].st[0] = s1;
	verts[3].st[1] = t2;
	verts[3].normal[0] = 0;
	verts[3].normal[1] = 0;
	verts[3].normal[2] = 1;
	verts[3].tangents[0][0] = 1;
	verts[3].tangents[0][1] = 0;
	verts[3].tangents[0][2] = 0;
	verts[3].tangents[1][0] = 0;
	verts[3].tangents[1][1] = 1;
	verts[3].tangents[1][2] = 0;

	DrawStretchPic( &verts[0], &indexes[0], 4, 6, hShader, false, 0.0f, 0.0f, 640.0f, 480.0f );
}
Exemple #13
0
/*
=============
DrawStretchPic
=============
*/
void idGuiModel::DrawStretchPic( const idDrawVert *dverts, const glIndex_t *dindexes, int vertCount, int indexCount, const idMaterial *hShader,
									   bool clip, float min_x, float min_y, float max_x, float max_y ) {
	if ( !R_IsInitialized() ) {
		return;
	}
	if ( !( dverts && dindexes && vertCount && indexCount && hShader ) ) {
		return;
	}

	// break the current surface if we are changing to a new material
	if ( hShader != surf->material ) {
		if ( surf->numVerts ) {
			AdvanceSurf();
		}
		const_cast<idMaterial *>(hShader)->EnsureNotPurged();	// in case it was a gui item started before a level change
		surf->material = hShader;
	}

	// add the verts and indexes to the current surface

	if ( clip ) {
		int i, j;

		// FIXME:	this is grim stuff, and should be rewritten if we have any significant
		//			number of guis asking for clipping
		idFixedWinding w;
		for ( i = 0; i < indexCount; i += 3 ) {
			w.Clear();
			w.AddPoint(idVec5(dverts[dindexes[i]].xyz.x, dverts[dindexes[i]].xyz.y, dverts[dindexes[i]].xyz.z, dverts[dindexes[i]].st.x, dverts[dindexes[i]].st.y));
			w.AddPoint(idVec5(dverts[dindexes[i+1]].xyz.x, dverts[dindexes[i+1]].xyz.y, dverts[dindexes[i+1]].xyz.z, dverts[dindexes[i+1]].st.x, dverts[dindexes[i+1]].st.y));
			w.AddPoint(idVec5(dverts[dindexes[i+2]].xyz.x, dverts[dindexes[i+2]].xyz.y, dverts[dindexes[i+2]].xyz.z, dverts[dindexes[i+2]].st.x, dverts[dindexes[i+2]].st.y));

			for ( j = 0; j < 3; j++ ) {
				if ( w[j].x < min_x || w[j].x > max_x ||
					w[j].y < min_y || w[j].y > max_y ) {
					break;
				}
			}
			if ( j < 3 ) {
				idPlane p;
				p.Normal().y = p.Normal().z = 0.0f; p.Normal().x = 1.0f; p.SetDist( min_x );
				w.ClipInPlace( p );
				p.Normal().y = p.Normal().z = 0.0f; p.Normal().x = -1.0f; p.SetDist( -max_x );
				w.ClipInPlace( p );
				p.Normal().x = p.Normal().z = 0.0f; p.Normal().y = 1.0f; p.SetDist( min_y );
				w.ClipInPlace( p );
				p.Normal().x = p.Normal().z = 0.0f; p.Normal().y = -1.0f; p.SetDist( -max_y );
				w.ClipInPlace( p );
			}

			int	numVerts = verts.Num();
			verts.SetNum( numVerts + w.GetNumPoints(), false );
			for ( j = 0 ; j < w.GetNumPoints() ; j++ ) {
				idDrawVert *dv = &verts[numVerts+j];

				dv->xyz.x = w[j].x;
				dv->xyz.y = w[j].y;
				dv->xyz.z = w[j].z;
				dv->st.x = w[j].s;
				dv->st.y = w[j].t;
				dv->normal.Set(0, 0, 1);
				dv->tangents[0].Set(1, 0, 0);
				dv->tangents[1].Set(0, 1, 0);
			}
			surf->numVerts += w.GetNumPoints();

			for ( j = 2; j < w.GetNumPoints(); j++ ) {
				indexes.Append( numVerts - surf->firstVert );
				indexes.Append( numVerts + j - 1 - surf->firstVert );
				indexes.Append( numVerts + j - surf->firstVert );
				surf->numIndexes += 3;
			}
		}

	} else {

		int numVerts = verts.Num();
		int numIndexes = indexes.Num();

		verts.AssureSize( numVerts + vertCount );
		indexes.AssureSize( numIndexes + indexCount );

		surf->numVerts += vertCount;
		surf->numIndexes += indexCount;

		for ( int i = 0; i < indexCount; i++ ) {
			indexes[numIndexes + i] = numVerts + dindexes[i] - surf->firstVert;
		}

		memcpy( &verts[numVerts], dverts, vertCount * sizeof( verts[0] ) );
	}
}
Exemple #14
0
/*
=================
R_LoadARBProgram
=================
*/
void R_LoadARBProgram( int progIndex ) {
	int		ofs;
	int		err;
	idStr	fullPath = "glprogs/";
	fullPath += progs[progIndex].name;
	char	*fileBuffer;
	char	*buffer;
	char	*start = NULL, *end;

	common->Printf( "%s", fullPath.c_str() );

	// load the program even if we don't support it, so
	// fs_copyfiles can generate cross-platform data dumps
	fileSystem->ReadFile( fullPath.c_str(), (void **)&fileBuffer, NULL );
	if ( !fileBuffer ) {
		common->Printf( ": File not found\n" );
		return;
	}

	// copy to stack memory and free
	buffer = (char *)_alloca( strlen( fileBuffer ) + 1 );
	strcpy( buffer, fileBuffer );
	fileSystem->FreeFile( fileBuffer );

	if ( !R_IsInitialized() ) {
		return;
	}

	//
	// submit the program string at start to GL
	//
	if ( progs[progIndex].ident == 0 ) {
		// allocate a new identifier for this program
		progs[progIndex].ident = PROG_USER + progIndex;
	}

	// vertex and fragment programs can both be present in a single file, so
	// scan for the proper header to be the start point, and stamp a 0 in after the end

	if ( progs[progIndex].target == GL_VERTEX_PROGRAM_ARB ) {
		if ( !glConfig.ARBVertexProgramAvailable ) {
			common->Printf( ": GL_VERTEX_PROGRAM_ARB not available\n" );
			return;
		}
		start = strstr( (char *)buffer, "!!ARBvp" );
	}
	if ( progs[progIndex].target == GL_FRAGMENT_PROGRAM_ARB ) {
		if ( !glConfig.ARBFragmentProgramAvailable ) {
			common->Printf( ": GL_FRAGMENT_PROGRAM_ARB not available\n" );
			return;
		}
		start = strstr( (char *)buffer, "!!ARBfp" );
	}
	if ( !start ) {
		common->Printf( ": !!ARB not found\n" );
		return;
	}
	end = strstr( start, "END" );

	if ( !end ) {
		common->Printf( ": END not found\n" );
		return;
	}
	end[3] = 0;

	qglBindProgramARB( progs[progIndex].target, progs[progIndex].ident );
	qglGetError();

	qglProgramStringARB( progs[progIndex].target, GL_PROGRAM_FORMAT_ASCII_ARB,
		strlen( start ), (unsigned char *)start );

	err = qglGetError();
	qglGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, (GLint *)&ofs );
	if ( err == GL_INVALID_OPERATION ) {
		const GLubyte *str = qglGetString( GL_PROGRAM_ERROR_STRING_ARB );
		common->Printf( "\nGL_PROGRAM_ERROR_STRING_ARB: %s\n", str );
		if ( ofs < 0 ) {
			common->Printf( "GL_PROGRAM_ERROR_POSITION_ARB < 0 with error\n" );
		} else if ( ofs >= (int)strlen( (char *)start ) ) {
			common->Printf( "error at end of program\n" );
		} else {
			common->Printf( "error at %i:\n%s", ofs, start + ofs );
		}
		return;
	}
	if ( ofs != -1 ) {
		common->Printf( "\nGL_PROGRAM_ERROR_POSITION_ARB != -1 without error\n" );
		return;
	}

	common->Printf( "\n" );
}