From ac0a4ff6a9cfa171c51cb2a513617d4ae917e1be Mon Sep 17 00:00:00 2001 From: divverent Date: Thu, 20 Oct 2011 17:40:34 +0000 Subject: [PATCH] sRGB: also handle sRGB for loading DDS textures git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@11449 d7cf8633-e32d-0410-b094-e92efae38249 --- gl_draw.c | 4 +-- gl_rmain.c | 16 ++++++------ gl_textures.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++--- r_textures.h | 2 +- 4 files changed, 74 insertions(+), 15 deletions(-) diff --git a/gl_draw.c b/gl_draw.c index 3ffbf439..44a83a94 100644 --- a/gl_draw.c +++ b/gl_draw.c @@ -392,7 +392,7 @@ reload: pic->lastusedframe = draw_frame; // load a high quality image from disk if possible - if (!loaded && r_texture_dds_load.integer != 0 && (pic->tex = R_LoadTextureDDSFile(drawtexturepool, va("dds/%s.dds", pic->name), pic->texflags, &ddshasalpha, ddsavgcolor, 0))) + if (!loaded && r_texture_dds_load.integer != 0 && (pic->tex = R_LoadTextureDDSFile(drawtexturepool, va("dds/%s.dds", pic->name), vid.sRGB2D, pic->texflags, &ddshasalpha, ddsavgcolor, 0))) { // note this loads even if autoload is true, otherwise we can't get the width/height loaded = true; @@ -517,7 +517,7 @@ rtexture_t *Draw_GetPicTexture(cachepic_t *pic) { qboolean ddshasalpha; float ddsavgcolor[4]; - pic->tex = R_LoadTextureDDSFile(drawtexturepool, va("dds/%s.dds", pic->name), pic->texflags, &ddshasalpha, ddsavgcolor, 0); + pic->tex = R_LoadTextureDDSFile(drawtexturepool, va("dds/%s.dds", pic->name), vid.sRGB2D, pic->texflags, &ddshasalpha, ddsavgcolor, 0); } if (pic->tex == NULL) { diff --git a/gl_rmain.c b/gl_rmain.c index f5489cfa..b61ea3f1 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -3302,7 +3302,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole Image_StripImageExtension(name, basename, sizeof(basename)); // check for DDS texture file first - if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel))) + if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel))) { basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel); if (basepixels == NULL) @@ -3336,7 +3336,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole skinframe->hasalpha = ddshasalpha; VectorCopy(ddsavgcolor, skinframe->avgcolor); if (r_loadfog && skinframe->hasalpha) - skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel); + skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel); //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]); } else @@ -3383,13 +3383,13 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole { mymiplevel = savemiplevel; if (r_loadnormalmap) - skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel); - skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel); + skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel); + skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel); if (r_loadgloss) - skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel); - skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel); - skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel); - skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel); + skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel); + skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel); + skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel); + skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel); } // _norm is the name used by tenebrae and has been adopted as standard diff --git a/gl_textures.c b/gl_textures.c index 00a9c33d..0c0b8102 100644 --- a/gl_textures.c +++ b/gl_textures.c @@ -2020,7 +2020,7 @@ int R_SaveTextureDDSFile(rtexture_t *rt, const char *filename, qboolean skipunco #endif } -rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filename, int flags, qboolean *hasalphaflag, float *avgcolor, int miplevel) // DDS textures are opaque, so miplevel isn't a pointer but just seen as a hint +rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filename, qboolean srgb, int flags, qboolean *hasalphaflag, float *avgcolor, int miplevel) // DDS textures are opaque, so miplevel isn't a pointer but just seen as a hint { int i, size, dds_format_flags, dds_miplevels, dds_width, dds_height; //int dds_flags; @@ -2031,10 +2031,10 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen gltexturepool_t *pool = (gltexturepool_t *)rtexturepool; textypeinfo_t *texinfo; int mip, mipwidth, mipheight, mipsize, mipsize_total; - unsigned int c; + unsigned int c, r, g, b; GLint oldbindtexnum = 0; - const unsigned char *mippixels; - const unsigned char *mippixels_start; + unsigned char *mippixels; + unsigned char *mippixels_start; unsigned char *ddspixels; unsigned char *dds; fs_offset_t ddsfilesize; @@ -2365,6 +2365,65 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen } } + // if we want sRGB, convert now + if(srgb) + { + if (vid.support.ext_texture_srgb) + { + switch(textype) + { + case TEXTYPE_DXT1: textype = TEXTYPE_SRGB_DXT1 ;break; + case TEXTYPE_DXT1A: textype = TEXTYPE_SRGB_DXT1A ;break; + case TEXTYPE_DXT3: textype = TEXTYPE_SRGB_DXT3 ;break; + case TEXTYPE_DXT5: textype = TEXTYPE_SRGB_DXT5 ;break; + case TEXTYPE_RGBA: textype = TEXTYPE_SRGB_RGBA ;break; + default: + break; + } + } + else + { + switch(textype) + { + case TEXTYPE_DXT1: + case TEXTYPE_DXT1A: + case TEXTYPE_DXT3: + case TEXTYPE_DXT5: + { + for (i = bytesperblock == 16 ? 8 : 0;i < mipsize;i += bytesperblock) + { + c = mippixels_start[i] + 256*mippixels_start[i+1]; + r = ((c >> 11) & 0x1F); + g = ((c >> 5) & 0x3F); + b = ((c ) & 0x1F); + r = floor(Image_LinearFloatFromsRGB(r * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB + g = floor(Image_LinearFloatFromsRGB(g * (255.0f / 63.0f)) * 63.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB + b = floor(Image_LinearFloatFromsRGB(b * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB + c = (r << 11) | (g << 5) | b; + mippixels_start[i] = c & 255; + mippixels_start[i+1] = c >> 8; + c = mippixels_start[i+2] + 256*mippixels_start[i+3]; + r = ((c >> 11) & 0x1F); + g = ((c >> 5) & 0x3F); + b = ((c ) & 0x1F); + r = floor(Image_LinearFloatFromsRGB(r * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB + g = floor(Image_LinearFloatFromsRGB(g * (255.0f / 63.0f)) * 63.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB + b = floor(Image_LinearFloatFromsRGB(b * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB + c = (r << 11) | (g << 5) | b; + mippixels_start[i+2] = c & 255; + mippixels_start[i+3] = c >> 8; + } + } + break; + case TEXTYPE_RGBA: + Image_MakeLinearColorsFromsRGB(mippixels, mippixels, mipsize_total / bytesperblock); + break; + default: + break; + } + } + } + // when not requesting mipmaps, do not load them if(!(flags & TEXF_MIPMAP)) dds_miplevels = 0; diff --git a/r_textures.h b/r_textures.h index 82e3189c..bc654a34 100644 --- a/r_textures.h +++ b/r_textures.h @@ -155,7 +155,7 @@ rtexture_t *R_LoadTexture2D(rtexturepool_t *rtexturepool, const char *identifier rtexture_t *R_LoadTexture3D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int depth, const unsigned char *data, textype_t textype, int flags, int miplevel, const unsigned int *palette); rtexture_t *R_LoadTextureCubeMap(rtexturepool_t *rtexturepool, const char *identifier, int width, const unsigned char *data, textype_t textype, int flags, int miplevel, const unsigned int *palette); rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int precision, qboolean filter); -rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filename, int flags, qboolean *hasalphaflag, float *avgcolor, int miplevel); +rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filename, qboolean srgb, int flags, qboolean *hasalphaflag, float *avgcolor, int miplevel); // saves a texture to a DDS file int R_SaveTextureDDSFile(rtexture_t *rt, const char *filename, qboolean skipuncompressed, qboolean hasalpha); -- 2.39.2