diff --git a/engine/client/cl_cmds.c b/engine/client/cl_cmds.c index 75b3c2ed..9a090bbc 100644 --- a/engine/client/cl_cmds.c +++ b/engine/client/cl_cmds.c @@ -349,7 +349,7 @@ void CL_SetSky_f( void ) return; } - ref.dllFuncs.R_SetupSky( Cmd_Argv( 1 )); + R_SetupSky( Cmd_Argv( 1 )); } /* diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index a240bc9b..1ad628cd 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -249,7 +249,7 @@ void CL_ParseMovevars( sizebuf_t *msg ) // update sky if changed if( Q_strcmp( clgame.oldmovevars.skyName, clgame.movevars.skyName ) && cl.video_prepped ) - ref.dllFuncs.R_SetupSky( clgame.movevars.skyName ); + R_SetupSky( clgame.movevars.skyName ); memcpy( &clgame.oldmovevars, &clgame.movevars, sizeof( movevars_t )); clgame.entities->curstate.scale = clgame.movevars.waveHeight; @@ -1646,6 +1646,9 @@ void CL_RegisterResources( sizebuf_t *msg ) CL_ClearWorld (); + // load skybox + R_SetupSky( clgame.movevars.skyName ); + // tell rendering system we have a new set of models. ref.dllFuncs.R_NewMap (); diff --git a/engine/client/cl_parse_48.c b/engine/client/cl_parse_48.c index 54ffbe8f..0654100c 100644 --- a/engine/client/cl_parse_48.c +++ b/engine/client/cl_parse_48.c @@ -664,6 +664,9 @@ void CL_LegacyPrecache_f( void ) if( clgame.entities ) clgame.entities->model = cl.worldmodel; + // load skybox + R_SetupSky( clgame.movevars.skyName ); + // tell rendering system we have a new set of models. ref.dllFuncs.R_NewMap (); diff --git a/engine/client/ref_common.c b/engine/client/ref_common.c index 9e8b01bc..2abcf86f 100644 --- a/engine/client/ref_common.c +++ b/engine/client/ref_common.c @@ -8,6 +8,8 @@ struct ref_state_s ref; ref_globals_t refState; +static const char* r_skyBoxSuffix[SKYBOX_MAX_SIDES] = { "rt", "bk", "lf", "ft", "up", "dn" }; + CVAR_DEFINE_AUTO( gl_vsync, "0", FCVAR_ARCHIVE, "enable vertical syncronization" ); CVAR_DEFINE_AUTO( r_showtextures, "0", FCVAR_CHEAT, "show all uploaded textures" ); CVAR_DEFINE_AUTO( r_adjust_fov, "1", FCVAR_ARCHIVE, "making FOV adjustment for wide-screens" ); @@ -49,13 +51,102 @@ void R_GetTextureParms( int *w, int *h, int texnum ) if( h ) *h = REF_GET_PARM( PARM_TEX_HEIGHT, texnum ); } -/* -================ -GL_FreeImage +static qboolean CheckSkybox( const char *name, char out[SKYBOX_MAX_SIDES][MAX_STRING] ) +{ + static const char *skybox_ext[3] = { "dds", "tga", "bmp" }; + static const char *skybox_delim[2] = { "", "_" }; // no space for HL style, underscore for Q1 style + int i; + + // search for skybox images + for( i = 0; i < ARRAYSIZE( skybox_ext ); i++ ) + { + int j; + + for( j = 0; j < ARRAYSIZE( skybox_delim ); j++ ) + { + int k, num_checked_sides = 0; + + for( k = 0; k < SKYBOX_MAX_SIDES; k++ ) + { + char sidename[MAX_VA_STRING]; + + Q_snprintf( sidename, sizeof( sidename ), "%s%s%s.%s", name, skybox_delim[j], r_skyBoxSuffix[k], skybox_ext[i] ); + if( g_fsapi.FileExists( sidename, false )) + { + Q_strncpy( out[k], sidename, sizeof( out[k] )); + num_checked_sides++; + } + } + + if( num_checked_sides == SKYBOX_MAX_SIDES ) + return true; // image exists + } + } + + return false; +} + +void R_SetupSky( const char *name ) +{ + string loadname; + char sidenames[SKYBOX_MAX_SIDES][MAX_STRING]; + int skyboxTextures[SKYBOX_MAX_SIDES] = { 0 }; + int i, len; + qboolean result; + + if( !COM_CheckString( name )) + { + ref.dllFuncs.R_SetupSky( NULL ); // unload skybox + return; + } + + Q_snprintf( loadname, sizeof( loadname ), "gfx/env/%s", name ); + COM_StripExtension( loadname ); + + // kill the underline suffix to find them manually later + len = Q_strlen( loadname ); + + if( loadname[len - 1] == '_' ) + loadname[len - 1] = '\0'; + result = CheckSkybox( loadname, sidenames ); + + // to prevent infinite recursion if default skybox was missed + if( !result && Q_stricmp( name, DEFAULT_SKYBOX_NAME )) + { + Con_Reportf( S_WARN "missed or incomplete skybox '%s'\n", name ); + R_SetupSky( DEFAULT_SKYBOX_NAME ); // force to default + return; + } + + ref.dllFuncs.R_SetupSky( NULL ); // unload skybox + Con_DPrintf( "SKY: " ); + + for( i = 0; i < SKYBOX_MAX_SIDES; i++ ) + { + skyboxTextures[i] = ref.dllFuncs.GL_LoadTexture( sidenames[i], NULL, 0, TF_CLAMP|TF_SKY ); + + if( !skyboxTextures[i] ) + break; + + Con_DPrintf( "%s%s%s", name, r_skyBoxSuffix[i], i != 5 ? ", " : ". " ); + } + + if( i == SKYBOX_MAX_SIDES ) + { + SetBits( world.flags, FWORLD_CUSTOM_SKYBOX ); + Con_DPrintf( "done\n" ); + ref.dllFuncs.R_SetupSky( skyboxTextures ); + return; // loaded + } + + Con_DPrintf( "^2failed\n" ); + for( i = 0; i < SKYBOX_MAX_SIDES; i++ ) + { + if( skyboxTextures[i] ) + ref.dllFuncs.GL_FreeTexture( skyboxTextures[i] ); + } +} -Frees image by name -================ -*/ void GAME_EXPORT GL_FreeImage( const char *name ) { int texnum; diff --git a/engine/client/ref_common.h b/engine/client/ref_common.h index dfbbf700..cbed5bc4 100644 --- a/engine/client/ref_common.h +++ b/engine/client/ref_common.h @@ -44,6 +44,8 @@ void R_GetTextureParms( int *w, int *h, int texnum ); void GL_RenderFrame( const struct ref_viewpass_s *rvp ); +void R_SetupSky( const char *name ); + // common engine and renderer cvars extern convar_t r_decals; extern convar_t r_adjust_fov; diff --git a/engine/common/com_strings.h b/engine/common/com_strings.h index e256d19a..b4bc9ece 100644 --- a/engine/common/com_strings.h +++ b/engine/common/com_strings.h @@ -62,7 +62,7 @@ GNU General Public License for more details. #define DEFAULT_SAVE_DIRECTORY "save/" // fallback to this skybox -#define DEFAULT_SKYBOX_PATH "gfx/env/desert" +#define DEFAULT_SKYBOX_NAME "desert" // playlist for startup videos #define DEFAULT_VIDEOLIST_PATH "media/StartupVids.txt" diff --git a/engine/ref_api.h b/engine/ref_api.h index 02cbfd91..cde1d242 100644 --- a/engine/ref_api.h +++ b/engine/ref_api.h @@ -82,6 +82,8 @@ GNU General Public License for more details. // (probably will be expanded at some point) #define kRenderScreenFadeModulate 0x1000 +#define SKYBOX_MAX_SIDES 6 // a box can only have 6 sides + typedef enum { DEMO_INACTIVE = 0, @@ -495,7 +497,7 @@ typedef struct ref_interface_s const byte *(*R_GetTextureOriginalBuffer)( unsigned int idx ); // not always available int (*GL_LoadTextureFromBuffer)( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update ); void (*GL_ProcessTexture)( int texnum, float gamma, int topColor, int bottomColor ); - void (*R_SetupSky)( const char *skyname ); + void (*R_SetupSky)( int *skyboxTextures ); // 2D void (*R_Set2DMode)( qboolean enable ); diff --git a/ref/gl/gl_context.c b/ref/gl/gl_context.c index 2a68d540..1fc2283d 100644 --- a/ref/gl/gl_context.c +++ b/ref/gl/gl_context.c @@ -342,6 +342,24 @@ static void GAME_EXPORT R_SetSkyCloudsTextures( int solidskyTexture, int alphask tr.alphaskyTexture = alphaskyTexture; } +/* +=============== +R_SetupSky +=============== +*/ +static void GAME_EXPORT R_SetupSky( int *skyboxTextures ) +{ + int i; + + R_UnloadSkybox(); + + if( !skyboxTextures ) + return; + + for( i = 0; i < SKYBOX_MAX_SIDES; i++ ) + tr.skyboxTextures[i] = skyboxTextures[i]; +} + static qboolean R_SetDisplayTransform( ref_screen_rotation_t rotate, int offset_x, int offset_y, float scale_x, float scale_y ) { qboolean ret = true; diff --git a/ref/gl/gl_local.h b/ref/gl/gl_local.h index 76338b3d..8c79f7ed 100644 --- a/ref/gl/gl_local.h +++ b/ref/gl/gl_local.h @@ -102,7 +102,6 @@ extern poolhandle_t r_temppool; #define HACKS_RELATED_HLMODS // some HL-mods works differently under Xash and can't be fixed without some hacks at least at current time #define SKYBOX_BASE_NUM 5800 // set skybox base (to let some mods load hi-res skyboxes) -#define SKYBOX_MAX_SIDES 6 // box can only have 6 sides typedef struct gltexture_s { @@ -491,6 +490,7 @@ void R_AddSkyBoxSurface( msurface_t *fa ); 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 ); @@ -539,7 +539,6 @@ void R_GetSpriteParms( int *frameWidth, int *frameHeight, int *numFrames, int cu void R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, const byte *data, qboolean dirty ); void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, int texnum ); qboolean R_SpeedsMessage( char *out, size_t size ); -void R_SetupSky( const char *skyboxname ); qboolean R_CullBox( const vec3_t mins, const vec3_t maxs ); int R_WorldToScreen( const vec3_t point, vec3_t screen ); void R_ScreenToWorld( const vec3_t screen, vec3_t point ); diff --git a/ref/gl/gl_rmisc.c b/ref/gl/gl_rmisc.c index 0ce9a8a1..83bc1422 100644 --- a/ref/gl/gl_rmisc.c +++ b/ref/gl/gl_rmisc.c @@ -146,8 +146,6 @@ void R_NewMap( void ) tx->texturechain = NULL; } - R_SetupSky( tr.movevars->skyName ); - GL_BuildLightmaps (); R_GenerateVBO(); R_ResetRipples(); diff --git a/ref/gl/gl_warp.c b/ref/gl/gl_warp.c index 74a1b79d..2c824259 100644 --- a/ref/gl/gl_warp.c +++ b/ref/gl/gl_warp.c @@ -21,7 +21,6 @@ GNU General Public License for more details. #define MAX_CLIP_VERTS 128 // skybox clip vertices #define TURBSCALE ( 256.0f / ( M_PI2 )) -static const char* r_skyBoxSuffix[SKYBOX_MAX_SIDES] = { "rt", "bk", "lf", "ft", "up", "dn" }; static const int r_skyTexOrder[SKYBOX_MAX_SIDES] = { 0, 2, 1, 3, 4, 5 }; static const vec3_t skyclip[SKYBOX_MAX_SIDES] = @@ -85,50 +84,6 @@ static struct float texturescale; // not all textures are 128x128, scale the texcoords down } g_ripple; -static qboolean CheckSkybox( const char *name, char out[6][MAX_STRING] ) -{ - const char *skybox_ext[3] = { "dds", "tga", "bmp" }; - int i, j, num_checked_sides; - char sidename[MAX_VA_STRING]; - - // search for skybox images - for( i = 0; i < 3; i++ ) - { - // check HL-style skyboxes - num_checked_sides = 0; - for( j = 0; j < SKYBOX_MAX_SIDES; j++ ) - { - // build side name - Q_snprintf( sidename, sizeof( sidename ), "%s%s.%s", name, r_skyBoxSuffix[j], skybox_ext[i] ); - if( gEngfuncs.fsapi->FileExists( sidename, false )) - { - Q_strncpy( out[j], sidename, sizeof( out[j] )); - num_checked_sides++; - } - } - - if( num_checked_sides == 6 ) - return true; // image exists - - // check Q1-style skyboxes - num_checked_sides = 0; - for( j = 0; j < SKYBOX_MAX_SIDES; j++ ) - { - // build side name - Q_snprintf( sidename, sizeof( sidename ), "%s_%s.%s", name, r_skyBoxSuffix[j], skybox_ext[i] ); - if( gEngfuncs.fsapi->FileExists( sidename, false )) - { - Q_strncpy( out[j], sidename, sizeof( out[j] )); - num_checked_sides++; - } - } - - if( num_checked_sides == 6 ) - return true; // images exists - } - - return false; -} static void DrawSkyPolygon( int nump, vec3_t vecs ) { @@ -362,7 +317,7 @@ R_UnloadSkybox Unload previous skybox ============== */ -static void R_UnloadSkybox( void ) +void R_UnloadSkybox( void ) { int i; @@ -426,67 +381,6 @@ void R_DrawSkyBox( void ) R_LoadIdentity(); } -/* -=============== -R_SetupSky -=============== -*/ -void R_SetupSky( const char *skyboxname ) -{ - char loadname[MAX_STRING]; - char sidenames[6][MAX_STRING]; - int i, len; - qboolean result; - - if( !COM_CheckString( skyboxname )) - { - R_UnloadSkybox(); - return; // clear old skybox - } - - Q_snprintf( loadname, sizeof( loadname ), "gfx/env/%s", skyboxname ); - COM_StripExtension( loadname ); - - // kill the underline suffix to find them manually later - len = Q_strlen( loadname ); - - if( loadname[len - 1] == '_' ) - loadname[len - 1] = '\0'; - result = CheckSkybox( loadname, sidenames ); - - // to prevent infinite recursion if default skybox was missed - if( !result && Q_stricmp( loadname, DEFAULT_SKYBOX_PATH )) - { - gEngfuncs.Con_Reportf( S_WARN "missed or incomplete skybox '%s'\n", skyboxname ); - R_SetupSky( "desert" ); // force to default - return; - } - - // release old skybox - R_UnloadSkybox(); - gEngfuncs.Con_DPrintf( "SKY: " ); - - for( i = 0; i < SKYBOX_MAX_SIDES; i++ ) - { - tr.skyboxTextures[i] = GL_LoadTexture( sidenames[i], NULL, 0, TF_CLAMP|TF_SKY ); - - if( !tr.skyboxTextures[i] ) - break; - - gEngfuncs.Con_DPrintf( "%s%s%s", skyboxname, r_skyBoxSuffix[i], i != 5 ? ", " : ". " ); - } - - if( i == 6 ) - { - SetBits( tr.world->flags, FWORLD_CUSTOM_SKYBOX ); - gEngfuncs.Con_DPrintf( "done\n" ); - return; // loaded - } - - gEngfuncs.Con_DPrintf( "^2failed\n" ); - R_UnloadSkybox(); -} - //============================================================================== // // RENDER CLOUDS diff --git a/ref/soft/r_context.c b/ref/soft/r_context.c index 46c0f6b4..6dceaf70 100644 --- a/ref/soft/r_context.c +++ b/ref/soft/r_context.c @@ -317,9 +317,16 @@ static void GAME_EXPORT R_ShowTextures( void ) // textures undone too } -void GAME_EXPORT R_SetupSky(const char *skyboxname) +static void GAME_EXPORT R_SetupSky( int *skyboxTextures ) { + int i; + // TODO: R_UnloadSkybox(); + if( !skyboxTextures ) + return; + + for( i = 0; i < SKYBOX_MAX_SIDES; i++ ) + tr.skyboxTextures[i] = skyboxTextures; } qboolean GAME_EXPORT VID_CubemapShot(const char *base, uint size, const float *vieworg, qboolean skyshot) diff --git a/ref/soft/r_local.h b/ref/soft/r_local.h index 64ca1c54..21ce42df 100644 --- a/ref/soft/r_local.h +++ b/ref/soft/r_local.h @@ -626,7 +626,6 @@ void R_GetSpriteParms( int *frameWidth, int *frameHeight, int *numFrames, int cu void R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, const byte *data, qboolean dirty ); void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, int texnum ); qboolean R_SpeedsMessage( char *out, size_t size ); -void R_SetupSky( const char *skyboxname ); qboolean R_CullBox( const vec3_t mins, const vec3_t maxs ); int R_WorldToScreen( const vec3_t point, vec3_t screen ); void R_ScreenToWorld( const vec3_t screen, vec3_t point );