예제 #1
0
	/*
	=============
	RB_DrawView
	=============
	*/
	const void     *RB_DrawView( const void *data )
	{
		const drawViewCommand_t *cmd;

		GLimp_LogComment( "--- RB_DrawView ---\n" );

		// finish any 2D drawing if needed
		if ( tess.numIndexes )
		{
			Tess_End();
		}

		cmd = ( const drawViewCommand_t * ) data;

		backEnd.refdef = cmd->refdef;
		backEnd.viewParms = cmd->viewParms;

#if defined( USE_D3D10 )
		D3D10_RenderView();
#else
		GL_RenderView();
#endif

		return ( const void * )( cmd + 1 );
	}
예제 #2
0
/*
==============
Tess_SurfaceVBOMD5Mesh
==============
*/
static void Tess_SurfaceVBOMD5Mesh( srfVBOMD5Mesh_t *srf )
{
	int        i;
	md5Model_t *model;

	GLimp_LogComment( "--- Tess_SurfaceVBOMD5Mesh ---\n" );

	if ( !srf->vbo || !srf->ibo )
	{
		return;
	}

	Tess_EndBegin();

	R_BindVBO( srf->vbo );
	R_BindIBO( srf->ibo );

	tess.numIndexes = srf->numIndexes;
	tess.numVertexes = srf->numVerts;

	model = srf->md5Model;

	tess.vboVertexSkinning = true;
	tess.numBones = srf->numBoneRemap;

	for ( i = 0; i < srf->numBoneRemap; i++ )
	{
		refBone_t *bone = &backEnd.currentEntity->e.skeleton.bones[ srf->boneRemapInverse[ i ] ];

		if ( backEnd.currentEntity->e.skeleton.type == SK_ABSOLUTE )
		{
			TransInitRotationQuat( model->bones[ srf->boneRemapInverse[ i ] ].rotation, &tess.bones[ i ] );
			TransAddTranslation( model->bones[ srf->boneRemapInverse[ i ] ].origin, &tess.bones[ i ] );
			TransInverse( &tess.bones[ i ], &tess.bones[ i ] );
			TransCombine( &tess.bones[ i ], &bone->t, &tess.bones[ i ] );
		} else {
			TransInit( &tess.bones[ i ] );
		}
		TransAddScale( backEnd.currentEntity->e.skeleton.scale, &tess.bones[ i ] );
		TransInsScale( model->internalScale, &tess.bones[ i ] );
	}

	Tess_End();
}
예제 #3
0
/*
==============
Tess_CheckOverflow
==============
*/
void Tess_CheckOverflow( int verts, int indexes )
{
	// FIXME: need to check if a vbo is bound, otherwise we fail on startup
	if ( glState.currentVBO != nullptr && glState.currentIBO != nullptr )
	{
		Tess_CheckVBOAndIBO( tess.vbo, tess.ibo );
	}

	if ( tess.buildingVBO )
	{
		return;
	}

	if ( tess.numVertexes + verts < SHADER_MAX_VERTEXES && tess.numIndexes + indexes < SHADER_MAX_INDEXES )
	{
		return;
	}

	if ( r_logFile->integer )
	{
		// don't just call LogComment, or we will get
		// a call to va() every frame!
		GLimp_LogComment( va
		                  ( "--- Tess_CheckOverflow(%i + %i vertices, %i + %i triangles ) ---\n", tess.numVertexes, verts,
		                    ( tess.numIndexes / 3 ), indexes ) );
	}

	Tess_End();

	if ( verts >= SHADER_MAX_VERTEXES )
	{
		ri.Error( ERR_DROP, "Tess_CheckOverflow: verts > std::max (%d > %d)", verts, SHADER_MAX_VERTEXES );
	}

	if ( indexes >= SHADER_MAX_INDEXES )
	{
		ri.Error( ERR_DROP, "Tess_CheckOverflow: indexes > std::max (%d > %d)", indexes, SHADER_MAX_INDEXES );
	}

	Tess_Begin( tess.stageIteratorFunc, tess.stageIteratorFunc2, tess.surfaceShader, tess.lightShader, tess.skipTangentSpaces, tess.skipVBO,
	            tess.lightmapNum, tess.fogNum );
}
예제 #4
0
/*
==============
Tess_SurfaceVBOMDVMesh
==============
*/
void Tess_SurfaceVBOMDVMesh( srfVBOMDVMesh_t *surface )
{
	refEntity_t *refEnt;

	GLimp_LogComment( "--- Tess_SurfaceVBOMDVMesh ---\n" );

	if ( !surface->vbo || !surface->ibo )
	{
		return;
	}

	Tess_EndBegin();

	R_BindVBO( surface->vbo );
	R_BindIBO( surface->ibo );

	tess.numIndexes = surface->numIndexes;
	tess.numVertexes = surface->numVerts;
	tess.vboVertexAnimation = true;

	refEnt = &backEnd.currentEntity->e;

	if ( refEnt->oldframe == refEnt->frame )
	{
		glState.vertexAttribsInterpolation = 0;
	}
	else
	{
		glState.vertexAttribsInterpolation = ( 1.0 - refEnt->backlerp );
	}

	glState.vertexAttribsOldFrame = refEnt->oldframe;
	glState.vertexAttribsNewFrame = refEnt->frame;

	Tess_End();
}
예제 #5
0
/*
** RB_DrawSun
*/
void RB_DrawSun( void )
{
#if 0
	float    size;
	float    dist;
	vec3_t   origin, vec1, vec2;
	vec3_t   temp;
	matrix_t transformMatrix;
	matrix_t modelViewMatrix;

	if ( !backEnd.skyRenderedThisView )
	{
		return;
	}

	if ( !r_drawSun->integer )
	{
		return;
	}

	GL_PushMatrix();

	GL_BindProgram( &tr.genericShader );

	// set uniforms
	GLSL_SetUniform_TCGen_Environment( &tr.genericShader,  qfalse );
	GLSL_SetUniform_InverseVertexColor( &tr.genericShader,  qfalse );

	if ( glConfig2.vboVertexSkinningAvailable )
	{
		GLSL_SetUniform_VertexSkinning( &tr.genericShader, qfalse );
	}

	GLSL_SetUniform_DeformGen( &tr.genericShader, DGEN_NONE );
	GLSL_SetUniform_AlphaTest( &tr.genericShader, -1.0 );

	MatrixSetupTranslation( transformMatrix, backEnd.viewParms.orientation.origin[ 0 ], backEnd.viewParms.orientation.origin[ 1 ],
	                        backEnd.viewParms.orientation.origin[ 2 ] );
	MatrixMultiply( backEnd.viewParms.world.viewMatrix, transformMatrix, modelViewMatrix );

	GL_LoadProjectionMatrix( backEnd.viewParms.projectionMatrix );
	GL_LoadModelViewMatrix( modelViewMatrix );

	GLSL_SetUniform_ModelMatrix( &tr.genericShader, backEnd.orientation.transformMatrix );
	GLSL_SetUniform_ModelViewProjectionMatrix( &tr.genericShader, glState.modelViewProjectionMatrix[ glState.stackIndex ] );

	GLSL_SetUniform_PortalClipping( &tr.genericShader, backEnd.viewParms.isPortal );

	if ( backEnd.viewParms.isPortal )
	{
		float plane[ 4 ];

		// clipping plane in world space
		plane[ 0 ] = backEnd.viewParms.portalPlane.normal[ 0 ];
		plane[ 1 ] = backEnd.viewParms.portalPlane.normal[ 1 ];
		plane[ 2 ] = backEnd.viewParms.portalPlane.normal[ 2 ];
		plane[ 3 ] = backEnd.viewParms.portalPlane.dist;

		GLSL_SetUniform_PortalPlane( &tr.genericShader, plane );
	}

	dist = backEnd.viewParms.skyFar / 1.75; // div sqrt(3)
	size = dist * 0.4;

	VectorScale( tr.sunDirection, dist, origin );
	PerpendicularVector( vec1, tr.sunDirection );
	CrossProduct( tr.sunDirection, vec1, vec2 );

	VectorScale( vec1, size, vec1 );
	VectorScale( vec2, size, vec2 );

	// farthest depth range
	glDepthRange( 1.0, 1.0 );

	// FIXME: use quad stamp
	Tess_Begin( Tess_StageIteratorGeneric, tr.sunShader, NULL, tess.skipTangentSpaces, qfalse, -1, tess.fogNum );
	VectorCopy( origin, temp );
	VectorSubtract( temp, vec1, temp );
	VectorSubtract( temp, vec2, temp );
	VectorCopy( temp, tess.xyz[ tess.numVertexes ] );
	tess.xyz[ tess.numVertexes ][ 3 ] = 1;
	tess.texCoords[ tess.numVertexes ][ 0 ] = 0;
	tess.texCoords[ tess.numVertexes ][ 1 ] = 0;
	tess.texCoords[ tess.numVertexes ][ 2 ] = 0;
	tess.texCoords[ tess.numVertexes ][ 3 ] = 1;
	tess.colors[ tess.numVertexes ][ 0 ] = 1;
	tess.colors[ tess.numVertexes ][ 1 ] = 1;
	tess.colors[ tess.numVertexes ][ 2 ] = 1;
	tess.numVertexes++;

	VectorCopy( origin, temp );
	VectorAdd( temp, vec1, temp );
	VectorSubtract( temp, vec2, temp );
	VectorCopy( temp, tess.xyz[ tess.numVertexes ] );
	tess.xyz[ tess.numVertexes ][ 3 ] = 1;
	tess.texCoords[ tess.numVertexes ][ 0 ] = 0;
	tess.texCoords[ tess.numVertexes ][ 1 ] = 1;
	tess.texCoords[ tess.numVertexes ][ 2 ] = 0;
	tess.texCoords[ tess.numVertexes ][ 3 ] = 1;
	tess.colors[ tess.numVertexes ][ 0 ] = 1;
	tess.colors[ tess.numVertexes ][ 1 ] = 1;
	tess.colors[ tess.numVertexes ][ 2 ] = 1;
	tess.numVertexes++;

	VectorCopy( origin, temp );
	VectorAdd( temp, vec1, temp );
	VectorAdd( temp, vec2, temp );
	VectorCopy( temp, tess.xyz[ tess.numVertexes ] );
	tess.xyz[ tess.numVertexes ][ 3 ] = 1;
	tess.texCoords[ tess.numVertexes ][ 0 ] = 1;
	tess.texCoords[ tess.numVertexes ][ 1 ] = 1;
	tess.texCoords[ tess.numVertexes ][ 2 ] = 0;
	tess.texCoords[ tess.numVertexes ][ 3 ] = 1;
	tess.colors[ tess.numVertexes ][ 0 ] = 1;
	tess.colors[ tess.numVertexes ][ 1 ] = 1;
	tess.colors[ tess.numVertexes ][ 2 ] = 1;
	tess.numVertexes++;

	VectorCopy( origin, temp );
	VectorSubtract( temp, vec1, temp );
	VectorAdd( temp, vec2, temp );
	VectorCopy( temp, tess.xyz[ tess.numVertexes ] );
	tess.xyz[ tess.numVertexes ][ 3 ] = 1;
	tess.texCoords[ tess.numVertexes ][ 0 ] = 1;
	tess.texCoords[ tess.numVertexes ][ 1 ] = 0;
	tess.texCoords[ tess.numVertexes ][ 2 ] = 0;
	tess.texCoords[ tess.numVertexes ][ 3 ] = 1;
	tess.colors[ tess.numVertexes ][ 0 ] = 1;
	tess.colors[ tess.numVertexes ][ 1 ] = 1;
	tess.colors[ tess.numVertexes ][ 2 ] = 1;
	tess.numVertexes++;

	tess.indexes[ tess.numIndexes++ ] = 0;
	tess.indexes[ tess.numIndexes++ ] = 1;
	tess.indexes[ tess.numIndexes++ ] = 2;
	tess.indexes[ tess.numIndexes++ ] = 0;
	tess.indexes[ tess.numIndexes++ ] = 2;
	tess.indexes[ tess.numIndexes++ ] = 3;

	Tess_End();

	// back to standard depth range
	glDepthRange( 0.0, 1.0 );

	GL_PopMatrix();
#endif
}
예제 #6
0
	/*
	=============
	RB_StretchPic
	=============
	*/
	const void     *RB_StretchPic( const void *data )
	{
		int                       i;
		const stretchPicCommand_t *cmd;
		shader_t                  *shader;
		int                       numVerts, numIndexes;

		GLimp_LogComment( "--- RB_StretchPic ---\n" );

		cmd = ( const stretchPicCommand_t * ) data;

		if ( !backEnd.projection2D )
		{
			RB_SetGL2D();
		}

		shader = cmd->shader;

		if ( shader != tess.surfaceShader )
		{
			if ( tess.numIndexes )
			{
				Tess_End();
			}

			backEnd.currentEntity = &backEnd.entity2D;
			Tess_Begin( Tess_StageIteratorGeneric, NULL, shader, NULL, qfalse, qfalse, -1, tess.fogNum );
		}

		Tess_CheckOverflow( 4, 6 );
		numVerts = tess.numVertexes;
		numIndexes = tess.numIndexes;

		tess.numVertexes += 4;
		tess.numIndexes += 6;

		tess.indexes[ numIndexes ] = numVerts + 3;
		tess.indexes[ numIndexes + 1 ] = numVerts + 0;
		tess.indexes[ numIndexes + 2 ] = numVerts + 2;
		tess.indexes[ numIndexes + 3 ] = numVerts + 2;
		tess.indexes[ numIndexes + 4 ] = numVerts + 0;
		tess.indexes[ numIndexes + 5 ] = numVerts + 1;

		for ( i = 0; i < 4; i++ )
		{
			tess.colors[ numVerts + i ][ 0 ] = backEnd.color2D[ 0 ];
			tess.colors[ numVerts + i ][ 1 ] = backEnd.color2D[ 1 ];
			tess.colors[ numVerts + i ][ 2 ] = backEnd.color2D[ 2 ];
			tess.colors[ numVerts + i ][ 3 ] = backEnd.color2D[ 3 ];
		}

		tess.xyz[ numVerts ][ 0 ] = cmd->x;
		tess.xyz[ numVerts ][ 1 ] = cmd->y;
		tess.xyz[ numVerts ][ 2 ] = 0;
		tess.xyz[ numVerts ][ 3 ] = 1;

		tess.texCoords[ numVerts ][ 0 ] = cmd->s1;
		tess.texCoords[ numVerts ][ 1 ] = cmd->t1;
		tess.texCoords[ numVerts ][ 2 ] = 0;
		tess.texCoords[ numVerts ][ 3 ] = 1;

		tess.xyz[ numVerts + 1 ][ 0 ] = cmd->x + cmd->w;
		tess.xyz[ numVerts + 1 ][ 1 ] = cmd->y;
		tess.xyz[ numVerts + 1 ][ 2 ] = 0;
		tess.xyz[ numVerts + 1 ][ 3 ] = 1;

		tess.texCoords[ numVerts + 1 ][ 0 ] = cmd->s2;
		tess.texCoords[ numVerts + 1 ][ 1 ] = cmd->t1;
		tess.texCoords[ numVerts + 1 ][ 2 ] = 0;
		tess.texCoords[ numVerts + 1 ][ 3 ] = 1;

		tess.xyz[ numVerts + 2 ][ 0 ] = cmd->x + cmd->w;
		tess.xyz[ numVerts + 2 ][ 1 ] = cmd->y + cmd->h;
		tess.xyz[ numVerts + 2 ][ 2 ] = 0;
		tess.xyz[ numVerts + 2 ][ 3 ] = 1;

		tess.texCoords[ numVerts + 2 ][ 0 ] = cmd->s2;
		tess.texCoords[ numVerts + 2 ][ 1 ] = cmd->t2;
		tess.texCoords[ numVerts + 2 ][ 2 ] = 0;
		tess.texCoords[ numVerts + 2 ][ 3 ] = 1;

		tess.xyz[ numVerts + 3 ][ 0 ] = cmd->x;
		tess.xyz[ numVerts + 3 ][ 1 ] = cmd->y + cmd->h;
		tess.xyz[ numVerts + 3 ][ 2 ] = 0;
		tess.xyz[ numVerts + 3 ][ 3 ] = 1;

		tess.texCoords[ numVerts + 3 ][ 0 ] = cmd->s1;
		tess.texCoords[ numVerts + 3 ][ 1 ] = cmd->t2;
		tess.texCoords[ numVerts + 3 ][ 2 ] = 0;
		tess.texCoords[ numVerts + 3 ][ 3 ] = 1;

		return ( const void * )( cmd + 1 );
	}
예제 #7
0
	static void RB_RenderDrawSurfaces( qboolean opaque, qboolean depthFill )
	{
		trRefEntity_t *entity, *oldEntity;
		shader_t      *shader, *oldShader;
		int           lightmapNum, oldLightmapNum;
		qboolean      depthRange, oldDepthRange;
		int           i;
		drawSurf_t    *drawSurf;

		GLimp_LogComment( "--- RB_RenderDrawSurfaces ---\n" );

		// draw everything
		oldEntity = NULL;
		oldShader = NULL;
		oldLightmapNum = -1;
		oldDepthRange = qfalse;
		depthRange = qfalse;
		backEnd.currentLight = NULL;

		for ( i = 0, drawSurf = backEnd.viewParms.drawSurfs; i < backEnd.viewParms.numDrawSurfs; i++, drawSurf++ )
		{
			// update locals
			entity = drawSurf->entity;
			shader = tr.sortedShaders[ drawSurf->shaderNum ];
			lightmapNum = drawSurf->lightmapNum;

			if ( opaque )
			{
				// skip all translucent surfaces that don't matter for this pass
				if ( shader->sort > SS_OPAQUE )
				{
					break;
				}
			}
			else
			{
				// skip all opaque surfaces that don't matter for this pass
				if ( shader->sort <= SS_OPAQUE )
				{
					continue;
				}
			}

			if ( entity == oldEntity && shader == oldShader && lightmapNum == oldLightmapNum )
			{
				// fast path, same as previous sort
				rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
				continue;
			}

			// change the tess parameters if needed
			// an "entityMergable" shader is a shader that can have surfaces from separate
			// entities merged into a single batch, like smoke and blood puff sprites
			if ( shader != oldShader || lightmapNum != oldLightmapNum || ( entity != oldEntity && !shader->entityMergable ) )
			{
				if ( oldShader != NULL )
				{
					Tess_End();
				}

				if ( depthFill )
				{
					Tess_Begin( Tess_StageIteratorDepthFill, NULL, shader, NULL, qtrue, qfalse, lightmapNum, tess.fogNum );
				}
				else
				{
					Tess_Begin( Tess_StageIteratorGeneric, NULL, shader, NULL, qfalse, qfalse, lightmapNum, tess.fogNum );
				}

				oldShader = shader;
				oldLightmapNum = lightmapNum;
			}

			// change the modelview matrix if needed
			if ( entity != oldEntity )
			{
				depthRange = qfalse;

				if ( entity != &tr.worldEntity )
				{
					backEnd.currentEntity = entity;

					// set up the transformation matrix
					R_RotateEntityForViewParms( backEnd.currentEntity, &backEnd.viewParms, &backEnd.orientation );

					if ( backEnd.currentEntity->e.renderfx & RF_DEPTHHACK )
					{
						// hack the depth range to prevent view model from poking into walls
						depthRange = qtrue;
					}
				}
				else
				{
					backEnd.currentEntity = &tr.worldEntity;
					backEnd.orientation = backEnd.viewParms.world;
				}

#if defined( USE_D3D10 )
				// TODO
#else
				GL_LoadModelViewMatrix( backEnd.orientation.modelViewMatrix );
#endif

				// change depthrange if needed
				if ( oldDepthRange != depthRange )
				{
#if defined( USE_D3D10 )
					// TODO
#else

					if ( depthRange )
					{
						qglDepthRange( 0, 0.3 );
					}
					else
					{
						qglDepthRange( 0, 1 );
					}

#endif
					oldDepthRange = depthRange;
				}

				oldEntity = entity;
			}

			// add the triangles for this surface
			rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
		}

		// draw the contents of the last shader batch
		if ( oldShader != NULL )
		{
			Tess_End();
		}

		// go back to the world modelview matrix
#if defined( USE_D3D10 )
		// TODO
#else
		GL_LoadModelViewMatrix( backEnd.viewParms.world.modelViewMatrix );
#endif

		if ( depthRange )
		{
#if defined( USE_D3D10 )
			// TODO
#else
			qglDepthRange( 0, 1 );
#endif
		}

#if defined( USE_D3D10 )
		// TODO
#else
		GL_CheckErrors();
#endif
	}
예제 #8
0
	/*
	=============
	RB_SwapBuffers
	=============
	*/
	const void     *RB_SwapBuffers( const void *data )
	{
		const swapBuffersCommand_t *cmd;

		// finish any 2D drawing if needed
		if ( tess.numIndexes )
		{
			Tess_End();
		}

		// texture swapping test
#if !defined( USE_D3D10 )

		if ( r_showImages->integer )
		{
			RB_ShowImages();
		}

#endif

		cmd = ( const swapBuffersCommand_t * ) data;

#if defined( USE_D3D10 )
		// TODO
#else

		// we measure overdraw by reading back the stencil buffer and
		// counting up the number of increments that have happened
		if ( r_measureOverdraw->integer )
		{
			int           i;
			long          sum = 0;
			unsigned char *stencilReadback;

			stencilReadback = ri.Hunk_AllocateTempMemory( glConfig.vidWidth * glConfig.vidHeight );
			qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencilReadback );

			for ( i = 0; i < glConfig.vidWidth * glConfig.vidHeight; i++ )
			{
				sum += stencilReadback[ i ];
			}

			backEnd.pc.c_overDraw += sum;
			ri.Hunk_FreeTempMemory( stencilReadback );
		}

#endif

#if defined( USE_D3D10 )
		// TODO
#else

		if ( !glState.finishCalled )
		{
			qglFinish();
		}

#endif

		GLimp_LogComment( "***************** RB_SwapBuffers *****************\n\n\n" );

		// present the information rendered to the back buffer to the front buffer (the screen)
		dx.swapChain->Present( 0, 0 );

		if ( r_fullscreen->modified )
		{
			bool        fullscreen;
			bool        needToToggle = qtrue;
			bool        sdlToggled = qfalse;
			SDL_Surface *s = SDL_GetVideoSurface();

			if ( s )
			{
				// Find out the current state
				fullscreen = !!( s->flags & SDL_FULLSCREEN );

				if ( r_fullscreen->integer > 0 && ri.Cvar_VariableIntegerValue( "in_nograb" ) > 0 )
				{
					ri.Printf( PRINT_ALL, "Fullscreen not allowed with in_nograb 1\n" );
					ri.Cvar_Set( "r_fullscreen", "0" );
					r_fullscreen->modified = qfalse;
				}

				// Is the state we want different from the current state?
				needToToggle = !!r_fullscreen->integer != fullscreen;

				if ( needToToggle )
				{
					sdlToggled = SDL_WM_ToggleFullScreen( s );
				}
			}

			if ( needToToggle )
			{
				// SDL_WM_ToggleFullScreen didn't work, so do it the slow way
				if ( !sdlToggled )
				{
					ri.Cmd_ExecuteText( EXEC_APPEND, "vid_restart" );
				}

				ri.IN_Restart();
			}

			r_fullscreen->modified = qfalse;
		}

		backEnd.projection2D = qfalse;

		return ( const void * )( cmd + 1 );
	}
예제 #9
0
/*
==============
Tess_EndBegin
==============
*/
void Tess_EndBegin()
{
	Tess_End();
	Tess_Begin( tess.stageIteratorFunc, tess.stageIteratorFunc2, tess.surfaceShader, tess.lightShader, tess.skipTangentSpaces, tess.skipVBO,
	            tess.lightmapNum, tess.fogNum );
}
예제 #10
0
/*
=================
Tess_SurfaceIQM

Compute vertices for this model surface
=================
*/
void Tess_SurfaceIQM( srfIQModel_t *surf ) {
	IQModel_t       *model = surf->data;
	int             i, j;
	int             offset = tess.numVertexes - surf->first_vertex;

	GLimp_LogComment( "--- RB_SurfaceIQM ---\n" );

	Tess_CheckOverflow( surf->num_vertexes, surf->num_triangles * 3 );

	// compute bones
	for ( i = 0; i < model->num_joints; i++ )
	{

		if ( backEnd.currentEntity->e.skeleton.type == SK_ABSOLUTE )
		{
			refBone_t *bone = &backEnd.currentEntity->e.skeleton.bones[ i ];

			TransInverse( &model->joints[ i ], &bones[ i ] );
			TransCombine( &bones[ i ], &bone->t, &bones[ i ] );
		}
		else
		{
			TransInit( &bones[ i ] );
		}
		TransAddScale( backEnd.currentEntity->e.skeleton.scale, &bones[ i ] );
		TransInsScale( model->internalScale, &bones[ i ] );
	}

	if( surf->vbo && surf->ibo ) {
		if( model->num_joints > 0 ) {
			Com_Memcpy( tess.bones, bones, model->num_joints * sizeof(transform_t) );
			tess.numBones = model->num_joints;
		} else {
			TransInitScale( model->internalScale * backEnd.currentEntity->e.skeleton.scale, &tess.bones[ 0 ] );
			tess.numBones = 1;
		}
		R_BindVBO( surf->vbo );
		R_BindIBO( surf->ibo );
		tess.vboVertexSkinning = true;

		tess.multiDrawIndexes[ tess.multiDrawPrimitives ] = ((glIndex_t *)nullptr) + surf->first_triangle * 3;
		tess.multiDrawCounts[ tess.multiDrawPrimitives ] = surf->num_triangles * 3;
		tess.multiDrawPrimitives++;

		Tess_End();
		return;
	}

	for ( i = 0; i < surf->num_triangles; i++ )
	{
		tess.indexes[ tess.numIndexes + i * 3 + 0 ] = offset + model->triangles[ 3 * ( surf->first_triangle + i ) + 0 ];
		tess.indexes[ tess.numIndexes + i * 3 + 1 ] = offset + model->triangles[ 3 * ( surf->first_triangle + i ) + 1 ];
		tess.indexes[ tess.numIndexes + i * 3 + 2 ] = offset + model->triangles[ 3 * ( surf->first_triangle + i ) + 2 ];
	}

	tess.attribsSet |= ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT;

	if( model->num_joints > 0 && model->blendWeights && model->blendIndexes ) {
		// deform the vertices by the lerped bones
		for ( i = 0; i < surf->num_vertexes; i++ )
		{
			int    idxIn = surf->first_vertex + i;
			int    idxOut = tess.numVertexes + i;
			const float weightFactor = 1.0f / 255.0f;
			vec3_t tangent, binormal, normal, tmp;

			if( model->blendWeights[ 4 * idxIn + 0 ] == 0 &&
			    model->blendWeights[ 4 * idxIn + 1 ] == 0 &&
			    model->blendWeights[ 4 * idxIn + 2 ] == 0 &&
			    model->blendWeights[ 4 * idxIn + 3 ] == 0 )
				model->blendWeights[ 4 * idxIn + 0 ] = 255;

			VectorClear( tess.verts[ idxOut ].xyz );
			VectorClear( normal );
			VectorClear( tangent );
			VectorClear( binormal );
			for ( j = 0; j < 4; j++ ) {
				int bone = model->blendIndexes[ 4 * idxIn + j ];
				float weight = weightFactor * model->blendWeights[ 4 * idxIn + j ];

				TransformPoint( &bones[ bone ],
						&model->positions[ 3 * idxIn ], tmp );
				VectorMA( tess.verts[ idxOut ].xyz, weight, tmp,
					  tess.verts[ idxOut ].xyz );

				TransformNormalVector( &bones[ bone ],
						       &model->normals[ 3 * idxIn ], tmp );
				VectorMA( normal, weight, tmp, normal );
				TransformNormalVector( &bones[ bone ],
						       &model->tangents[ 3 * idxIn ], tmp );
				VectorMA( tangent, weight, tmp, tangent );
				TransformNormalVector( &bones[ bone ],
						       &model->bitangents[ 3 * idxIn ], tmp );
				VectorMA( binormal, weight, tmp, binormal );
			}
			VectorNormalize( normal );
			VectorNormalize( tangent );
			VectorNormalize( binormal );

			R_TBNtoQtangents( tangent, binormal, normal, tess.verts[ idxOut ].qtangents );

			tess.verts[ idxOut ].texCoords[ 0 ] = model->texcoords[ 2 * idxIn + 0 ];
			tess.verts[ idxOut ].texCoords[ 1 ] = model->texcoords[ 2 * idxIn + 1 ];
		}
	} else {
		for ( i = 0; i < surf->num_vertexes; i++ )
		{
			int    idxIn = surf->first_vertex + i;
			int    idxOut = tess.numVertexes + i;
			float  scale = model->internalScale * backEnd.currentEntity->e.skeleton.scale;

			VectorScale( &model->positions[ 3 * idxIn ], scale, tess.verts[ idxOut ].xyz );
			R_TBNtoQtangents( &model->tangents[ 3 * idxIn ],
					  &model->bitangents[ 3 * idxIn ],
					  &model->normals[ 3 * idxIn ],
					  tess.verts[ idxOut ].qtangents );

			tess.verts[ idxOut ].texCoords[ 0 ] = model->texcoords[ 2 * idxIn + 0 ];
			tess.verts[ idxOut ].texCoords[ 1 ] = model->texcoords[ 2 * idxIn + 1 ];
		}
	}

	tess.numIndexes  += 3 * surf->num_triangles;
	tess.numVertexes += surf->num_vertexes;
}
예제 #11
0
/*
==================
RB_RenderFlare
==================
*/
void RB_RenderFlare(flare_t * f)
{
	float           size;
	vec3_t          color;

	backEnd.pc.c_flareRenders++;

#if 1
	//VectorScale(f->color, f->drawIntensity, color);
	VectorScale(colorWhite, f->drawIntensity, color);

	size = backEnd.viewParms.viewportWidth * (r_flareSize->value / 640.0f + 8 / -f->eyeZ);
#else
	/*
	   As flare sizes stay nearly constant with increasing distance we must decrease the intensity
	   to achieve a reasonable visual result. The intensity is ~ (size^2 / distance^2) which can be
	   got by considering the ratio of  (flaresurface on screen) : (Surface of sphere defined by flare origin and distance from flare)
	   An important requirement is: intensity <= 1 for all distances.

	   The formula used here to compute the intensity is as follows:
	   intensity = flareCoeff * size^2 / (distance + size*sqrt(flareCoeff))^2.
	   As you can see, the intensity will have a max. of 1 when the distance is 0.

	   The coefficient flareCoeff will determine the falloff speed with increasing distance.
	 */
	float           distance, intensity, factor;

	// We don't want too big values anyways when dividing by distance
	if(f->eyeZ > -1.0f)
		distance = 1.0f;
	else
		distance = -f->eyeZ;

	// calculate the flare size
	size = backEnd.viewParms.viewportWidth * (r_flareSize->value / 640.0f + 8 / distance);

	factor = distance + size * sqrt(flareCoeff);
	intensity = flareCoeff * size * size / (factor * factor);

	VectorScale(f->color, f->drawIntensity * intensity, color);
	iColor[0] = color[0] * 255;
	iColor[1] = color[1] * 255;
	iColor[2] = color[2] * 255;
#endif

	Tess_Begin(Tess_StageIteratorGeneric, tr.flareShader, NULL, qfalse, qfalse, -1);

	// FIXME: use quadstamp?
	tess.xyz[tess.numVertexes][0] = f->windowX - size;
	tess.xyz[tess.numVertexes][1] = f->windowY - size;
	tess.xyz[tess.numVertexes][2] = 0;
	tess.xyz[tess.numVertexes][3] = 1;
	tess.texCoords[tess.numVertexes][0] = 0;
	tess.texCoords[tess.numVertexes][1] = 0;
	tess.texCoords[tess.numVertexes][2] = 0;
	tess.texCoords[tess.numVertexes][3] = 1;
	tess.colors[tess.numVertexes][0] = color[0];
	tess.colors[tess.numVertexes][1] = color[1];
	tess.colors[tess.numVertexes][2] = color[2];
	tess.colors[tess.numVertexes][3] = 1;
	tess.numVertexes++;

	tess.xyz[tess.numVertexes][0] = f->windowX - size;
	tess.xyz[tess.numVertexes][1] = f->windowY + size;
	tess.xyz[tess.numVertexes][2] = 0;
	tess.xyz[tess.numVertexes][3] = 1;
	tess.texCoords[tess.numVertexes][0] = 0;
	tess.texCoords[tess.numVertexes][1] = 1;
	tess.texCoords[tess.numVertexes][2] = 0;
	tess.texCoords[tess.numVertexes][3] = 1;
	tess.colors[tess.numVertexes][0] = color[0];
	tess.colors[tess.numVertexes][1] = color[1];
	tess.colors[tess.numVertexes][2] = color[2];
	tess.colors[tess.numVertexes][3] = 1;
	tess.numVertexes++;

	tess.xyz[tess.numVertexes][0] = f->windowX + size;
	tess.xyz[tess.numVertexes][1] = f->windowY + size;
	tess.xyz[tess.numVertexes][2] = 0;
	tess.xyz[tess.numVertexes][3] = 1;
	tess.texCoords[tess.numVertexes][0] = 1;
	tess.texCoords[tess.numVertexes][1] = 1;
	tess.texCoords[tess.numVertexes][2] = 0;
	tess.texCoords[tess.numVertexes][3] = 1;
	tess.colors[tess.numVertexes][0] = color[0];
	tess.colors[tess.numVertexes][1] = color[1];
	tess.colors[tess.numVertexes][2] = color[2];
	tess.colors[tess.numVertexes][3] = 1;
	tess.numVertexes++;

	tess.xyz[tess.numVertexes][0] = f->windowX + size;
	tess.xyz[tess.numVertexes][1] = f->windowY - size;
	tess.xyz[tess.numVertexes][2] = 0;
	tess.xyz[tess.numVertexes][3] = 1;
	tess.texCoords[tess.numVertexes][0] = 1;
	tess.texCoords[tess.numVertexes][1] = 0;
	tess.texCoords[tess.numVertexes][2] = 0;
	tess.texCoords[tess.numVertexes][3] = 1;
	tess.colors[tess.numVertexes][0] = color[0];
	tess.colors[tess.numVertexes][1] = color[1];
	tess.colors[tess.numVertexes][2] = color[2];
	tess.colors[tess.numVertexes][3] = 1;
	tess.numVertexes++;

	tess.indexes[tess.numIndexes++] = 0;
	tess.indexes[tess.numIndexes++] = 1;
	tess.indexes[tess.numIndexes++] = 2;
	tess.indexes[tess.numIndexes++] = 0;
	tess.indexes[tess.numIndexes++] = 2;
	tess.indexes[tess.numIndexes++] = 3;

	Tess_End();
}
예제 #12
0
파일: tr_sky.cpp 프로젝트: GenaSG/etlegacy
/*
** RB_DrawSun
*/
void RB_DrawSun(void)
{
	float    size;
	float    dist;
	vec3_t   origin, vec1, vec2;
	vec3_t   temp;
	matrix_t transformMatrix;
	matrix_t modelViewMatrix;

	if (!backEnd.skyRenderedThisView)
	{
		return;
	}
	if (!r_drawSun->integer)
	{
		return;
	}

#if defined(USE_D3D10)
	//TODO
#else
	GL_PushMatrix();

	gl_genericShader->DisableAlphaTesting();
	gl_genericShader->DisablePortalClipping();
	gl_genericShader->DisableVertexSkinning();
	gl_genericShader->DisableVertexAnimation();
	gl_genericShader->DisableDeformVertexes();
	gl_genericShader->DisableTCGenEnvironment();

	gl_genericShader->BindProgram();

	// set uniforms
	gl_genericShader->SetUniform_ColorModulate(CGEN_VERTEX, AGEN_VERTEX);
#endif

	MatrixSetupTranslation(transformMatrix, backEnd.viewParms.orientation.origin[0], backEnd.viewParms.orientation.origin[1], backEnd.viewParms.orientation.origin[2]);
	MatrixMultiplyMOD(backEnd.viewParms.world.viewMatrix, transformMatrix, modelViewMatrix);

#if defined(USE_D3D10)
	//TODO
#else
	GL_LoadProjectionMatrix(backEnd.viewParms.projectionMatrix);
	GL_LoadModelViewMatrix(modelViewMatrix);

	gl_genericShader->SetUniform_ModelMatrix(backEnd.orientation.transformMatrix);
	gl_genericShader->SetUniform_ModelViewProjectionMatrix(glState.modelViewProjectionMatrix[glState.stackIndex]);

	gl_genericShader->SetPortalClipping(backEnd.viewParms.isPortal);
#endif
	if (backEnd.viewParms.isPortal)
	{
		float plane[4];

		// clipping plane in world space
		plane[0] = backEnd.viewParms.portalPlane.normal[0];
		plane[1] = backEnd.viewParms.portalPlane.normal[1];
		plane[2] = backEnd.viewParms.portalPlane.normal[2];
		plane[3] = backEnd.viewParms.portalPlane.dist;

#if defined(USE_D3D10)
		//TODO
#else
		gl_genericShader->SetUniform_PortalPlane(plane);
#endif
	}


	dist = backEnd.viewParms.skyFar / 1.75; // div sqrt(3)
	size = dist * 0.4;

	VectorScale(tr.sunDirection, dist, origin);
	PerpendicularVector(vec1, tr.sunDirection);
	CrossProduct(tr.sunDirection, vec1, vec2);

	VectorScale(vec1, size, vec1);
	VectorScale(vec2, size, vec2);

	// farthest depth range
#if defined(USE_D3D10)
	//TODO
#else
	glDepthRange(1.0, 1.0);
#endif

	// FIXME: use quad stamp
	Tess_Begin(Tess_StageIteratorGeneric, NULL, tr.sunShader, NULL, tess.skipTangentSpaces, qfalse, -1, tess.fogNum);
	VectorCopy(origin, temp);
	VectorSubtract(temp, vec1, temp);
	VectorSubtract(temp, vec2, temp);
	VectorCopy(temp, tess.xyz[tess.numVertexes]);
	tess.xyz[tess.numVertexes][3]       = 1;
	tess.texCoords[tess.numVertexes][0] = 0;
	tess.texCoords[tess.numVertexes][1] = 0;
	tess.texCoords[tess.numVertexes][2] = 0;
	tess.texCoords[tess.numVertexes][3] = 1;
	tess.colors[tess.numVertexes][0]    = 1;
	tess.colors[tess.numVertexes][1]    = 1;
	tess.colors[tess.numVertexes][2]    = 1;
	tess.numVertexes++;

	VectorCopy(origin, temp);
	VectorAdd(temp, vec1, temp);
	VectorSubtract(temp, vec2, temp);
	VectorCopy(temp, tess.xyz[tess.numVertexes]);
	tess.xyz[tess.numVertexes][3]       = 1;
	tess.texCoords[tess.numVertexes][0] = 0;
	tess.texCoords[tess.numVertexes][1] = 1;
	tess.texCoords[tess.numVertexes][2] = 0;
	tess.texCoords[tess.numVertexes][3] = 1;
	tess.colors[tess.numVertexes][0]    = 1;
	tess.colors[tess.numVertexes][1]    = 1;
	tess.colors[tess.numVertexes][2]    = 1;
	tess.numVertexes++;

	VectorCopy(origin, temp);
	VectorAdd(temp, vec1, temp);
	VectorAdd(temp, vec2, temp);
	VectorCopy(temp, tess.xyz[tess.numVertexes]);
	tess.xyz[tess.numVertexes][3]       = 1;
	tess.texCoords[tess.numVertexes][0] = 1;
	tess.texCoords[tess.numVertexes][1] = 1;
	tess.texCoords[tess.numVertexes][2] = 0;
	tess.texCoords[tess.numVertexes][3] = 1;
	tess.colors[tess.numVertexes][0]    = 1;
	tess.colors[tess.numVertexes][1]    = 1;
	tess.colors[tess.numVertexes][2]    = 1;
	tess.numVertexes++;

	VectorCopy(origin, temp);
	VectorSubtract(temp, vec1, temp);
	VectorAdd(temp, vec2, temp);
	VectorCopy(temp, tess.xyz[tess.numVertexes]);
	tess.xyz[tess.numVertexes][3]       = 1;
	tess.texCoords[tess.numVertexes][0] = 1;
	tess.texCoords[tess.numVertexes][1] = 0;
	tess.texCoords[tess.numVertexes][2] = 0;
	tess.texCoords[tess.numVertexes][3] = 1;
	tess.colors[tess.numVertexes][0]    = 1;
	tess.colors[tess.numVertexes][1]    = 1;
	tess.colors[tess.numVertexes][2]    = 1;
	tess.numVertexes++;

	tess.indexes[tess.numIndexes++] = 0;
	tess.indexes[tess.numIndexes++] = 1;
	tess.indexes[tess.numIndexes++] = 2;
	tess.indexes[tess.numIndexes++] = 0;
	tess.indexes[tess.numIndexes++] = 2;
	tess.indexes[tess.numIndexes++] = 3;

	Tess_End();

	// back to normal depth range
#if defined(USE_D3D10)
	//TODO
#else
	glDepthRange(0.0, 1.0);

	GL_PopMatrix();
#endif
}