00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00037 image_t *r_envmaptextures[MAX_ENVMAPTEXTURES];
00038
00039
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
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) {
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);
00226
00227 VectorScale(temp, brightness, temp);
00228
00229 max = 0.0;
00230
00231 for (j = 0; j < 3; j++) {
00232 if (temp[j] > max)
00233 max = temp[j];
00234
00235 if (temp[j] < 0.0)
00236 temp[j] = 0.0;
00237 }
00238
00239 if (max > 1.0)
00240 VectorScale(temp, 1.0 / max, temp);
00241
00242 for (j = 0; j < 3; j++) {
00243 temp[j] -= 0.5;
00244 temp[j] *= contrast;
00245 temp[j] += 0.5;
00246
00247 if (temp[j] > 1.0)
00248 temp[j] = 1.0;
00249 else if (temp[j] < 0)
00250 temp[j] = 0;
00251 }
00252
00253
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;
00261
00262 if (temp[j] > 255)
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
00315 c = width * height;
00316
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;
00328 image->upload_height = scaledHeight;
00329
00330
00331 if (!mipmap && scaledWidth == width && scaledHeight == height) {
00332
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) {
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
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
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
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;
00407
00408 const byte *u = (src - (width * bpp));
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;
00414
00415 for (k = 0; k < bpp; k++)
00416 dest[k] = (u[k] + d[k] + l[k] + r[k]) / 4;
00417 }
00418 }
00419
00420
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
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
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
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
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
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
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
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
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
00627 if (!image || !image->texnum)
00628 return;
00629
00630
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;
00655
00656
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;
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},
00714 {"GL_LINEAR", GL_LINEAR, GL_LINEAR},
00715 {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
00716 {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
00717 {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
00718 {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
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;
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