Exemplo n.º 1
0
/*
==================
RB_RenderDrawSurfList
==================
*/
void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
	shader_t		*shader, *oldShader;
	int				fogNum, oldFogNum;
	int				entityNum, oldEntityNum;
	int				dlighted, oldDlighted;
	int				pshadowed, oldPshadowed;
	int             cubemapIndex, oldCubemapIndex;
	qboolean		depthRange, oldDepthRange, isCrosshair, wasCrosshair;
	int				i;
	drawSurf_t		*drawSurf;
	int				oldSort;
	float			originalTime;
	FBO_t*			fbo = NULL;
	qboolean		inQuery = qfalse;

	float			depth[2];


	// save original time for entity shader offsets
	originalTime = backEnd.refdef.floatTime;

	fbo = glState.currentFBO;

	// draw everything
	oldEntityNum = -1;
	backEnd.currentEntity = &tr.worldEntity;
	oldShader = NULL;
	oldFogNum = -1;
	oldDepthRange = qfalse;
	wasCrosshair = qfalse;
	oldDlighted = qfalse;
	oldPshadowed = qfalse;
	oldCubemapIndex = -1;
	oldSort = -1;

	depth[0] = 0.f;
	depth[1] = 1.f;

	backEnd.pc.c_surfaces += numDrawSurfs;

	for (i = 0, drawSurf = drawSurfs ; i < numDrawSurfs ; i++, drawSurf++) {
		if ( drawSurf->sort == oldSort && drawSurf->cubemapIndex == oldCubemapIndex) {
			if (backEnd.depthFill && shader && shader->sort != SS_OPAQUE)
				continue;

			// fast path, same as previous sort
			rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
			continue;
		}
		oldSort = drawSurf->sort;
		R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed );
		cubemapIndex = drawSurf->cubemapIndex;

		//
		// change the tess parameters if needed
		// a "entityMergable" shader is a shader that can have surfaces from seperate
		// entities merged into a single batch, like smoke and blood puff sprites
		if ( shader != NULL && ( shader != oldShader || fogNum != oldFogNum || dlighted != oldDlighted || pshadowed != oldPshadowed || cubemapIndex != oldCubemapIndex
			|| ( entityNum != oldEntityNum && !shader->entityMergable ) ) ) {
			if (oldShader != NULL) {
				RB_EndSurface();
			}
			RB_BeginSurface( shader, fogNum, cubemapIndex );
			backEnd.pc.c_surfBatches++;
			oldShader = shader;
			oldFogNum = fogNum;
			oldDlighted = dlighted;
			oldPshadowed = pshadowed;
			oldCubemapIndex = cubemapIndex;
		}

		if (backEnd.depthFill && shader && shader->sort != SS_OPAQUE)
			continue;

		//
		// change the modelview matrix if needed
		//
		if ( entityNum != oldEntityNum ) {
			qboolean sunflare = qfalse;
			depthRange = isCrosshair = qfalse;

			if ( entityNum != REFENTITYNUM_WORLD ) {
				backEnd.currentEntity = &backEnd.refdef.entities[entityNum];
				backEnd.refdef.floatTime = originalTime - backEnd.currentEntity->e.shaderTime;
				// we have to reset the shaderTime as well otherwise image animations start
				// from the wrong frame
				tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;

				// set up the transformation matrix
				R_RotateForEntity( backEnd.currentEntity, &backEnd.viewParms, &backEnd.or );

				// set up the dynamic lighting if needed
				if ( backEnd.currentEntity->needDlights ) {
					R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or );
				}

				if(backEnd.currentEntity->e.renderfx & RF_DEPTHHACK)
				{
					// hack the depth range to prevent view model from poking into walls
					depthRange = qtrue;
					
					if(backEnd.currentEntity->e.renderfx & RF_CROSSHAIR)
						isCrosshair = qtrue;
				}
			} else {
				backEnd.currentEntity = &tr.worldEntity;
				backEnd.refdef.floatTime = originalTime;
				backEnd.or = backEnd.viewParms.world;
				// we have to reset the shaderTime as well otherwise image animations on
				// the world (like water) continue with the wrong frame
				tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
				R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or );
			}

			GL_SetModelviewMatrix( backEnd.or.modelMatrix );

			//
			// change depthrange. Also change projection matrix so first person weapon does not look like coming
			// out of the screen.
			//
			if (oldDepthRange != depthRange || wasCrosshair != isCrosshair)
			{
				if (depthRange)
				{
					if(backEnd.viewParms.stereoFrame != STEREO_CENTER)
					{
						if(isCrosshair)
						{
							if(oldDepthRange)
							{
								// was not a crosshair but now is, change back proj matrix
								GL_SetProjectionMatrix( backEnd.viewParms.projectionMatrix );
							}
						}
						else
						{
							viewParms_t temp = backEnd.viewParms;

							R_SetupProjection(&temp, r_znear->value, 0, qfalse);

							GL_SetProjectionMatrix( temp.projectionMatrix );
						}
					}

 					if(!oldDepthRange)
					{
						depth[0] = 0;
						depth[1] = 0.3f;
 						qglDepthRange (depth[0], depth[1]);
	 				}
				}
				else
				{
					if(!wasCrosshair && backEnd.viewParms.stereoFrame != STEREO_CENTER)
					{
						GL_SetProjectionMatrix( backEnd.viewParms.projectionMatrix );
					}

					if (!sunflare)
						qglDepthRange (0, 1);

					depth[0] = 0;
					depth[1] = 1;
				}

				oldDepthRange = depthRange;
				wasCrosshair = isCrosshair;
			}

			oldEntityNum = entityNum;
		}

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

	backEnd.refdef.floatTime = originalTime;

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

	if (inQuery) {
		qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
	}

	if (glRefConfig.framebufferObject)
		FBO_Bind(fbo);

	// go back to the world modelview matrix

	GL_SetModelviewMatrix( backEnd.viewParms.world.modelMatrix );

	qglDepthRange (0, 1);
}
Exemplo n.º 2
0
void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
	shader_t		*shader, *oldShader;
	int				fogNum, oldFogNum;
	int				entityNum, oldEntityNum;
	int				dlighted, oldDlighted;
	int				depthRange, oldDepthRange;
	int				i;
	drawSurf_t		*drawSurf;
	unsigned int	oldSort;
	float			originalTime;
	trRefEntity_t	*curEnt;
	postRender_t	*pRender;
	bool			didShadowPass = false;
#ifdef __MACOS__
	int				macEventTime;

	Sys_PumpEvents();		// crutch up the mac's limited buffer queue size

	// we don't want to pump the event loop too often and waste time, so
	// we are going to check every shader change
	macEventTime = ri.Milliseconds() + MAC_EVENT_PUMP_MSEC;
#endif

	if (g_bRenderGlowingObjects)
	{ //only shadow on initial passes
		didShadowPass = true;
	}

	// save original time for entity shader offsets
	originalTime = backEnd.refdef.floatTime;

	// clear the z buffer, set the modelview, etc
	RB_BeginDrawingView ();

	// draw everything
	oldEntityNum = -1;
	backEnd.currentEntity = &tr.worldEntity;
	oldShader = NULL;
	oldFogNum = -1;
	oldDepthRange = qfalse;
	oldDlighted = qfalse;
	oldSort = (unsigned int) -1;
	depthRange = qfalse;

	backEnd.pc.c_surfaces += numDrawSurfs;

	for (i = 0, drawSurf = drawSurfs ; i < numDrawSurfs ; i++, drawSurf++) {
		if ( drawSurf->sort == oldSort ) {
			// fast path, same as previous sort
			rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
			continue;
		}
		R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted );

		// If we're rendering glowing objects, but this shader has no stages with glow, skip it!
		if ( g_bRenderGlowingObjects && !shader->hasGlow )
		{
			shader = oldShader;
			entityNum = oldEntityNum;
			fogNum = oldFogNum;
			dlighted = oldDlighted;
			continue;
		}

		oldSort = drawSurf->sort;

		//
		// change the tess parameters if needed
		// a "entityMergable" shader is a shader that can have surfaces from seperate
		// entities merged into a single batch, like smoke and blood puff sprites
		if (entityNum != TR_WORLDENT &&
			g_numPostRenders < MAX_POST_RENDERS)
		{
			if ( (backEnd.refdef.entities[entityNum].e.renderfx & RF_DISTORTION)/* ||
				(backEnd.refdef.entities[entityNum].e.renderfx & RF_FORCE_ENT_ALPHA)*/)
				//not sure if we need this alpha fix for sp or not, leaving it out for now -rww
			{ //must render last
				curEnt = &backEnd.refdef.entities[entityNum];
				pRender = &g_postRenders[g_numPostRenders];

				g_numPostRenders++;

				depthRange = 0;
				//figure this stuff out now and store it
				if ( curEnt->e.renderfx & RF_NODEPTH )
				{
					depthRange = 2;
				}
				else if ( curEnt->e.renderfx & RF_DEPTHHACK )
				{
					depthRange = 1;
				}
				pRender->depthRange = depthRange;

				//It is not necessary to update the old* values because
				//we are not updating now with the current values.
				depthRange = oldDepthRange;

				//store off the ent num
				pRender->entNum = entityNum;

				//remember the other values necessary for rendering this surf
				pRender->drawSurf = drawSurf;
				pRender->dlighted = dlighted;
				pRender->fogNum = fogNum;
				pRender->shader = shader;

				//assure the info is back to the last set state
				shader = oldShader;
				entityNum = oldEntityNum;
				fogNum = oldFogNum;
				dlighted = oldDlighted;

				oldSort = (unsigned int)-1; //invalidate this thing, cause we may want to postrender more surfs of the same sort

				//continue without bothering to begin a draw surf
				continue;
			}
		}

		if (shader != oldShader || fogNum != oldFogNum || dlighted != oldDlighted 
			|| ( entityNum != oldEntityNum && !shader->entityMergable ) )
		{
			if (oldShader != NULL) {
#ifdef __MACOS__	// crutch up the mac's limited buffer queue size
				int		t;

				t = ri.Milliseconds();
				if ( t > macEventTime ) {
					macEventTime = t + MAC_EVENT_PUMP_MSEC;
					Sys_PumpEvents();
				}
#endif
				RB_EndSurface();

				if (!didShadowPass && shader && shader->sort > SS_BANNER)
				{
					RB_ShadowFinish();
					didShadowPass = true;
				}
			}
			RB_BeginSurface( shader, fogNum );
			oldShader = shader;
			oldFogNum = fogNum;
			oldDlighted = dlighted;
		}

		//
		// change the modelview matrix if needed
		//
		if ( entityNum != oldEntityNum ) {
			depthRange = qfalse;

			if ( entityNum != TR_WORLDENT ) {
				backEnd.currentEntity = &backEnd.refdef.entities[entityNum];
				backEnd.refdef.floatTime = originalTime - backEnd.currentEntity->e.shaderTime;

				// set up the transformation matrix
				R_RotateForEntity( backEnd.currentEntity, &backEnd.viewParms, &backEnd.ori );

				// set up the dynamic lighting if needed
				if ( backEnd.currentEntity->needDlights ) {
#ifdef VV_LIGHTING
					VVLightMan.R_TransformDlights( &backEnd.ori );
#else
					R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.ori );
#endif
				}

				if ( backEnd.currentEntity->e.renderfx & RF_NODEPTH ) {
					// No depth at all, very rare but some things for seeing through walls
					depthRange = 2;
				}
				else 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.refdef.floatTime = originalTime;
				backEnd.ori = backEnd.viewParms.world;
#ifdef VV_LIGHTING
				VVLightMan.R_TransformDlights( &backEnd.ori );
#else
				R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.ori );
#endif
			}

			qglLoadMatrixf( backEnd.ori.modelMatrix );

			//
			// change depthrange if needed
			//
			if ( oldDepthRange != depthRange ) {
				switch ( depthRange ) {
					default:
					case 0:
						qglDepthRange (0, 1);	
						break;

					case 1:
						qglDepthRange (0, .3);	
						break;

					case 2:
						qglDepthRange (0, 0);
						break;
				}

				oldDepthRange = depthRange;
			}

			oldEntityNum = entityNum;
		}

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

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

	if (tr_stencilled && tr_distortionPrePost)
	{ //ok, cap it now
		RB_CaptureScreenImage();
		RB_DistortionFill();
	}

	//render distortion surfs (or anything else that needs to be post-rendered)
	if (g_numPostRenders > 0)
	{
		int lastPostEnt = -1;

		while (g_numPostRenders > 0)
		{
			g_numPostRenders--;
			pRender = &g_postRenders[g_numPostRenders];

			RB_BeginSurface( pRender->shader, pRender->fogNum );

			backEnd.currentEntity = &backEnd.refdef.entities[pRender->entNum];

			backEnd.refdef.floatTime = originalTime - backEnd.currentEntity->e.shaderTime;

			// set up the transformation matrix
			R_RotateForEntity( backEnd.currentEntity, &backEnd.viewParms, &backEnd.ori );

			// set up the dynamic lighting if needed
			if ( backEnd.currentEntity->needDlights )
			{
#ifdef VV_LIGHTING
				VVLightMan.R_TransformDlights( &backEnd.ori );
#else
				R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.ori );
#endif
			}

			qglLoadMatrixf( backEnd.ori.modelMatrix );

			depthRange = pRender->depthRange;
			switch ( depthRange )
			{
				default:
				case 0:
					qglDepthRange (0, 1);	
					break;

				case 1:
					qglDepthRange (0, .3);	
					break;

				case 2:
					qglDepthRange (0, 0);
					break;
			}

			if ((backEnd.currentEntity->e.renderfx & RF_DISTORTION) &&
				lastPostEnt != pRender->entNum)
			{ //do the capture now, we only need to do it once per ent
				int x, y;
				int rad = backEnd.currentEntity->e.radius;
				//We are going to just bind this, and then the CopyTexImage is going to
				//stomp over this texture num in texture memory.
				GL_Bind( tr.screenImage );

				if (R_WorldCoordToScreenCoord( backEnd.currentEntity->e.origin, &x, &y ))
				{
					int cX, cY;
					cX = glConfig.vidWidth-x-(rad/2);
					cY = glConfig.vidHeight-y-(rad/2);

					if (cX+rad > glConfig.vidWidth)
					{ //would it go off screen?
						cX = glConfig.vidWidth-rad;
					}
					else if (cX < 0)
					{ //cap it off at 0
						cX = 0;
					}

					if (cY+rad > glConfig.vidHeight)
					{ //would it go off screen?
						cY = glConfig.vidHeight-rad;
					}
					else if (cY < 0)
					{ //cap it off at 0
						cY = 0;
					}

					//now copy a portion of the screen to this texture
					qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, cX, cY, rad, rad, 0);

					lastPostEnt = pRender->entNum;
				}
			}

			rb_surfaceTable[ *pRender->drawSurf->surface ]( pRender->drawSurf->surface );
			RB_EndSurface();
		}
	}

	// go back to the world modelview matrix
	qglLoadMatrixf( backEnd.viewParms.world.modelMatrix );
	if ( depthRange ) {
		qglDepthRange (0, 1);
	}

#if 0
	RB_DrawSun();
#endif
	if (tr_stencilled && !tr_distortionPrePost)
	{ //draw in the stencil buffer's cutout
		RB_DistortionFill();
	}
	if (!didShadowPass)
	{
		// darken down any stencil shadows
		RB_ShadowFinish();
		didShadowPass = true;
	}

// add light flares on lights that aren't obscured
//	RB_RenderFlares();

#ifdef __MACOS__
	Sys_PumpEvents();		// crutch up the mac's limited buffer queue size
#endif
}
Exemplo n.º 3
0
void
R_DrawAliasModel ( entity_t *e )
{
	int i;
	dmdl_t      *paliashdr;
	float an;
	vec3_t bbox [ 8 ];
	image_t     *skin;

	if ( !( e->flags & RF_WEAPONMODEL ) )
	{
		if ( R_CullAliasModel( bbox, e ) )
		{
			return;
		}
	}

	if ( e->flags & RF_WEAPONMODEL )
	{
		if ( gl_lefthand->value == 2 )
		{
			return;
		}
	}

	paliashdr = (dmdl_t *) currentmodel->extradata;

	/* get lighting information */
	if ( currententity->flags & ( RF_SHELL_HALF_DAM | RF_SHELL_GREEN | RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_DOUBLE ) )
	{
		VectorClear( shadelight );

		if ( currententity->flags & RF_SHELL_HALF_DAM )
		{
			shadelight [ 0 ] = 0.56;
			shadelight [ 1 ] = 0.59;
			shadelight [ 2 ] = 0.45;
		}

		if ( currententity->flags & RF_SHELL_DOUBLE )
		{
			shadelight [ 0 ] = 0.9;
			shadelight [ 1 ] = 0.7;
		}

		if ( currententity->flags & RF_SHELL_RED )
		{
			shadelight [ 0 ] = 1.0;
		}

		if ( currententity->flags & RF_SHELL_GREEN )
		{
			shadelight [ 1 ] = 1.0;
		}

		if ( currententity->flags & RF_SHELL_BLUE )
		{
			shadelight [ 2 ] = 1.0;
		}
	}
	else if ( currententity->flags & RF_FULLBRIGHT )
	{
		for ( i = 0; i < 3; i++ )
		{
			shadelight [ i ] = 1.0;
		}
	}
	else
	{
		R_LightPoint( currententity->origin, shadelight );

		/* player lighting hack for communication back to server */
		if ( currententity->flags & RF_WEAPONMODEL )
		{
			/* pick the greatest component, which should be the same
			   as the mono value returned by software */
			if ( shadelight [ 0 ] > shadelight [ 1 ] )
			{
				if ( shadelight [ 0 ] > shadelight [ 2 ] )
				{
					gl_lightlevel->value = 150 * shadelight [ 0 ];
				}
				else
				{
					gl_lightlevel->value = 150 * shadelight [ 2 ];
				}
			}
			else
			{
				if ( shadelight [ 1 ] > shadelight [ 2 ] )
				{
					gl_lightlevel->value = 150 * shadelight [ 1 ];
				}
				else
				{
					gl_lightlevel->value = 150 * shadelight [ 2 ];
				}
			}
		}
	}

	if ( currententity->flags & RF_MINLIGHT )
	{
		for ( i = 0; i < 3; i++ )
		{
			if ( shadelight [ i ] > 0.1 )
			{
				break;
			}
		}

		if ( i == 3 )
		{
			shadelight [ 0 ] = 0.1;
			shadelight [ 1 ] = 0.1;
			shadelight [ 2 ] = 0.1;
		}
	}

	if ( currententity->flags & RF_GLOW )
	{
		/* bonus items will pulse with time */
		float scale;
		float min;

		scale = 0.1 * sin( r_newrefdef.time * 7 );

		for ( i = 0; i < 3; i++ )
		{
			min = shadelight [ i ] * 0.8;
			shadelight [ i ] += scale;

			if ( shadelight [ i ] < min )
			{
				shadelight [ i ] = min;
			}
		}
	}

	/* ir goggles color override */
	if ( r_newrefdef.rdflags & RDF_IRGOGGLES && currententity->flags & RF_IR_VISIBLE )
	{
		shadelight [ 0 ] = 1.0;
		shadelight [ 1 ] = 0.0;
		shadelight [ 2 ] = 0.0;
	}

	shadedots =
		r_avertexnormal_dots [ ( (int) ( currententity->angles [ 1 ] * ( SHADEDOT_QUANT / 360.0 ) ) ) & ( SHADEDOT_QUANT - 1 ) ];

	an = currententity->angles [ 1 ] / 180 * M_PI;
	shadevector [ 0 ] = cos( -an );
	shadevector [ 1 ] = sin( -an );
	shadevector [ 2 ] = 1;
	VectorNormalize( shadevector );

	/* locate the proper data */
	c_alias_polys += paliashdr->num_tris;

	/* draw all the triangles */
	if ( currententity->flags & RF_DEPTHHACK ) /* hack the depth range to prevent view model from poking into walls */
	{
		qglDepthRange( gldepthmin, gldepthmin + 0.3 * ( gldepthmax - gldepthmin ) );
	}

	if ( ( currententity->flags & RF_WEAPONMODEL ) && ( gl_lefthand->value == 1.0F ) )
	{
		extern void R_MYgluPerspective ( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar );

		qglMatrixMode( GL_PROJECTION );
		qglPushMatrix();
		qglLoadIdentity();
		qglScalef( -1, 1, 1 );
		R_MYgluPerspective( r_newrefdef.fov_y, (float) r_newrefdef.width / r_newrefdef.height,  4,  4096 );
		qglMatrixMode( GL_MODELVIEW );

		qglCullFace( GL_BACK );
	}

	qglPushMatrix();
	e->angles [ PITCH ] = -e->angles [ PITCH ];
	R_RotateForEntity( e );
	e->angles [ PITCH ] = -e->angles [ PITCH ];

	/* select skin */
	if ( currententity->skin )
	{
		skin = currententity->skin; /* custom player skin */
	}
	else
	{
		if ( currententity->skinnum >= MAX_MD2SKINS )
		{
			skin = currentmodel->skins [ 0 ];
		}
		else
		{
			skin = currentmodel->skins [ currententity->skinnum ];

			if ( !skin )
			{
				skin = currentmodel->skins [ 0 ];
			}
		}
	}

	if ( !skin )
	{
		skin = r_notexture; /* fallback... */
	}

	R_Bind( skin->texnum );

	/* draw it */
	qglShadeModel( GL_SMOOTH );

	R_TexEnv( GL_MODULATE );

	if ( currententity->flags & RF_TRANSLUCENT )
	{
		qglEnable( GL_BLEND );
	}

	if ( ( currententity->frame >= paliashdr->num_frames ) ||
		 ( currententity->frame < 0 ) )
	{
		ri.Con_Printf( PRINT_ALL, "R_DrawAliasModel %s: no such frame %d\n",
				currentmodel->name, currententity->frame );
		currententity->frame = 0;
		currententity->oldframe = 0;
	}

	if ( ( currententity->oldframe >= paliashdr->num_frames ) ||
		 ( currententity->oldframe < 0 ) )
	{
		ri.Con_Printf( PRINT_ALL, "R_DrawAliasModel %s: no such oldframe %d\n",
				currentmodel->name, currententity->oldframe );
		currententity->frame = 0;
		currententity->oldframe = 0;
	}

	if ( !gl_lerpmodels->value )
	{
		currententity->backlerp = 0;
	}

	R_DrawAliasFrameLerp( paliashdr, currententity->backlerp );

	R_TexEnv( GL_REPLACE );
	qglShadeModel( GL_FLAT );

	qglPopMatrix();

	if ( ( currententity->flags & RF_WEAPONMODEL ) && ( gl_lefthand->value == 1.0F ) )
	{
		qglMatrixMode( GL_PROJECTION );
		qglPopMatrix();
		qglMatrixMode( GL_MODELVIEW );
		qglCullFace( GL_FRONT );
	}

	if ( currententity->flags & RF_TRANSLUCENT )
	{
		qglDisable( GL_BLEND );
	}

	if ( currententity->flags & RF_DEPTHHACK )
	{
		qglDepthRange( gldepthmin, gldepthmax );
	}

	if ( gl_shadows->value &&
		 !( currententity->flags & ( RF_TRANSLUCENT | RF_WEAPONMODEL | RF_NOSHADOW ) ) )
	{
		qglPushMatrix();

		/* don't rotate shadows on ungodly axes */
		qglTranslatef( e->origin [ 0 ], e->origin [ 1 ], e->origin [ 2 ] );
		qglRotatef( e->angles [ 1 ], 0, 0, 1 );

		qglDisable( GL_TEXTURE_2D );
		qglEnable( GL_BLEND );
		qglColor4f( 0, 0, 0, 0.5f );
		R_DrawAliasShadow( paliashdr, currententity->frame );
		qglEnable( GL_TEXTURE_2D );
		qglDisable( GL_BLEND );
		qglPopMatrix();
	}

	qglColor4f( 1, 1, 1, 1 );
}
Exemplo n.º 4
0
/*
=================
R_DrawAliasModel
=================
*/
void R_DrawAliasModel (entity_t *e)
{
	maliasmodel_t	*paliashdr;
	vec3_t		bbox[8];
	qboolean	mirrormodel = false;
	int			i;

	// also skip this for viewermodels and cameramodels
	if ( !(e->flags & RF_WEAPONMODEL || e->flags & RF_VIEWERMODEL || e->renderfx & RF2_CAMERAMODEL) )
	{
		if (R_CullAliasModel(bbox, e))
			return;
	}

	// mirroring support
	if (e->flags & RF_WEAPONMODEL)
	{
		if (r_lefthand->value == 2)
			return;
		else if (r_lefthand->value == 1)
			mirrormodel = true;
	}
	else if (e->renderfx & RF2_CAMERAMODEL)
	{
		if (r_lefthand->value==1)
			mirrormodel = true;
	}
	else if (e->flags & RF_MIRRORMODEL)
		mirrormodel = true;
	// end mirroring support

	paliashdr = (maliasmodel_t *)currentmodel->extradata;

	R_SetShadeLight ();

	if (e->flags & RF_DEPTHHACK) // hack the depth range to prevent view model from poking into walls
	{
		if (r_newrefdef.rdflags & RDF_NOWORLDMODEL)
			GL_DepthRange (gldepthmin, gldepthmin + 0.01*(gldepthmax-gldepthmin));
		else
			GL_DepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
	}

	// mirroring support
	if (mirrormodel)
		R_FlipModel(true);

	for (i=0; i < paliashdr->num_meshes; i++)
		c_alias_polys += paliashdr->meshes[i].num_tris;

	qglPushMatrix ();
	e->angles[ROLL] = -e->angles[ROLL];		// roll is backwards
	R_RotateForEntity (e, true);
	e->angles[ROLL] = -e->angles[ROLL];		// roll is backwards

	GL_ShadeModel (GL_SMOOTH);

	GL_TexEnv(GL_MODULATE);

	if ( (e->frame >= paliashdr->num_frames) || (e->frame < 0) )
	{
		VID_Printf (PRINT_ALL, "R_DrawAliasModel %s: no such frame %d\n", currentmodel->name, e->frame);
		e->frame = 0;
		e->oldframe = 0;
	}

	if ( (e->oldframe >= paliashdr->num_frames) || (e->oldframe < 0))
	{
		VID_Printf (PRINT_ALL, "R_DrawAliasModel %s: no such oldframe %d\n",
			currentmodel->name, e->oldframe);
		e->frame = 0;
		e->oldframe = 0;
	}

	if (!r_lerpmodels->value)
		e->backlerp = 0;

	R_DrawAliasFrameLerp (paliashdr, e);

	GL_TexEnv(GL_REPLACE);
	GL_ShadeModel (GL_FLAT);

	qglPopMatrix ();

	// mirroring support
	if (mirrormodel)
		R_FlipModel(false);

	// show model bounding box
	R_DrawAliasModelBBox (bbox, e);

	if (e->flags & RF_DEPTHHACK)
		GL_DepthRange (gldepthmin, gldepthmax);

	aliasShadowAlpha = R_CalcShadowAlpha(e);

	if (!(e->flags & (RF_WEAPONMODEL | RF_NOSHADOW))
		// no shadows from shells
		&& !( (e->flags & (RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM)) && (e->flags & RF_TRANSLUCENT) )
		&& r_shadows->value >= 1 && aliasShadowAlpha >= DIV255)
	{
 		qglPushMatrix ();
		GL_DisableTexture(0);
		GL_Enable (GL_BLEND);

		if (r_shadows->value == 3) {
			e->angles[ROLL] = -e->angles[ROLL];		// roll is backwards
			R_RotateForEntity (e, true);
			e->angles[ROLL] = -e->angles[ROLL];		// roll is backwards
			R_DrawAliasVolumeShadow (paliashdr, bbox);
		}
		else {
			R_RotateForEntity (e, false);
			R_DrawAliasPlanarShadow (paliashdr);
		}

		GL_Disable (GL_BLEND);
		GL_EnableTexture(0);
		qglPopMatrix ();
	}
}
Exemplo n.º 5
0
void R_DrawBrushModel(entity_t *e) {
	int k;
	vec3_t mins, maxs;
	model_t *clmodel;
	bool rotated;
	int i;
	extern vec3_t lightcolor;
	int lnum;
	vec3_t dist;
	float add;
	float modelorg[3];

	clmodel = e->model;

	if (e->angles[0] || e->angles[1] || e->angles[2]) {
		rotated = true;
		for (i = 0; i < 3; i++) {
			mins[i] = e->origin[i] - clmodel->radius;
			maxs[i] = e->origin[i] + clmodel->radius;
		}
	} else {
		rotated = false;
		VectorAdd(e->origin, clmodel->mins, mins);
		VectorAdd(e->origin, clmodel->maxs, maxs);
	}

	if (R_CullBox(mins, maxs))
		return;

	//Lighting for model
	//dynamic lights for non lightmaped bmodels
	if (clmodel->firstmodelsurface == 0) {
		R_LightPoint(e->origin);
		for (lnum = 0; lnum < MAX_DLIGHTS; lnum++) {
			if (cl_dlights[lnum].die >= cl.time) {
				VectorSubtract(e->origin, cl_dlights[lnum].origin, dist);
				add = cl_dlights[lnum].radius - VectorLength(dist);
				if (add > 0) {
					lightcolor[0] += add * cl_dlights[lnum].colour[0];
					lightcolor[1] += add * cl_dlights[lnum].colour[1];
					lightcolor[2] += add * cl_dlights[lnum].colour[2];
				}
			}
		}
		VectorScale(lightcolor, 1.0f / 100.0f, lightcolor);

		if (gl_ammoflash.getBool()) {
			lightcolor[0] += sin(2 * cl.time * M_PI) / 4;
			lightcolor[1] += sin(2 * cl.time * M_PI) / 4;
			lightcolor[2] += sin(2 * cl.time * M_PI) / 4;
		}

		glColor3fv(lightcolor);
	} else {
		glColor3f(1.0, 1.0, 1.0);
		memset(lightmap_polys, 0, sizeof (lightmap_polys));
	}

	VectorSubtract(r_refdef.vieworg, e->origin, modelorg);
	if (rotated) {
		vec3_t temp;
		vec3_t forward, right, up;

		VectorCopy(modelorg, temp);
		AngleVectors(e->angles, forward, right, up);
		modelorg[0] = DotProduct(temp, forward);
		modelorg[1] = -DotProduct(temp, right);
		modelorg[2] = DotProduct(temp, up);
	}

	glPushMatrix();
	e->angles[0] = -e->angles[0]; // stupid quake bug
	R_RotateForEntity(e);
	e->angles[0] = -e->angles[0]; // stupid quake bug

	// calculate dynamic lighting for bmodel if it's not an
	// instanced model
	if (clmodel->firstmodelsurface != 0 && !gl_flashblend.getBool()) {
		for (k = 0; k < MAX_DLIGHTS; k++) {
			if ((cl_dlights[k].die < cl.time) ||
					(!cl_dlights[k].radius))
				continue;

			R_MarkLights(&cl_dlights[k], 1 << k,
					clmodel->nodes + clmodel->hulls[0].firstclipnode);
		}
	}

	R_DrawBrush(clmodel, &modelorg[0]);

	glPopMatrix();
}
Exemplo n.º 6
0
/*
==================
RB_RenderDrawSurfList
==================
*/
void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs )
{
	shader_t   *shader, *oldShader;
	int        fogNum, oldFogNum;
	int        entityNum, oldEntityNum;
	int        frontFace;
	int        dlighted, oldDlighted;
	qboolean   depthRange, oldDepthRange;
	int        i;
	drawSurf_t *drawSurf;
	int        oldSort;
	float      originalTime;

#ifdef __MACOS__
	int        macEventTime;

	Sys_PumpEvents(); // crutch up the mac's limited buffer queue size

	// we don't want to pump the event loop too often and waste time, so
	// we are going to check every shader change
	macEventTime = ri.Milliseconds() + MAC_EVENT_PUMP_MSEC;
#endif

	// save original time for entity shader offsets
	originalTime = backEnd.refdef.floatTime;

	// clear the z buffer, set the modelview, etc
	RB_BeginDrawingView();

	// draw everything
	oldEntityNum = -1;
	backEnd.currentEntity = &tr.worldEntity;
	oldShader = NULL;
	oldFogNum = -1;
	oldDepthRange = qfalse;
	oldDlighted = qfalse;
	oldSort = -1;
	depthRange = qfalse;

	backEnd.pc.c_surfaces += numDrawSurfs;

	for ( i = 0, drawSurf = drawSurfs; i < numDrawSurfs; i++, drawSurf++ )
	{
		if ( drawSurf->sort == oldSort )
		{
			// fast path, same as previous sort
			rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
			continue;
		}

		oldSort = drawSurf->sort;
		R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &frontFace, &dlighted );

		//
		// 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 || fogNum != oldFogNum || dlighted != oldDlighted
		     || ( entityNum != oldEntityNum && !shader->entityMergable ) )
		{
			if ( oldShader != NULL )
			{
#ifdef __MACOS__ // crutch up the mac's limited buffer queue size
				int t;

				t = ri.Milliseconds();

				if ( t > macEventTime )
				{
					macEventTime = t + MAC_EVENT_PUMP_MSEC;
					Sys_PumpEvents();
				}

#endif
				RB_EndSurface();
			}

			RB_BeginSurface( shader, fogNum );
			oldShader = shader;
			oldFogNum = fogNum;
			oldDlighted = dlighted;
		}

		//
		// change the modelview matrix if needed
		//
		if ( entityNum != oldEntityNum )
		{
			depthRange = qfalse;

			if ( entityNum != ENTITYNUM_WORLD )
			{
				backEnd.currentEntity = &backEnd.refdef.entities[ entityNum ];
				backEnd.refdef.floatTime = originalTime; // - backEnd.currentEntity->e.shaderTime; // JPW NERVE pulled this to match q3ta

				// we have to reset the shaderTime as well otherwise image animations start
				// from the wrong frame
//              tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;

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

				// set up the dynamic lighting if needed
				if ( backEnd.currentEntity->needDlights )
				{
					R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &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.refdef.floatTime = originalTime;
				backEnd.orientation = backEnd.viewParms.world;

				// we have to reset the shaderTime as well otherwise image animations on
				// the world (like water) continue with the wrong frame
//              tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;

				R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.orientation );
			}

			glLoadMatrixf( backEnd.orientation.modelMatrix );

			//
			// change depthrange if needed
			//
			if ( oldDepthRange != depthRange )
			{
				if ( depthRange )
				{
					glDepthRange( 0, 0.3 );
				}
				else
				{
					glDepthRange( 0, 1 );
				}

				oldDepthRange = depthRange;
			}

			oldEntityNum = entityNum;
		}

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

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

	// go back to the world modelview matrix
	backEnd.currentEntity = &tr.worldEntity;
	backEnd.refdef.floatTime = originalTime;
	backEnd.orientation = backEnd.viewParms.world;
	R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.orientation );

	glLoadMatrixf( backEnd.viewParms.world.modelMatrix );

	if ( depthRange )
	{
		glDepthRange( 0, 1 );
	}

	// (SA) draw sun
	RB_DrawSun();

	// darken down any stencil shadows
	RB_ShadowFinish();

	// add light flares on lights that aren't obscured
	RB_RenderFlares();

#ifdef __MACOS__
	Sys_PumpEvents(); // crutch up the mac's limited buffer queue size
#endif
}
Exemplo n.º 7
0
/*
==================
RB_RenderDrawSurfList
==================
*/
void RB_RenderDrawSurfList(drawSurf_t *drawSurfs, int numDrawSurfs)
{
	shader_t        *shader, *oldShader;
	int fogNum, oldFogNum;
	int entityNum, oldEntityNum;
	int dlighted, oldDlighted;
	qboolean depthRange, oldDepthRange;
	int i;
	drawSurf_t      *drawSurf;
	int oldSort;
	float originalTime;
	int oldNumVerts, oldNumIndex;
//GR - tessellation flag
	int atiTess = 0, oldAtiTess;
#ifdef __MACOS__
	int macEventTime;

	Sys_PumpEvents();       // crutch up the mac's limited buffer queue size

	// we don't want to pump the event loop too often and waste time, so
	// we are going to check every shader change
	macEventTime = ri.Milliseconds() + MAC_EVENT_PUMP_MSEC;
#endif

	// save original time for entity shader offsets
	originalTime = backEnd.refdef.floatTime;

	// clear the z buffer, set the modelview, etc
	RB_BeginDrawingView();

	// draw everything
	oldEntityNum = -1;
	backEnd.currentEntity = &tr.worldEntity;
	oldShader = NULL;
	oldFogNum = -1;
	oldDepthRange = qfalse;
	oldDlighted = qfalse;
	oldSort = -1;
	depthRange = qfalse;
// GR - tessellation also forces to draw everything
	oldAtiTess = -1;

	backEnd.pc.c_surfaces += numDrawSurfs;

	for(i = 0, drawSurf = drawSurfs ; i < numDrawSurfs ; i++, drawSurf++)
	{
		if(drawSurf->sort == oldSort)
		{
			// fast path, same as previous sort
			oldNumVerts = tess.numVertexes;
			oldNumIndex = tess.numIndexes;

			rb_surfaceTable[ *drawSurf->surface ](drawSurf->surface);
			/*
			            // RF, convert the newly created vertexes into dust particles, and overwrite
			            if (backEnd.currentEntity->e.reFlags & REFLAG_ZOMBIEFX) {
			                RB_ZombieFX( 0, drawSurf, oldNumVerts, oldNumIndex );
			            }
			            else if (backEnd.currentEntity->e.reFlags & REFLAG_ZOMBIEFX2) {
			                RB_ZombieFX( 1, drawSurf, oldNumVerts, oldNumIndex );
			            }
			*/
			continue;
		}

		oldSort = drawSurf->sort;
// GR - also extract tesselation flag
		R_DecomposeSort(drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted, &atiTess);

		//
		// change the tess parameters if needed
		// a "entityMergable" shader is a shader that can have surfaces from seperate
		// entities merged into a single batch, like smoke and blood puff sprites
		if(shader != oldShader || fogNum != oldFogNum || dlighted != oldDlighted
// GR - force draw on tessellation flag change
		        || (atiTess != oldAtiTess)
		        || (entityNum != oldEntityNum && !shader->entityMergable))
		{
			if(oldShader != NULL)
			{
#ifdef __MACOS__    // crutch up the mac's limited buffer queue size
				int t;

				t = ri.Milliseconds();

				if(t > macEventTime)
				{
					macEventTime = t + MAC_EVENT_PUMP_MSEC;
					Sys_PumpEvents();
				}

#endif
// GR - pass tessellation flag to the shader command
//		make sure to use oldAtiTess!!!
				tess.ATI_tess = (oldAtiTess == ATI_TESS_TRUFORM);

				RB_EndSurface();
			}

			RB_BeginSurface(shader, fogNum);
			oldShader = shader;
			oldFogNum = fogNum;
			oldDlighted = dlighted;
// GR - update old tessellation flag
			oldAtiTess = atiTess;
		}

		//
		// change the modelview matrix if needed
		//
		if(entityNum != oldEntityNum)
		{
			depthRange = qfalse;

			if(entityNum != ENTITYNUM_WORLD)
			{
				backEnd.currentEntity = &backEnd.refdef.entities[entityNum];
				backEnd.refdef.floatTime = originalTime - backEnd.currentEntity->e.shaderTime;

				// we have to reset the shaderTime as well otherwise image animations start
				// from the wrong frame
//				tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;

				// set up the transformation matrix
				R_RotateForEntity(backEnd.currentEntity, &backEnd.viewParms, &backEnd.or);

				// set up the dynamic lighting if needed
				if(backEnd.currentEntity->needDlights)
				{
					R_TransformDlights(backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or);
				}

				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.refdef.floatTime = originalTime;
				backEnd.or = backEnd.viewParms.world;

				// we have to reset the shaderTime as well otherwise image animations on
				// the world (like water) continue with the wrong frame
//				tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;

				R_TransformDlights(backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or);
			}

			qglLoadMatrixf(backEnd.or.modelMatrix);

			//
			// change depthrange if needed
			//
			if(oldDepthRange != depthRange)
			{
				if(depthRange)
				{
					qglDepthRange(0, 0.3);
				}
				else
				{
					qglDepthRange(0, 1);
				}

				oldDepthRange = depthRange;
			}

			oldEntityNum = entityNum;
		}

		// RF, ZOMBIEFX, store the tess indexes, so we can grab the calculated
		// vertex positions and normals, and convert them into dust particles
		oldNumVerts = tess.numVertexes;
		oldNumIndex = tess.numIndexes;

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

		// RF, convert the newly created vertexes into dust particles, and overwrite
		if(backEnd.currentEntity->e.reFlags & REFLAG_ZOMBIEFX)
		{
			RB_ZombieFX(0, drawSurf, oldNumVerts, oldNumIndex);
		}
		else if(backEnd.currentEntity->e.reFlags & REFLAG_ZOMBIEFX2)
		{
			RB_ZombieFX(1, drawSurf, oldNumVerts, oldNumIndex);
		}
	}

	// draw the contents of the last shader batch
	if(oldShader != NULL)
	{
// GR - pass tessellation flag to the shader command
//		make sure to use oldAtiTess!!!
		tess.ATI_tess = (oldAtiTess == ATI_TESS_TRUFORM);

		RB_EndSurface();
	}

	// go back to the world modelview matrix
	backEnd.currentEntity = &tr.worldEntity;
	backEnd.refdef.floatTime = originalTime;
	backEnd.or = backEnd.viewParms.world;
	R_TransformDlights(backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or);

	qglLoadMatrixf(backEnd.viewParms.world.modelMatrix);

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

	// (SA) draw sun
	RB_DrawSun();


	// darken down any stencil shadows
	RB_ShadowFinish();

	// add light flares on lights that aren't obscured
	RB_RenderFlares();

#ifdef __MACOS__
	Sys_PumpEvents();       // crutch up the mac's limited buffer queue size
#endif
}
Exemplo n.º 8
0
void R_DrawAliasModel(entity_t *e) {
    extern void AddFire(vec3_t org, float size);

    int lnum;
    vec3_t dist;
    float add;
    model_t *clmodel;
    vec3_t mins, maxs;
    aliashdr_t *paliashdr;
    float an; //s, t,
    int anim;
    md2_t *pheader; // LH / muff
    int shell; //QMB :model shells

    //not implemented yet
    //	byte		c, *color;	//QMB :color map

    //does the model need a shell?
    if (cl.items & IT_QUAD && e == &cl.viewent)
        shell = true;
    else
        shell = false;

    //set get the model from the e
    clmodel = e->model;

    //work out its max and mins
    VectorAdd(e->origin, clmodel->mins, mins);
    VectorAdd(e->origin, clmodel->maxs, maxs);
    //make sure its in screen
    if (R_CullBox(mins, maxs) && e != &cl.viewent)
        return;

    //QMB: FIXME
    //should use a particle emitter linked to the model for its org
    //needs to be linked when the model is created and distroyed when
    //the entity is distroyed
    //check if its a fire and add the particle effect
    if (!strcmp(clmodel->name, "progs/flame.mdl"))
        AddFire(e->origin, 4);

    if (!strcmp(clmodel->name, "progs/flame2.mdl")) {
        AddFire(e->origin, 10);
        return; //do not draw the big fire model, its just a place holder for the particles
    }

    // get lighting information
    //QMB: FIXME
    //SHOULD CHANGE TO A PASSED VAR
    //get vertex normals (for lighting and shells)
    shadedots = r_avertexnormal_dots[((int) (e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];

    //make a default lighting direction
    an = e->angles[1] / 180 * M_PI;
    shadevector[0] = cos(-an);
    shadevector[1] = sin(-an);
    shadevector[2] = 1; //e->angles[0];
    VectorNormalize(shadevector);

    //get the light for the model
    R_LightPoint(e->origin); // LordHavoc: lightcolor is all that matters from this

    //work out lighting from the dynamic lights
    for (lnum = 0; lnum < MAX_DLIGHTS; lnum++) {
        //if the light is alive
        if (cl_dlights[lnum].die >= cl.time) {
            //work out the distance to the light
            VectorSubtract(e->origin, cl_dlights[lnum].origin, dist);
            add = cl_dlights[lnum].radius - VectorLength(dist);
            //if its close enough add light from it
            if (add > 0) {
                lightcolor[0] += add * cl_dlights[lnum].colour[0];
                lightcolor[1] += add * cl_dlights[lnum].colour[1];
                lightcolor[2] += add * cl_dlights[lnum].colour[2];
            }
        }
    }

    //scale lighting to floating point
    VectorScale(lightcolor, 1.0f / 200.0f, lightcolor);

    // locate the proper data
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

    if (gl_n_patches && gl_npatches.getBool()) {
        glEnable(GL_PN_TRIANGLES_ATI);
        glPNTrianglesiATI(GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI, gl_npatches.getInt());

        if (true)
            glPNTrianglesiATI(GL_PN_TRIANGLES_POINT_MODE_ATI, GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI);
        else
            glPNTrianglesiATI(GL_PN_TRIANGLES_POINT_MODE_ATI, GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI);

        if (true)
            glPNTrianglesiATI(GL_PN_TRIANGLES_NORMAL_MODE_ATI, GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI);
        else
            glPNTrianglesiATI(GL_PN_TRIANGLES_NORMAL_MODE_ATI, GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI);
    }

    if (clmodel->aliastype == MD3IDHEADER) {
        //do nothing for testing
        if (!r_modeltexture.getBool()) {
            GL_DisableTMU(GL_TEXTURE0_ARB);
        }//disable texture if needed

        R_DrawQ3Model(e, false, false);

        if (!r_modeltexture.getBool()) {
            GL_EnableTMU(GL_TEXTURE0_ARB);
        }//enable texture if needed

        if (r_celshading.getBool() || r_outline.getBool()) {
            glCullFace(GL_BACK);
            glEnable(GL_BLEND);
            glPolygonMode(GL_FRONT, GL_LINE);

            if (e == &cl.viewent) {
                glLineWidth(1.0f);
            } else {
                glLineWidth(5.0f);
            }

            glEnable(GL_LINE_SMOOTH);

            GL_DisableTMU(GL_TEXTURE0_ARB);

            glColor3f(0.0, 0.0, 0.0);
            R_DrawQ3Model(e, false, true);
            glColor3f(1.0, 1.0, 1.0);

            GL_EnableTMU(GL_TEXTURE0_ARB);

            glPolygonMode(GL_FRONT, GL_FILL);
            glDisable(GL_BLEND);
            glCullFace(GL_FRONT);
        }

        if (shell) {
            glBindTexture(GL_TEXTURE_2D, quadtexture);
            glColor4f(1.0, 1.0, 1.0, 0.5);
            glEnable(GL_BLEND);
            R_DrawQ3Model(e, true, false);
            glDisable(GL_BLEND);
            glColor3f(1.0, 1.0, 1.0);
        }
    } else if (clmodel->aliastype != ALIASTYPE_MD2) {
        paliashdr = (aliashdr_t *) Mod_Extradata(e->model);
        c_alias_polys += paliashdr->numtris;

        glPushMatrix();

        //interpolate unless its the viewmodel
        if (e != &cl.viewent)
            R_BlendedRotateForEntity(e);
        else
            R_RotateForEntity(e);

        glTranslatef(paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]);
        glScalef(paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]);

        anim = (int) (cl.time * 10) & 3;
        glBindTexture(GL_TEXTURE_2D, paliashdr->gl_texturenum[e->skinnum][anim]);

        // draw all the triangles
        if (!r_modeltexture.getBool()) {
            GL_DisableTMU(GL_TEXTURE0_ARB);
        } else {
            //highlighting test code
            if (0 && gl_textureunits > 2) {
                GL_EnableTMU(GL_TEXTURE1_ARB);

                glBindTexture(GL_TEXTURE_2D, TextureManager::highlighttexture);

                glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
                glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
                glEnable(GL_TEXTURE_GEN_S);
                glEnable(GL_TEXTURE_GEN_T);
                //need correct mode
                glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
                glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
                glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.0);

                //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
            }
        }

        glColor3fv(lightcolor);
        R_SetupAliasBlendedFrame(e->frame, paliashdr, e, false, false);
        glDisable(GL_TEXTURE_1D);

        if (r_celshading.getBool() || r_outline.getBool()) {
            glColor3f(0.0, 0.0, 0.0);
            R_SetupAliasBlendedFrame(e->frame, paliashdr, e, false, true);
            glColor3f(1.0, 1.0, 1.0);
        }

        if (!r_modeltexture.getBool()) {
            GL_EnableTMU(GL_TEXTURE0_ARB);
        } else {
            if (0 && gl_textureunits > 2) {
                //highlighting test code
                glDisable(GL_TEXTURE_GEN_S);
                glDisable(GL_TEXTURE_GEN_T);
                GL_DisableTMU(GL_TEXTURE1_ARB);
                glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
            }
        }
        glActiveTexture(GL_TEXTURE0_ARB);

        //colour map code... not working yet...
        /*		if (e->colormap != vid.colormap && !gl_nocolors.value)
                {
                    if (paliashdr->gl_texturenumColorMap&&paliashdr->gl_texturenumColorMap){
                        glBindTexture(GL_TEXTURE_2D,paliashdr->gl_texturenumColorMap);
                        c = (byte)e->colormap & 0xF0;
                        c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges
                        color = (byte *) (&d_8to24table[c]);
                        //glColor3fv(color);
                        glColor3f(1.0,1.0,1.0);
                    }
                }*/
        if (shell) {
            glBindTexture(GL_TEXTURE_2D, quadtexture);
            glColor4f(1.0, 1.0, 1.0, 0.5);
            glEnable(GL_BLEND);
            R_SetupAliasBlendedFrame(e->frame, paliashdr, e, true, false);
            glDisable(GL_BLEND);
            glColor3f(1.0, 1.0, 1.0);
        }
        glPopMatrix();

    } else {
        pheader = (md2_t *) Mod_Extradata(e->model);
        c_alias_polys += pheader->num_tris;

        glBindTexture(GL_TEXTURE_2D, pheader->gl_texturenum[e->skinnum]);
        R_SetupQ2AliasFrame(e, pheader);
    }

    if (gl_n_patches && gl_npatches.getBool()) {
        glDisable(GL_PN_TRIANGLES_ATI);
    }

    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}
Exemplo n.º 9
0
/*
* R_DrawAliasFrameLerp
* 
* Interpolates between two frames and origins
*/
static void R_DrawAliasFrameLerp( const meshbuffer_t *mb, float backlerp )
{
	int i, meshnum;
	int features;
	float backv[3], frontv[3];
	vec3_t normal, oldnormal;
	qboolean calcVerts, calcNormals, calcSTVectors;
	vec3_t move;
	maliasframe_t *frame, *oldframe;
	maliasmesh_t *mesh;
	maliasvertex_t *v, *ov;
	entity_t *e;
	model_t	*mod;
	maliasmodel_t *model;
	shader_t *shader;

	MB_NUM2ENTITY( mb->sortkey, e );
	mod = Mod_ForHandle( mb->LODModelHandle );
	model = ( maliasmodel_t * )mod->extradata;

	meshnum = -mb->infokey - 1;
	if( meshnum < 0 || meshnum >= model->nummeshes )
		return;
	mesh = model->meshes + meshnum;

	frame = model->frames + e->frame;
	oldframe = model->frames + e->oldframe;
	for( i = 0; i < 3; i++ )
		move[i] = frame->translate[i] + ( oldframe->translate[i] - frame->translate[i] ) * backlerp;

	MB_NUM2SHADER( mb->shaderkey, shader );

	features = MF_NONBATCHED | shader->features;
	if( !mb->vboIndex ) {
		features &= ~MF_HARDWARE;
	}

	if( ri.params & RP_SHADOWMAPVIEW )
	{
		features &= ~( MF_COLORS|MF_SVECTORS|MF_ENABLENORMALS );
		if( !( shader->features & MF_DEFORMVS ) )
			features &= ~MF_NORMALS;
	}
	else
	{
		if( features & MF_SVECTORS )
			features |= MF_NORMALS;
#ifdef HARDWARE_OUTLINES
		if( e->outlineHeight )
			features |= MF_NORMALS|(glConfig.ext.GLSL ? MF_ENABLENORMALS : 0);
#endif
	}

	calcNormals = calcSTVectors = qfalse;
	calcNormals = ( ( features & MF_NORMALS ) != 0 ) && ( ( e->frame != 0 ) || ( e->oldframe != 0 ) );
	calcSTVectors = ( ( features & MF_SVECTORS ) != 0 ) && calcNormals;

	if( mb->vboIndex != 0 )
	{
		calcVerts = calcNormals = calcSTVectors = qfalse;
	}
	else
	{
		if( !e->frame && !e->oldframe )
		{
			calcVerts = qfalse;

			if( calcNormals )
			{
				v = mesh->vertexes;
				for( i = 0; i < mesh->numverts; i++, v++ )
					R_LatLongToNorm( v->latlong, inNormalsArray[i] );
			}
		}
		else if( e->frame == e->oldframe )
		{
			calcVerts = qtrue;

			for( i = 0; i < 3; i++ )
				frontv[i] = frame->scale[i];

			v = mesh->vertexes + e->frame * mesh->numverts;
			for( i = 0; i < mesh->numverts; i++, v++ )
			{
				Vector4Set( inVertsArray[i],
					move[0] + v->point[0]*frontv[0],
					move[1] + v->point[1]*frontv[1],
					move[2] + v->point[2]*frontv[2], 1 );

				if( calcNormals )
					R_LatLongToNorm( v->latlong, inNormalsArray[i] );
			}
		}
		else
		{
			calcVerts = qtrue;

			for( i = 0; i < 3; i++ )
			{
				backv[i] = backlerp * oldframe->scale[i];
				frontv[i] = ( 1.0f - backlerp ) * frame->scale[i];
			}

			v = mesh->vertexes + e->frame * mesh->numverts;
			ov = mesh->vertexes + e->oldframe * mesh->numverts;
			for( i = 0; i < mesh->numverts; i++, v++, ov++ )
			{
				Vector4Set( inVertsArray[i],
					move[0] + v->point[0]*frontv[0] + ov->point[0]*backv[0],
					move[1] + v->point[1]*frontv[1] + ov->point[1]*backv[1],
					move[2] + v->point[2]*frontv[2] + ov->point[2]*backv[2], 1 );

				if( calcNormals )
				{
					R_LatLongToNorm( v->latlong, normal );
					R_LatLongToNorm( ov->latlong, oldnormal );

					VectorSet( inNormalsArray[i],
						normal[0] + ( oldnormal[0] - normal[0] ) * backlerp,
						normal[1] + ( oldnormal[1] - normal[1] ) * backlerp,
						normal[2] + ( oldnormal[2] - normal[2] ) * backlerp );
				}
			}
		}

		if( calcSTVectors )
			R_BuildTangentVectors( mesh->numverts, inVertsArray, inNormalsArray, mesh->stArray, mesh->numtris, mesh->elems, inSVectorsArray );
	}

	alias_mesh.xyzArray = calcVerts ? inVertsArray : mesh->xyzArray;
	alias_mesh.elems = mesh->elems;
	alias_mesh.numElems = mesh->numtris * 3;
	alias_mesh.numVerts = mesh->numverts;

	alias_mesh.stArray = mesh->stArray;
	if( features & MF_NORMALS )
		alias_mesh.normalsArray = calcNormals ? inNormalsArray : mesh->normalsArray;
	if( features & MF_SVECTORS )
		alias_mesh.sVectorsArray = calcSTVectors ? inSVectorsArray : mesh->sVectorsArray;

	R_RotateForEntity( e );
	R_PushMesh( &alias_mesh, mb->vboIndex != 0, features );
	R_RenderMeshBuffer( mb, NULL );
}
Exemplo n.º 10
0
/*
==================
RB_RenderDrawSurfList
==================
*/
void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
	shader_t        *shader, *oldShader;
	int fogNum, oldFogNum;
	int entityNum, oldEntityNum;
	int dlighted, oldDlighted;
	qboolean depthRange, oldDepthRange, isCrosshair, wasCrosshair;
	int i;
	drawSurf_t      *drawSurf;
	int oldSort;
	float originalTime;
	int oldNumVerts, oldNumIndex;
//GR - tessellation flag
	int atiTess = 0, oldAtiTess;

	// save original time for entity shader offsets
	originalTime = backEnd.refdef.floatTime;

	// clear the z buffer, set the modelview, etc
	RB_BeginDrawingView();

	// draw everything
	oldEntityNum = -1;
	backEnd.currentEntity = &tr.worldEntity;
	oldShader = NULL;
	oldFogNum = -1;
	oldDepthRange = qfalse;
	wasCrosshair = qfalse;
	oldDlighted = qfalse;
	oldSort = -1;
	depthRange = qfalse;
// GR - tessellation also forces to draw everything
	oldAtiTess = -1;

	backEnd.pc.c_surfaces += numDrawSurfs;

	for ( i = 0, drawSurf = drawSurfs ; i < numDrawSurfs ; i++, drawSurf++ ) {
		if ( drawSurf->sort == oldSort ) {
			// fast path, same as previous sort
			oldNumVerts = tess.numVertexes;
			oldNumIndex = tess.numIndexes;

			rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );

			// RF, convert the newly created vertexes into dust particles, and overwrite
			if (backEnd.currentEntity->e.reFlags & REFLAG_ZOMBIEFX) {
				RB_ZombieFX( 0, drawSurf, oldNumVerts, oldNumIndex );
			}
			else if (backEnd.currentEntity->e.reFlags & REFLAG_ZOMBIEFX2) {
				RB_ZombieFX( 1, drawSurf, oldNumVerts, oldNumIndex );
			}
			continue;
		}
		oldSort = drawSurf->sort;
// GR - also extract tesselation flag
		R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted, &atiTess );

		//
		// change the tess parameters if needed
		// a "entityMergable" shader is a shader that can have surfaces from seperate
		// entities merged into a single batch, like smoke and blood puff sprites
		if ( shader != NULL && ( shader != oldShader || fogNum != oldFogNum || dlighted != oldDlighted
// GR - force draw on tessellation flag change
			 || ( atiTess != oldAtiTess )
			 || ( entityNum != oldEntityNum && !shader->entityMergable ) ) ){
			if ( oldShader != NULL ) {
// GR - pass tessellation flag to the shader command
//		make sure to use oldAtiTess!!!
				tess.ATI_tess = ( oldAtiTess == ATI_TESS_TRUFORM );

				RB_EndSurface();
			}
			RB_BeginSurface( shader, fogNum );
			oldShader = shader;
			oldFogNum = fogNum;
			oldDlighted = dlighted;
// GR - update old tessellation flag
			oldAtiTess = atiTess;
		}

		//
		// change the modelview matrix if needed
		//
		if ( entityNum != oldEntityNum ) {
			depthRange = isCrosshair = qfalse;

			if ( entityNum != REFENTITYNUM_WORLD ) {
				backEnd.currentEntity = &backEnd.refdef.entities[entityNum];
				backEnd.refdef.floatTime = originalTime - backEnd.currentEntity->e.shaderTime;

				// we have to reset the shaderTime as well otherwise image animations start
				// from the wrong frame
//				tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;

				// set up the transformation matrix
				R_RotateForEntity( backEnd.currentEntity, &backEnd.viewParms, &backEnd.or );

				// set up the dynamic lighting if needed
				if ( backEnd.currentEntity->needDlights ) {
					R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or );
				}

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

					if(backEnd.currentEntity->e.renderfx & RF_CROSSHAIR)
						isCrosshair = qtrue;
				}
			} else {
				backEnd.currentEntity = &tr.worldEntity;
				backEnd.refdef.floatTime = originalTime;
				backEnd.or = backEnd.viewParms.world;

				// we have to reset the shaderTime as well otherwise image animations on
				// the world (like water) continue with the wrong frame
//				tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;

				R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or );
			}

			qglLoadMatrixf( backEnd.or.modelMatrix );

			//
			// change depthrange. Also change projection matrix so first person weapon does not look like coming
			// out of the screen.
			//
			if (oldDepthRange != depthRange || wasCrosshair != isCrosshair)
			{
				if (depthRange)
				{
					if(backEnd.viewParms.stereoFrame != STEREO_CENTER)
					{
						if(isCrosshair)
						{
							if(oldDepthRange)
							{
								// was not a crosshair but now is, change back proj matrix
								qglMatrixMode(GL_PROJECTION);
								qglLoadMatrixf(backEnd.viewParms.projectionMatrix);
								qglMatrixMode(GL_MODELVIEW);
							}
						}
						else
						{
							viewParms_t temp = backEnd.viewParms;

							R_SetupProjection(&temp, r_znear->value, qfalse);

							qglMatrixMode(GL_PROJECTION);
							qglLoadMatrixf(temp.projectionMatrix);
							qglMatrixMode(GL_MODELVIEW);
						}
					}

					if(!oldDepthRange)
						qglDepthRange (0, 0.3);
				}
				else
				{
					if(!wasCrosshair && backEnd.viewParms.stereoFrame != STEREO_CENTER)
					{
						qglMatrixMode(GL_PROJECTION);
						qglLoadMatrixf(backEnd.viewParms.projectionMatrix);
						qglMatrixMode(GL_MODELVIEW);
					}
					qglDepthRange( 0, 1 );
				}

				oldDepthRange = depthRange;
				wasCrosshair = isCrosshair;
			}

			oldEntityNum = entityNum;
		}

		// RF, ZOMBIEFX, store the tess indexes, so we can grab the calculated
		// vertex positions and normals, and convert them into dust particles
		oldNumVerts = tess.numVertexes;
		oldNumIndex = tess.numIndexes;

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

		// RF, convert the newly created vertexes into dust particles, and overwrite
		if ( backEnd.currentEntity->e.reFlags & REFLAG_ZOMBIEFX ) {
			RB_ZombieFX( 0, drawSurf, oldNumVerts, oldNumIndex );
		} else if ( backEnd.currentEntity->e.reFlags & REFLAG_ZOMBIEFX2 )     {
			RB_ZombieFX( 1, drawSurf, oldNumVerts, oldNumIndex );
		}
	}

	// draw the contents of the last shader batch
	if ( oldShader != NULL ) {
// GR - pass tessellation flag to the shader command
//		make sure to use oldAtiTess!!!
		tess.ATI_tess = ( oldAtiTess == ATI_TESS_TRUFORM );

		RB_EndSurface();
	}

	// go back to the world modelview matrix
	backEnd.currentEntity = &tr.worldEntity;
	backEnd.refdef.floatTime = originalTime;
	backEnd.or = backEnd.viewParms.world;
	R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or );

	qglLoadMatrixf( backEnd.viewParms.world.modelMatrix );
	if ( depthRange ) {
		qglDepthRange( 0, 1 );
	}

	if (r_drawSun->integer) {
		RB_DrawSun(0.2, tr.sunShader);
	}

	// darken down any stencil shadows
	RB_ShadowFinish();

	// add light flares on lights that aren't obscured
	RB_RenderFlares();
}
Exemplo n.º 11
0
/*
=================
R_DrawQ3Model

Modified Dr Labmans
md3 code splitting it
up to make it easier
to add dynamic lighting code
=================
*/
void R_DrawQ3Model (entity_t *e)
{
   md3header_t      *header;
   //md3shader_t      *shader;
   md3surface_t   *surf;

/*	if (!gl_notrans.value)	// always true if not -nehahra
	{
		r_modelalpha = e->transparency;
		if (r_modelalpha == 0)
			r_modelalpha = 1.0;
	}
	else
	{
		r_modelalpha = 1.0;
	}
*/
/*************** FIXME: combine with alias model code! ***************/


   R_CalcMD3Lighting (e, e->model);

   // Get the model data
   header = (md3header_t *)Mod_Extradata (e->model);

   // locate the proper data "huh surface related"!
   surf = (md3surface_t *)((byte *)header + header->surface_offs);

   c_alias_polys += surf->num_surf_tris;

/*******JDH*******
   //get pointer to shaders
   shader = (md3shader_t *)((byte *)surf + surf->shader_offs);

	//shaders = shader[(currententity->skinnum%surf->num_surf_shaders)].texnum;
	shaders = shader[ e->skinnum % surf->num_surf_shaders ].index;

   if (shaders) {
      GL_Bind(shaders);
   } else {
      GL_Bind(0);
   }
*******JDH*******/

   glPushMatrix();

   //interpolate unless its the viewmodel
   if (gl_interpolate_animation.value && (e != &cl.viewent))
   {
      R_BlendedRotateForEntity (e);
   }
   else
   {
      R_RotateForEntity (e);
   }

   if (gl_smoothmodels.value)
      glShadeModel (GL_SMOOTH);

   if (gl_affinemodels.value)
      glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);

   R_SetupQ3AliasFrame (e->frame, header, e, gl_mtexable);
   glShadeModel (GL_FLAT);

   if (gl_affinemodels.value)
      glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

   glPopMatrix();
}
Exemplo n.º 12
0
/*
=================
R_ShadowPassDrawBrushModel
=================
*/
void R_ShadowPassDrawBrushModel( cl_entity_t *e, const plight_t *pl )
{
	Vector	mins, maxs;
	model_t	*clmodel;
	bool	rotated;

	clmodel = e->model;

	if( e->angles != g_vecZero )
	{
		for( int i = 0; i < 3; i++ )
		{
			mins[i] = e->origin[i] - clmodel->radius;
			maxs[i] = e->origin[i] + clmodel->radius;
		}
		rotated = true;
	}
	else
	{
		mins = e->origin + clmodel->mins;
		maxs = e->origin + clmodel->maxs;
		rotated = false;
	}

	if( R_CullBox( mins, maxs, RI.clipFlags ))
		return;

	if( RI.params & ( RP_SKYPORTALVIEW|RP_PORTALVIEW|RP_SCREENVIEW ))
	{
		if( rotated )
		{
			if( R_VisCullSphere( e->origin, clmodel->radius ))
				return;
		}
		else
		{
			if( R_VisCullBox( mins, maxs ))
				return;
		}
	}

	if( rotated ) R_RotateForEntity( e );
	else R_TranslateForEntity( e );

	if( rotated ) tr.modelorg = RI.objectMatrix.VectorITransform( RI.vieworg );
	else tr.modelorg = RI.vieworg - e->origin;

	// accumulate lit surfaces
	msurface_t *psurf = &clmodel->surfaces[clmodel->firstmodelsurface];
	for( int i = 0; i < clmodel->nummodelsurfaces; i++, psurf++ )
	{
		float *v;
		int k;

		if( psurf->flags & (SURF_DRAWTILED|SURF_PORTAL|SURF_REFLECT))
			continue;

		R_AddToGrassChain( psurf, pl->frustum, pl->clipflags, false );

		if( R_CullSurfaceExt( psurf, pl->frustum, 0 ))
			continue;

		// draw depth-mask on transparent textures
		if( psurf->flags & SURF_TRANSPARENT )
		{
			pglEnable( GL_ALPHA_TEST );
			pglEnable( GL_TEXTURE_2D );
			pglAlphaFunc( GL_GREATER, 0.0f );
			GL_Bind( GL_TEXTURE0, psurf->texinfo->texture->gl_texturenum );
		}

		pglBegin( GL_POLYGON );
		for( k = 0, v = psurf->polys->verts[0]; k < psurf->polys->numverts; k++, v += VERTEXSIZE )
		{
			if( psurf->flags & SURF_TRANSPARENT )
				pglTexCoord2f( v[3], v[4] );
			pglVertex3fv( v );
		}
		pglEnd();

		if( psurf->flags & SURF_TRANSPARENT )
		{
			pglDisable( GL_ALPHA_TEST );
			pglDisable( GL_TEXTURE_2D );
		}
	}

	R_LoadIdentity();	// restore worldmatrix
}
Exemplo n.º 13
0
/*
==================
RB_RenderDrawSurfList
==================
*/
void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
	shader_t		*shader;
	int				fogNum;
	qboolean		depthRange, oldDepthRange;
	int				i;
	drawSurf_t		*drawSurf;
	int				oldSort;
	const surfaceType_t	*surface;

	// clear the z buffer, set the modelview, etc
	RB_BeginDrawingView ();

	// Prepare initial values that will trigger the needed settings
	backEnd.currentModel = (sceneModel_t*)-1;
	oldDepthRange = qfalse;
	oldSort = -1;
	depthRange = qfalse;

	// Clear for endsurface first run
	tess.numIndexes = 0;

	backEnd.pc.c_surfaces += numDrawSurfs;
	if (!(backEnd.refdef->rdflags & RDF_NOWORLDMODEL)) {
		backEnd.sceneZfar = backEnd.viewParms.zFar;
	}

	for (i = 0, drawSurf = drawSurfs ; i < numDrawSurfs ; i++, drawSurf++) {
		/* Rendering a model? */
		if ( drawSurf->sort & QSORT_HAVEMODEL_MASK ) {
			const drawModel_t *drawModel;
			unsigned int index;

			RB_EndSurface();

			oldSort = drawSurf->sort;
			drawModel = (drawModel_t*) drawSurf->data;
			backEnd.currentModel = drawModel->model;
			index = R_SortToIndex( oldSort );
			surface = drawModel->surface[index];
			// set up the transformation matrix
			R_RotateForEntity( backEnd.currentModel, &backEnd.viewParms, &backEnd.or );
			R_TransformDlights( backEnd.refdef->numDlights, backEnd.refdef->dlights, &backEnd.or );
			//Load the temporary matrix to show the model
			qglLoadMatrixf( backEnd.or.modelMatrix );

			depthRange = 0;
			//figure this stuff out now and store it
			if ( backEnd.currentModel->renderfx & RF_NODEPTH ) {
				depthRange = 2;
			} else if ( backEnd.currentModel->renderfx & RF_DEPTHHACK ) {
				depthRange = 1;
			}
			if ( oldDepthRange != depthRange ) {
				oldDepthRange = depthRange;
				switch ( depthRange ) {
				default:
				case 0:
					qglDepthRange (0, 1);	
					break;
				case 1:
					qglDepthRange (0, .3);	
					break;
				case 2:
					qglDepthRange (0, 0);
					break;
				}
			}
			shader = R_SortToShader( oldSort );
			fogNum = R_SortToFog( oldSort );
			RB_BeginSurface( shader, fogNum );
			if ( mme_saveStencil->integer == 1) {
				if  ( backEnd.currentModel->renderfx & RF_STENCIL) {
					if (!backEnd.doingStencil) {
						qglStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
						backEnd.doingStencil = qtrue;
					}
				} else {
					if (backEnd.doingStencil) {
						qglStencilOp( GL_KEEP, GL_KEEP, GL_ZERO );
						backEnd.doingStencil = qfalse;
					}
				}
			}
			rb_surfaceTable[ *surface ]( surface );
			continue;
		} 
		if ( drawSurf->sort == oldSort ) {
			// fast path, same as previous sort
			rb_surfaceTable[ *((byte *)drawSurf->data) ]( drawSurf->data );
			continue;
		}
		RB_EndSurface();
		oldSort = drawSurf->sort;
		shader = R_SortToShader( oldSort );
		fogNum = R_SortToFog( oldSort );
		RB_BeginSurface( shader, fogNum );
		if ( backEnd.currentModel ) {
			if (backEnd.doingStencil) {
				qglStencilOp( GL_KEEP, GL_KEEP, GL_ZERO );
				backEnd.doingStencil = qfalse;
			}
			backEnd.currentModel = 0;
			backEnd.or = backEnd.viewParms.world;
			R_TransformDlights( backEnd.refdef->numDlights, backEnd.refdef->dlights, &backEnd.or );
			qglLoadMatrixf( backEnd.or.modelMatrix );
			if ( oldDepthRange ) {
				depthRange = 0;
				oldDepthRange = 0;
				qglDepthRange (0, 1);
			}
		}
		rb_surfaceTable[ *((byte *)drawSurf->data) ]( drawSurf->data );
		if ( mme_saveStencil->integer == 1) {
			if  (backEnd.currentModel && backEnd.currentModel->renderfx & RF_STENCIL) {
				if (!backEnd.doingStencil) {
					qglStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
					backEnd.doingStencil = qtrue;
				}
			} else {
				if (backEnd.doingStencil) {
					qglStencilOp( GL_KEEP, GL_KEEP, GL_ZERO );
					backEnd.doingStencil = qfalse;
				}
			}
		}
		// add the triangles for this surface
	}

//	if ( backEnd.currentModel && tess.numVertexes ) 
//		Com_Printf( "Shader batch for a model?\n" );
	// draw the contents of the last shader batch
	RB_EndSurface();

	// go back to the world modelview matrix
	qglLoadMatrixf( backEnd.viewParms.world.modelMatrix );
	if ( depthRange ) {
		qglDepthRange (0, 1);
	}

#if 0
	RB_DrawSun();
#endif
	// darken down any stencil shadows
	RB_ShadowFinish();		

	// add light flares on lights that aren't obscured
	RB_RenderFlares();
}
Exemplo n.º 14
0
/*
=================
R_DrawAliasModelShadow
Just draws the shadow for a model
=================
*/
void R_DrawAliasModelShadow (entity_t *e)
{
	maliasmodel_t	*paliashdr;
	vec3_t		bbox[8];
	qboolean	mirrormodel = false;

	if (!r_shadows->value)
		return;
	if (e->flags & (RF_WEAPONMODEL | RF_NOSHADOW))
		return;
	// no shadows from shells
	if ( (e->flags & (RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM))
		&& (e->flags & RF_TRANSLUCENT) )
		return;

	// also skip this for viewermodels and cameramodels
	if ( !(e->flags & RF_WEAPONMODEL || e->flags & RF_VIEWERMODEL || e->renderfx & RF2_CAMERAMODEL) )
	{
		if (R_CullAliasModel(bbox, e))
			return;
	}

	aliasShadowAlpha = R_CalcShadowAlpha(e);
	if (aliasShadowAlpha < DIV255) // out of range
		return;

	if (e->renderfx & RF2_CAMERAMODEL)
	{
		if (r_lefthand->value==1)
			mirrormodel = true;
	}
	else if (e->flags & RF_MIRRORMODEL)
		mirrormodel = true;

	paliashdr = (maliasmodel_t *)currentmodel->extradata;

	// mirroring support
//	if (mirrormodel)
//		R_FlipModel(true);

	if ( (e->frame >= paliashdr->num_frames) || (e->frame < 0) )
	{
		e->frame = 0;
		e->oldframe = 0;
	}

	if ( (e->oldframe >= paliashdr->num_frames) || (e->oldframe < 0))
	{
		e->frame = 0;
		e->oldframe = 0;
	}

	//if ( !r_lerpmodels->value )
	//	e->backlerp = 0;
	
	qglPushMatrix ();
	GL_DisableTexture(0);
	GL_Enable (GL_BLEND);
				
	if (r_shadows->value == 3) {
		e->angles[ROLL] = -e->angles[ROLL];		// roll is backwards
		R_RotateForEntity (e, true);
		e->angles[ROLL] = -e->angles[ROLL];		// roll is backwards
		R_DrawAliasVolumeShadow (paliashdr, bbox);
	}
	else {
		R_RotateForEntity (e, false);
		R_DrawAliasPlanarShadow (paliashdr);
	}

	GL_Disable (GL_BLEND);
	GL_EnableTexture(0);
	qglPopMatrix ();

	// mirroring support
//	if (mirrormodel)
//		R_FlipModel(false);
}
Exemplo n.º 15
0
/*
=================
R_DrawAliasModel

=================
*/
void R_DrawAliasModel (entity_t *e)
{
	int			i, j;
	int			lnum;
	vec3_t		dist;
	float		add;
	model_t		*clmodel;
	vec3_t		mins, maxs;
	aliashdr_t	*paliashdr;
	trivertx_t	*verts, *v;
	int			index;
	float		s, t, an;
	int			anim;

	clmodel = currententity->model;

	VectorAdd (currententity->origin, clmodel->mins, mins);
	VectorAdd (currententity->origin, clmodel->maxs, maxs);

	if (R_CullBox (mins, maxs))
		return;


	VectorCopy (currententity->origin, r_entorigin);
	VectorSubtract (r_origin, r_entorigin, modelorg);

	//
	// get lighting information
	//

	ambientlight = shadelight = R_LightPoint (currententity->origin);

	// allways give the gun some light
	if (e == &cl.viewent && ambientlight < 24)
		ambientlight = shadelight = 24;

	for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
	{
		if (cl_dlights[lnum].die >= cl.time)
		{
			VectorSubtract (currententity->origin,
							cl_dlights[lnum].origin,
							dist);
			add = cl_dlights[lnum].radius - Length(dist);

			if (add > 0) {
				ambientlight += add;
				//ZOID models should be affected by dlights as well
				shadelight += add;
			}
		}
	}

	// clamp lighting so it doesn't overbright as much
	if (ambientlight > 128)
		ambientlight = 128;
	if (ambientlight + shadelight > 192)
		shadelight = 192 - ambientlight;

	// ZOID: never allow players to go totally black
	i = currententity - cl_entities;
	if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
		if (ambientlight < 8)
			ambientlight = shadelight = 8;

	// HACK HACK HACK -- no fullbright colors, so make torches full light
	if (!strcmp (clmodel->name, "progs/flame2.mdl")
		|| !strcmp (clmodel->name, "progs/flame.mdl") )
		ambientlight = shadelight = 256;

	shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
	shadelight = shadelight / 200.0;
	
	an = e->angles[1]/180*M_PI;
	shadevector[0] = cos(-an);
	shadevector[1] = sin(-an);
	shadevector[2] = 1;
	VectorNormalize (shadevector);

	//
	// locate the proper data
	//
	paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model);

	c_alias_polys += paliashdr->numtris;

	//
	// draw all the triangles
	//

	GL_DisableMultitexture();

    glPushMatrix ();
	R_RotateForEntity (e);

	if (!strcmp (clmodel->name, "progs/eyes.mdl") && gl_doubleeyes.value) {
		glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2] - (22 + 8));
// double size of eyes, since they are really hard to see in gl
		glScalef (paliashdr->scale[0]*2, paliashdr->scale[1]*2, paliashdr->scale[2]*2);
	} else {
		glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]);
		glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]);
	}

	anim = (int)(cl.time*10) & 3;
    GL_Bind(paliashdr->gl_texturenum[currententity->skinnum][anim]);

	// we can't dynamically colormap textures, so they are cached
	// seperately for the players.  Heads are just uncolored.
	if (currententity->colormap != vid.colormap && !gl_nocolors.value)
	{
		i = currententity - cl_entities;
		if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
		    GL_Bind(playertextures - 1 + i);
	}

	if (gl_smoothmodels.value)
		glShadeModel (GL_SMOOTH);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

	if (gl_affinemodels.value)
		glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);

	R_SetupAliasFrame (currententity->frame, paliashdr);

	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

	glShadeModel (GL_FLAT);
	if (gl_affinemodels.value)
		glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

	glPopMatrix ();

	if (r_shadows.value)
	{
		glPushMatrix ();
		R_RotateForEntity (e);
		glDisable (GL_TEXTURE_2D);
		glEnable (GL_BLEND);
		glColor4f (0,0,0,0.5);
		GL_DrawAliasShadow (paliashdr, lastposenum);
		glEnable (GL_TEXTURE_2D);
		glDisable (GL_BLEND);
		glColor4f (1,1,1,1);
		glPopMatrix ();
	}

}
Exemplo n.º 16
0
/*
=================
R_DrawAliasModel -- johnfitz -- almost completely rewritten
=================
*/
void R_DrawAliasModel (entity_t *e)
{
	aliashdr_t	*paliashdr;
	int			i, anim;
	gltexture_t	*tx, *fb;
	lerpdata_t	lerpdata;

	//
	// setup pose/lerp data -- do it first so we don't miss updates due to culling
	//
	paliashdr = (aliashdr_t *)Mod_Extradata (e->model);
	R_SetupAliasFrame (paliashdr, e->frame, &lerpdata);
	R_SetupEntityTransform (e, &lerpdata);

	//
	// cull it
	//
	if (R_CullModelForEntity(e))
		return;

	//
	// transform it
	//
    glPushMatrix ();
	R_RotateForEntity (lerpdata.origin, lerpdata.angles);
	glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]);
	glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]);

	//
	// random stuff
	//
	if (gl_smoothmodels.value && !r_drawflat_cheatsafe)
		glShadeModel (GL_SMOOTH);
	if (gl_affinemodels.value)
		glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
	overbright = gl_overbright_models.value;
	shading = true;

	//
	// set up for alpha blending
	//
	if (r_drawflat_cheatsafe || r_lightmap_cheatsafe) //no alpha in drawflat or lightmap mode
		entalpha = 1;
	else
		entalpha = ENTALPHA_DECODE(e->alpha);
	if (entalpha == 0)
		goto cleanup;
	if (entalpha < 1)
	{
		if (!gl_texture_env_combine) overbright = false; //overbright can't be done in a single pass without combiners
		glDepthMask(GL_FALSE);
		glEnable(GL_BLEND);
	}

	//
	// set up lighting
	//
	rs_aliaspolys += paliashdr->numtris;
	R_SetupAliasLighting (e);

	//
	// set up textures
	//
	GL_DisableMultitexture();
	anim = (int)(cl.time*10) & 3;
	tx = paliashdr->gltextures[e->skinnum][anim];
	fb = paliashdr->fbtextures[e->skinnum][anim];
	if (e->colormap != vid.colormap && !gl_nocolors.value)
	{
		i = e - cl_entities;
		if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
		    tx = playertextures[i - 1];
	}
	if (!gl_fullbrights.value)
		fb = NULL;

	//
	// draw it
	//
	if (r_drawflat_cheatsafe)
	{
		glDisable (GL_TEXTURE_2D);
		GL_DrawAliasFrame (paliashdr, lerpdata);
		glEnable (GL_TEXTURE_2D);
		srand((int) (cl.time * 1000)); //restore randomness
	}
	else if (r_fullbright_cheatsafe)
	{
		GL_Bind (tx);
		shading = false;
		glColor4f(1,1,1,entalpha);
		GL_DrawAliasFrame (paliashdr, lerpdata);
		if (fb)
		{
			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
			GL_Bind(fb);
			glEnable(GL_BLEND);
			glBlendFunc (GL_ONE, GL_ONE);
			glDepthMask(GL_FALSE);
			glColor3f(entalpha,entalpha,entalpha);
			Fog_StartAdditive ();
			GL_DrawAliasFrame (paliashdr, lerpdata);
			Fog_StopAdditive ();
			glDepthMask(GL_TRUE);
			glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
			glDisable(GL_BLEND);
		}
	}
	else if (r_lightmap_cheatsafe)
	{
		glDisable (GL_TEXTURE_2D);
		shading = false;
		glColor3f(1,1,1);
		GL_DrawAliasFrame (paliashdr, lerpdata);
		glEnable (GL_TEXTURE_2D);
	}
	else if (overbright)
	{
		if  (gl_texture_env_combine && gl_mtexable && gl_texture_env_add && fb) //case 1: everything in one pass
		{
			GL_Bind (tx);
			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
			glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
			glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
			glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT);
			glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 2.0f);
			GL_EnableMultitexture(); // selects TEXTURE1
			GL_Bind (fb);
			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
			glEnable(GL_BLEND);
			GL_DrawAliasFrame (paliashdr, lerpdata);
			glDisable(GL_BLEND);
			GL_DisableMultitexture();
			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
		}
		else if (gl_texture_env_combine) //case 2: overbright in one pass, then fullbright pass
		{
		// first pass
			GL_Bind(tx);
			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
			glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
			glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
			glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT);
			glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 2.0f);
			GL_DrawAliasFrame (paliashdr, lerpdata);
			glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.0f);
			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
		// second pass
			if (fb)
			{
				glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
				GL_Bind(fb);
				glEnable(GL_BLEND);
				glBlendFunc (GL_ONE, GL_ONE);
				glDepthMask(GL_FALSE);
				shading = false;
				glColor3f(entalpha,entalpha,entalpha);
				Fog_StartAdditive ();
				GL_DrawAliasFrame (paliashdr, lerpdata);
				Fog_StopAdditive ();
				glDepthMask(GL_TRUE);
				glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
				glDisable(GL_BLEND);
				glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
			}
		}
		else //case 3: overbright in two passes, then fullbright pass
		{
		// first pass
			GL_Bind(tx);
			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
			GL_DrawAliasFrame (paliashdr, lerpdata);
		// second pass -- additive with black fog, to double the object colors but not the fog color
			glEnable(GL_BLEND);
			glBlendFunc (GL_ONE, GL_ONE);
			glDepthMask(GL_FALSE);
			Fog_StartAdditive ();
			GL_DrawAliasFrame (paliashdr, lerpdata);
			Fog_StopAdditive ();
			glDepthMask(GL_TRUE);
			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
			glDisable(GL_BLEND);
		// third pass
			if (fb)
			{
				glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
				GL_Bind(fb);
				glEnable(GL_BLEND);
				glBlendFunc (GL_ONE, GL_ONE);
				glDepthMask(GL_FALSE);
				shading = false;
				glColor3f(entalpha,entalpha,entalpha);
				Fog_StartAdditive ();
				GL_DrawAliasFrame (paliashdr, lerpdata);
				Fog_StopAdditive ();
				glDepthMask(GL_TRUE);
				glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
				glDisable(GL_BLEND);
				glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
			}
		}
	}
	else
	{
		if (gl_mtexable && gl_texture_env_add && fb) //case 4: fullbright mask using multitexture
		{
			GL_DisableMultitexture(); // selects TEXTURE0
			GL_Bind (tx);
			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
			GL_EnableMultitexture(); // selects TEXTURE1
			GL_Bind (fb);
			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
			glEnable(GL_BLEND);
			GL_DrawAliasFrame (paliashdr, lerpdata);
			glDisable(GL_BLEND);
			GL_DisableMultitexture();
			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
		}
		else //case 5: fullbright mask without multitexture
		{
		// first pass
			GL_Bind(tx);
			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
			GL_DrawAliasFrame (paliashdr, lerpdata);
		// second pass
			if (fb)
			{
				GL_Bind(fb);
				glEnable(GL_BLEND);
				glBlendFunc (GL_ONE, GL_ONE);
				glDepthMask(GL_FALSE);
				shading = false;
				glColor3f(entalpha,entalpha,entalpha);
				Fog_StartAdditive ();
				GL_DrawAliasFrame (paliashdr, lerpdata);
				Fog_StopAdditive ();
				glDepthMask(GL_TRUE);
				glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
				glDisable(GL_BLEND);
			}
		}
	}

cleanup:
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
	glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	glShadeModel (GL_FLAT);
	glDepthMask(GL_TRUE);
	glDisable(GL_BLEND);
	glColor3f(1,1,1);
	glPopMatrix ();
}
Exemplo n.º 17
0
/*
=================
R_GetPortalOrientation

entityNum is the entity that the portal surface is a part of, which may
be moving and rotating.

Returns qtrue if it should be mirrored
=================
*/
qboolean R_GetPortalOrientations( drawSurf_t *drawSurf, int entityNum, 
							 orientation_t *surface, orientation_t *camera,
							 vec3_t pvsOrigin, qboolean *mirror ) {
	int			i;
	cplane_t	originalPlane, plane;
	trRefEntity_t	*e;
	float		d;
	vec3_t		transformed;

	// create plane axis for the portal we are seeing
	R_PlaneForSurface( drawSurf->surface, &originalPlane );

	// rotate the plane if necessary
	if ( entityNum != TR_WORLDENT ) {
		tr.currentEntityNum = entityNum;
		tr.currentEntity = &tr.refdef.entities[entityNum];

		// get the orientation of the entity
		R_RotateForEntity( tr.currentEntity, &tr.viewParms, &tr.or );

		// rotate the plane, but keep the non-rotated version for matching
		// against the portalSurface entities
		R_LocalNormalToWorld( originalPlane.normal, plane.normal );
		plane.dist = originalPlane.dist + DotProduct( plane.normal, tr.or.origin );

		// translate the original plane
		originalPlane.dist = originalPlane.dist + DotProduct( originalPlane.normal, tr.or.origin );
	} else {
		plane = originalPlane;
	}

	VectorCopy( plane.normal, surface->axis[0] );
	PerpendicularVector( surface->axis[1], surface->axis[0] );
	CrossProduct( surface->axis[0], surface->axis[1], surface->axis[2] );

	// locate the portal entity closest to this plane.
	// origin will be the origin of the portal, origin2 will be
	// the origin of the camera
	for ( i = 0 ; i < tr.refdef.num_entities ; i++ ) {
		e = &tr.refdef.entities[i];
		if ( e->e.reType != RT_PORTALSURFACE ) {
			continue;
		}

		d = DotProduct( e->e.origin, originalPlane.normal ) - originalPlane.dist;
		if ( d > 64 || d < -64) {
			continue;
		}

		// get the pvsOrigin from the entity
		VectorCopy( e->e.oldorigin, pvsOrigin );

		// if the entity is just a mirror, don't use as a camera point
		if ( e->e.oldorigin[0] == e->e.origin[0] && 
			e->e.oldorigin[1] == e->e.origin[1] && 
			e->e.oldorigin[2] == e->e.origin[2] ) {
			VectorScale( plane.normal, plane.dist, surface->origin );
			VectorCopy( surface->origin, camera->origin );
			VectorSubtract( vec3_origin, surface->axis[0], camera->axis[0] );
			VectorCopy( surface->axis[1], camera->axis[1] );
			VectorCopy( surface->axis[2], camera->axis[2] );

			*mirror = qtrue;
			return qtrue;
		}

		// project the origin onto the surface plane to get
		// an origin point we can rotate around
		d = DotProduct( e->e.origin, plane.normal ) - plane.dist;
		VectorMA( e->e.origin, -d, surface->axis[0], surface->origin );
			
		// now get the camera origin and orientation
		VectorCopy( e->e.oldorigin, camera->origin );
		AxisCopy( e->e.axis, camera->axis );
		VectorSubtract( vec3_origin, camera->axis[0], camera->axis[0] );
		VectorSubtract( vec3_origin, camera->axis[1], camera->axis[1] );

		// optionally rotate
		if ( e->e.frame ) {
			// continuous rotate
			d = (tr.refdef.time/1000.0f) * e->e.frame;
			VectorCopy( camera->axis[1], transformed );
			RotatePointAroundVector( camera->axis[1], camera->axis[0], transformed, d );
			CrossProduct( camera->axis[0], camera->axis[1], camera->axis[2] );
		} else if (e->e.skinNum){
			// bobbing rotate
			//d = 4 * sin( tr.refdef.time * 0.003 );
			d = e->e.skinNum;
			VectorCopy( camera->axis[1], transformed );
			RotatePointAroundVector( camera->axis[1], camera->axis[0], transformed, d );
			CrossProduct( camera->axis[0], camera->axis[1], camera->axis[2] );
		}
		*mirror = qfalse;
		return qtrue;
	}

	// if we didn't locate a portal entity, don't render anything.
	// We don't want to just treat it as a mirror, because without a
	// portal entity the server won't have communicated a proper entity set
	// in the snapshot

	// unfortunately, with local movement prediction it is easily possible
	// to see a surface before the server has communicated the matching
	// portal surface entity, so we don't want to print anything here...

	//VID_Printf( PRINT_ALL, "Portal surface without a portal entity\n" );

	return qfalse;
}
Exemplo n.º 18
0
void GL_DrawAliasShadow (entity_t *e, dmdl_t *paliashdr, int posenum)
{
    dtrivertx_t	*verts;
    int		*order;
    vec3_t	point;
    float	height, lheight;
    int		count;
    daliasframe_t	*frame;

    lheight = currententity->origin[2] - lightspot[2];

    frame = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames
                              + currententity->frame * paliashdr->framesize);
    verts = frame->verts;

//	height = 0;
    order = (int *)((byte *)paliashdr + paliashdr->ofs_glcmds);
    height = -lheight + 0.1f; // was 1.0f, lowered shadows to ground more - MrG

    // Knightmare- don't draw shadow above entity
    if ((currententity->origin[2]+height) > currententity->origin[2])
        return;

    // Knightmare- don't draw shadows above view origin
    if (r_newrefdef.vieworg[2] < (currententity->origin[2] + height))
        return;

    qglPushMatrix ();
    R_RotateForEntity (e, false);
    qglDisable (GL_TEXTURE_2D);
    qglEnable (GL_BLEND);
    qglColor4f (0, 0, 0, gl_shadowalpha->value); // was 0.5

    // Knightmare- Stencil shadows by MrG
    if (gl_config.have_stencil)
    {
        qglEnable(GL_STENCIL_TEST);
        qglStencilFunc(GL_EQUAL, 1, 2);
        qglStencilOp(GL_KEEP,GL_KEEP,GL_INCR);
    }
    // End Stencil shadows - MrG

    while (1)
    {
        // get the vertex count and primitive type
        count = *order++;
        if (!count)
            break;		// done
        if (count < 0)
        {
            count = -count;
            qglBegin (GL_TRIANGLE_FAN);
        }
        else
            qglBegin (GL_TRIANGLE_STRIP);

        do
        {
            // normals and vertexes come from the frame list
            /*
            			point[0] = verts[order[2]].v[0] * frame->scale[0] + frame->translate[0];
            			point[1] = verts[order[2]].v[1] * frame->scale[1] + frame->translate[1];
            			point[2] = verts[order[2]].v[2] * frame->scale[2] + frame->translate[2];
            */

            memcpy( point, s_lerped[order[2]], sizeof( point )  );

            point[0] -= shadevector[0]*(point[2]+lheight);
            point[1] -= shadevector[1]*(point[2]+lheight);
            point[2] = height;
//			height -= 0.001;
            qglVertex3fv (point);

            order += 3;

//			verts++;

        } while (--count);

        qglEnd ();
    }

    // Knightmare- disable Stencil shadows
    if (gl_config.have_stencil)
        qglDisable(GL_STENCIL_TEST);

    qglColor4f (1,1,1,1);
    qglEnable (GL_TEXTURE_2D);
    qglDisable (GL_BLEND);
    qglPopMatrix ();
}
Exemplo n.º 19
0
/*
==================
RB_RenderDrawSurfList
==================
*/
void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
	shader_t		*shader, *oldShader;
	int				fogNum, oldFogNum;
	int				entityNum, oldEntityNum;
	int				dlighted, oldDlighted;
	qboolean		depthRange, oldDepthRange, isCrosshair, wasCrosshair;
	int				i;
	drawSurf_t		*drawSurf;
	int				oldSort;
	float			originalTime;

	// save original time for entity shader offsets
	originalTime = backEnd.refdef.floatTime;

	// clear the z buffer, set the modelview, etc
	RB_BeginDrawingView ();

	// draw everything
	oldEntityNum = -1;
	backEnd.currentEntity = &tr.worldEntity;
	oldShader = NULL;
	oldFogNum = -1;
	oldDepthRange = qfalse;
	wasCrosshair = qfalse;
	oldDlighted = qfalse;
	oldSort = -1;
	depthRange = qfalse;

	backEnd.pc.c_surfaces += numDrawSurfs;

	for (i = 0, drawSurf = drawSurfs ; i < numDrawSurfs ; i++, drawSurf++) {
		if ( drawSurf->sort == oldSort ) {
			// fast path, same as previous sort
			rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
			continue;
		}
		oldSort = drawSurf->sort;
		R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted );

		//
		// change the tess parameters if needed
		// a "entityMergable" shader is a shader that can have surfaces from seperate
		// entities merged into a single batch, like smoke and blood puff sprites
		if (shader != oldShader || fogNum != oldFogNum || dlighted != oldDlighted 
			|| ( entityNum != oldEntityNum && !shader->entityMergable ) ) {
			if (oldShader != NULL) {
				RB_EndSurface();
			}
			RB_BeginSurface( shader, fogNum );
			oldShader = shader;
			oldFogNum = fogNum;
			oldDlighted = dlighted;
		}

		//
		// change the modelview matrix if needed
		//
		if ( entityNum != oldEntityNum ) {
			depthRange = isCrosshair = qfalse;

			if ( entityNum != ENTITYNUM_WORLD ) {
				backEnd.currentEntity = &backEnd.refdef.entities[entityNum];
				backEnd.refdef.floatTime = originalTime - backEnd.currentEntity->e.shaderTime;
				// we have to reset the shaderTime as well otherwise image animations start
				// from the wrong frame
				tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;

				// set up the transformation matrix
				R_RotateForEntity( backEnd.currentEntity, &backEnd.viewParms, &backEnd.or );

				// set up the dynamic lighting if needed
				if ( backEnd.currentEntity->needDlights ) {
					R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or );
				}

				if(backEnd.currentEntity->e.renderfx & RF_DEPTHHACK)
				{
					// hack the depth range to prevent view model from poking into walls
					depthRange = qtrue;
					
					if(backEnd.currentEntity->e.renderfx & RF_CROSSHAIR)
						isCrosshair = qtrue;
				}
			} else {
				backEnd.currentEntity = &tr.worldEntity;
				backEnd.refdef.floatTime = originalTime;
				backEnd.or = backEnd.viewParms.world;
				// we have to reset the shaderTime as well otherwise image animations on
				// the world (like water) continue with the wrong frame
				tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
				R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or );
			}

			qglLoadMatrixf( backEnd.or.modelMatrix );

			//
			// change depthrange. Also change projection matrix so first person weapon does not look like coming
			// out of the screen.
			//
			if (oldDepthRange != depthRange || wasCrosshair != isCrosshair)
			{
				if (depthRange)
				{
					if(backEnd.viewParms.stereoFrame != STEREO_CENTER)
					{
						if(isCrosshair)
						{
							if(oldDepthRange)
							{
								// was not a crosshair but now is, change back proj matrix
								qglMatrixMode(GL_PROJECTION);
								qglLoadMatrixf(backEnd.viewParms.projectionMatrix);
								qglMatrixMode(GL_MODELVIEW);
							}
						}
						else
						{
							viewParms_t temp = backEnd.viewParms;

							R_SetupProjection(&temp, r_znear->value, qfalse);

							qglMatrixMode(GL_PROJECTION);
							qglLoadMatrixf(temp.projectionMatrix);
							qglMatrixMode(GL_MODELVIEW);
						}
					}

					if(!oldDepthRange)
						qglDepthRange (0, 0.3);
				}
				else
				{
					if(!wasCrosshair && backEnd.viewParms.stereoFrame != STEREO_CENTER)
					{
						qglMatrixMode(GL_PROJECTION);
						qglLoadMatrixf(backEnd.viewParms.projectionMatrix);
						qglMatrixMode(GL_MODELVIEW);
					}

					qglDepthRange (0, 1);
				}

				oldDepthRange = depthRange;
				wasCrosshair = isCrosshair;
			}

			oldEntityNum = entityNum;
		}

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

	backEnd.refdef.floatTime = originalTime;

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

	// go back to the world modelview matrix
	qglLoadMatrixf( backEnd.viewParms.world.modelMatrix );
	if ( depthRange ) {
		qglDepthRange (0, 1);
	}

#if 0
	RB_DrawSun();
#endif
	// darken down any stencil shadows
	RB_ShadowFinish();		

	// add light flares on lights that aren't obscured
	RB_RenderFlares();
}
Exemplo n.º 20
0
/*
=================
R_DrawAliasModel

=================
*/
void R_DrawAliasModel (entity_t *e)
{
    int			i;
    dmdl_t		*paliashdr;
    float		an;
    vec3_t		bbox[8];
    image_t		*skin;

    if ( !( e->flags & RF_WEAPONMODEL ) )
    {
        if ( R_CullAliasModel( bbox, e ) )
            return;
    }

    if ( e->flags & RF_WEAPONMODEL )
    {
        if ( r_lefthand->value == 2 )
            return;
    }

    paliashdr = (dmdl_t *)currentmodel->extradata;

    //
    // get lighting information
    //
    // PMM - rewrote, reordered to handle new shells & mixing
    // PMM - 3.20 code .. replaced with original way of doing it to keep mod authors happy
    //
    if ( currententity->flags & ( RF_SHELL_HALF_DAM | RF_SHELL_GREEN | RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_DOUBLE ) )
    {
        VectorClear (shadelight);
        if (currententity->flags & RF_SHELL_HALF_DAM)
        {
            shadelight[0] = 0.56;
            shadelight[1] = 0.59;
            shadelight[2] = 0.45;
        }
        if ( currententity->flags & RF_SHELL_DOUBLE )
        {
            shadelight[0] = 0.9;
            shadelight[1] = 0.7;
        }
        if ( currententity->flags & RF_SHELL_RED )
            shadelight[0] = 1.0;
        if ( currententity->flags & RF_SHELL_GREEN )
            shadelight[1] = 1.0;
        if ( currententity->flags & RF_SHELL_BLUE )
            shadelight[2] = 1.0;
    }
    /*
    		// PMM -special case for godmode
    		if ( (currententity->flags & RF_SHELL_RED) &&
    			(currententity->flags & RF_SHELL_BLUE) &&
    			(currententity->flags & RF_SHELL_GREEN) )
    		{
    			for (i=0 ; i<3 ; i++)
    				shadelight[i] = 1.0;
    		}
    		else if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_DOUBLE ) )
    		{
    			VectorClear (shadelight);

    			if ( currententity->flags & RF_SHELL_RED )
    			{
    				shadelight[0] = 1.0;
    				if (currententity->flags & (RF_SHELL_BLUE|RF_SHELL_DOUBLE) )
    					shadelight[2] = 1.0;
    			}
    			else if ( currententity->flags & RF_SHELL_BLUE )
    			{
    				if ( currententity->flags & RF_SHELL_DOUBLE )
    				{
    					shadelight[1] = 1.0;
    					shadelight[2] = 1.0;
    				}
    				else
    				{
    					shadelight[2] = 1.0;
    				}
    			}
    			else if ( currententity->flags & RF_SHELL_DOUBLE )
    			{
    				shadelight[0] = 0.9;
    				shadelight[1] = 0.7;
    			}
    		}
    		else if ( currententity->flags & ( RF_SHELL_HALF_DAM | RF_SHELL_GREEN ) )
    		{
    			VectorClear (shadelight);
    			// PMM - new colors
    			if ( currententity->flags & RF_SHELL_HALF_DAM )
    			{
    				shadelight[0] = 0.56;
    				shadelight[1] = 0.59;
    				shadelight[2] = 0.45;
    			}
    			if ( currententity->flags & RF_SHELL_GREEN )
    			{
    				shadelight[1] = 1.0;
    			}
    		}
    	}
    			//PMM - ok, now flatten these down to range from 0 to 1.0.
    	//		max_shell_val = max(shadelight[0], max(shadelight[1], shadelight[2]));
    	//		if (max_shell_val > 0)
    	//		{
    	//			for (i=0; i<3; i++)
    	//			{
    	//				shadelight[i] = shadelight[i] / max_shell_val;
    	//			}
    	//		}
    	// pmm
    */
    else if ( currententity->flags & RF_FULLBRIGHT )
    {
        for (i=0 ; i<3 ; i++)
            shadelight[i] = 1.0;
    }
    else
    {
        R_LightPoint (currententity->origin, shadelight);

        // player lighting hack for communication back to server
        // big hack!
        if ( currententity->flags & RF_WEAPONMODEL )
        {
            // pick the greatest component, which should be the same
            // as the mono value returned by software
            if (shadelight[0] > shadelight[1])
            {
                if (shadelight[0] > shadelight[2])
                    r_lightlevel->value = 150*shadelight[0];
                else
                    r_lightlevel->value = 150*shadelight[2];
            }
            else
            {
                if (shadelight[1] > shadelight[2])
                    r_lightlevel->value = 150*shadelight[1];
                else
                    r_lightlevel->value = 150*shadelight[2];
            }

        }

        if ( gl_monolightmap->string[0] != '0' )
        {
            float s = shadelight[0];

            if ( s < shadelight[1] )
                s = shadelight[1];
            if ( s < shadelight[2] )
                s = shadelight[2];

            shadelight[0] = s;
            shadelight[1] = s;
            shadelight[2] = s;
        }
    }

    if ( currententity->flags & RF_MINLIGHT )
    {
        for (i=0 ; i<3 ; i++)
            if (shadelight[i] > 0.1)
                break;
        if (i == 3)
        {
            shadelight[0] = 0.1;
            shadelight[1] = 0.1;
            shadelight[2] = 0.1;
        }
    }

    if ( currententity->flags & RF_GLOW )
    {   // bonus items will pulse with time
        float	scale;
        float	min;

        scale = 0.1 * sin(r_newrefdef.time*7);
        for (i=0 ; i<3 ; i++)
        {
            min = shadelight[i] * 0.8;
            shadelight[i] += scale;
            if (shadelight[i] < min)
                shadelight[i] = min;
        }
    }

// =================
// PGM	ir goggles color override
    if ( r_newrefdef.rdflags & RDF_IRGOGGLES && currententity->flags & RF_IR_VISIBLE)
    {
        shadelight[0] = 1.0;
        shadelight[1] = 0.0;
        shadelight[2] = 0.0;
    }
// PGM
// =================

    shadedots = r_avertexnormal_dots[((int)(currententity->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];

    an = currententity->angles[1]/180*M_PI;
    shadevector[0] = cos(-an);
    shadevector[1] = sin(-an);
    shadevector[2] = 1;
    VectorNormalize (shadevector);

    //
    // locate the proper data
    //

    c_alias_polys += paliashdr->num_tris;

    //
    // draw all the triangles
    //
    if (currententity->flags & RF_DEPTHHACK) // hack the depth range to prevent view model from poking into walls
        qglDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));

    if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) )
    {
        extern void MYgluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar );

        qglMatrixMode( GL_PROJECTION );
        qglPushMatrix();
        qglLoadIdentity();
        qglScalef( -1, 1, 1 );
        MYgluPerspective( r_newrefdef.fov_y, ( float ) r_newrefdef.width / r_newrefdef.height,  4,  4096);
        qglMatrixMode( GL_MODELVIEW );

        qglCullFace( GL_BACK );
    }

    qglPushMatrix ();
    e->angles[PITCH] = -e->angles[PITCH];				// sigh.
    e->angles[ROLL] = e->angles[ROLL] * R_RollMult();	// Knightmare- roll is backwards
    R_RotateForEntity (e, true);
    e->angles[PITCH] = -e->angles[PITCH];				// sigh.
    e->angles[ROLL] = e->angles[ROLL] * R_RollMult();	// Knightmare- roll is backwards

    // select skin
    if (currententity->skin)
        skin = currententity->skin;	// custom player skin
    else
    {
        if (currententity->skinnum >= MAX_MD2SKINS)
            skin = currentmodel->skins[0];
        else
        {
            skin = currentmodel->skins[currententity->skinnum];
            if (!skin)
                skin = currentmodel->skins[0];
        }
    }
    if (!skin)
        skin = r_notexture;	// fallback...
    GL_Bind(skin->texnum);

    // draw it

    qglShadeModel (GL_SMOOTH);

    GL_TexEnv( GL_MODULATE );
    if ( currententity->flags & RF_TRANSLUCENT )
    {
        qglEnable (GL_BLEND);
    }


    if ( (currententity->frame >= paliashdr->num_frames)
            || (currententity->frame < 0) )
    {
        ri.Con_Printf (PRINT_ALL, "R_DrawAliasModel %s: no such frame %d\n",
                       currentmodel->name, currententity->frame);
        currententity->frame = 0;
        currententity->oldframe = 0;
    }

    if ( (currententity->oldframe >= paliashdr->num_frames)
            || (currententity->oldframe < 0))
    {
        ri.Con_Printf (PRINT_ALL, "R_DrawAliasModel %s: no such oldframe %d\n",
                       currentmodel->name, currententity->oldframe);
        currententity->frame = 0;
        currententity->oldframe = 0;
    }

    if ( !r_lerpmodels->value )
        currententity->backlerp = 0;
    GL_DrawAliasFrameLerp (paliashdr, currententity->backlerp);

    GL_TexEnv( GL_REPLACE );
    qglShadeModel (GL_FLAT);

    qglPopMatrix ();

//#if 1
    if (gl_showbbox->value)	// Knightmare- show bbox option
    {
        qglColor4f (1.0f, 1.0f, 1.0f, 1.0f);
        qglDisable( GL_CULL_FACE );
        qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
        qglDisable( GL_TEXTURE_2D );
        /*	qglBegin( GL_TRIANGLE_STRIP );
        	for ( i = 0; i < 8; i++ )
        	{
        		qglVertex3fv( bbox[i] );
        	}
        	qglEnd();*/
        qglBegin( GL_QUADS );

        qglVertex3fv( bbox[0] );
        qglVertex3fv( bbox[1] );
        qglVertex3fv( bbox[3] );
        qglVertex3fv( bbox[2] );

        qglVertex3fv( bbox[4] );
        qglVertex3fv( bbox[5] );
        qglVertex3fv( bbox[7] );
        qglVertex3fv( bbox[6] );

        qglVertex3fv( bbox[0] );
        qglVertex3fv( bbox[1] );
        qglVertex3fv( bbox[5] );
        qglVertex3fv( bbox[4] );

        qglVertex3fv( bbox[2] );
        qglVertex3fv( bbox[3] );
        qglVertex3fv( bbox[7] );
        qglVertex3fv( bbox[6] );

        qglEnd();

        qglEnable( GL_TEXTURE_2D );
        qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
        qglEnable( GL_CULL_FACE );
    }
//#endif

    if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) )
    {
        qglMatrixMode( GL_PROJECTION );
        qglPopMatrix();
        qglMatrixMode( GL_MODELVIEW );
        qglCullFace( GL_FRONT );
    }

    if ( currententity->flags & RF_TRANSLUCENT )
    {
        qglDisable (GL_BLEND);
    }

    if (currententity->flags & RF_DEPTHHACK)
        qglDepthRange (gldepthmin, gldepthmax);

    if (gl_shadows->value && !(currententity->flags & (RF_TRANSLUCENT | RF_WEAPONMODEL)))
    {
        //	qglPushMatrix ();
        //	R_RotateForEntity (e, false);
        //	qglDisable (GL_TEXTURE_2D);
        //	qglEnable (GL_BLEND);
        //	qglColor4f (0, 0, 0, gl_shadowalpha->value); // was 0.5

        GL_DrawAliasShadow (e, paliashdr, currententity->frame );

        //	qglEnable (GL_TEXTURE_2D);
        //	qglDisable (GL_BLEND);
        //	qglPopMatrix ();
    }
    qglColor4f (1,1,1,1);
}
Exemplo n.º 21
0
/*
 * RB_RenderDrawSurfList
 */
void
RB_RenderDrawSurfList(drawSurf_t *drawSurfs, int numDrawSurfs)
{
	material_t	*shader, *oldShader;
	int		fogNum, oldFogNum;
	int		entityNum, oldEntityNum;
	int		dlighted, oldDlighted;
	int		pshadowed, oldPshadowed;
	qbool		depthRange, oldDepthRange, isCrosshair, wasCrosshair;
	int		i;
	drawSurf_t              *drawSurf;
	int		oldSort;
	float		originalTime;
	float		depth[2];
	FBO_t		* fbo	= NULL;
	qbool		inQuery = qfalse;

	/* save original time for entity shader offsets */
	originalTime = backEnd.refdef.floatTime;

	/* clear the z buffer, set the modelview, etc */
	RB_BeginDrawingView ();

	fbo = glState.currentFBO;

	/* draw everything */
	oldEntityNum = -1;
	backEnd.currentEntity = &tr.worldEntity;
	oldShader = NULL;
	oldFogNum = -1;
	oldDepthRange	= qfalse;
	wasCrosshair	= qfalse;
	oldDlighted	= qfalse;
	oldPshadowed	= qfalse;
	oldSort = -1;
	depthRange = qfalse;
	depth[0] = 0.f;
	depth[1] = 1.f;

	backEnd.pc.c_surfaces += numDrawSurfs;

	for(i = 0, drawSurf = drawSurfs; i < numDrawSurfs; i++, drawSurf++){
		if(drawSurf->sort == oldSort){
			/* fast path, same as previous sort */
			rb_surfaceTable[ *drawSurf->surface ](drawSurf->surface);
			continue;
		}
		oldSort = drawSurf->sort;
		R_DecomposeSort(drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed);

		/*
		 * change the tess parameters if needed
		 * a "entityMergable" shader is a shader that can have surfaces from seperate
		 * entities merged into a single batch, like smoke and blood puff sprites */
		if(shader != oldShader || fogNum != oldFogNum || dlighted != oldDlighted || pshadowed !=
		   oldPshadowed
		   || (entityNum != oldEntityNum && !shader->entityMergable)){
			if(oldShader != NULL){
				RB_EndSurface();
			}
			RB_BeginSurface(shader, fogNum);
			backEnd.pc.c_surfBatches++;
			oldShader = shader;
			oldFogNum = fogNum;
			oldDlighted = dlighted;
			oldPshadowed = pshadowed;
		}

		/*
		 * change the modelview matrix if needed
		 *  */
		if(entityNum != oldEntityNum){
			qbool sunflare = qfalse;
			depthRange = isCrosshair = qfalse;

#ifdef REACTION
			/* if we were rendering to a FBO and the previous entity was a sunflare
			 * and the current one isn't, switch back to the main fbo */
			if(oldEntityNum != -1 && fbo &&
			   RF_SUNFLARE == (backEnd.refdef.entities[oldEntityNum].e.renderfx & RF_SUNFLARE) &&
			   0 == (backEnd.refdef.entities[entityNum].e.renderfx & RF_SUNFLARE)){
				if(inQuery){
					inQuery = qfalse;
					qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
				}
				FBO_Bind(fbo);
				qglDepthRange(depth[0], depth[1]);
			}
#endif

			if(entityNum != ENTITYNUM_WORLD){
				backEnd.currentEntity = &backEnd.refdef.entities[entityNum];
				backEnd.refdef.floatTime = originalTime - backEnd.currentEntity->e.shaderTime;
				/* we have to reset the shaderTime as well otherwise image animations start
				 * from the wrong frame */
				tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;

				/* set up the transformation matrix */
				R_RotateForEntity(backEnd.currentEntity, &backEnd.viewParms, &backEnd.or);

				/* set up the dynamic lighting if needed */
				if(backEnd.currentEntity->needDlights){
					R_TransformDlights(backEnd.refdef.num_dlights, backEnd.refdef.dlights,
						&backEnd.or);
				}

#ifdef REACTION
				/* if the current entity is a sunflare */
				if(backEnd.currentEntity->e.renderfx & RF_SUNFLARE){
					/* if we're rendering to a fbo */
					if(fbo){
						copyv3(backEnd.currentEntity->e.origin,
							backEnd.sunFlarePos);
						/* switch FBO */
						FBO_Bind(tr.godRaysFbo);

						qglClearColor(0.0f, 0.0f, 0.0f, 1.0f);
						qglClear(GL_COLOR_BUFFER_BIT);

						qglDepthRange(1.f, 1.f);
						if(glRefConfig.occlusionQuery && !inQuery &&
						   !backEnd.hasSunFlare){
							inQuery = qtrue;
							tr.sunFlareQueryActive[tr.sunFlareQueryIndex] = qtrue;
							qglBeginQueryARB(
								GL_SAMPLES_PASSED_ARB,
								tr.sunFlareQuery[tr.sunFlareQueryIndex]);
						}
						/* backEnd.hasSunFlare = qtrue; */
						sunflare = qtrue;
					}else{
						depthRange = qtrue;
					}
				}
#endif

				if(backEnd.currentEntity->e.renderfx & RF_DEPTHHACK){
					/* hack the depth range to prevent view model from poking into walls */
					depthRange = qtrue;

					if(backEnd.currentEntity->e.renderfx & RF_CROSSHAIR)
						isCrosshair = qtrue;
				}
			}else{
				backEnd.currentEntity = &tr.worldEntity;
				backEnd.refdef.floatTime = originalTime;
				backEnd.or = backEnd.viewParms.world;
				/* we have to reset the shaderTime as well otherwise image animations on
				 * the world (like water) continue with the wrong frame */
				tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
				R_TransformDlights(backEnd.refdef.num_dlights, backEnd.refdef.dlights,
					&backEnd.or);
			}

			GL_SetModelviewMatrix(backEnd.or.modelMatrix);

			/*
			 * change depthrange. Also change projection matrix so first person weapon does not look like coming
			 * out of the screen.
			 *  */
			if(oldDepthRange != depthRange || wasCrosshair != isCrosshair){
				if(depthRange){
					if(backEnd.viewParms.stereoFrame != STEREO_CENTER){
						if(isCrosshair){
							if(oldDepthRange){
								/* was not a crosshair but now is, change back proj matrix */
								GL_SetProjectionMatrix(
									backEnd.viewParms.projectionMatrix);
							}
						}else{
							viewParms_t temp = backEnd.viewParms;

							R_SetupProjection(&temp, r_znear->value, 0, qfalse);

							GL_SetProjectionMatrix(temp.projectionMatrix);
						}
					}

#ifdef REACTION
					if(!oldDepthRange){
						depth[0] = 0;
						depth[1] = 0.3f;
						qglDepthRange (0, 0.3);
					}
#endif
				}else{
					if(!wasCrosshair && backEnd.viewParms.stereoFrame != STEREO_CENTER){
						GL_SetProjectionMatrix(backEnd.viewParms.projectionMatrix);
					}

					if(!sunflare)
						qglDepthRange (0, 1);
					depth[0] = 0;
					depth[1] = 1;
				}

				oldDepthRange	= depthRange;
				wasCrosshair	= isCrosshair;
			}

			oldEntityNum = entityNum;
		}

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

	backEnd.refdef.floatTime = originalTime;

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

	if(inQuery){
		inQuery = qfalse;
		qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
	}
	FBO_Bind(fbo);

	/* go back to the world modelview matrix */

	GL_SetModelviewMatrix(backEnd.viewParms.world.modelMatrix);
	/* if ( depthRange ) { */
	qglDepthRange (0, 1);
	/* } */

#if 0
	RB_DrawSun();
#endif
	/* darken down any stencil shadows */
	RB_ShadowFinish();

	/* add light flares on lights that aren't obscured */
	RB_RenderFlares();

	if(glRefConfig.framebufferObject)
		FBO_Bind(NULL);
}
Exemplo n.º 22
0
/*
==================
RB_RenderDrawSurfList
==================
*/
void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs )
{
	shader_t		*shader, *oldShader;
	int				fogNum, oldFogNum;
	int				entityNum, oldEntityNum;
	int				dlighted, oldDlighted;
	qboolean		depthRange, oldDepthRange;
	int				i;
	drawSurf_t		*drawSurf;
	unsigned int	oldSort;
	float			originalTime;

	// save original time for entity shader offsets
	originalTime = backEnd.refdef.floatTime;

	// clear the z buffer, set the modelview, etc
	RB_BeginDrawingView ();

	// draw everything
	oldEntityNum = -1;
	backEnd.currentEntity = &tr.worldEntity;
	oldShader = NULL;
	oldFogNum = -1;
	oldDepthRange = qfalse;
	oldDlighted = qfalse;
	oldSort = (unsigned int)~0;
	depthRange = qfalse;

	backEnd.pc.c_surfaces += numDrawSurfs;

	for( i = 0, drawSurf = drawSurfs ; i < numDrawSurfs ; i++, drawSurf++ )
	{
		if ( drawSurf->sort == (unsigned int)oldSort ) {
			// fast path, same as previous sort
			rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
			continue;
		}
		oldSort = drawSurf->sort;
		R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted );

		//
		// change the tess parameters if needed
		// a "entityMergable" shader is a shader that can have surfaces from seperate
		// entities merged into a single batch, like smoke and blood puff sprites
		if (shader != oldShader || fogNum != oldFogNum || dlighted != oldDlighted 
			|| ( entityNum != oldEntityNum && !shader->entityMergable ) ) {
			if (oldShader != NULL) {
				RB_EndSurface();
			}
			RB_BeginSurface( shader, fogNum, GL_TRIANGLES );
			oldShader = shader;
			oldFogNum = fogNum;
			oldDlighted = dlighted;
		}

		//
		// change the modelview matrix if needed
		//
		if ( entityNum != oldEntityNum ) {
			depthRange = qfalse;

			if ( entityNum != ENTITYNUM_WORLD ) {
				backEnd.currentEntity = &backEnd.refdef.entities[entityNum];
				backEnd.refdef.floatTime = originalTime - backEnd.currentEntity->e.shaderTime;
				// we have to reset the shaderTime as well otherwise image animations start
				// from the wrong frame
				tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;

				// set up the transformation matrix
				R_RotateForEntity( backEnd.currentEntity, &backEnd.viewParms, &backEnd.or );

				// set up the dynamic lighting if needed
				if ( backEnd.currentEntity->needDlights ) {
					R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or );
				}

				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.refdef.floatTime = originalTime;
				backEnd.or = backEnd.viewParms.world;
				// we have to reset the shaderTime as well otherwise image animations on
				// the world (like water) continue with the wrong frame
				tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
				R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or );
			}

			R_StateSetModelViewMatrixCountedRaw( backEnd.or.modelMatrix );

			//
			// change depthrange if needed
			//
			if( oldDepthRange != depthRange )
			{
				R_StateSetDefaultDepthRange( 0, depthRange ? 0.3F : 1.0F );
				oldDepthRange = depthRange;
			}

			oldEntityNum = entityNum;
		}

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

	backEnd.refdef.floatTime = originalTime;

	// draw the contents of the last shader batch
	if( oldShader )
		RB_EndSurface();

	// go back to the world modelview matrix
	R_StateSetModelViewMatrixCountedRaw( backEnd.viewParms.world.modelMatrix );
	if( depthRange )
		R_StateSetDefaultDepthRange( 0, 1 );

#if 0
	RB_DrawSun();
#endif
	// darken down any stencil shadows
	RB_ShadowFinish();		

	// add light flares on lights that aren't obscured
	RB_RenderFlares();
}