diff options
| -rw-r--r-- | code/renderer/tr_flares.c | 124 | ||||
| -rw-r--r-- | code/renderer/tr_init.c | 2 | ||||
| -rw-r--r-- | code/renderer/tr_local.h | 3 | ||||
| -rw-r--r-- | code/renderer/tr_shader.c | 11 | ||||
| -rw-r--r-- | code/renderer/tr_surface.c | 67 | 
5 files changed, 121 insertions, 86 deletions
diff --git a/code/renderer/tr_flares.c b/code/renderer/tr_flares.c index 65fb2ba..51181c0 100644 --- a/code/renderer/tr_flares.c +++ b/code/renderer/tr_flares.c @@ -75,6 +75,7 @@ typedef struct flare_s {  	int			windowX, windowY;  	float		eyeZ; +	vec3_t		origin;  	vec3_t		color;  } flare_t; @@ -83,6 +84,8 @@ typedef struct flare_s {  flare_t		r_flareStructs[MAX_FLARES];  flare_t		*r_activeFlares, *r_inactiveFlares; +int flareCoeff; +  /*  ==================  R_ClearFlares @@ -113,11 +116,22 @@ void RB_AddFlare( void *surface, int fogNum, vec3_t point, vec3_t color, vec3_t  	int				i;  	flare_t			*f, *oldest;  	vec3_t			local; -	float			d; +	float			d = 1;  	vec4_t			eye, clip, normalized, window;  	backEnd.pc.c_flareAdds++; +	if(normal && (normal[0] || normal[1] || normal[2])) +	{ +		VectorSubtract( backEnd.viewParms.or.origin, point, local ); +		VectorNormalizeFast(local); +		d = DotProduct(local, normal); + +		// If the viewer is behind the flare don't add it. +		if(d < 0) +			return; +	} +  	// if the point is off the screen, don't bother adding it  	// calculate screen coordinates and depth  	R_TransformModelToClip( point, backEnd.or.modelMatrix,  @@ -171,16 +185,12 @@ void RB_AddFlare( void *surface, int fogNum, vec3_t point, vec3_t color, vec3_t  	f->addedFrame = backEnd.viewParms.frameCount;  	f->fogNum = fogNum; +	VectorCopy(point, f->origin);  	VectorCopy( color, f->color );  	// fade the intensity of the flare down as the  	// light surface turns away from the viewer -	if ( normal ) { -		VectorSubtract( backEnd.viewParms.or.origin, point, local ); -		VectorNormalizeFast( local ); -		d = DotProduct( local, normal ); -		VectorScale( f->color, d, f->color );  -	} +	VectorScale( f->color, d, f->color );   	// save info needed to test  	f->windowX = backEnd.viewParms.viewportX + window[0]; @@ -197,31 +207,39 @@ RB_AddDlightFlares  void RB_AddDlightFlares( void ) {  	dlight_t		*l;  	int				i, j, k; -	fog_t			*fog; +	fog_t			*fog = NULL;  	if ( !r_flares->integer ) {  		return;  	}  	l = backEnd.refdef.dlights; -	fog = tr.world->fogs; + +	if(tr.world) +		fog = tr.world->fogs; +  	for (i=0 ; i<backEnd.refdef.num_dlights ; i++, l++) { -		// find which fog volume the light is in  -		for ( j = 1 ; j < tr.world->numfogs ; j++ ) { -			fog = &tr.world->fogs[j]; -			for ( k = 0 ; k < 3 ; k++ ) { -				if ( l->origin[k] < fog->bounds[0][k] || l->origin[k] > fog->bounds[1][k] ) { +		if(fog) +		{ +			// find which fog volume the light is in  +			for ( j = 1 ; j < tr.world->numfogs ; j++ ) { +				fog = &tr.world->fogs[j]; +				for ( k = 0 ; k < 3 ; k++ ) { +					if ( l->origin[k] < fog->bounds[0][k] || l->origin[k] > fog->bounds[1][k] ) { +						break; +					} +				} +				if ( k == 3 ) {  					break;  				}  			} -			if ( k == 3 ) { -				break; +			if ( j == tr.world->numfogs ) { +				j = 0;  			}  		} -		if ( j == tr.world->numfogs ) { +		else  			j = 0; -		}  		RB_AddFlare( (void *)l, j, l->origin, l->color, NULL );  	} @@ -294,16 +312,61 @@ void RB_RenderFlare( flare_t *f ) {  	float			size;  	vec3_t			color;  	int				iColor[3]; +	float distance, intensity, factor; +	byte fogFactors[3] = {255, 255, 255};  	backEnd.pc.c_flareRenders++; -	VectorScale( f->color, f->drawIntensity*tr.identityLight, color ); -	iColor[0] = color[0] * 255; -	iColor[1] = color[1] * 255; -	iColor[2] = color[2] * 255; +	// We don't want too big values anyways when dividing by distance. +	if(f->eyeZ > -1.0f) +		distance = 1.0f; +	else +		distance = -f->eyeZ; + +	// calculate the flare size.. +	size = backEnd.viewParms.viewportWidth * ( r_flareSize->value/640.0f + 8 / distance ); + +/* + * This is an alternative to intensity scaling. It changes the size of the flare on screen instead + * with growing distance. See in the description at the top why this is not the way to go. +	// size will change ~ 1/r. +	size = backEnd.viewParms.viewportWidth * (r_flareSize->value / (distance * -2.0f)); +*/ -	size = backEnd.viewParms.viewportWidth * ( r_flareSize->value/640.0f + 8 / -f->eyeZ ); +/* + * As flare sizes stay nearly constant with increasing distance we must decrease the intensity + * to achieve a reasonable visual result. The intensity is ~ (size^2 / distance^2) which can be + * got by considering the ratio of + * (flaresurface on screen) : (Surface of sphere defined by flare origin and distance from flare) + * An important requirement is: + * intensity <= 1 for all distances. + * + * The formula used here to compute the intensity is as follows: + * intensity = flareCoeff * size^2 / (distance + size*sqrt(flareCoeff))^2 + * As you can see, the intensity will have a max. of 1 when the distance is 0. + * The coefficient flareCoeff will determine the falloff speed with increasing distance. + */ + +	factor = distance + size * sqrt(flareCoeff); +	 +	intensity = flareCoeff * size * size / (factor * factor); + +	VectorScale(f->color, f->drawIntensity * tr.identityLight * intensity, color); + +// Calculations for fogging +	if(f->fogNum) +	{ +		tess.numVertexes = 1; +		VectorCopy(f->origin, tess.xyz[0]); +		tess.fogNum = f->fogNum; +	 +		RB_CalcModulateColorsByFog(fogFactors); +	} +	iColor[0] = color[0] * fogFactors[0]; +	iColor[1] = color[1] * fogFactors[1]; +	iColor[2] = color[2] * fogFactors[2]; +	  	RB_BeginSurface( tr.flareShader, f->fogNum );  	// FIXME: use quadstamp? @@ -382,6 +445,21 @@ void RB_RenderFlares (void) {  		return;  	} +	if(r_flareCoeff->modified) +	{ +		if(r_flareCoeff->value == 0.0f) +			flareCoeff = atof(FLARE_STDCOEFF); +		else +			flareCoeff = r_flareCoeff->value; +			 +		r_flareCoeff->modified = qfalse; +	} + +	// Reset currentEntity to world so that any previously referenced entities +	// don't have influence on the rendering of these flares (i.e. RF_ renderer flags). +	backEnd.currentEntity = &tr.worldEntity; +	backEnd.or = backEnd.viewParms.world; +  //	RB_AddDlightFlares();  	// perform z buffer readback on each flare in this view diff --git a/code/renderer/tr_init.c b/code/renderer/tr_init.c index 70b969c..bf234b4 100644 --- a/code/renderer/tr_init.c +++ b/code/renderer/tr_init.c @@ -30,6 +30,7 @@ static void GfxInfo_f( void );  cvar_t	*r_flareSize;  cvar_t	*r_flareFade; +cvar_t	*r_flareCoeff;  cvar_t	*r_railWidth;  cvar_t	*r_railCoreWidth; @@ -997,6 +998,7 @@ void R_Register( void )  	r_flareSize = ri.Cvar_Get ("r_flareSize", "40", CVAR_CHEAT);  	r_flareFade = ri.Cvar_Get ("r_flareFade", "7", CVAR_CHEAT); +	r_flareCoeff = ri.Cvar_Get ("r_flareCoeff", FLARE_STDCOEFF, CVAR_CHEAT);  	r_showSmp = ri.Cvar_Get ("r_showSmp", "0", CVAR_CHEAT);  	r_skipBackEnd = ri.Cvar_Get ("r_skipBackEnd", "0", CVAR_CHEAT); diff --git a/code/renderer/tr_local.h b/code/renderer/tr_local.h index 1b47f96..0fecbcd 100644 --- a/code/renderer/tr_local.h +++ b/code/renderer/tr_local.h @@ -976,6 +976,9 @@ extern glstate_t	glState;		// outside of TR since it shouldn't be cleared during  //  extern cvar_t	*r_flareSize;  extern cvar_t	*r_flareFade; +// coefficient for the flare intensity falloff function. +#define FLARE_STDCOEFF "150" +extern cvar_t	*r_flareCoeff;  extern cvar_t	*r_railWidth;  extern cvar_t	*r_railCoreWidth; diff --git a/code/renderer/tr_shader.c b/code/renderer/tr_shader.c index ddcbfca..a489459 100644 --- a/code/renderer/tr_shader.c +++ b/code/renderer/tr_shader.c @@ -3010,6 +3010,17 @@ static void CreateInternalShaders( void ) {  static void CreateExternalShaders( void ) {  	tr.projectionShadowShader = R_FindShader( "projectionShadow", LIGHTMAP_NONE, qtrue );  	tr.flareShader = R_FindShader( "flareShader", LIGHTMAP_NONE, qtrue ); + +	// Hack to make fogging work correctly on flares. Fog colors are calculated +	// in tr_flare.c already. +	if(!tr.flareShader->defaultShader) +	{ +		int index; +		 +		for(index = 0; index < tr.flareShader->numUnfoggedPasses; index++) +			tr.flareShader->stages[index]->adjustColorsForFog = ACFF_NONE; +	} +  	tr.sunShader = R_FindShader( "sun", LIGHTMAP_NONE, qtrue );  } diff --git a/code/renderer/tr_surface.c b/code/renderer/tr_surface.c index c95e6b2..a1346c8 100644 --- a/code/renderer/tr_surface.c +++ b/code/renderer/tr_surface.c @@ -1214,71 +1214,12 @@ void RB_SurfaceBad( surfaceType_t *surfType ) {  	ri.Printf( PRINT_ALL, "Bad surface tesselated.\n" );  } -#if 0 - -void RB_SurfaceFlare( srfFlare_t *surf ) { -	vec3_t		left, up; -	float		radius; -	byte		color[4]; -	vec3_t		dir; -	vec3_t		origin; -	float		d; - -	// calculate the xyz locations for the four corners -	radius = 30; -	VectorScale( backEnd.viewParms.or.axis[1], radius, left ); -	VectorScale( backEnd.viewParms.or.axis[2], radius, up ); -	if ( backEnd.viewParms.isMirror ) { -		VectorSubtract( vec3_origin, left, left ); -	} - -	color[0] = color[1] = color[2] = color[3] = 255; - -	VectorMA( surf->origin, 3, surf->normal, origin ); -	VectorSubtract( origin, backEnd.viewParms.or.origin, dir ); -	VectorNormalize( dir ); -	VectorMA( origin, r_ignore->value, dir, origin ); - -	d = -DotProduct( dir, surf->normal ); -	if ( d < 0 ) { -		return; -	} -#if 0 -	color[0] *= d; -	color[1] *= d; -	color[2] *= d; -#endif - -	RB_AddQuadStamp( origin, left, up, color ); -} - -#else - -void RB_SurfaceFlare( srfFlare_t *surf ) { -#if 0 -	vec3_t		left, up; -	byte		color[4]; - -	color[0] = surf->color[0] * 255; -	color[1] = surf->color[1] * 255; -	color[2] = surf->color[2] * 255; -	color[3] = 255; - -	VectorClear( left ); -	VectorClear( up ); - -	left[0] = r_ignore->value; - -	up[1] = r_ignore->value; -	 -	RB_AddQuadStampExt( surf->origin, left, up, color, 0, 0, 1, 1 ); -#endif +void RB_SurfaceFlare(srfFlare_t *surf) +{ +	if (r_flares->integer) +		RB_AddFlare(surf, tess.fogNum, surf->origin, surf->color, surf->normal);  } -#endif - - -  void RB_SurfaceDisplayList( srfDisplayList_t *surf ) {  	// all apropriate state must be set in RB_BeginSurface  	// this isn't implemented yet...  | 
