Compare commits

..

12 Commits

Author SHA1 Message Date
Alibek Omarov
3fb92e22fd Documentation: extensions: add documentation piece for lightmapped water 2024-08-26 21:28:06 +03:00
Alibek Omarov
7364765d62 ref: gl: implement reading engine's world flag and extra info for lightmapped water
* Rename gl_litwater to gl_litwater_force because it doesn't affect maps that declare
  litwater support
2024-08-26 21:27:13 +03:00
Alibek Omarov
b64329d1ee engine: add _litwater worldspawn key to allow mod developers to declare lightmapped water support 2024-08-26 17:10:06 +03:00
Alibek Omarov
ff1d3c4257 ref: gl: add cvars to scale and set minimum light for lightmapped water 2024-08-25 23:15:39 +03:00
Alibek Omarov
d418fb5f28 ref: gl: don't draw water backfaces when drawing lightmapped water 2024-08-25 22:30:12 +03:00
Alibek Omarov
62d7959843 ref: gl: move EmitWaterPolys to gl_rsurf and make it static. Slight refactoring, don't set SURF_DRAWTURB_QUADS if context isn't OpenGL 2024-08-25 19:19:03 +03:00
Alibek Omarov
980f356fe9 ref: gl: discard surfaces that don't have lightmaps in one place, remove unneeded checks 2024-08-25 18:56:46 +03:00
Alibek Omarov
83194ca0f5 ref: gl: support lightmapped water on transparent brushes 2024-08-22 23:13:34 +03:00
Alibek Omarov
d23968b12e ref: gl: add lightmapped water rendering, including wavy water 2024-08-22 23:13:08 +03:00
Alibek Omarov
5034b860c8 ref: gl: split lightmap chain handling from R_RenderBrushPoly 2024-08-22 23:08:52 +03:00
Alibek Omarov
5a708f90c6 ref: gl: build lightmap texcoords for subdivided SURF_DRAWTURB surface 2024-08-22 23:00:38 +03:00
Alibek Omarov
4118ac2561 ref: gl: add cvar gl_litwater to enable lightmapped water 2024-08-22 21:42:04 +03:00
22 changed files with 816 additions and 407 deletions

View File

@@ -0,0 +1,19 @@
## Lightmapped water
Xash3D FWGS supports lightmapped water, as an extension. It adds three new cvars and new worldspawn key values.
### For level designers:
If you're a level designer and intend to make your level to have lightmapped water, you can put these keyvalues to worldspawn entity description (always first entity in entities list):
| Key | Value | Description |
| ---------------------- | ------- | ----------- |
| `_litwater` | integer | Set to any non-zero value to enable lightmapped water. Overrides `gl_litwater_force` cvar value. |
| `_litwater_minlight` | integer | Minimal lightmap value water surface will receive. Helps to avoid too dark areas when water isn't properly lit. If not set, defaults to zero. |
| `_litwater_scale` | float | Scales up lightmap value for water surfaces. If not set, defaults to 1.0. |
### For players:
Some of the maps already have computed lightmap for water surfaces and sometimes water has been properly lit but the support hasn't been declared by the level designer.
As a player, you can enable it in `Video options` menu or through console with `gl_litwater_force` cvar. There are also `gl_litwater_minlight` and `gl_litwater_scale` cvars that function similar to keys above. The default values has been set to `192` and `1.25` respectively to slightly avoid issues with maps that wasn't intended to have lightmapped water.

View File

@@ -14,9 +14,6 @@
****/
#ifndef CONST_H
#define CONST_H
#include <stddef.h> // ptrdiff_t
//
// Constants shared by the engine and dlls
// This header file included by engine files and DLL files.
@@ -724,7 +721,7 @@ enum
};
typedef int func_t;
typedef ptrdiff_t string_t;
typedef int string_t;
typedef unsigned short word;

View File

@@ -56,8 +56,6 @@ color24 gTracerColors[] =
};
*/
#define TRACER_COLORINDEX_DEFAULT 4
// Temporary entity array
#define TENTPRIORITY_LOW 0
#define TENTPRIORITY_HIGH 1

View File

@@ -250,7 +250,7 @@ static particle_t *R_AllocTracer( const vec3_t org, const vec3_t vel, float life
VectorCopy( vel, p->vel );
p->die = cl.time + life;
p->ramp = tracerlength.value;
p->color = TRACER_COLORINDEX_DEFAULT; // select custom color
p->color = 4; // select custom color
p->packedColor = 255; // alpha
return p;

View File

@@ -524,6 +524,9 @@ static void SND_Spatialize( channel_t *ch )
dist = VectorNormalizeLength( source_vec );
dot = DotProduct( s_listener.right, source_vec );
// don't pan sounds with no attenuation
if( ch->dist_mult <= 0.0f ) dot = 0.0f;
// fill out channel volumes for single location
S_SpatializeChannel( &ch->leftvol, &ch->rightvol, ch->master_vol, gain, dot, dist * ch->dist_mult );

View File

@@ -126,20 +126,14 @@ dll_user_t *FS_FindLibrary( const char *dllname, qboolean directpath )
=============================================================================
*/
static void COM_GenerateCommonLibraryName( const char *name, const char *ext, const char *suffix, char *out, size_t size )
static void COM_GenerateCommonLibraryName( const char *name, const char *ext, char *out, size_t size )
{
#if ( XASH_WIN32 || XASH_LINUX || XASH_APPLE ) && XASH_X86
if( suffix )
Q_snprintf( out, size, "%s_%s.%s", name, suffix, ext );
else Q_snprintf( out, size, "%s.%s", name, ext );
Q_snprintf( out, size, "%s.%s", name, ext );
#elif ( XASH_WIN32 || XASH_LINUX || XASH_APPLE )
if( suffix )
Q_snprintf( out, size, "%s_%s_%s.%s", name, Q_buildarch(), suffix, ext );
else Q_snprintf( out, size, "%s_%s.%s", name, Q_buildarch(), ext );
Q_snprintf( out, size, "%s_%s.%s", name, Q_buildarch(), ext );
#else
if( suffix )
Q_snprintf( out, size, "%s_%s_%s_%s.%s", name, Q_buildos(), Q_buildarch(), suffix, ext );
else Q_snprintf( out, size, "%s_%s_%s.%s", name, Q_buildos(), Q_buildarch(), ext );
Q_snprintf( out, size, "%s_%s_%s.%s", name, Q_buildos(), Q_buildarch(), ext );
#endif
}
@@ -160,7 +154,7 @@ static void COM_GenerateClientLibraryPath( const char *name, char *out, size_t s
// we don't have any library prefixes, so we can safely append dll_path here
Q_snprintf( dllpath, sizeof( dllpath ), "%s/%s", GI->dll_path, name );
COM_GenerateCommonLibraryName( dllpath, OS_LIB_EXT, NULL, out, size );
COM_GenerateCommonLibraryName( dllpath, OS_LIB_EXT, out, size );
#endif
}
@@ -217,13 +211,7 @@ static void COM_GenerateServerLibraryPath( char *out, size_t size )
COM_StripExtension( dllpath );
COM_StripIntelSuffix( dllpath );
#if XASH_ARCH_USES_ONLY_ABI2
COM_GenerateCommonLibraryName( dllpath, ext, NULL, out, size );
#elif XASH_64BIT
COM_GenerateCommonLibraryName( dllpath, ext, "st64", out, size );
#else
COM_GenerateCommonLibraryName( dllpath, ext, NULL, out, size );
#endif
COM_GenerateCommonLibraryName( dllpath, ext, out, size );
#endif
}

View File

@@ -420,8 +420,7 @@ void NET_InitMasters( void )
// keep main master always there
NET_AddMaster( MASTERSERVER_ADR, false );
NET_AddMaster( "aaaa.mentality.rip:27010", false ); // IPv6-only
NET_AddMaster( "mentality.rip:27011", false ); // testing server, might be offline
NET_AddMaster( "aaaa.mentality.rip:27011", false ); // IPv6-only, testing server, might be offline
NET_AddMaster( "mentality.rip:27011", false );
NET_LoadMasters( );
}

View File

@@ -1677,9 +1677,10 @@ static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod )
// mark models that have origin brushes
if( !VectorIsNull( bm->origin ))
SetBits( mod->flags, MODEL_HAS_ORIGIN );
#ifdef HACKS_RELATED_HLMODS
// c2a1 doesn't have origin brush it's just placed at center of the level
if( !Q_stricmp( name, "maps/c2a1.bsp" ) && ( i == 11 ))
if( i == 11 && !Q_stricmp( name, "maps/c2a1.bsp" ))
SetBits( mod->flags, MODEL_HAS_ORIGIN );
#endif
}
@@ -1835,6 +1836,8 @@ static void Mod_LoadEntities( model_t *mod, dbspmodel_t *bmod )
world.generator[0] = '\0';
world.compiler[0] = '\0';
world.message[0] = '\0';
world.litwater_minlight = -1;
world.litwater_scale = -1.0f;
bmod->wadlist.count = 0;
// parse all the wads for loading textures in right ordering
@@ -1893,6 +1896,15 @@ static void Mod_LoadEntities( model_t *mod, dbspmodel_t *bmod )
Q_strncpy( world.compiler, token, sizeof( world.compiler ));
else if( !Q_stricmp( keyname, "generator" ) || !Q_stricmp( keyname, "_generator" ))
Q_strncpy( world.generator, token, sizeof( world.generator ));
else if( !Q_stricmp( keyname, "_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" ))
world.litwater_scale = Q_atof( token );
}
return; // all done
}

View File

@@ -119,6 +119,10 @@ typedef struct world_static_s
// Potentially Hearable Set
byte *compressed_phs;
size_t *phsofs;
// lightmapped water extra info
float litwater_scale;
int litwater_minlight;
} world_static_t;
#ifndef REF_DLL

View File

@@ -125,7 +125,7 @@ typedef struct enginefuncs_s
void (*pfnAngleVectors)( const float *rgflVector, float *forward, float *right, float *up );
edict_t* (*pfnCreateEntity)( void );
void (*pfnRemoveEntity)( edict_t* e );
edict_t* (*pfnCreateNamedEntity)( string_t className );
edict_t* (*pfnCreateNamedEntity)( int className );
void (*pfnMakeStatic)( edict_t *ent );
int (*pfnEntIsOnFloor)( edict_t *e );
int (*pfnDropToFloor)( edict_t* e );
@@ -168,8 +168,8 @@ typedef struct enginefuncs_s
void* (*pfnPvAllocEntPrivateData)( edict_t *pEdict, long cb );
void* (*pfnPvEntPrivateData)( edict_t *pEdict );
void (*pfnFreeEntPrivateData)( edict_t *pEdict );
const char *(*pfnSzFromIndex)( string_t iString );
string_t (*pfnAllocString)( const char *szValue );
const char *(*pfnSzFromIndex)( int iString );
int (*pfnAllocString)( const char *szValue );
struct entvars_s *(*pfnGetVarsOfEnt)( edict_t *pEdict );
edict_t* (*pfnPEntityOfEntOffset)( int iEntOffset );
int (*pfnEntOffsetOfPEntity)( const edict_t *pEdict );

View File

@@ -85,8 +85,8 @@ typedef struct entvars_s
int modelindex;
string_t model;
string_t viewmodel; // player's viewmodel
string_t weaponmodel; // what other players see
int viewmodel; // player's viewmodel
int weaponmodel; // what other players see
vec3_t absmin; // BB max translated to world coord
vec3_t absmax; // BB max translated to world coord
@@ -144,7 +144,7 @@ typedef struct entvars_s
int flags;
int colormap; // lowbyte topcolor, highbyte bottomcolor
string_t team;
int team;
float max_health;
float teleport_time;

View File

@@ -80,10 +80,11 @@ GNU General Public License for more details.
#define MODEL_CLIENT BIT( 30 ) // client sprite
// goes into world.flags
#define FWORLD_SKYSPHERE BIT( 0 )
#define FWORLD_CUSTOM_SKYBOX BIT( 1 )
#define FWORLD_WATERALPHA BIT( 2 )
#define FWORLD_HAS_DELUXEMAP BIT( 3 )
#define FWORLD_SKYSPHERE BIT( 0 )
#define FWORLD_CUSTOM_SKYBOX BIT( 1 )
#define FWORLD_WATERALPHA BIT( 2 )
#define FWORLD_HAS_DELUXEMAP BIT( 3 )
#define FWORLD_HAS_LITWATER BIT( 4 )
// special rendermode for screenfade modulate
// (probably will be expanded at some point)

View File

@@ -3000,6 +3000,25 @@ static void *GAME_EXPORT pfnPvEntPrivateData( edict_t *pEdict )
}
#ifdef XASH_64BIT
static struct str64_s
{
size_t maxstringarray;
qboolean allowdup;
char *staticstringarray;
char *pstringarray;
char *pstringarraystatic;
char *pstringbase;
char *poldstringbase;
char *plast;
qboolean dynamic;
size_t maxalloc;
size_t numdups;
size_t numoverflows;
size_t totalalloc;
} str64;
#endif
/*
==================
SV_EmptyStringPool
@@ -3009,7 +3028,17 @@ Free strings on server stop. Reset string pointer on 64 bits
*/
void SV_EmptyStringPool( void )
{
#ifdef XASH_64BIT
if( str64.dynamic ) // switch only after array fill (more space for multiplayer games)
str64.pstringbase = str64.pstringarray;
else
{
str64.pstringbase = str64.poldstringbase = str64.pstringarraystatic;
str64.plast = str64.pstringbase + 1;
}
#else
Mem_EmptyPool( svgame.stringspool );
#endif
}
/*
@@ -3023,8 +3052,23 @@ this helps not to lose strings that belongs to static game part
*/
void SV_SetStringArrayMode( qboolean dynamic )
{
#ifdef XASH_64BIT
Con_Reportf( "%s(%d) %d\n", __func__, dynamic, str64.dynamic );
if( dynamic == str64.dynamic )
return;
str64.dynamic = dynamic;
SV_EmptyStringPool();
#endif
}
#if XASH_AMD64 && XASH_LINUX && !XASH_ANDROID
#define USE_MMAP
#include <sys/mman.h>
#endif
/*
==================
SV_AllocStringPool
@@ -3037,13 +3081,104 @@ this case need patched game dll with MAKE_STRING checking ptrdiff size
*/
static void SV_AllocStringPool( void )
{
#ifdef XASH_64BIT
void *ptr = NULL;
string lenstr;
Con_Reportf( "%s()\n", __func__ );
if( Sys_GetParmFromCmdLine( "-str64alloc", lenstr ) )
{
str64.maxstringarray = Q_atoi( lenstr );
if( str64.maxstringarray < 1024 || str64.maxstringarray >= INT_MAX )
str64.maxstringarray = 65536;
}
else str64.maxstringarray = 65536;
if( Sys_CheckParm( "-str64dup" ) )
str64.allowdup = true;
#ifdef USE_MMAP
{
uint flags;
size_t pagesize = sysconf( _SC_PAGESIZE );
int arrlen = (str64.maxstringarray * 2) & ~(pagesize - 1);
void *base = svgame.dllFuncs.pfnGameInit;
void *start = svgame.hInstance - arrlen;
#if defined(MAP_ANON)
flags = MAP_ANON | MAP_PRIVATE;
#elif defined(MAP_ANONYMOUS)
flags = MAP_ANONYMOUS | MAP_PRIVATE;
#endif
while( start - base > INT_MIN )
{
void *mapptr = mmap((void*)((unsigned long)start & ~(pagesize - 1)), arrlen, PROT_READ | PROT_WRITE, flags, 0, 0 );
if( mapptr && mapptr != (void*)-1 && mapptr - base > INT_MIN && mapptr - base < INT_MAX )
{
ptr = mapptr;
break;
}
if( mapptr ) munmap( mapptr, arrlen );
start -= arrlen;
}
if( !ptr )
{
start = base;
while( start - base < INT_MAX )
{
void *mapptr = mmap((void*)((unsigned long)start & ~(pagesize - 1)), arrlen, PROT_READ | PROT_WRITE, flags, 0, 0 );
if( mapptr && mapptr != (void*)-1 && mapptr - base > INT_MIN && mapptr - base < INT_MAX )
{
ptr = mapptr;
break;
}
if( mapptr ) munmap( mapptr, arrlen );
start += arrlen;
}
}
if( ptr )
{
Con_Reportf( "%s: Allocated string array near the server library: %p %p\n", __func__, base, ptr );
}
else
{
Con_Reportf( "%s: Failed to allocate string array near the server library!\n", __func__ );
ptr = str64.staticstringarray = Mem_Calloc( host.mempool, str64.maxstringarray * 2 );
}
}
#else
ptr = str64.staticstringarray = Mem_Calloc( host.mempool, str64.maxstringarray * 2 );
#endif
str64.pstringarray = ptr;
str64.pstringarraystatic = (byte*)ptr + str64.maxstringarray;
str64.pstringbase = str64.poldstringbase = ptr;
str64.plast = (byte*)ptr + 1;
svgame.globals->pStringBase = ptr;
#else
svgame.stringspool = Mem_AllocPool( "Server Strings" );
svgame.globals->pStringBase = "";
#endif
}
static void SV_FreeStringPool( void )
{
#ifdef XASH_64BIT
Con_Reportf( "%s()\n", __func__ );
#ifdef USE_MMAP
if( str64.pstringarray != str64.staticstringarray )
munmap( str64.pstringarray, (str64.maxstringarray * 2) & ~(sysconf( _SC_PAGESIZE ) - 1) );
else
#endif
Mem_Free( str64.staticstringarray );
#else
Mem_FreePool( &svgame.stringspool );
#endif
}
/*
@@ -3114,6 +3249,9 @@ string_t GAME_EXPORT SV_AllocString( const char *szValue )
{
char *newString = NULL;
uint len;
#ifdef XASH_64BIT
int cmp;
#endif
if( svgame.physFuncs.pfnAllocString != NULL )
{
@@ -3129,16 +3267,67 @@ string_t GAME_EXPORT SV_AllocString( const char *szValue )
return i;
}
#ifdef XASH_64BIT
cmp = 1;
if( !str64.allowdup )
{
for( newString = str64.poldstringbase + 1;
newString < str64.plast && ( cmp = Q_strcmp( newString, szValue ) );
newString += Q_strlen( newString ) + 1 );
}
if( cmp )
{
uint len = SV_ProcessString( NULL, szValue );
if( str64.plast - str64.poldstringbase + len + 1 > str64.maxstringarray )
{
str64.plast = str64.pstringbase + 1;
str64.poldstringbase = str64.pstringbase;
str64.numoverflows++;
}
//MsgDev( D_NOTE, "SV_AllocString: %ld %s\n", str64.plast - svgame.globals->pStringBase, szValue );
SV_ProcessString( str64.plast, szValue );
str64.totalalloc += len;
newString = str64.plast;
str64.plast += len;
}
else
{
str64.numdups++;
//MsgDev( D_NOTE, "SV_AllocString: dup %ld %s\n", newString - svgame.globals->pStringBase, szValue );
}
if( newString - str64.pstringarray > str64.maxalloc )
str64.maxalloc = newString - str64.pstringarray;
return newString - svgame.globals->pStringBase;
#else
len = SV_ProcessString( NULL, szValue );
newString = Mem_Malloc( svgame.stringspool, len );
SV_ProcessString( newString, szValue );
return newString - svgame.globals->pStringBase;
#endif
}
void SV_PrintStr64Stats_f( void )
{
#ifdef XASH_64BIT
Con_Printf( "====================\n" );
Con_Printf( "64 bit string pool statistics\n" );
Con_Printf( "====================\n" );
Con_Printf( "string array size: %lu\n", str64.maxstringarray );
Con_Printf( "total alloc %lu\n", str64.totalalloc );
Con_Printf( "maximum array usage: %lu\n", str64.maxalloc );
Con_Printf( "overflow counter: %lu\n", str64.numoverflows );
Con_Printf( "dup string counter: %lu\n", str64.numdups );
#else
Con_Printf( "Not implemented\n" );
#endif
}
/*
@@ -3152,8 +3341,17 @@ string_t SV_MakeString( const char *szValue )
{
if( svgame.physFuncs.pfnMakeString != NULL )
return svgame.physFuncs.pfnMakeString( szValue );
#ifdef XASH_64BIT
{
long long ptrdiff = szValue - svgame.globals->pStringBase;
if( ptrdiff > INT_MAX || ptrdiff < INT_MIN )
return SV_AllocString(szValue);
else
return (int)ptrdiff;
}
#else
return szValue - svgame.globals->pStringBase;
#endif
}
/*

View File

@@ -445,9 +445,6 @@ void R_GenerateVBO( void );
void R_ClearVBO( void );
void R_AddDecalVBO( decal_t *pdecal, msurface_t *surf );
void R_LightmapCoord( const vec3_t v, const msurface_t *surf, const float sample_size, vec2_t coords );
qboolean R_HasGeneratedVBO( void );
void R_EnableVBO( qboolean enable );
qboolean R_HasEnabledVBO( void );
//
// gl_rpart.c
@@ -497,11 +494,10 @@ void R_ClearSkyBox( void );
void R_DrawSkyBox( void );
void R_DrawClouds( void );
void R_UnloadSkybox( void );
void EmitWaterPolys( msurface_t *warp, qboolean reverse );
void R_InitRipples( void );
void R_ResetRipples( void );
void R_AnimateRipples( void );
void R_UploadRipples( texture_t *image );
float R_UploadRipples( texture_t *image );
//#include "vid_common.h"
@@ -752,6 +748,9 @@ 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_force;
extern convar_t gl_litwater_minlight;
extern convar_t gl_litwater_scale;
extern convar_t r_lighting_extended;
extern convar_t r_lighting_ambient;

View File

@@ -20,6 +20,9 @@ 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_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" );
CVAR_DEFINE_AUTO( r_lighting_ambient, "0.3", FCVAR_GLCONFIG, "map ambient lighting scale" );
CVAR_DEFINE_AUTO( r_detailtextures, "1", FCVAR_ARCHIVE, "enable detail textures support" );
@@ -742,8 +745,10 @@ static void R_RenderInfo_f( void )
gEngfuncs.Con_Printf( "GL4ES_VERSION: %s\n", version );
if( extensions )
gEngfuncs.Con_Reportf( "GL4ES_EXTENSIONS: %s\n", extensions );
}
gEngfuncs.Con_Printf( "GL_MAX_TEXTURE_SIZE: %i\n", glConfig.max_2d_texture_size );
if( GL_Support( GL_ARB_MULTITEXTURE ))
@@ -1148,10 +1153,6 @@ void GL_InitExtensions( void )
gEngfuncs.Cvar_SetValue( "gl_finish", 1 );
#endif
// we do not want to write vbo code that does not use multitexture
if( !GL_Support( GL_ARB_VERTEX_BUFFER_OBJECT_EXT ) || !GL_Support( GL_ARB_MULTITEXTURE ) || glConfig.max_texture_units < 2 )
gEngfuncs.Cvar_FullSet( "gl_vbo", "0", FCVAR_READ_ONLY );
R_RenderInfo_f();
tr.framecount = tr.visframecount = 1;
@@ -1209,6 +1210,9 @@ 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_force );
gEngfuncs.Cvar_RegisterVariable( &gl_litwater_minlight );
gEngfuncs.Cvar_RegisterVariable( &gl_litwater_scale );
// these cvar not used by engine but some mods requires this
gEngfuncs.Cvar_RegisterVariable( &gl_polyoffset );

View File

@@ -1010,32 +1010,29 @@ void R_GammaChanged( qboolean do_reset_gamma )
}
}
static void R_CheckCvars( void )
static void R_CheckGamma( void )
{
qboolean rebuild = false;
if( FBitSet( gl_overbright.flags, FCVAR_CHANGED ))
{
rebuild = true;
ClearBits( gl_overbright.flags, FCVAR_CHANGED );
rebuild = true;
}
if( FBitSet( r_vbo.flags, FCVAR_CHANGED ))
if( gl_overbright.value && FBitSet( r_vbo.flags|r_vbo_overbrightmode.flags, FCVAR_CHANGED ))
{
rebuild = true;
ClearBits( r_vbo.flags, FCVAR_CHANGED );
R_EnableVBO( r_vbo.value ? true : false );
if( R_HasEnabledVBO( ))
R_GenerateVBO();
if( gl_overbright.value )
rebuild = true;
ClearBits( r_vbo_overbrightmode.flags, FCVAR_CHANGED );
}
if( FBitSet( r_vbo_overbrightmode.flags, FCVAR_CHANGED ) && gl_overbright.value )
// 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 ))
{
ClearBits( r_vbo_overbrightmode.flags, FCVAR_CHANGED );
rebuild = true;
ClearBits( gl_litwater_scale.flags, FCVAR_CHANGED );
ClearBits( gl_litwater_minlight.flags, FCVAR_CHANGED );
}
if( rebuild )
@@ -1057,7 +1054,7 @@ void R_BeginFrame( qboolean clearScene )
pglClear( GL_COLOR_BUFFER_BIT );
}
R_CheckCvars();
R_CheckGamma();
R_Set2DMode( true );

View File

@@ -147,10 +147,7 @@ void R_NewMap( void )
}
GL_BuildLightmaps ();
R_ClearVBO();
if( R_HasEnabledVBO( ))
R_GenerateVBO();
R_GenerateVBO();
R_ResetRipples();
if( gEngfuncs.drawFuncs->R_NewMap != NULL )

View File

@@ -229,9 +229,10 @@ void CL_DrawTracers( double frametime, particle_t *cl_active_tracers )
VectorAdd( verts[0], delta, verts[2] );
VectorAdd( verts[1], delta, verts[3] );
if( p->color < 0 || p->color > sizeof( gTracerColors ) / sizeof( gTracerColors[0] ))
if( p->color > sizeof( gTracerColors ) / sizeof( gTracerColors[0] ))
{
p->color = TRACER_COLORINDEX_DEFAULT;
gEngfuncs.Con_Printf( S_ERROR "UserTracer with color(%d) > %zu\n", p->color, sizeof( gTracerColors ) / sizeof( gTracerColors[0] ));
p->color = 0;
}
color = gTracerColors[p->color];

File diff suppressed because it is too large Load Diff

View File

@@ -19,7 +19,6 @@ GNU General Public License for more details.
#define SKYCLOUDS_QUALITY 12
#define MAX_CLIP_VERTS 128 // skybox clip vertices
#define TURBSCALE ( 256.0f / ( M_PI2 ))
static const int r_skyTexOrder[SKYBOX_MAX_SIDES] = { 0, 2, 1, 3, 4, 5 };
@@ -55,12 +54,6 @@ static const int vec_to_st[SKYBOX_MAX_SIDES][3] =
{ -2, 1, -3 }
};
// speed up sin calculations
static float r_turbsin[] =
{
#include "warpsin.h"
};
#define RIPPLES_CACHEWIDTH_BITS 7
#define RIPPLES_CACHEWIDTH ( 1 << RIPPLES_CACHEWIDTH_BITS )
#define RIPPLES_CACHEWIDTH_MASK (( RIPPLES_CACHEWIDTH ) - 1 )
@@ -81,10 +74,8 @@ static struct
uint32_t texture[RIPPLES_TEXSIZE];
int gl_texturenum;
int rippletexturenum;
float texturescale; // not all textures are 128x128, scale the texcoords down
} g_ripple;
static void DrawSkyPolygon( int nump, vec3_t vecs )
{
int i, j, axis;
@@ -558,89 +549,6 @@ void R_DrawClouds( void )
pglFogf( GL_FOG_DENSITY, RI.fogDensity );
}
/*
=============
EmitWaterPolys
Does a water warp on the pre-fragmented glpoly_t chain
=============
*/
void EmitWaterPolys( msurface_t *warp, qboolean reverse )
{
float *v, nv, waveHeight;
float s, t, os, ot;
glpoly2_t *p;
int i;
const qboolean useQuads = FBitSet( warp->flags, SURF_DRAWTURB_QUADS ) && glConfig.context == CONTEXT_TYPE_GL;
if( !warp->polys ) return;
// set the current waveheight
if( warp->polys->verts[0][2] >= RI.vieworg[2] )
waveHeight = -RI.currententity->curstate.scale;
else waveHeight = RI.currententity->curstate.scale;
// reset fog color for nonlightmapped water
GL_ResetFogColor();
if( useQuads )
pglBegin( GL_QUADS );
for( p = warp->polys; p; p = p->next )
{
if( reverse )
v = p->verts[0] + ( p->numverts - 1 ) * VERTEXSIZE;
else v = p->verts[0];
if( !useQuads )
pglBegin( GL_POLYGON );
for( i = 0; i < p->numverts; i++ )
{
if( waveHeight )
{
nv = r_turbsin[(int)(gp_cl->time * 160.0f + v[1] + v[0]) & 255] + 8.0f;
nv = (r_turbsin[(int)(v[0] * 5.0f + gp_cl->time * 171.0f - v[1]) & 255] + 8.0f ) * 0.8f + nv;
nv = nv * waveHeight + v[2];
}
else nv = v[2];
os = v[3];
ot = v[4];
if( !r_ripple.value )
{
s = os + r_turbsin[(int)((ot * 0.125f + gp_cl->time) * TURBSCALE) & 255];
t = ot + r_turbsin[(int)((os * 0.125f + gp_cl->time) * TURBSCALE) & 255];
}
else
{
s = os / g_ripple.texturescale;
t = ot / g_ripple.texturescale;
}
s *= ( 1.0f / SUBDIVIDE_SIZE );
t *= ( 1.0f / SUBDIVIDE_SIZE );
pglTexCoord2f( s, t );
pglVertex3f( v[0], v[1], nv );
if( reverse )
v -= VERTEXSIZE;
else v += VERTEXSIZE;
}
if( !useQuads )
pglEnd();
}
if( useQuads )
pglEnd();
GL_SetupFogColorForSurfaces();
}
/*
============================================================
@@ -750,43 +658,39 @@ void R_AnimateRipples( void )
R_RunRipplesAnimation( g_ripple.oldbuf, g_ripple.curbuf );
}
void R_UploadRipples( texture_t *image )
float R_UploadRipples( texture_t *image )
{
gl_texture_t *glt;
uint32_t *pixels;
int wbits, wmask, wshft;
int y;
float texturescale;
// discard unuseful textures
if( !r_ripple.value || image->width > RIPPLES_CACHEWIDTH || image->width != image->height )
{
GL_Bind( XASH_TEXTURE0, image->gl_texturenum );
return;
return 0.0f;
}
glt = R_GetTexture( image->gl_texturenum );
if( !glt || !glt->original || !glt->original->buffer || !FBitSet( glt->flags, TF_EXPAND_SOURCE ))
{
GL_Bind( XASH_TEXTURE0, image->gl_texturenum );
return;
return 0.0f;
}
GL_Bind( XASH_TEXTURE0, g_ripple.rippletexturenum );
if( r_ripple.value == 1.0f )
texturescale = Q_max( 1.0f, image->width / 64.0f );
else texturescale = 1.0f;
// no updates this frame
if( !g_ripple.update && image->gl_texturenum == g_ripple.gl_texturenum )
return;
return texturescale;
g_ripple.gl_texturenum = image->gl_texturenum;
if( r_ripple.value == 1.0f )
{
g_ripple.texturescale = Q_max( 1.0f, image->width / 64.0f );
}
else
{
g_ripple.texturescale = 1.0f;
}
pixels = (uint32_t *)glt->original->buffer;
wbits = MostSignificantBit( image->width );
@@ -813,4 +717,6 @@ void R_UploadRipples( texture_t *image )
pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, image->width, image->width, 0,
GL_RGBA, GL_UNSIGNED_BYTE, g_ripple.texture );
return texturescale;
}

View File

@@ -236,9 +236,10 @@ void GAME_EXPORT CL_DrawTracers( double frametime, particle_t *cl_active_tracers
VectorAdd( verts[0], delta, verts[2] );
VectorAdd( verts[1], delta, verts[3] );
if( p->color < 0 || p->color > sizeof( gTracerColors ) / sizeof( gTracerColors[0] ))
if( p->color > sizeof( gTracerColors ) / sizeof( gTracerColors[0] ))
{
p->color = TRACER_COLORINDEX_DEFAULT;
gEngfuncs.Con_Printf( S_ERROR "UserTracer with color(%d) > %zu\n", p->color, sizeof( gTracerColors ) / sizeof( gTracerColors[0] ));
p->color = 0;
}
color = gTracerColors[p->color];

View File

@@ -27,7 +27,7 @@ WINSDK_LATEST=$(ls -1 "C:/Program Files (x86)/Windows Kits/10/bin" | grep -E '^1
echo "Latest installed Windows SDK is $WINSDK_LATEST"
"C:/Program Files (x86)/Windows Kits/10/bin/$WINSDK_LATEST/x64/signtool.exe" \
sign //f scripts/fwgs.pfx //fd SHA256 //p "$FWGS_PFX_PASSWORD" *.dll *.exe
/f scripts/fwgs.pfx /fd SHA256 /p "$FWGS_PFX_PASSWORD" *.dll *.exe
if [ "$ARCH" = "i386" ]; then # VGUI is already signed
cp 3rdparty/vgui_support/vgui-dev/lib/win32_vc6/vgui.dll .