2
0
mirror of https://github.com/FWGS/xash3d-fwgs synced 2024-11-22 01:45:19 +01:00

engine: bring back texture replacement

This commit is contained in:
Alibek Omarov 2024-06-11 06:16:21 +03:00
parent d57d8e0d5d
commit 4e2708c1ac
14 changed files with 309 additions and 28 deletions

View File

@ -0,0 +1,40 @@
### HD (external) textures support
Xash3D supports loading texture replacements in TGA format for almost all types of models in the game, except alias models at this time.
Textures are expected to be located at:
* `modfolder/materials/<mapname>` - for a specific map
* `modfolder/materials/common` - common for all maps
* `modfolder/materials/decals` - for decals
* `modfolder/materials/models/<model>` - for models (texture name must match the internal texture name in the model)
Support for high-resolution textures is enabled setting `host_allow_materials` cvar to `1` or in the menu, in "Video options" section.
#### Xash3D FWGS additions
In addition to paths above, Xash3D FWGS checks following paths:
* `modfolder/materials/sprites/<sprite>` - for sprites, except HUD sprites
Also, to check which texture replacements are loaded successfully, failed or weren't found, a mod developer can set `host_allow_materials` cvar value to `2`. The engine will spew log at any developer level in the following format:
```
Looking for <replacement> replacement... <status code> (<path relative to mod directory>)
```
Status codes:
* `OK` - texture replacement file was found and loaded into GPU memory successfully
* `FAIL` - texture file was found but hasn't been parsed or loaded successfully. Refer to engine log for more details.
* `MISS` - texture file wasn't found
Example:
```
Looking for maps/bounce.bsp:!waterblue tex replacement...OK (materials/common/!waterblue.tga)
Looking for maps/bounce.bsp:!waterblue_luma tex replacement...MISS (not found)
Looking for {shot2 decal replacement...MISS (materials/decals/{shot2.tga)
Looking for {shot4 decal replacement...MISS (materials/decals/{shot4.tga)
Looking for {shot3 decal replacement...MISS (materials/decals/{shot3.tga)
Looking for models/gman tex replacement...FAIL (materials/models/gman/GMan_Case1.tga)
Looking for models/gman tex replacement...FAIL (materials/models/gman/inside_1.tga)
```

View File

@ -1,5 +1,5 @@
/*
features.h - engine features that can be enabled by mod-maker request
enginefeatures.h - engine features that can be enabled by mod-maker request
Copyright (C) 2012 Uncle Mike
This program is free software: you can redistribute it and/or modify
@ -27,6 +27,7 @@ GNU General Public License for more details.
#define ENGINE_COMPUTE_STUDIO_LERP (1<<7) // enable MOVETYPE_STEP lerping back in engine
#define ENGINE_LINEAR_GAMMA_SPACE (1<<8) // disable influence of gamma/brightness cvars to textures/lightmaps, for mods with custom renderer
#define ENGINE_DISABLE_HDTEXTURES (1U<<30) // disable support of HD-textures in case custom renderer have separate way to load them
#define ENGINE_STEP_POSHISTORY_LERP (1U<<31) // enable MOVETYPE_STEP interpolation based on position history. Incompatible with ENGINE_COMPUTE_STUDIO_LERP!
// adjust the mask when features will be added or removed

View File

@ -2981,8 +2981,47 @@ int GAME_EXPORT CL_DecalIndex( int id )
if( cl.decal_index[id] == 0 )
{
int gl_texturenum = 0;
Image_SetForceFlags( IL_LOAD_DECAL );
cl.decal_index[id] = ref.dllFuncs.GL_LoadTexture( host.draw_decals[id], NULL, 0, TF_DECAL );
if( Mod_AllowMaterials( ))
{
string decalname;
if( Q_snprintf( decalname, sizeof( decalname ), "materials/decals/%s.tga", host.draw_decals[id] ) > 0 )
{
if( g_fsapi.FileExists( decalname, false ))
{
gl_texturenum = ref.dllFuncs.GL_LoadTexture( decalname, NULL, 0, TF_DECAL );
if( host_allow_materials.value == 2.0f )
Con_Printf( "Looking for %s decal replacement...%s (%s)\n", host.draw_decals[id], gl_texturenum != 0 ? S_GREEN "OK" : S_RED "FAIL", decalname );
}
else if( host_allow_materials.value == 2.0f )
Con_Printf( "Looking for %s decal replacement..." S_YELLOW "MISS (%s)\n", host.draw_decals[id], decalname );
}
else if( host_allow_materials.value == 2.0f )
Con_Printf( "Looking for %s decal replacement..." S_YELLOW "MISS (overflow)\n", host.draw_decals[id] );
if( gl_texturenum )
{
byte *fin;
Q_snprintf( decalname, sizeof( decalname ), "decals.wad/%s", host.draw_decals[id] );
if(( fin = g_fsapi.LoadFile( decalname, NULL, false )) != NULL )
{
mip_t *mip = (mip_t *)fin;
ref.dllFuncs.R_OverrideTextureSourceSize( gl_texturenum, mip->width, mip->height );
Mem_Free( fin );
}
}
}
if( !gl_texturenum )
gl_texturenum = ref.dllFuncs.GL_LoadTexture( host.draw_decals[id], NULL, 0, TF_DECAL );
cl.decal_index[id] = gl_texturenum;
Image_ClearForceFlags();
}

View File

@ -157,7 +157,7 @@ extern convar_t gl_vsync;
extern convar_t scr_loading;
extern convar_t scr_download;
extern convar_t cmd_scripting;
extern convar_t cl_allow_levelshots;
extern convar_t host_allow_materials;
extern convar_t host_developer;
extern convar_t host_limitlocal;
extern convar_t host_maxfps;
@ -165,6 +165,8 @@ extern convar_t sys_timescale;
extern convar_t cl_filterstuffcmd;
extern convar_t rcon_password;
#define Mod_AllowMaterials() ( host_allow_materials.value != 0.0f && !FBitSet( host.features, ENGINE_DISABLE_HDTEXTURES ))
/*
==============================================================

View File

@ -63,6 +63,7 @@ CVAR_DEFINE( host_maxfps, "fps_max", "72", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "host
static CVAR_DEFINE_AUTO( host_framerate, "0", FCVAR_FILTERABLE, "locks frame timing to this value in seconds" );
static CVAR_DEFINE( host_sleeptime, "sleeptime", "1", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "milliseconds to sleep for each frame. higher values reduce fps accuracy" );
static CVAR_DEFINE_AUTO( host_sleeptime_debug, "0", 0, "print sleeps between frames" );
CVAR_DEFINE_AUTO( host_allow_materials, "0", FCVAR_LATCH|FCVAR_ARCHIVE, "allow texture replacements from materials/ folder" );
CVAR_DEFINE( con_gamemaps, "con_mapfilter", "1", FCVAR_ARCHIVE, "when true show only maps in game folder" );
typedef struct feature_message_s
@ -1327,6 +1328,7 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
Cmd_AddRestrictedCommand ( "crash", Host_Crash_f, "a way to force a bus error for development reasons");
}
Cvar_RegisterVariable( &host_allow_materials );
Cvar_RegisterVariable( &host_serverstate );
Cvar_RegisterVariable( &host_maxfps );
Cvar_RegisterVariable( &host_framerate );
@ -1372,6 +1374,9 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
Wcon_InitConsoleCommands ();
#endif
// disable texture replacements for dedicated
Cvar_FullSet( "host_allow_materials", "0", FCVAR_READ_ONLY );
Cmd_AddRestrictedCommand( "quit", Sys_Quit, "quit the game" );
Cmd_AddRestrictedCommand( "exit", Sys_Quit, "quit the game" );
}

View File

@ -2066,7 +2066,39 @@ static qboolean Mod_LooksLikeWaterTexture( const char *name )
return false;
}
static void Mod_InitSkyClouds( mip_t *mt, texture_t *tx, qboolean custom_palette )
static void Mod_TextureReplacementReport( const char *modelname, const char *texname, const char *type, int gl_texturenum, const char *foundpath )
{
if( host_allow_materials.value != 2.0f )
return;
if( gl_texturenum > 0 ) // found and loaded successfully
Con_Printf( "Looking for %s:%s%s tex replacement..." S_GREEN "OK (%s)\n", modelname, texname, type, foundpath );
else if( gl_texturenum < 0 ) // not found
Con_Printf( "Looking for %s:%s%s tex replacement..." S_YELLOW "MISS (%s)\n", modelname, texname, type, foundpath );
else // found but not loaded
Con_Printf( "Looking for %s:%s%s tex replacement..." S_RED "FAIL (%s)\n", modelname, texname, type, foundpath );
}
static qboolean Mod_SearchForTextureReplacement( char *out, size_t size, const char *modelname, const char *texname, const char *type )
{
const char *subdirs[] = { modelname, "common" };
int i;
for( i = 0; i < ARRAYSIZE( subdirs ); i++ )
{
if( Q_snprintf( out, size, "materials/%s/%s%s.tga", subdirs[i], texname, type ) < 0 )
continue; // truncated name
if( g_fsapi.FileExists( out, false ))
return true; // found, load it
}
Mod_TextureReplacementReport( modelname, texname, type, -1, "not found" );
return false;
}
static void Mod_InitSkyClouds( model_t *mod, mip_t *mt, texture_t *tx, qboolean custom_palette )
{
#if !XASH_DEDICATED
rgbdata_t r_temp, *r_sky;
@ -2074,12 +2106,47 @@ static void Mod_InitSkyClouds( mip_t *mt, texture_t *tx, qboolean custom_palette
uint transpix;
int r, g, b;
int i, j, p;
char texname[32];
int solidskyTexture, alphaskyTexture;
string texname;
int solidskyTexture = 0, alphaskyTexture = 0;
if( !ref.initialized )
return;
if( Mod_AllowMaterials( ))
{
rgbdata_t *pic;
if( Mod_SearchForTextureReplacement( texname, sizeof( texname ), mod->name, mt->name, "_solid" ))
{
pic = FS_LoadImage( texname, NULL, 0 );
if( pic )
{
// need to do rename texture to properly cleanup these textures on reload
solidskyTexture = GL_LoadTextureInternal( "solid_sky", pic, TF_NOMIPMAP );
Mod_TextureReplacementReport( mod->name, mt->name, "_solid", solidskyTexture, texname );
FS_FreeImage( pic );
}
}
if( Mod_SearchForTextureReplacement( texname, sizeof( texname ), mod->name, mt->name, "_alpha" ))
{
pic = FS_LoadImage( texname, NULL, 0 );
if( pic )
{
alphaskyTexture = GL_LoadTextureInternal( "alpha_sky", pic, TF_NOMIPMAP );
Mod_TextureReplacementReport( mod->name, mt->name, "_alpha", alphaskyTexture, texname );
FS_FreeImage( pic );
}
}
if( !solidskyTexture || !alphaskyTexture )
{
ref.dllFuncs.GL_FreeTexture( solidskyTexture );
ref.dllFuncs.GL_FreeTexture( alphaskyTexture );
}
else goto done; // replacements found, notify the renderer and exit
}
Q_snprintf( texname, sizeof( texname ), "%s%s.mip", ( mt->offsets[0] > 0 ) ? "#" : "", tx->name );
if( mt->offsets[0] > 0 )
@ -2170,6 +2237,14 @@ static void Mod_InitSkyClouds( mip_t *mt, texture_t *tx, qboolean custom_palette
FS_FreeImage( r_sky );
Mem_Free( trans );
if( !solidskyTexture || !alphaskyTexture )
{
ref.dllFuncs.GL_FreeTexture( solidskyTexture );
ref.dllFuncs.GL_FreeTexture( alphaskyTexture );
return;
}
done:
// notify the renderer
ref.dllFuncs.R_SetSkyCloudsTextures( solidskyTexture, alphaskyTexture );
@ -2184,6 +2259,9 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
mip_t *mipTex = NULL;
qboolean usesCustomPalette = false;
uint32_t txFlags = 0;
char texpath[MAX_VA_STRING];
char safemtname[16]; // only for external textures
qboolean load_external = false;
// don't load texture data on dedicated server, as there is no renderer.
// but count the wadusage for automatic precache
@ -2192,6 +2270,14 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
// but there is no facility for this yet
texture = mod->textures[textureIndex];
mipTex = Mod_GetMipTexForTexture( bmod, textureIndex );
usesCustomPalette = Mod_CalcMipTexUsesCustomPalette( mod, bmod, textureIndex );
// check for multi-layered sky texture (quake1 specific)
if( bmod->isworld && Q_strncmp( mipTex->name, "sky", 3 ) == 0 && ( mipTex->width / mipTex->height ) == 2 )
{
Mod_InitSkyClouds( mod, mipTex, texture, usesCustomPalette ); // load quake sky
return;
}
if( FBitSet( host.features, ENGINE_IMPROVED_LINETRACE ) && mipTex->name[0] == '{' )
SetBits( txFlags, TF_KEEP_SOURCE ); // Paranoia2 texture alpha-tracing
@ -2200,23 +2286,31 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
if( Mod_LooksLikeWaterTexture( mipTex->name ))
SetBits( txFlags, TF_KEEP_SOURCE | TF_EXPAND_SOURCE );
usesCustomPalette = Mod_CalcMipTexUsesCustomPalette( mod, bmod, textureIndex );
// Texture loading order:
// 1. HQ from disk
// 2. From WAD
// 3. Internal from map
// check for multi-layered sky texture (quake1 specific)
if( bmod->isworld && Q_strncmp( mipTex->name, "sky", 3 ) == 0 && ( mipTex->width / mipTex->height ) == 2 )
texture->gl_texturenum = 0;
Q_strncpy( safemtname, mipTex->name, sizeof( safemtname ));
if( safemtname[0] == '*' )
safemtname[0] = '!'; // replace unexpected symbol
if( Mod_AllowMaterials( ))
{
Mod_InitSkyClouds( mipTex, texture, usesCustomPalette ); // load quake sky
return;
#if !XASH_DEDICATED
if( Mod_SearchForTextureReplacement( texpath, sizeof( texpath ), mod->name, safemtname, "" ))
{
texture->gl_texturenum = ref.dllFuncs.GL_LoadTexture( texpath, NULL, 0, txFlags );
load_external = texture->gl_texturenum != 0;
Mod_TextureReplacementReport( mod->name, safemtname, "", texture->gl_texturenum, texpath );
}
#endif // !XASH_DEDICATED
}
// Texture loading order:
// 1. From WAD
// 2. Internal from map
// Try WAD texture (force while r_wadtextures is 1)
if(( r_wadtextures.value && bmod->wadlist.count > 0 ) || mipTex->offsets[0] <= 0 )
if( !texture->gl_texturenum && (( r_wadtextures.value && bmod->wadlist.count > 0 ) || mipTex->offsets[0] <= 0 ))
{
char texpath[MAX_VA_STRING];
int wadIndex = Mod_FindTextureInWadList( &bmod->wadlist, mipTex->name, texpath, sizeof( texpath ));
if( wadIndex >= 0 )
@ -2251,9 +2345,20 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
}
// Check for luma texture
if( FBitSet( REF_GET_PARM( PARM_TEX_FLAGS, texture->gl_texturenum ), TF_HAS_LUMA ))
texture->fb_texturenum = 0;
if( load_external ) // external textures will not have TF_HAS_LUMA flag because it set only from WAD images loader
{
if( Mod_SearchForTextureReplacement( texpath, sizeof( texpath ), mod->name, safemtname, "_luma" ))
{
texture->fb_texturenum = ref.dllFuncs.GL_LoadTexture( texpath, NULL, 0, TF_MAKELUMA );
Mod_TextureReplacementReport( mod->name, safemtname, "_luma", texture->fb_texturenum, texpath );
}
}
if( FBitSet( REF_GET_PARM( PARM_TEX_FLAGS, texture->gl_texturenum ), TF_HAS_LUMA ) && !texture->fb_texturenum )
{
char texName[64];
Q_snprintf( texName, sizeof( texName ), "#%s:%s_luma.mip", loadstat.name, mipTex->name );
if( mipTex->offsets[0] > 0 )

View File

@ -568,6 +568,7 @@ typedef struct ref_interface_s
int (*GL_LoadTextureArray)( const char **names, int flags );
int (*GL_CreateTextureArray)( const char *name, int width, int height, int depth, const void *buffer, texFlags_t flags );
void (*GL_FreeTexture)( unsigned int texnum );
void (*R_OverrideTextureSourceSize)( unsigned int texnum, unsigned int srcWidth, unsigned int srcHeight ); // used to override decal size for texture replacement
// Decals manipulating (draw & remove)
void (*DrawSingleDecal)( struct decal_s *pDecal, struct msurface_s *fa );
@ -673,6 +674,7 @@ typedef int (*REFAPI)( int version, ref_interface_t *pFunctionTable, ref_api_t*
ENGINE_SHARED_CVAR( f, r_sprite_lighting ) \
ENGINE_SHARED_CVAR( f, r_drawviewmodel ) \
ENGINE_SHARED_CVAR( f, r_glowshellfreq ) \
ENGINE_SHARED_CVAR( f, host_allow_materials ) \
#define DECLARE_ENGINE_SHARED_CVAR_LIST() \
ENGINE_SHARED_CVAR_LIST( DECLARE_ENGINE_SHARED_CVAR )

View File

@ -561,6 +561,8 @@ static void *Mod_LoadAllSkins( model_t *mod, int numskins, daliasskintype_t *psk
size = m_pAliasHeader->skinwidth * m_pAliasHeader->skinheight;
// TODO: texture replacement support here
for( i = 0; i < numskins; i++ )
{
if( pskintype->type == ALIAS_SKIN_SINGLE )

View File

@ -400,6 +400,14 @@ static void GAME_EXPORT VGUI_SetupDrawing( qboolean rect )
}
}
static void GAME_EXPORT R_OverrideTextureSourceSize( unsigned int texnum, uint srcWidth, uint srcHeight )
{
gl_texture_t *tx = R_GetTexture( texnum );
tx->srcWidth = srcWidth;
tx->srcHeight = srcHeight;
}
static void* GAME_EXPORT R_GetProcAddress( const char *name )
{
#ifdef XASH_GL4ES
@ -504,6 +512,7 @@ static ref_interface_t gReffuncs =
GL_LoadTextureArray,
GL_CreateTextureArray,
GL_FreeTexture,
R_OverrideTextureSourceSize,
DrawSingleDecal,
R_DecalSetupVerts,

View File

@ -13,6 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include <stdarg.h>
#include "gl_local.h"
#include "crclib.h"
@ -2349,3 +2350,38 @@ void R_ShutdownImages( void )
memset( gl_textures, 0, sizeof( gl_textures ));
gl_numTextures = 0;
}
void R_TextureReplacementReport( const char *modelname, int gl_texturenum, const char *foundpath )
{
if( host_allow_materials->value != 2.0f )
return;
if( gl_texturenum > 0 )
gEngfuncs.Con_Printf( "Looking for %s tex replacement..." S_GREEN "OK (%s)\n", modelname, foundpath );
else if( gl_texturenum < 0 )
gEngfuncs.Con_Printf( "Looking for %s tex replacement..." S_YELLOW "MISS (%s)\n", modelname, foundpath );
else
gEngfuncs.Con_Printf( "Looking for %s tex replacement..." S_RED "FAIL (%s)\n", modelname, foundpath );
}
qboolean R_SearchForTextureReplacement( char *out, size_t size, const char *modelname, const char *fmt, ... )
{
va_list ap;
int ret;
va_start( ap, fmt );
ret = Q_vsnprintf( out, size, fmt, ap );
va_end( ap );
if( ret < 0 )
{
R_TextureReplacementReport( modelname, -1, "overflow" );
return false;
}
if( gEngfuncs.fsapi->FileExists( out, false ))
return true;
R_TextureReplacementReport( modelname, -1, out );
return false;
}

View File

@ -288,6 +288,7 @@ extern gl_globals_t tr;
extern float gldepthmin, gldepthmax;
#define r_numEntities (tr.draw_list->num_solid_entities + tr.draw_list->num_trans_entities)
#define r_numStatics (r_stats.c_client_ents)
#define Mod_AllowMaterials() (host_allow_materials->value && !FBitSet( gp_host->features, ENGINE_DISABLE_HDTEXTURES ))
//
// gl_backend.c
@ -373,6 +374,8 @@ void R_TextureList_f( void );
void R_InitImages( void );
void R_ShutdownImages( void );
int GL_TexMemory( void );
qboolean R_SearchForTextureReplacement( char *out, size_t size, const char *modelname, const char *fmt, ... ) _format( 4 );
void R_TextureReplacementReport( const char *modelname, int gl_texturenum, const char *foundpath );
//
// gl_rlight.c

View File

@ -67,8 +67,21 @@ static const byte *R_SpriteLoadFrame( model_t *mod, const void *pin, mspritefram
}
else
{
Q_snprintf( texname, sizeof( texname ), "#%s(%s:%i%i).spr", sprite_name, group_suffix, num / 10, num % 10 );
gl_texturenum = GL_LoadTexture( texname, pin, pinframe.width * pinframe.height * bytes, r_texFlags );
// partial HD-textures support
if( Mod_AllowMaterials( ))
{
if( R_SearchForTextureReplacement( texname, sizeof( texname ), sprite_name, "materials/%s/%s%i%i.tga", sprite_name, group_suffix, num / 10, num % 10 ))
{
gl_texturenum = GL_LoadTexture( texname, NULL, 0, r_texFlags );
R_TextureReplacementReport( sprite_name, gl_texturenum, texname );
}
}
if( gl_texturenum == 0 )
{
Q_snprintf( texname, sizeof( texname ), "#%s(%s:%i%i).spr", sprite_name, group_suffix, num / 10, num % 10 );
gl_texturenum = GL_LoadTexture( texname, pin, pinframe.width * pinframe.height * bytes, r_texFlags );
}
}
// setup frame description

View File

@ -3729,6 +3729,7 @@ static void R_StudioLoadTexture( model_t *mod, studiohdr_t *phdr, mstudiotexture
int flags = 0;
char texname[128], name[128], mdlname[128];
texture_t *tx = NULL;
qboolean load_external = false;
if( ptexture->flags & STUDIO_NF_NORMALMAP )
flags |= (TF_NORMALMAP);
@ -3787,17 +3788,31 @@ static void R_StudioLoadTexture( model_t *mod, studiohdr_t *phdr, mstudiotexture
if( FBitSet( ptexture->flags, STUDIO_NF_NOMIPS ))
SetBits( flags, TF_NOMIPMAP );
// NOTE: replace index with pointer to start of imagebuffer, ImageLib expected it
//ptexture->index = (int)((byte *)phdr) + ptexture->index;
gEngfuncs.Image_SetMDLPointer((byte *)phdr + ptexture->index);
size = sizeof( mstudiotexture_t ) + ptexture->width * ptexture->height + 768;
if( FBitSet( gp_host->features, ENGINE_IMPROVED_LINETRACE ) && FBitSet( ptexture->flags, STUDIO_NF_MASKED ))
flags |= TF_KEEP_SOURCE; // Paranoia2 texture alpha-tracing
// build the texname
Q_snprintf( texname, sizeof( texname ), "#%s/%s.mdl", mdlname, name );
ptexture->index = GL_LoadTexture( texname, (byte *)ptexture, size, flags );
// NOTE: colormaps must have the palette for properly work. Ignore them
if( Mod_AllowMaterials( ) && !FBitSet( ptexture->flags, STUDIO_NF_COLORMAP ))
{
if( R_SearchForTextureReplacement( texname, sizeof( texname ), mdlname, "materials/%s/%s.tga", mdlname, name ))
{
int gl_texturenum = GL_LoadTexture( texname, NULL, 0, flags );
R_TextureReplacementReport( mdlname, gl_texturenum, texname );
if(( load_external = gl_texturenum != 0 ))
ptexture->index = gl_texturenum;
}
}
if( !load_external )
{
// NOTE: replace index with pointer to start of imagebuffer, ImageLib expected it
gEngfuncs.Image_SetMDLPointer((byte *)phdr + ptexture->index);
size = sizeof( mstudiotexture_t ) + ptexture->width * ptexture->height + 768;
// build the texname
Q_snprintf( texname, sizeof( texname ), "#%s/%s.mdl", mdlname, name );
ptexture->index = GL_LoadTexture( texname, (byte *)ptexture, size, flags );
}
if( !ptexture->index )
{

View File

@ -398,6 +398,14 @@ static void GAME_EXPORT VGUI_SetupDrawing( qboolean rect )
{
}
static void GAME_EXPORT R_OverrideTextureSourceSize( unsigned int texnum, uint srcWidth, uint srcHeight )
{
image_t *tx = R_GetTexture( texnum );
tx->srcWidth = srcWidth;
tx->srcHeight = srcHeight;
}
static const char *R_GetConfigName( void )
{
return "ref_soft"; // software specific cvars will go to ref_soft.cfg
@ -498,6 +506,7 @@ static ref_interface_t gReffuncs =
GL_LoadTextureArray,
GL_CreateTextureArray,
GL_FreeTexture,
R_OverrideTextureSourceSize,
DrawSingleDecal,
R_DecalSetupVerts,