diff --git a/engine/common/mod_bmodel.c b/engine/common/mod_bmodel.c index 8b5e513e..04fa238f 100644 --- a/engine/common/mod_bmodel.c +++ b/engine/common/mod_bmodel.c @@ -1897,7 +1897,10 @@ static void Mod_LoadEntities( model_t *mod, dbspmodel_t *bmod ) else if( !Q_stricmp( keyname, "generator" ) || !Q_stricmp( keyname, "_generator" )) Q_strncpy( world.generator, token, sizeof( world.generator )); else if( !Q_stricmp( keyname, "_litwater" )) - SetBits( world.flags, FWORLD_HAS_LITWATER ); + { + if( Q_atoi( token ) != 0 ) + SetBits( world.flags, FWORLD_HAS_LITWATER ); + } else if( !Q_stricmp( keyname, "_litwater_minlight" )) world.litwater_minlight = Q_atoi( token ); else if( !Q_stricmp( keyname, "_litwater_scale" )) diff --git a/ref/gl/gl_local.h b/ref/gl/gl_local.h index 9b1dbc3d..3586e984 100644 --- a/ref/gl/gl_local.h +++ b/ref/gl/gl_local.h @@ -748,7 +748,7 @@ extern convar_t gl_test; // cvar to testify new effects extern convar_t gl_msaa; extern convar_t gl_stencilbits; extern convar_t gl_overbright; -extern convar_t gl_litwater; +extern convar_t gl_litwater_force; extern convar_t gl_litwater_minlight; extern convar_t gl_litwater_scale; diff --git a/ref/gl/gl_opengl.c b/ref/gl/gl_opengl.c index 69db4586..d3b62057 100644 --- a/ref/gl/gl_opengl.c +++ b/ref/gl/gl_opengl.c @@ -20,7 +20,7 @@ CVAR_DEFINE_AUTO( gl_test, "0", 0, "engine developer cvar for quick testing new CVAR_DEFINE_AUTO( gl_msaa, "1", FCVAR_GLCONFIG, "enable or disable multisample anti-aliasing" ); CVAR_DEFINE_AUTO( gl_stencilbits, "8", FCVAR_GLCONFIG|FCVAR_READ_ONLY, "pixelformat stencil bits (0 - auto)" ); CVAR_DEFINE_AUTO( gl_overbright, "1", FCVAR_GLCONFIG, "overbrights" ); -CVAR_DEFINE_AUTO( gl_litwater, "0", FCVAR_GLCONFIG, "enable lightmapped water" ); +CVAR_DEFINE_AUTO( gl_litwater_force, "0", FCVAR_GLCONFIG, "force enable lightmapped water, even if support not declared in the map" ); CVAR_DEFINE_AUTO( gl_litwater_minlight, "192", FCVAR_GLCONFIG, "minimal light water receives, helps avoid too dark lightmapped water" ); CVAR_DEFINE_AUTO( gl_litwater_scale, "1.5", FCVAR_GLCONFIG, "lightmapped water scale factor" ); CVAR_DEFINE_AUTO( r_lighting_extended, "1", FCVAR_GLCONFIG, "allow to get lighting from world and bmodels" ); @@ -1210,7 +1210,7 @@ static void GL_InitCommands( void ) gEngfuncs.Cvar_RegisterVariable( &gl_stencilbits ); gEngfuncs.Cvar_RegisterVariable( &gl_round_down ); gEngfuncs.Cvar_RegisterVariable( &gl_overbright ); - gEngfuncs.Cvar_RegisterVariable( &gl_litwater ); + gEngfuncs.Cvar_RegisterVariable( &gl_litwater_force ); gEngfuncs.Cvar_RegisterVariable( &gl_litwater_minlight ); gEngfuncs.Cvar_RegisterVariable( &gl_litwater_scale ); diff --git a/ref/gl/gl_rmain.c b/ref/gl/gl_rmain.c index 13a8be06..3bf6628a 100644 --- a/ref/gl/gl_rmain.c +++ b/ref/gl/gl_rmain.c @@ -1027,7 +1027,8 @@ static void R_CheckGamma( void ) ClearBits( r_vbo_overbrightmode.flags, FCVAR_CHANGED ); } - if( FBitSet( gl_litwater_scale.flags|gl_litwater_minlight.flags, FCVAR_CHANGED )) + // we only recalculate lightmap on the fly if map hasn't declared support for lightmapped water + if( !FBitSet( tr.world->flags, FWORLD_HAS_LITWATER ) && FBitSet( gl_litwater_scale.flags|gl_litwater_minlight.flags, FCVAR_CHANGED )) { rebuild = true; ClearBits( gl_litwater_scale.flags, FCVAR_CHANGED ); diff --git a/ref/gl/gl_rsurf.c b/ref/gl/gl_rsurf.c index ce61d6e4..f8b18141 100644 --- a/ref/gl/gl_rsurf.c +++ b/ref/gl/gl_rsurf.c @@ -52,6 +52,42 @@ static qboolean R_AddSurfToVBO( msurface_t *surf, qboolean buildlightmaps ); static void R_DrawVBO( qboolean drawlightmaps, qboolean drawtextures ); static void R_RenderLightmap( msurface_t *fa ); +static qboolean Mod_HaveLightmappedWater( void ) +{ + // if this flag set, it's level designer's job to ensure water has been properly lit + if( FBitSet( tr.world->flags, FWORLD_HAS_LITWATER )) + return true; + + // otherwise, check user preference, as some maps have lightmapped water + return gl_litwater_force.value ? true : false; +} + +static int Mod_LightmappedWaterMinlight( void ) +{ + if( FBitSet( tr.world->flags, FWORLD_HAS_LITWATER )) + { + if( tr.world->litwater_minlight >= 0 ) + return tr.world->litwater_minlight; + + return 0; + } + + return Q_max( (int)gl_litwater_minlight.value, 0 ); +} + +static float Mod_LightmappedWaterScale( void ) +{ + if( FBitSet( tr.world->flags, FWORLD_HAS_LITWATER )) + { + if( tr.world->litwater_scale >= 0.0f ) + return tr.world->litwater_scale; + + return 1.0f; + } + + return gl_litwater_scale.value; +} + byte *Mod_GetCurrentVis( void ) { if( gEngfuncs.drawFuncs->Mod_GetCurrentVis && tr.fCustomRendering ) @@ -739,6 +775,8 @@ static void R_BuildLightMap( msurface_t *surf, byte *dest, int stride, qboolean mextrasurf_t *info = surf->info; color24 *lm; int lightscale; + const int litwater_minlight = Mod_LightmappedWaterMinlight(); + const float litwater_scale = Mod_LightmappedWaterScale(); sample_size = gEngfuncs.Mod_SampleSizeForFace( surf ); smax = ( info->lightextents[0] / sample_size ) + 1; @@ -786,8 +824,9 @@ static void R_BuildLightMap( msurface_t *surf, byte *dest, int stride, qboolean // when the it wasn't properly lit by the level designer if( FBitSet( surf->flags, SURF_DRAWTURB )) { - t *= gl_litwater_scale.value; - t = Q_max( gl_litwater_minlight.value, t ); + float ft = t * litwater_scale; + + t = Q_max( litwater_minlight, Q_rint( ft )); } if( t > 1023 ) @@ -1334,7 +1373,7 @@ static void R_RenderBrushPoly( msurface_t *fa, int cull_type ) EmitWaterPolys( fa, (cull_type == CULL_BACKSIDE), ripplescale ); // add lightmaps if requested - if( gl_litwater.value ) + if( Mod_HaveLightmappedWater( )) R_RenderLightmap( fa ); return; @@ -1629,7 +1668,7 @@ void R_DrawWaterSurfaces( void ) { EmitWaterPolys( s, false, ripplescale ); - if( gl_litwater.value ) + if( Mod_HaveLightmappedWater( )) R_RenderLightmap( s ); } @@ -1835,7 +1874,7 @@ void R_DrawBrushModel( cl_entity_t *e ) { if( FBitSet( psurf->flags, SURF_DRAWTURB )) { - if( gl_litwater.value ) + if( Mod_HaveLightmappedWater( )) continue; // we don't want back faces when drawing lightmaps to avoid Z fighting } else