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... |