cvar_t gl_max_size = {CVAR_SAVE, "gl_max_size", "2048", "maximum allowed texture size, can be used to reduce video memory usage, limited by hardware capabilities (typically 2048, 4096, or 8192)"};
cvar_t gl_max_lightmapsize = {CVAR_SAVE, "gl_max_lightmapsize", "1024", "maximum allowed texture size for lightmap textures, use larger values to improve rendering speed, as long as there is enough video memory available (setting it too high for the hardware will cause very bad performance)"};
cvar_t gl_picmip = {CVAR_SAVE, "gl_picmip", "0", "reduces resolution of textures by powers of 2, for example 1 will halve width/height, reducing texture memory usage by 75%"};
+cvar_t gl_picmip_world = {CVAR_SAVE, "gl_picmip_world", "0", "extra picmip level for world textures (may be negative, which will then reduce gl_picmip for these)"};
+cvar_t r_picmipworld = {CVAR_SAVE, "r_picmipworld", "1", "whether gl_picmip shall apply to world textures too (setting this to 0 is a shorthand for gl_picmip_world -9999999)"};
+cvar_t gl_picmip_sprites = {CVAR_SAVE, "gl_picmip_sprites", "0", "extra picmip level for sprite textures (may be negative, which will then reduce gl_picmip for these)"};
+cvar_t r_picmipsprites = {CVAR_SAVE, "r_picmipsprites", "1", "make gl_picmip affect sprites too (saves some graphics memory in sprite heavy games) (setting this to 0 is a shorthand for gl_picmip_sprites -9999999)"};
+cvar_t gl_picmip_other = {CVAR_SAVE, "gl_picmip_other", "0", "extra picmip level for other textures (may be negative, which will then reduce gl_picmip for these)"};
cvar_t r_lerpimages = {CVAR_SAVE, "r_lerpimages", "1", "bilinear filters images when scaling them up to power of 2 size (mode 1), looks better than glquake (mode 0)"};
cvar_t gl_texture_anisotropy = {CVAR_SAVE, "gl_texture_anisotropy", "1", "anisotropic filtering quality (if supported by hardware), 1 sample (no anisotropy) and 8 sample (8 tap anisotropy) are recommended values"};
cvar_t gl_texturecompression = {CVAR_SAVE, "gl_texturecompression", "0", "whether to compress textures, a value of 0 disables compression (even if the individual cvars are 1), 1 enables fast (low quality) compression at startup, 2 enables slow (high quality) compression at startup"};
{
maxsize = bound(1, gl_max_size.integer, maxsize);
picmip = gl_picmip.integer;
+ if (flags & TEXF_ISWORLD)
+ {
+ if (r_picmipworld.integer)
+ picmip += gl_picmip_world.integer;
+ else
+ picmip = 0;
+ }
+ else
+ picmip += gl_picmip_other.integer;
+ picmip = bound(0, picmip, 31); // can't do more than 31 or >> operator gets funny
}
break;
case GLTEXTURETYPE_3D:
Cmd_AddCommand("r_texturestats", R_TextureStats_f, "print information about all loaded textures and some statistics");
Cvar_RegisterVariable (&gl_max_size);
Cvar_RegisterVariable (&gl_picmip);
+ Cvar_RegisterVariable (&gl_picmip_world);
+ Cvar_RegisterVariable (&r_picmipworld);
+ Cvar_RegisterVariable (&gl_picmip_sprites);
+ Cvar_RegisterVariable (&r_picmipsprites);
+ Cvar_RegisterVariable (&gl_picmip_other);
Cvar_RegisterVariable (&gl_max_lightmapsize);
Cvar_RegisterVariable (&r_lerpimages);
Cvar_RegisterVariable (&gl_texture_anisotropy);
//cvar_t r_subdivide_size = {CVAR_SAVE, "r_subdivide_size", "128", "how large water polygons should be (smaller values produce more polygons which give better warping effects)"};
cvar_t r_novis = {0, "r_novis", "0", "draws whole level, see also sv_cullentities_pvs 0"};
-cvar_t r_picmipworld = {CVAR_SAVE, "r_picmipworld", "1", "whether gl_picmip shall apply to world textures too"};
cvar_t r_nosurftextures = {0, "r_nosurftextures", "0", "pretends there was no texture lump found in the q1bsp/hlbsp loading (useful for debugging this rare case)"};
cvar_t r_subdivisions_tolerance = {0, "r_subdivisions_tolerance", "4", "maximum error tolerance on curve subdivision for rendering purposes (in other words, the curves will be given as many polygons as necessary to represent curves at this quality)"};
cvar_t r_subdivisions_mintess = {0, "r_subdivisions_mintess", "0", "minimum number of subdivisions (values above 0 will smooth curves that don't need it)"};
{
// Cvar_RegisterVariable(&r_subdivide_size);
Cvar_RegisterVariable(&r_novis);
- Cvar_RegisterVariable(&r_picmipworld);
Cvar_RegisterVariable(&r_nosurftextures);
Cvar_RegisterVariable(&r_subdivisions_tolerance);
Cvar_RegisterVariable(&r_subdivisions_mintess);
}
else
{
- skinframe = R_SkinFrame_LoadExternal(gamemode == GAME_TENEBRAE ? tx->name : va("textures/%s/%s", mapname, tx->name), TEXF_ALPHA | TEXF_MIPMAP | (r_picmipworld.integer ? TEXF_PICMIP : 0) | TEXF_COMPRESS, false);
+ skinframe = R_SkinFrame_LoadExternal(gamemode == GAME_TENEBRAE ? tx->name : va("textures/%s/%s", mapname, tx->name), TEXF_ALPHA | TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS, false);
if (!skinframe)
- skinframe = R_SkinFrame_LoadExternal(gamemode == GAME_TENEBRAE ? tx->name : va("textures/%s", tx->name), TEXF_ALPHA | TEXF_MIPMAP | (r_picmipworld.integer ? TEXF_PICMIP : 0) | TEXF_COMPRESS, false);
+ skinframe = R_SkinFrame_LoadExternal(gamemode == GAME_TENEBRAE ? tx->name : va("textures/%s", tx->name), TEXF_ALPHA | TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS, false);
if (!skinframe)
{
// did not find external texture, load it from the bsp or wad3
{
tx->width = image_width;
tx->height = image_height;
- skinframe = R_SkinFrame_LoadInternalBGRA(tx->name, TEXF_ALPHA | TEXF_MIPMAP | (r_picmipworld.integer ? TEXF_PICMIP : 0), pixels, image_width, image_height);
+ skinframe = R_SkinFrame_LoadInternalBGRA(tx->name, TEXF_ALPHA | TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP, pixels, image_width, image_height);
}
if (freepixels)
Mem_Free(freepixels);
}
else if (mtdata) // texture included
- skinframe = R_SkinFrame_LoadInternalQuake(tx->name, TEXF_MIPMAP | (r_picmipworld.integer ? TEXF_PICMIP : 0), false, r_fullbrights.integer, mtdata, tx->width, tx->height);
+ skinframe = R_SkinFrame_LoadInternalQuake(tx->name, TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP, false, r_fullbrights.integer, mtdata, tx->width, tx->height);
}
// if skinframe is still NULL the "missing" texture will be used
if (skinframe)
strlcpy (out[i].name, in[i].name, sizeof (out[i].name));
out[i].surfaceflags = LittleLong(in[i].surfaceflags);
out[i].supercontents = Mod_Q3BSP_SuperContentsFromNativeContents(loadmodel, LittleLong(in[i].contents));
- Mod_LoadTextureFromQ3Shader(out + i, out[i].name, true, true, TEXF_MIPMAP | (r_picmipworld.integer ? TEXF_PICMIP : 0) | TEXF_COMPRESS);
+ Mod_LoadTextureFromQ3Shader(out + i, out[i].name, true, true, TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS);
// restore the surfaceflags and supercontents
out[i].surfaceflags = LittleLong(in[i].surfaceflags);
out[i].supercontents = Mod_Q3BSP_SuperContentsFromNativeContents(loadmodel, LittleLong(in[i].contents));
loadmodel->num_textures = numtextures;
loadmodel->data_textures = Mem_Alloc(loadmodel->mempool, loadmodel->num_textures * sizeof(texture_t));
for (i = 0;i < numtextures;i++)
- Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i, texturenames[i], true, true, TEXF_MIPMAP | TEXF_ALPHA | (r_picmipworld.integer ? TEXF_PICMIP : 0) | TEXF_COMPRESS);
+ Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i, texturenames[i], true, true, TEXF_MIPMAP | TEXF_ALPHA | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS);
// free the texturenames array since we are now done with it
for (i = 0;i < numtextures;i++)
memcpy (&entry->shader, shader, sizeof (q3shaderinfo_t));
}
-extern cvar_t r_picmipworld;
extern cvar_t mod_q3shader_default_offsetmapping;
void Mod_LoadQ3Shaders(void)
{
#include "image.h"
cvar_t r_mipsprites = {CVAR_SAVE, "r_mipsprites", "1", "mipmaps sprites so they render faster in the distance and do not display noise artifacts"};
-cvar_t r_picmipsprites = {CVAR_SAVE, "r_picmipsprites", "1", "make gl_picmip affect sprites too (saves some graphics memory in sprite heavy games)"};
cvar_t r_labelsprites_scale = {CVAR_SAVE, "r_labelsprites_scale", "1", "global scale to apply to label sprites before conversion to HUD coordinates"};
cvar_t r_labelsprites_roundtopixels = {CVAR_SAVE, "r_labelsprites_roundtopixels", "1", "try to make label sprites sharper by rounding their size to 0.5x or 1x and by rounding their position to whole pixels if possible"};
void Mod_SpriteInit (void)
{
Cvar_RegisterVariable(&r_mipsprites);
- Cvar_RegisterVariable(&r_picmipsprites);
Cvar_RegisterVariable(&r_labelsprites_scale);
Cvar_RegisterVariable(&r_labelsprites_roundtopixels);
}
float modelradius, interval;
char name[MAX_QPATH], fogname[MAX_QPATH];
const void *startframes;
- int texflags = (r_mipsprites.integer ? TEXF_MIPMAP : 0) | (r_picmipsprites.integer ? TEXF_PICMIP : 0) | TEXF_ALPHA | TEXF_CLAMP;
+ int texflags = (r_mipsprites.integer ? TEXF_MIPMAP : 0) | TEXF_ISSPRITE | TEXF_PICMIP | TEXF_ALPHA | TEXF_CLAMP;
modelradius = 0;
if (loadmodel->numframes < 1)
const dsprite2_t *pinqsprite;
skinframe_t *skinframe;
float modelradius;
- int texflags = (r_mipsprites.integer ? TEXF_MIPMAP : 0) | (r_picmipsprites.integer ? TEXF_PICMIP : 0) | TEXF_COMPRESS | TEXF_ALPHA | TEXF_CLAMP;
+ int texflags = (r_mipsprites.integer ? TEXF_MIPMAP : 0) | TEXF_ISSPRITE | TEXF_PICMIP | TEXF_COMPRESS | TEXF_ALPHA | TEXF_CLAMP;
loadmodel->modeldatatypestring = "SPR2";
#define TEXF_LOWPRECISION 0x00001000
// indicates texture should support R_UpdateTexture, actual uploads may be delayed until R_Mesh_TexBind if gl_nopartialtextureupdates is on
#define TEXF_ALLOWUPDATES 0x00002000
+// indicates texture should be affected by gl_picmip_world and r_picmipworld (maybe others in the future) instead of gl_picmip_other
+#define TEXF_ISWORLD 0x00004000
+// indicates texture should be affected by gl_picmip_sprites and r_picmipsprites (maybe others in the future) instead of gl_picmip_other
+#define TEXF_ISSPRITE 0x00008000
// used for checking if textures mismatch
#define TEXF_IMPORTANTBITS (TEXF_ALPHA | TEXF_MIPMAP | TEXF_CLAMP | TEXF_FORCENEAREST | TEXF_FORCELINEAR | TEXF_PICMIP | TEXF_COMPRESS | TEXF_COMPARE | TEXF_LOWPRECISION)