r_image.c

Go to the documentation of this file.
00001 
00005 /*
00006 Copyright (C) 1997-2001 Id Software, Inc.
00007 
00008 This program is free software; you can redistribute it and/or
00009 modify it under the terms of the GNU General Public License
00010 as published by the Free Software Foundation; either version 2
00011 of the License, or (at your option) any later version.
00012 
00013 This program is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00016 
00017 See the GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with this program; if not, write to the Free Software
00021 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00022 
00023 */
00024 
00025 #include "r_local.h"
00026 #include "r_error.h"
00027 #include "r_geoscape.h"
00028 #include "../../shared/images.h"
00029 
00030 #define MAX_IMAGEHASH 256
00031 static image_t *imageHash[MAX_IMAGEHASH];
00032 
00033 image_t r_images[MAX_GL_TEXTURES];
00034 int r_numImages;
00035 
00036 /* generic environment map */
00037 image_t *r_envmaptextures[MAX_ENVMAPTEXTURES];
00038 
00039 /* lense flares */
00040 image_t *r_flaretextures[NUM_FLARETEXTURES];
00041 
00042 #define MAX_TEXTURE_SIZE 8192
00043 
00048 void R_ImageClearMaterials (void)
00049 {
00050     int i;
00051     const size_t length = lengthof(r_images);
00052 
00053     /* clear previously loaded materials */
00054     for (i = 0; i < length; i++) {
00055         image_t *image = &r_images[i];
00056         material_t *m = &image->material;
00057         materialStage_t *s = m->stages;
00058 
00059         while (s) {  /* free the stages chain */
00060             materialStage_t *ss = s->next;
00061             Mem_Free(s);
00062             s = ss;
00063         }
00064 
00065         memset(m, 0, sizeof(*m));
00066 
00067         m->bump = DEFAULT_BUMP;
00068         m->parallax = DEFAULT_PARALLAX;
00069         m->specular = DEFAULT_SPECULAR;
00070         m->hardness = DEFAULT_HARDNESS;
00071         m->glowscale = DEFAULT_GLOWSCALE;
00072     }
00073 }
00074 
00078 void R_ImageList_f (void)
00079 {
00080     int i;
00081     image_t *image;
00082     int texels;
00083 
00084     Com_Printf("------------------\n");
00085     texels = 0;
00086 
00087     for (i = 0, image = r_images; i < r_numImages; i++, image++) {
00088         if (!image->texnum)
00089             continue;
00090         texels += image->upload_width * image->upload_height;
00091         switch (image->type) {
00092         case it_effect:
00093             Com_Printf("EF");
00094             break;
00095         case it_skin:
00096             Com_Printf("SK");
00097             break;
00098         case it_wrappic:
00099             Com_Printf("WR");
00100             break;
00101         case it_chars:
00102             Com_Printf("CH");
00103             break;
00104         case it_static:
00105             Com_Printf("ST");
00106             break;
00107         case it_normalmap:
00108             Com_Printf("NM");
00109             break;
00110         case it_material:
00111             Com_Printf("MA");
00112             break;
00113         case it_lightmap:
00114             Com_Printf("LM");
00115             break;
00116         case it_world:
00117             Com_Printf("WO");
00118             break;
00119         case it_pic:
00120             Com_Printf("PI");
00121             break;
00122         default:
00123             Com_Printf("  ");
00124             break;
00125         }
00126 
00127         Com_Printf(" %4i %4i RGB: %5i idx: %s\n", image->upload_width, image->upload_height, image->texnum, image->name);
00128     }
00129     Com_Printf("Total textures: %i (max textures: %i)\n", r_numImages, MAX_GL_TEXTURES);
00130     Com_Printf("Total texel count (not counting mipmaps): %i\n", texels);
00131 }
00132 
00141 void R_LoadImage (const char *name, byte **pic, int *width, int *height)
00142 {
00143     char filenameTemp[MAX_QPATH];
00144     SDL_Surface *surf;
00145 
00146     if (!name || name[0] == '\0')
00147         Com_Error(ERR_FATAL, "R_LoadImage: NULL name");
00148 
00149     Com_StripExtension(name, filenameTemp, sizeof(filenameTemp));
00150 
00151     if (Img_LoadImage(filenameTemp, &surf)) {
00152         const size_t size = (surf->w * surf->h) * 4;
00153         *width = surf->w;
00154         *height = surf->h;
00155         *pic = Mem_PoolAlloc(size, vid_imagePool, 0);
00156         memcpy(*pic, surf->pixels, size);
00157         SDL_FreeSurface(surf);
00158     }
00159 }
00160 
00161 void R_ScaleTexture (unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight)
00162 {
00163     int i, j;
00164     unsigned frac;
00165     unsigned p1[MAX_TEXTURE_SIZE], p2[MAX_TEXTURE_SIZE];
00166     const unsigned fracstep = inwidth * 0x10000 / outwidth;
00167 
00168     assert(outwidth <= MAX_TEXTURE_SIZE);
00169 
00170     frac = fracstep >> 2;
00171     for (i = 0; i < outwidth; i++) {
00172         p1[i] = 4 * (frac >> 16);
00173         frac += fracstep;
00174     }
00175     frac = 3 * (fracstep >> 2);
00176     for (i = 0; i < outwidth; i++) {
00177         p2[i] = 4 * (frac >> 16);
00178         frac += fracstep;
00179     }
00180 
00181     for (i = 0; i < outheight; i++, out += outwidth) {
00182         const int index = inwidth * (int) ((i + 0.25) * inheight / outheight);
00183         const unsigned *inrow = in + index;
00184         const int index2 = inwidth * (int) ((i + 0.75) * inheight / outheight);
00185         const unsigned *inrow2 = in + index2;
00186 
00187         assert(index < inwidth * inheight);
00188         assert(index2 < inwidth * inheight);
00189 
00190         for (j = 0; j < outwidth; j++) {
00191             const byte *pix1 = (const byte *) inrow + p1[j];
00192             const byte *pix2 = (const byte *) inrow + p2[j];
00193             const byte *pix3 = (const byte *) inrow2 + p1[j];
00194             const byte *pix4 = (const byte *) inrow2 + p2[j];
00195             ((byte *) (out + j))[0] = (pix1[0] + pix2[0] + pix3[0] + pix4[0]) >> 2;
00196             ((byte *) (out + j))[1] = (pix1[1] + pix2[1] + pix3[1] + pix4[1]) >> 2;
00197             ((byte *) (out + j))[2] = (pix1[2] + pix2[2] + pix3[2] + pix4[2]) >> 2;
00198             ((byte *) (out + j))[3] = (pix1[3] + pix2[3] + pix3[3] + pix4[3]) >> 2;
00199         }
00200     }
00201 }
00202 
00208 void R_FilterTexture (byte *in, int width, int height, imagetype_t type, int bpp)
00209 {
00210     const float scale = 1.0 / 255.0;
00211 
00212     byte *p = in;
00213     const byte *end = p + width * height * bpp;
00214     const float brightness = type == it_lightmap ? r_modulate->value : r_brightness->value;
00215     const float contrast = r_contrast->value;
00216     const float saturation = r_saturation->value;
00217     vec3_t intensity, luminosity, temp;
00218     int j;
00219     float max, d;
00220 
00221     VectorSet(luminosity, 0.2125, 0.7154, 0.0721);
00222 
00223     for (; p != end; p += bpp) {
00224         VectorCopy(p, temp);
00225         VectorScale(temp, scale, temp);  /* convert to float */
00226 
00227         VectorScale(temp, brightness, temp);  /* apply brightness */
00228 
00229         max = 0.0;  /* determine brightest component */
00230 
00231         for (j = 0; j < 3; j++) {
00232             if (temp[j] > max)
00233                 max = temp[j];
00234 
00235             if (temp[j] < 0.0)  /* enforcing positive values */
00236                 temp[j] = 0.0;
00237         }
00238 
00239         if (max > 1.0)  /* clamp without changing hue */
00240             VectorScale(temp, 1.0 / max, temp);
00241 
00242         for (j = 0; j < 3; j++) {  /* apply contrast */
00243             temp[j] -= 0.5;  /* normalize to -0.5 through 0.5 */
00244             temp[j] *= contrast;  /* scale */
00245             temp[j] += 0.5;
00246 
00247             if (temp[j] > 1.0)  /* clamp */
00248                 temp[j] = 1.0;
00249             else if (temp[j] < 0)
00250                 temp[j] = 0;
00251         }
00252 
00253         /* finally saturation, which requires rgb */
00254         d = DotProduct(temp, luminosity);
00255 
00256         VectorSet(intensity, d, d, d);
00257         VectorMix(intensity, temp, saturation, temp);
00258 
00259         for (j = 0; j < 3; j++) {
00260             temp[j] *= 255;  /* back to byte */
00261 
00262             if (temp[j] > 255)  /* clamp */
00263                 temp[j] = 255;
00264             else if (temp[j] < 0)
00265                 temp[j] = 0;
00266 
00267             p[j] = (byte)temp[j];
00268         }
00269     }
00270 }
00271 
00279 void R_GetScaledTextureSize (int width, int height, int *scaledWidth, int *scaledHeight)
00280 {
00281     for (*scaledWidth = 1; *scaledWidth < width; *scaledWidth <<= 1) {}
00282     for (*scaledHeight = 1; *scaledHeight < height; *scaledHeight <<= 1) {}
00283 
00284     while (*scaledWidth > r_config.maxTextureSize || *scaledHeight > r_config.maxTextureSize) {
00285         *scaledWidth >>= 1;
00286         *scaledHeight >>= 1;
00287     }
00288 
00289     if (*scaledWidth > MAX_TEXTURE_SIZE)
00290         *scaledWidth = MAX_TEXTURE_SIZE;
00291     else if (*scaledWidth < 1)
00292         *scaledWidth = 1;
00293 
00294     if (*scaledHeight > MAX_TEXTURE_SIZE)
00295         *scaledHeight = MAX_TEXTURE_SIZE;
00296     else if (*scaledHeight < 1)
00297         *scaledHeight = 1;
00298 }
00299 
00304 void R_UploadTexture (unsigned *data, int width, int height, image_t* image)
00305 {
00306     unsigned *scaled;
00307     int scaledWidth, scaledHeight;
00308     int samples = r_config.gl_compressed_solid_format ? r_config.gl_compressed_solid_format : r_config.gl_solid_format;
00309     int i, c;
00310     byte *scan;
00311     const qboolean mipmap = (image->type != it_pic && image->type != it_chars);
00312     const qboolean clamp = (image->type == it_pic);
00313 
00314     /* scan the texture for any non-255 alpha */
00315     c = width * height;
00316     /* set scan to the first alpha byte */
00317     for (i = 0, scan = ((byte *) data) + 3; i < c; i++, scan += 4) {
00318         if (*scan != 255) {
00319             samples = r_config.gl_compressed_alpha_format ? r_config.gl_compressed_alpha_format : r_config.gl_alpha_format;
00320             break;
00321         }
00322     }
00323 
00324     R_GetScaledTextureSize(width, height, &scaledWidth, &scaledHeight);
00325 
00326     image->has_alpha = (samples == r_config.gl_alpha_format || samples == r_config.gl_compressed_alpha_format);
00327     image->upload_width = scaledWidth;  /* after power of 2 and scales */
00328     image->upload_height = scaledHeight;
00329 
00330     /* some images need very little attention (pics, fonts, etc..) */
00331     if (!mipmap && scaledWidth == width && scaledHeight == height) {
00332         /* no mipmapping for these images - just use GL_NEAREST here to not waste memory */
00333         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00334         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00335         glTexImage2D(GL_TEXTURE_2D, 0, samples, scaledWidth, scaledHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
00336         return;
00337     }
00338 
00339     if (scaledWidth != width || scaledHeight != height) {  /* whereas others need to be scaled */
00340         scaled = (unsigned *)Mem_PoolAllocExt(scaledWidth * scaledHeight * sizeof(unsigned), qfalse, vid_imagePool, 0);
00341         R_ScaleTexture(data, width, height, scaled, scaledWidth, scaledHeight);
00342     } else {
00343         scaled = data;
00344     }
00345 
00346     /* and filter */
00347     if (image->type == it_effect || image->type == it_world || image->type == it_material || image->type == it_skin)
00348         R_FilterTexture((byte*)scaled, scaledWidth, scaledHeight, image->type, 4);
00349 
00350     /* and mipmapped */
00351     if (mipmap) {
00352         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, r_config.gl_filter_min);
00353         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, r_config.gl_filter_max);
00354         glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
00355         if (r_config.anisotropic) {
00356             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, r_config.maxAnisotropic);
00357             R_CheckError();
00358         }
00359         if (r_texture_lod->integer && r_config.lod_bias) {
00360             glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, r_texture_lod->value);
00361             R_CheckError();
00362         }
00363     } else {
00364         if (r_config.anisotropic) {
00365             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
00366             R_CheckError();
00367         }
00368         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, r_config.gl_filter_max);
00369         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, r_config.gl_filter_max);
00370     }
00371     R_CheckError();
00372 
00373     if (clamp) {
00374         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00375         R_CheckError();
00376         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00377         R_CheckError();
00378     }
00379 
00380     glTexImage2D(GL_TEXTURE_2D, 0, samples, scaledWidth, scaledHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
00381     R_CheckError();
00382 
00383     if (scaled != data)
00384         Mem_Free(scaled);
00385 }
00386 
00391 void R_SoftenTexture (byte *in, int width, int height, int bpp)
00392 {
00393     byte *out;
00394     int i, j, k;
00395     const int size = width * height * bpp;
00396 
00397     /* soften into a copy of the original image, as in-place would be incorrect */
00398     out = (byte *)Mem_PoolAllocExt(size, qfalse, vid_imagePool, 0);
00399     if (!out)
00400         Com_Error(ERR_FATAL, "Mem_PoolAllocExt: failed on allocation of %i bytes for R_SoftenTexture", width * height * bpp);
00401 
00402     memcpy(out, in, size);
00403 
00404     for (i = 1; i < height - 1; i++) {
00405         for (j = 1; j < width - 1; j++) {
00406             const byte *src = in + ((i * width) + j) * bpp;  /* current input pixel */
00407 
00408             const byte *u = (src - (width * bpp));  /* and it's neighbors */
00409             const byte *d = (src + (width * bpp));
00410             const byte *l = (src - (1 * bpp));
00411             const byte *r = (src + (1 * bpp));
00412 
00413             byte *dest = out + ((i * width) + j) * bpp;  /* current output pixel */
00414 
00415             for (k = 0; k < bpp; k++)
00416                 dest[k] = (u[k] + d[k] + l[k] + r[k]) / 4;
00417         }
00418     }
00419 
00420     /* copy the softened image over the input image, and free it */
00421     memcpy(in, out, size);
00422     Mem_Free(out);
00423 }
00424 
00425 void R_UploadAlpha (const image_t *image, const byte *alphaData)
00426 {
00427     R_BindTexture(image->texnum);
00428 
00429     /* upload alpha map into the r_dayandnighttexture */
00430     glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, image->width, image->height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, alphaData);
00431     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, r_config.gl_filter_max);
00432     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, r_config.gl_filter_max);
00433     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00434     if (image->type == it_wrappic)
00435         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00436 }
00437 
00438 static inline void R_DeleteImage (image_t *image)
00439 {
00440     image_t *next = image->hashNext;
00441     image_t *prev = image->hashPrev;
00442 
00443     /* free it */
00444     glDeleteTextures(1, (GLuint *) &image->texnum);
00445     R_CheckError();
00446 
00447     if (next) {
00448         assert(next->hashPrev == image);
00449         next->hashPrev = prev;
00450     }
00451     if (prev) {
00452         assert(prev->hashNext == image);
00453         prev->hashNext = next;
00454     } else {
00455         const unsigned int hash = Com_HashKey(image->name, MAX_IMAGEHASH);
00456         assert(imageHash[hash] == image);
00457         imageHash[hash] = next;
00458     }
00459 
00460     memset(image, 0, sizeof(*image));
00461 }
00462 
00463 image_t *R_GetImage (const char *name)
00464 {
00465     image_t *image;
00466     const unsigned hash = Com_HashKey(name, MAX_IMAGEHASH);
00467 
00468     /* look for it */
00469     for (image = imageHash[hash]; image; image = image->hashNext)
00470         if (!strcmp(name, image->name))
00471             return image;
00472 
00473     return NULL;
00474 }
00475 
00486 image_t *R_LoadImageData (const char *name, byte * pic, int width, int height, imagetype_t type)
00487 {
00488     image_t *image;
00489     int i;
00490     size_t len;
00491     unsigned hash;
00492 
00493     len = strlen(name);
00494     if (len >= sizeof(image->name))
00495         Com_Error(ERR_DROP, "R_LoadImageData: \"%s\" is too long", name);
00496     if (len == 0)
00497         Com_Error(ERR_DROP, "R_LoadImageData: name is empty");
00498 
00499     /* look for it */
00500     image = R_GetImage(name);
00501     if (image) {
00502         assert(image->texnum);
00503         Com_Printf("R_LoadImageData: image '%s' is already uploaded\n", name);
00504         return image;
00505     }
00506 
00507     /* find a free image_t */
00508     for (i = 0, image = r_images; i < r_numImages; i++, image++)
00509         if (!image->texnum)
00510             break;
00511 
00512     if (i == r_numImages) {
00513         if (r_numImages >= MAX_GL_TEXTURES)
00514             Com_Error(ERR_DROP, "R_LoadImageData: MAX_GL_TEXTURES hit");
00515         r_numImages++;
00516     }
00517     image = &r_images[i];
00518     image->has_alpha = qfalse;
00519     image->type = type;
00520     image->width = width;
00521     image->height = height;
00522     image->texnum = i + 1;
00523 
00524     Q_strncpyz(image->name, name, sizeof(image->name));
00525     /* drop extension */
00526     if (len >= 4 && image->name[len - 4] == '.') {
00527         image->name[len - 4] = '\0';
00528         Com_Printf("Image with extension: '%s'\n", name);
00529     }
00530 
00531     hash = Com_HashKey(image->name, MAX_IMAGEHASH);
00532     image->hashNext = imageHash[hash];
00533     if (imageHash[hash])
00534         imageHash[hash]->hashPrev = image;
00535     imageHash[hash] = image;
00536 
00537     if (pic) {
00538         R_BindTexture(image->texnum);
00539         R_UploadTexture((unsigned *) pic, width, height, image);
00540     }
00541     return image;
00542 }
00543 
00555 image_t *R_FindImage (const char *pname, imagetype_t type)
00556 {
00557     char lname[MAX_QPATH];
00558     image_t *image;
00559     SDL_Surface *surf;
00560 
00561     if (!pname || !pname[0])
00562         Com_Error(ERR_FATAL, "R_FindImage: NULL name");
00563 
00564     /* drop extension */
00565     Com_StripExtension(pname, lname, sizeof(lname));
00566 
00567     image = R_GetImage(lname);
00568     if (image)
00569         return image;
00570 
00571     if (Img_LoadImage(lname, &surf)) {
00572         image = R_LoadImageData(lname, surf->pixels, surf->w, surf->h, type);
00573         SDL_FreeSurface(surf);
00574         if (image->type == it_world) {
00575             image->normalmap = R_FindImage(va("%s_nm", image->name), it_normalmap);
00576             if (image->normalmap == r_noTexture)
00577                 image->normalmap = NULL;
00578         }
00579         if (image->type != it_glowmap) {
00580             image->glowmap = R_FindImage(va("%s_gm", image->name), it_glowmap);
00581             if (image->glowmap == r_noTexture)
00582                 image->glowmap = NULL;
00583         }
00584         if (image->type != it_normalmap) {
00585             image->normalmap = R_FindImage(va("%s_nm", image->name), it_normalmap);
00586             if (image->normalmap == r_noTexture)
00587                 image->normalmap = NULL;
00588         }
00589         if (image->type != it_specularmap) {
00590             image->specularmap = R_FindImage(va("%s_sm", image->name), it_specularmap);
00591             if (image->specularmap == r_noTexture)
00592                 image->specularmap = NULL;
00593         }
00594         if (image->type != it_roughnessmap) {
00595             image->roughnessmap = R_FindImage(va("%s_rm", image->name), it_roughnessmap);
00596             if (image->roughnessmap == r_noTexture)
00597                 image->roughnessmap = NULL;
00598         }
00599     }
00600 
00601     /* no fitting texture found */
00602     if (!image)
00603         image = r_noTexture;
00604 
00605     return image;
00606 }
00607 
00608 qboolean R_ImageExists (const char *pname)
00609 {
00610     const char **types = Img_GetImageTypes();
00611     int i;
00612 
00613     for (i = 0; types[i]; i++) {
00614         if (FS_CheckFile("%s.%s", pname, types[i]) != -1)
00615             return qtrue;
00616     }
00617     return qfalse;
00618 }
00619 
00624 void R_FreeImage (image_t *image)
00625 {
00626     /* free image slot */
00627     if (!image || !image->texnum)
00628         return;
00629 
00630     /* also free the several maps if they are loaded */
00631     if (image->normalmap)
00632         R_DeleteImage(image->normalmap);
00633     if (image->glowmap)
00634         R_DeleteImage(image->glowmap);
00635     if (image->roughnessmap)
00636         R_DeleteImage(image->roughnessmap);
00637     if (image->specularmap)
00638         R_DeleteImage(image->specularmap);
00639     R_DeleteImage(image);
00640 }
00641 
00646 void R_FreeWorldImages (void)
00647 {
00648     int i;
00649     image_t *image;
00650 
00651     R_CheckError();
00652     for (i = 0, image = r_images; i < r_numImages; i++, image++) {
00653         if (image->type < it_world)
00654             continue;           /* keep them */
00655 
00656         /* free it */
00657         R_FreeImage(image);
00658     }
00659 }
00660 
00661 void R_InitImages (void)
00662 {
00663     int i;
00664 
00665 #ifdef SDL_IMAGE_VERSION
00666     SDL_version version;
00667 
00668     SDL_IMAGE_VERSION(&version)
00669     Com_Printf("SDL_image version %i.%i.%i\n", version.major, version.minor, version.patch);
00670 #else
00671     Com_Printf("could not get SDL_image version\n");
00672 #endif
00673 
00674     r_numImages = 0;
00675 
00676     for (i = 0; i < MAX_ENVMAPTEXTURES; i++) {
00677         r_envmaptextures[i] = R_FindImage(va("pics/envmaps/envmap_%i", i), it_effect);
00678         if (r_envmaptextures[i] == r_noTexture)
00679             Com_Error(ERR_FATAL, "Could not load environment map %i", i);
00680     }
00681 
00682     for (i = 0; i < NUM_FLARETEXTURES; i++) {
00683         r_flaretextures[i] = R_FindImage(va("pics/flares/flare_%i", i), it_effect);
00684         if (r_flaretextures[i] == r_noTexture)
00685             Com_Error(ERR_FATAL, "Could not load lens flare %i", i);
00686     }
00687 }
00688 
00692 void R_ShutdownImages (void)
00693 {
00694     int i;
00695     image_t *image;
00696 
00697     R_CheckError();
00698     for (i = 0, image = r_images; i < r_numImages; i++, image++) {
00699         if (!image->texnum)
00700             continue;           /* free image_t slot */
00701         R_DeleteImage(image);
00702     }
00703     memset(imageHash, 0, sizeof(imageHash));
00704 }
00705 
00706 
00707 typedef struct {
00708     const char *name;
00709     int minimize, maximize;
00710 } glTextureMode_t;
00711 
00712 static const glTextureMode_t gl_texture_modes[] = {
00713     {"GL_NEAREST", GL_NEAREST, GL_NEAREST}, /* no filtering, no mipmaps */
00714     {"GL_LINEAR", GL_LINEAR, GL_LINEAR}, /* bilinear filtering, no mipmaps */
00715     {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST}, /* no filtering, mipmaps */
00716     {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR}, /* bilinear filtering, mipmaps */
00717     {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST}, /* trilinear filtering, mipmaps */
00718     {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR} /* bilinear filtering, trilinear filtering, mipmaps */
00719 };
00720 
00721 void R_TextureMode (const char *string)
00722 {
00723     int i;
00724     image_t *image;
00725     const size_t size = lengthof(gl_texture_modes);
00726     const glTextureMode_t *mode;
00727 
00728     mode = NULL;
00729     for (i = 0; i < size; i++) {
00730         mode = &gl_texture_modes[i];
00731         if (!Q_strcasecmp(mode->name, string))
00732             break;
00733     }
00734 
00735     if (mode == NULL) {
00736         Com_Printf("bad filter name\n");
00737         return;
00738     }
00739 
00740     for (i = 0, image = r_images; i < r_numImages; i++, image++) {
00741         if (image->type == it_chars || image->type == it_pic || image->type == it_wrappic)
00742             continue; /* no mipmaps */
00743 
00744         R_BindTexture(image->texnum);
00745         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mode->minimize);
00746         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mode->maximize);
00747         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, r_config.maxAnisotropic);
00748         R_CheckError();
00749     }
00750 }
00751 
00752 typedef struct {
00753     const char *name;
00754     int mode;
00755 } gltmode_t;
00756 
00757 static const gltmode_t gl_alpha_modes[] = {
00758     {"GL_RGBA", GL_RGBA},
00759     {"GL_RGBA8", GL_RGBA8},
00760     {"GL_RGB5_A1", GL_RGB5_A1},
00761     {"GL_RGBA4", GL_RGBA4},
00762     {"GL_RGBA2", GL_RGBA2},
00763     {"GL_LUMINANCE4_ALPHA4", GL_LUMINANCE4_ALPHA4},
00764     {"GL_LUMINANCE6_ALPHA2", GL_LUMINANCE6_ALPHA2},
00765     {"GL_LUMINANCE8_ALPHA8", GL_LUMINANCE8_ALPHA8},
00766     {"GL_LUMINANCE12_ALPHA4", GL_LUMINANCE12_ALPHA4},
00767     {"GL_LUMINANCE12_ALPHA12", GL_LUMINANCE12_ALPHA12},
00768     {"GL_LUMINANCE16_ALPHA16", GL_LUMINANCE16_ALPHA16}
00769 };
00770 
00771 
00772 void R_TextureAlphaMode (const char *string)
00773 {
00774     int i;
00775     const size_t size = lengthof(gl_alpha_modes);
00776 
00777     for (i = 0; i < size; i++) {
00778         const gltmode_t *mode = &gl_alpha_modes[i];
00779         if (!Q_strcasecmp(mode->name, string)) {
00780             r_config.gl_alpha_format = mode->mode;
00781             return;
00782         }
00783     }
00784 
00785     Com_Printf("bad alpha texture mode name (%s)\n", string);
00786 }
00787 
00788 static const gltmode_t gl_solid_modes[] = {
00789     {"GL_RGB", GL_RGB},
00790     {"GL_RGB8", GL_RGB8},
00791     {"GL_RGB5", GL_RGB5},
00792     {"GL_RGB4", GL_RGB4},
00793     {"GL_R3_G3_B2", GL_R3_G3_B2},
00794     {"GL_RGB2", GL_RGB2_EXT},
00795     {"GL_RGB4", GL_RGB4_EXT},
00796     {"GL_RGB5", GL_RGB5_EXT},
00797     {"GL_RGB8", GL_RGB8_EXT},
00798     {"GL_RGB10", GL_RGB10_EXT},
00799     {"GL_RGB12", GL_RGB12_EXT},
00800     {"GL_RGB16", GL_RGB16_EXT},
00801     {"GL_LUMINANCE", GL_LUMINANCE},
00802     {"GL_LUMINANCE4", GL_LUMINANCE4},
00803     {"GL_LUMINANCE8", GL_LUMINANCE8},
00804     {"GL_LUMINANCE12", GL_LUMINANCE12},
00805     {"GL_LUMINANCE16", GL_LUMINANCE16}
00806 };
00807 
00808 void R_TextureSolidMode (const char *string)
00809 {
00810     int i;
00811     const size_t size = lengthof(gl_solid_modes);
00812 
00813     for (i = 0; i < size; i++) {
00814         const gltmode_t *mode = &gl_solid_modes[i];
00815         if (!Q_strcasecmp(mode->name, string)) {
00816             r_config.gl_solid_format = mode->mode;
00817             return;
00818         }
00819     }
00820 
00821     Com_Printf("bad solid texture mode name (%s)\n", string);
00822 }
00823 

Generated by  doxygen 1.6.2