X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=gl_textures.c;h=a768e193f56bf7e509753db776152104634c968e;hb=d1a66b1504773e5da10463fd15d524697b0c2ba2;hp=e473f6fdad0f05d17127ee54ca65bd5fa165e920;hpb=4bdfa2e9bcc9150a43d44e87d412997d47d5b745;p=xonotic%2Fdarkplaces.git diff --git a/gl_textures.c b/gl_textures.c index e473f6fd..a768e193 100644 --- a/gl_textures.c +++ b/gl_textures.c @@ -9,6 +9,16 @@ cvar_t gl_picmip = {CVAR_SAVE, "gl_picmip", "0", "reduces resolution of textures 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 r_precachetextures = {CVAR_SAVE, "r_precachetextures", "1", "0 = never upload textures until used, 1 = upload most textures before use (exceptions: rarely used skin colormap layers), 2 = upload all textures before use (can increase texture memory usage significantly)"}; 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"}; +cvar_t gl_texturecompression_color = {CVAR_SAVE, "gl_texturecompression_color", "1", "whether to compress colormap (diffuse) textures"}; +cvar_t gl_texturecompression_normal = {CVAR_SAVE, "gl_texturecompression_normal", "1", "whether to compress normalmap (normalmap) textures"}; +cvar_t gl_texturecompression_gloss = {CVAR_SAVE, "gl_texturecompression_gloss", "1", "whether to compress glossmap (specular) textures"}; +cvar_t gl_texturecompression_glow = {CVAR_SAVE, "gl_texturecompression_glow", "1", "whether to compress glowmap (luma) textures"}; +cvar_t gl_texturecompression_2d = {CVAR_SAVE, "gl_texturecompression_2d", "1", "whether to compress 2d (hud/menu) textures other than the font"}; +cvar_t gl_texturecompression_q3bsplightmaps = {CVAR_SAVE, "gl_texturecompression_q3bsplightmaps", "1", "whether to compress lightmaps in q3bsp format levels"}; +cvar_t gl_texturecompression_q3bspdeluxemaps = {CVAR_SAVE, "gl_texturecompression_q3bspdeluxemaps", "1", "whether to compress deluxemaps in q3bsp format levels (only levels compiled with q3map2 -deluxe have these)"}; +cvar_t gl_texturecompression_sky = {CVAR_SAVE, "gl_texturecompression_sky", "0", "whether to compress sky textures"}; +cvar_t gl_texturecompression_lightcubemaps = {CVAR_SAVE, "gl_texturecompression_lightcubemaps", "1", "whether to compress light cubemaps (spotlights and other light projection images)"}; int gl_filter_min = GL_LINEAR_MIPMAP_LINEAR; int gl_filter_mag = GL_LINEAR; @@ -29,16 +39,22 @@ typedef struct textypeinfo_s int textype; int inputbytesperpixel; int internalbytesperpixel; + float glinternalbytesperpixel; int glformat; int glinternalformat; } textypeinfo_t; -static textypeinfo_t textype_palette = {TEXTYPE_PALETTE, 1, 4, GL_RGBA , 3}; -static textypeinfo_t textype_rgb = {TEXTYPE_RGB , 3, 3, GL_RGB , 3}; -static textypeinfo_t textype_rgba = {TEXTYPE_RGBA , 4, 4, GL_RGBA , 3}; -static textypeinfo_t textype_palette_alpha = {TEXTYPE_PALETTE, 1, 4, GL_RGBA , 4}; -static textypeinfo_t textype_rgba_alpha = {TEXTYPE_RGBA , 4, 4, GL_RGBA , 4}; +static textypeinfo_t textype_palette = {TEXTYPE_PALETTE, 1, 4, 4.0f, GL_RGBA , 3}; +static textypeinfo_t textype_rgb = {TEXTYPE_RGB , 3, 3, 4.0f, GL_RGB , 3}; +static textypeinfo_t textype_rgba = {TEXTYPE_RGBA , 4, 4, 4.0f, GL_RGBA , 3}; +static textypeinfo_t textype_palette_alpha = {TEXTYPE_PALETTE, 1, 4, 4.0f, GL_RGBA , 4}; +static textypeinfo_t textype_rgba_alpha = {TEXTYPE_RGBA , 4, 4, 4.0f, GL_RGBA , 4}; +static textypeinfo_t textype_palette_compress = {TEXTYPE_PALETTE, 1, 4, 0.5f, GL_RGBA , GL_COMPRESSED_RGB_ARB}; +static textypeinfo_t textype_rgb_compress = {TEXTYPE_RGB , 3, 3, 0.5f, GL_RGB , GL_COMPRESSED_RGB_ARB}; +static textypeinfo_t textype_rgba_compress = {TEXTYPE_RGBA , 4, 4, 0.5f, GL_RGBA , GL_COMPRESSED_RGB_ARB}; +static textypeinfo_t textype_palette_alpha_compress = {TEXTYPE_PALETTE, 1, 4, 1.0f, GL_RGBA , GL_COMPRESSED_RGBA_ARB}; +static textypeinfo_t textype_rgba_alpha_compress = {TEXTYPE_RGBA , 4, 4, 1.0f, GL_RGBA , GL_COMPRESSED_RGBA_ARB}; #define GLTEXTURETYPE_1D 0 #define GLTEXTURETYPE_2D 1 @@ -69,7 +85,7 @@ typedef struct gltexture_s // pointer to next texture in texturepool chain struct gltexture_s *chain; // name of the texture (this might be removed someday), no duplicates - char identifier[32]; + char identifier[MAX_QPATH + 32]; // original data size in *inputtexels int inputwidth, inputheight, inputdepth; // copy of the original texture(s) supplied to the upload function, for @@ -86,7 +102,8 @@ typedef struct gltexture_s int texturetype; // palette if the texture is TEXTYPE_PALETTE const unsigned int *palette; - // power of 2 size, after gl_picmip and gl_max_size are applied + // actual stored texture size after gl_picmip and gl_max_size are applied + // (power of 2 if gl_support_arb_texture_non_power_of_two is not supported) int tilewidth, tileheight, tiledepth; // 1 or 6 depending on texturetype int sides; @@ -118,35 +135,72 @@ static int texturebuffersize = 0; static textypeinfo_t *R_GetTexTypeInfo(int textype, int flags) { - if (flags & TEXF_ALPHA) + if ((flags & TEXF_COMPRESS) && gl_texturecompression.integer >= 1 && gl_support_texture_compression) { - switch(textype) + if (flags & TEXF_ALPHA) { - case TEXTYPE_PALETTE: - return &textype_palette_alpha; - case TEXTYPE_RGB: - Host_Error("R_GetTexTypeInfo: RGB format has no alpha, TEXF_ALPHA not allowed"); - return NULL; - case TEXTYPE_RGBA: - return &textype_rgba_alpha; - default: - Host_Error("R_GetTexTypeInfo: unknown texture format"); - return NULL; + switch(textype) + { + case TEXTYPE_PALETTE: + return &textype_palette_alpha_compress; + case TEXTYPE_RGB: + Host_Error("R_GetTexTypeInfo: RGB format has no alpha, TEXF_ALPHA not allowed"); + return NULL; + case TEXTYPE_RGBA: + return &textype_rgba_alpha_compress; + default: + Host_Error("R_GetTexTypeInfo: unknown texture format"); + return NULL; + } + } + else + { + switch(textype) + { + case TEXTYPE_PALETTE: + return &textype_palette_compress; + case TEXTYPE_RGB: + return &textype_rgb_compress; + case TEXTYPE_RGBA: + return &textype_rgba_compress; + default: + Host_Error("R_GetTexTypeInfo: unknown texture format"); + return NULL; + } } } else { - switch(textype) + if (flags & TEXF_ALPHA) { - case TEXTYPE_PALETTE: - return &textype_palette; - case TEXTYPE_RGB: - return &textype_rgb; - case TEXTYPE_RGBA: - return &textype_rgba; - default: - Host_Error("R_GetTexTypeInfo: unknown texture format"); - return NULL; + switch(textype) + { + case TEXTYPE_PALETTE: + return &textype_palette_alpha; + case TEXTYPE_RGB: + Host_Error("R_GetTexTypeInfo: RGB format has no alpha, TEXF_ALPHA not allowed"); + return NULL; + case TEXTYPE_RGBA: + return &textype_rgba_alpha; + default: + Host_Error("R_GetTexTypeInfo: unknown texture format"); + return NULL; + } + } + else + { + switch(textype) + { + case TEXTYPE_PALETTE: + return &textype_palette; + case TEXTYPE_RGB: + return &textype_rgb; + case TEXTYPE_RGBA: + return &textype_rgba; + default: + Host_Error("R_GetTexTypeInfo: unknown texture format"); + return NULL; + } } } } @@ -351,20 +405,35 @@ static void GL_Texture_CalcImageSize(int texturetype, int flags, int inwidth, in if (outwidth) { - for (width2 = 1;width2 < inwidth;width2 <<= 1); - for (width2 >>= picmip;width2 > maxsize;width2 >>= 1); + if (gl_support_arb_texture_non_power_of_two) + width2 = min(inwidth >> picmip, maxsize); + else + { + for (width2 = 1;width2 < inwidth;width2 <<= 1); + for (width2 >>= picmip;width2 > maxsize;width2 >>= 1); + } *outwidth = max(1, width2); } if (outheight) { - for (height2 = 1;height2 < inheight;height2 <<= 1); - for (height2 >>= picmip;height2 > maxsize;height2 >>= 1); + if (gl_support_arb_texture_non_power_of_two) + height2 = min(inheight >> picmip, maxsize); + else + { + for (height2 = 1;height2 < inheight;height2 <<= 1); + for (height2 >>= picmip;height2 > maxsize;height2 >>= 1); + } *outheight = max(1, height2); } if (outdepth) { - for (depth2 = 1;depth2 < indepth;depth2 <<= 1); - for (depth2 >>= picmip;depth2 > maxsize;depth2 >>= 1); + if (gl_support_arb_texture_non_power_of_two) + depth2 = min(indepth >> picmip, maxsize); + else + { + for (depth2 = 1;depth2 < indepth;depth2 <<= 1); + for (depth2 >>= picmip;depth2 > maxsize;depth2 >>= 1); + } *outdepth = max(1, depth2); } } @@ -392,7 +461,7 @@ static int R_CalcTexelDataSize (gltexture_t *glt) } } - return size * glt->textype->internalbytesperpixel * glt->sides; + return (int)(size * glt->textype->glinternalbytesperpixel) * glt->sides; } void R_TextureStats_Print(qboolean printeach, qboolean printpool, qboolean printtotal) @@ -496,6 +565,16 @@ void R_Textures_Init (void) Cvar_RegisterVariable (&r_lerpimages); Cvar_RegisterVariable (&r_precachetextures); Cvar_RegisterVariable (&gl_texture_anisotropy); + Cvar_RegisterVariable (&gl_texturecompression); + Cvar_RegisterVariable (&gl_texturecompression_color); + Cvar_RegisterVariable (&gl_texturecompression_normal); + Cvar_RegisterVariable (&gl_texturecompression_gloss); + Cvar_RegisterVariable (&gl_texturecompression_glow); + Cvar_RegisterVariable (&gl_texturecompression_2d); + Cvar_RegisterVariable (&gl_texturecompression_q3bsplightmaps); + Cvar_RegisterVariable (&gl_texturecompression_q3bspdeluxemaps); + Cvar_RegisterVariable (&gl_texturecompression_sky); + Cvar_RegisterVariable (&gl_texturecompression_lightcubemaps); R_RegisterModule("R_Textures", r_textures_start, r_textures_shutdown, r_textures_newmap); } @@ -649,9 +728,18 @@ static void R_Upload(gltexture_t *glt, unsigned char *data, int fragx, int fragy qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR // these are rounded up versions of the size to do better resampling - for (width = 1;width < glt->inputwidth ;width <<= 1); - for (height = 1;height < glt->inputheight;height <<= 1); - for (depth = 1;depth < glt->inputdepth ;depth <<= 1); + if (gl_support_arb_texture_non_power_of_two) + { + width = glt->inputwidth; + height = glt->inputheight; + depth = glt->inputdepth; + } + else + { + for (width = 1;width < glt->inputwidth ;width <<= 1); + for (height = 1;height < glt->inputheight;height <<= 1); + for (depth = 1;depth < glt->inputdepth ;depth <<= 1); + } R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel); R_MakeResizeBufferBigger(fragwidth * fragheight * fragdepth * glt->sides * glt->bytesperpixel); @@ -712,6 +800,14 @@ static void R_Upload(gltexture_t *glt, unsigned char *data, int fragx, int fragy } } mip = 0; + if (gl_support_texture_compression) + { + if (gl_texturecompression.integer >= 2) + qglHint(GL_TEXTURE_COMPRESSION_HINT_ARB, GL_NICEST); + else + qglHint(GL_TEXTURE_COMPRESSION_HINT_ARB, GL_FASTEST); + CHECKGLERROR + } switch(glt->texturetype) { case GLTEXTURETYPE_1D: @@ -831,7 +927,7 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *iden size = width * height * depth * sides * texinfo->inputbytesperpixel; if (size < 1) { - Con_Printf ("R_LoadTexture: bogus texture size (%dx%dx%dx%dbppx%dsides = %d bytes)\n", width, height, depth, texinfo->inputbytesperpixel * 8, sides); + Con_Printf ("R_LoadTexture: bogus texture size (%dx%dx%dx%dbppx%dsides = %d bytes)\n", width, height, depth, texinfo->inputbytesperpixel * 8, sides, size); return NULL; }