]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_draw.c
remove an unused variable
[divverent/darkplaces.git] / gl_draw.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20
21 #include "quakedef.h"
22 #include "image.h"
23 #include "wad.h"
24
25 #include "cl_video.h"
26
27
28 static rtexture_t *char_texture;
29
30 //=============================================================================
31 /* Support Routines */
32
33 #define FONT_FILESIZE 13468
34 #define MAX_CACHED_PICS 1024
35 #define CACHEPICHASHSIZE 256
36 static cachepic_t *cachepichash[CACHEPICHASHSIZE];
37 static cachepic_t cachepics[MAX_CACHED_PICS];
38 static int numcachepics;
39
40 static rtexturepool_t *drawtexturepool;
41
42 static unsigned char concharimage[FONT_FILESIZE] =
43 {
44 #include "lhfont.h"
45 };
46
47 static rtexture_t *draw_generateconchars(void)
48 {
49         int i;
50         unsigned char buffer[65536][4], *data = NULL;
51         double random;
52
53         data = LoadTGA (concharimage, FONT_FILESIZE, 256, 256);
54 // Gold numbers
55         for (i = 0;i < 8192;i++)
56         {
57                 random = lhrandom (0.0,1.0);
58                 buffer[i][0] = 83 + (unsigned char)(random * 64);
59                 buffer[i][1] = 71 + (unsigned char)(random * 32);
60                 buffer[i][2] = 23 + (unsigned char)(random * 16);
61                 buffer[i][3] = data[i*4+0];
62         }
63 // White chars
64         for (i = 8192;i < 32768;i++)
65         {
66                 random = lhrandom (0.0,1.0);
67                 buffer[i][0] = 95 + (unsigned char)(random * 64);
68                 buffer[i][1] = 95 + (unsigned char)(random * 64);
69                 buffer[i][2] = 95 + (unsigned char)(random * 64);
70                 buffer[i][3] = data[i*4+0];
71         }
72 // Gold numbers
73         for (i = 32768;i < 40960;i++)
74         {
75                 random = lhrandom (0.0,1.0);
76                 buffer[i][0] = 83 + (unsigned char)(random * 64);
77                 buffer[i][1] = 71 + (unsigned char)(random * 32);
78                 buffer[i][2] = 23 + (unsigned char)(random * 16);
79                 buffer[i][3] = data[i*4+0];
80         }
81 // Red chars
82         for (i = 40960;i < 65536;i++)
83         {
84                 random = lhrandom (0.0,1.0);
85                 buffer[i][0] = 96 + (unsigned char)(random * 64);
86                 buffer[i][1] = 43 + (unsigned char)(random * 32);
87                 buffer[i][2] = 27 + (unsigned char)(random * 32);
88                 buffer[i][3] = data[i*4+0];
89         }
90
91 #if 0
92         Image_WriteTGARGBA ("gfx/generated_conchars.tga", 256, 256, &buffer[0][0]);
93 #endif
94
95         Mem_Free(data);
96         return R_LoadTexture2D(drawtexturepool, "conchars", 256, 256, &buffer[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
97 }
98
99 static char *pointerimage =
100         "333333332......."
101         "26777761........"
102         "2655541........."
103         "265541.........."
104         "2654561........."
105         "26414561........"
106         "251.14561......."
107         "21...14561......"
108         "1.....141......."
109         ".......1........"
110         "................"
111         "................"
112         "................"
113         "................"
114         "................"
115         "................"
116 ;
117
118 static rtexture_t *draw_generatemousepointer(void)
119 {
120         int i;
121         unsigned char buffer[256][4];
122         for (i = 0;i < 256;i++)
123         {
124                 if (pointerimage[i] == '.')
125                 {
126                         buffer[i][0] = 0;
127                         buffer[i][1] = 0;
128                         buffer[i][2] = 0;
129                         buffer[i][3] = 0;
130                 }
131                 else
132                 {
133                         buffer[i][0] = (pointerimage[i] - '0') * 16;
134                         buffer[i][1] = (pointerimage[i] - '0') * 16;
135                         buffer[i][2] = (pointerimage[i] - '0') * 16;
136                         buffer[i][3] = 255;
137                 }
138         }
139         return R_LoadTexture2D(drawtexturepool, "mousepointer", 16, 16, &buffer[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
140 }
141
142 // must match NUMCROSSHAIRS in r_crosshairs.c
143 #define NUMCROSSHAIRS 6
144
145 static char *crosshairtexdata[NUMCROSSHAIRS] =
146 {
147         "................"
148         "................"
149         "................"
150         "...33......33..."
151         "...355....553..."
152         "....577..775...."
153         ".....77..77....."
154         "................"
155         "................"
156         ".....77..77....."
157         "....577..775...."
158         "...355....553..."
159         "...33......33..."
160         "................"
161         "................"
162         "................"
163         ,
164         "................"
165         "................"
166         "................"
167         "...3........3..."
168         "....5......5...."
169         ".....7....7....."
170         "......7..7......"
171         "................"
172         "................"
173         "......7..7......"
174         ".....7....7....."
175         "....5......5...."
176         "...3........3..."
177         "................"
178         "................"
179         "................"
180         ,
181         "................"
182         ".......77......."
183         ".......77......."
184         "................"
185         "................"
186         ".......44......."
187         ".......44......."
188         ".77..44..44..77."
189         ".77..44..44..77."
190         ".......44......."
191         ".......44......."
192         "................"
193         "................"
194         ".......77......."
195         ".......77......."
196         "................"
197         ,
198         "................"
199         "................"
200         "................"
201         "................"
202         "................"
203         "................"
204         "................"
205         "................"
206         "........7777777."
207         "........752....."
208         "........72......"
209         "........7......."
210         "........7......."
211         "........7......."
212         "........7......."
213         "................"
214         ,
215         "................"
216         "................"
217         "................"
218         "................"
219         "................"
220         "........7......."
221         "................"
222         "........4......."
223         ".....7.4.4.7...."
224         "........4......."
225         "................"
226         "........7......."
227         "................"
228         "................"
229         "................"
230         "................"
231         ,
232         "................"
233         "................"
234         "................"
235         "................"
236         "................"
237         "................"
238         "................"
239         ".......55......."
240         ".......55......."
241         "................"
242         "................"
243         "................"
244         "................"
245         "................"
246         "................"
247         "................"
248 };
249
250 static rtexture_t *draw_generatecrosshair(int num)
251 {
252         int i;
253         char *in;
254         unsigned char data[16*16][4];
255         in = crosshairtexdata[num];
256         for (i = 0;i < 16*16;i++)
257         {
258                 if (in[i] == '.')
259                 {
260                         data[i][0] = 255;
261                         data[i][1] = 255;
262                         data[i][2] = 255;
263                         data[i][3] = 0;
264                 }
265                 else
266                 {
267                         data[i][0] = 255;
268                         data[i][1] = 255;
269                         data[i][2] = 255;
270                         data[i][3] = (unsigned char) ((int) (in[i] - '0') * 255 / 7);
271                 }
272         }
273         return R_LoadTexture2D(drawtexturepool, va("crosshair%i", num), 16, 16, &data[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
274 }
275
276 static rtexture_t *draw_generateditherpattern(void)
277 {
278 #if 1
279         int x, y;
280         unsigned char data[8*8*4];
281         for (y = 0;y < 8;y++)
282         {
283                 for (x = 0;x < 8;x++)
284                 {
285                         data[(y*8+x)*4+0] = data[(y*8+x)*4+1] = data[(y*8+x)*4+2] = ((x^y) & 4) ? 255 : 0;
286                         data[(y*8+x)*4+3] = 255;
287                 }
288         }
289         return R_LoadTexture2D(drawtexturepool, "ditherpattern", 8, 8, data, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_PRECACHE, NULL);
290 #else
291         unsigned char data[16];
292         memset(data, 255, sizeof(data));
293         data[0] = data[1] = data[2] = data[12] = data[13] = data[14] = 0;
294         return R_LoadTexture2D(drawtexturepool, "ditherpattern", 2, 2, data, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_PRECACHE, NULL);
295 #endif
296 }
297
298 /*
299 ================
300 Draw_CachePic
301 ================
302 */
303 // FIXME: move this to client somehow
304 cachepic_t      *Draw_CachePic (const char *path, qboolean persistent)
305 {
306         int crc, hashkey;
307         cachepic_t *pic;
308         qpic_t *p;
309         int flags;
310
311         if (!strncmp(CLVIDEOPREFIX, path, sizeof(CLVIDEOPREFIX) - 1))
312
313         {
314                 clvideo_t *video;
315
316                 video = CL_GetVideo(path);
317                 if( video )
318                         return &video->cpif;
319         }
320
321         crc = CRC_Block((unsigned char *)path, strlen(path));
322         hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
323         for (pic = cachepichash[hashkey];pic;pic = pic->chain)
324                 if (!strcmp (path, pic->name))
325                         return pic;
326
327         if (numcachepics == MAX_CACHED_PICS)
328         {
329                 Con_Printf ("Draw_CachePic: numcachepics == MAX_CACHED_PICS\n");
330                 // FIXME: support NULL in callers?
331                 return cachepics; // return the first one
332         }
333         pic = cachepics + (numcachepics++);
334         strlcpy (pic->name, path, sizeof(pic->name));
335         // link into list
336         pic->chain = cachepichash[hashkey];
337         cachepichash[hashkey] = pic;
338
339         flags = TEXF_ALPHA;
340         if (persistent)
341                 flags |= TEXF_PRECACHE;
342         if (!strcmp(path, "gfx/colorcontrol/ditherpattern"))
343                 flags |= TEXF_CLAMP;
344
345         // load the pic from disk
346         pic->tex = loadtextureimage(drawtexturepool, path, 0, 0, false, flags);
347         if (pic->tex == NULL && !strncmp(path, "gfx/", 4))
348         {
349                 // compatibility with older versions
350                 pic->tex = loadtextureimage(drawtexturepool, path + 4, 0, 0, false, flags);
351                 // failed to find gfx/whatever.tga or similar, try the wad
352                 if (pic->tex == NULL && (p = (qpic_t *)W_GetLumpName (path + 4)))
353                 {
354                         if (!strcmp(path, "gfx/conchars"))
355                         {
356                                 // conchars is a raw image and with color 0 as transparent instead of 255
357                                 pic->tex = R_LoadTexture2D(drawtexturepool, path, 128, 128, (unsigned char *)p, TEXTYPE_PALETTE, flags, palette_font);
358                         }
359                         else
360                                 pic->tex = R_LoadTexture2D(drawtexturepool, path, p->width, p->height, p->data, TEXTYPE_PALETTE, flags, palette_transparent);
361                 }
362         }
363
364         if (pic->tex == NULL && !strcmp(path, "gfx/conchars"))
365                 pic->tex = draw_generateconchars();
366         if (pic->tex == NULL && !strcmp(path, "ui/mousepointer"))
367                 pic->tex = draw_generatemousepointer();
368         if (pic->tex == NULL && !strcmp(path, "gfx/prydoncursor001"))
369                 pic->tex = draw_generatemousepointer();
370         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair1"))
371                 pic->tex = draw_generatecrosshair(0);
372         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair2"))
373                 pic->tex = draw_generatecrosshair(1);
374         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair3"))
375                 pic->tex = draw_generatecrosshair(2);
376         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair4"))
377                 pic->tex = draw_generatecrosshair(3);
378         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair5"))
379                 pic->tex = draw_generatecrosshair(4);
380         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair6"))
381                 pic->tex = draw_generatecrosshair(5);
382         if (pic->tex == NULL && !strcmp(path, "gfx/colorcontrol/ditherpattern"))
383                 pic->tex = draw_generateditherpattern();
384         if (pic->tex == NULL)
385         {
386                 Con_Printf("Draw_CachePic: failed to load %s\n", path);
387                 pic->tex = r_texture_notexture;
388         }
389
390         pic->width = R_TextureWidth(pic->tex);
391         pic->height = R_TextureHeight(pic->tex);
392         return pic;
393 }
394
395 cachepic_t *Draw_NewPic(const char *picname, int width, int height, int alpha, unsigned char *pixels)
396 {
397         int crc, hashkey;
398         cachepic_t *pic;
399
400         crc = CRC_Block((unsigned char *)picname, strlen(picname));
401         hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
402         for (pic = cachepichash[hashkey];pic;pic = pic->chain)
403                 if (!strcmp (picname, pic->name))
404                         break;
405
406         if (pic)
407         {
408                 if (pic->tex && pic->width == width && pic->height == height)
409                 {
410                         R_UpdateTexture(pic->tex, pixels);
411                         return pic;
412                 }
413         }
414         else
415         {
416                 if (pic == NULL)
417                 {
418                         if (numcachepics == MAX_CACHED_PICS)
419                         {
420                                 Con_Printf ("Draw_NewPic: numcachepics == MAX_CACHED_PICS\n");
421                                 // FIXME: support NULL in callers?
422                                 return cachepics; // return the first one
423                         }
424                         pic = cachepics + (numcachepics++);
425                         strcpy (pic->name, picname);
426                         // link into list
427                         pic->chain = cachepichash[hashkey];
428                         cachepichash[hashkey] = pic;
429                 }
430         }
431
432         pic->width = width;
433         pic->height = height;
434         if (pic->tex)
435                 R_FreeTexture(pic->tex);
436         pic->tex = R_LoadTexture2D(drawtexturepool, picname, width, height, pixels, TEXTYPE_RGBA, alpha ? TEXF_ALPHA : 0, NULL);
437         return pic;
438 }
439
440 void Draw_FreePic(const char *picname)
441 {
442         int crc;
443         int hashkey;
444         cachepic_t *pic;
445         // this doesn't really free the pic, but does free it's texture
446         crc = CRC_Block((unsigned char *)picname, strlen(picname));
447         hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
448         for (pic = cachepichash[hashkey];pic;pic = pic->chain)
449         {
450                 if (!strcmp (picname, pic->name) && pic->tex)
451                 {
452                         R_FreeTexture(pic->tex);
453                         pic->width = 0;
454                         pic->height = 0;
455                         return;
456                 }
457         }
458 }
459
460 /*
461 ===============
462 Draw_Init
463 ===============
464 */
465 static void gl_draw_start(void)
466 {
467         drawtexturepool = R_AllocTexturePool();
468
469         numcachepics = 0;
470         memset(cachepichash, 0, sizeof(cachepichash));
471
472         char_texture = Draw_CachePic("gfx/conchars", true)->tex;
473 }
474
475 static void gl_draw_shutdown(void)
476 {
477         R_FreeTexturePool(&drawtexturepool);
478
479         numcachepics = 0;
480         memset(cachepichash, 0, sizeof(cachepichash));
481 }
482
483 static void gl_draw_newmap(void)
484 {
485 }
486
487 void GL_Draw_Init (void)
488 {
489         numcachepics = 0;
490         memset(cachepichash, 0, sizeof(cachepichash));
491
492         R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap);
493 }
494
495 float blendvertex3f[9] = {-5000, -5000, 10, 10000, -5000, 10, -5000, 10000, 10};
496
497 int quadelements[768];
498 void R_DrawQueue(void)
499 {
500         int pos, num, chartexnum, texnum, batch;
501         float x, y, w, h, s, t, u, v, *av, *at, c[4];
502         cachepic_t *pic;
503         drawqueue_t *dq;
504         char *str;
505         int batchcount;
506         unsigned int color;
507         drawqueuemesh_t *mesh;
508         rmeshstate_t m;
509
510         if (!r_render.integer)
511                 return;
512
513         if (!quadelements[1])
514         {
515                 // elements for rendering a series of quads as triangles
516                 for (batch = 0, pos = 0, num = 0;batch < 128;batch++, num += 4)
517                 {
518                         quadelements[pos++] = num;
519                         quadelements[pos++] = num + 1;
520                         quadelements[pos++] = num + 2;
521                         quadelements[pos++] = num;
522                         quadelements[pos++] = num + 2;
523                         quadelements[pos++] = num + 3;
524                 }
525         }
526
527         r_view_width = bound(0, r_refdef.width, vid.width);
528         r_view_height = bound(0, r_refdef.height, vid.height);
529         r_view_depth = 1;
530         r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
531         r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
532         r_view_z = 0;
533         r_view_matrix = r_refdef.viewentitymatrix;
534         GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
535
536         qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
537         GL_SetupView_Mode_Ortho(0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100);
538         qglDepthFunc(GL_LEQUAL);
539         R_Mesh_Matrix(&r_identitymatrix);
540
541         chartexnum = R_GetTexture(char_texture);
542
543         memset(&m, 0, sizeof(m));
544
545         pic = NULL;
546         texnum = 0;
547         color = 0;
548         GL_Color(1,1,1,1);
549
550         batch = false;
551         batchcount = 0;
552         for (pos = 0;pos < r_refdef.drawqueuesize;pos += ((drawqueue_t *)(r_refdef.drawqueue + pos))->size)
553         {
554                 dq = (drawqueue_t *)(r_refdef.drawqueue + pos);
555                 color = dq->color;
556
557                 if(dq->flags == DRAWFLAG_ADDITIVE)
558                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
559                 else if(dq->flags == DRAWFLAG_MODULATE)
560                         GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
561                 else if(dq->flags == DRAWFLAG_2XMODULATE)
562                         GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
563                 else
564                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
565
566                 GL_DepthMask(true);
567                 GL_DepthTest(false);
568
569                 c[0] = (float) ((color >> 24) & 0xFF) * (1.0f / 255.0f);
570                 c[1] = (float) ((color >> 16) & 0xFF) * (1.0f / 255.0f);
571                 c[2] = (float) ((color >>  8) & 0xFF) * (1.0f / 255.0f);
572                 c[3] = (float) ( color        & 0xFF) * (1.0f / 255.0f);
573                 x = dq->x;
574                 y = dq->y;
575                 w = dq->scalex;
576                 h = dq->scaley;
577
578                 switch(dq->command)
579                 {
580                 case DRAWQUEUE_STRING:
581                         GL_Color(c[0], c[1], c[2], c[3]);
582                         str = (char *)(dq + 1);
583                         batchcount = 0;
584                         m.pointer_vertex = varray_vertex3f;
585                         m.pointer_color = NULL;
586                         m.pointer_texcoord[0] = varray_texcoord2f[0];
587                         m.tex[0] = chartexnum;
588                         R_Mesh_State(&m);
589                         at = varray_texcoord2f[0];
590                         av = varray_vertex3f;
591                         while ((num = *str++) && x < vid_conwidth.integer)
592                         {
593                                 if (num != ' ')
594                                 {
595                                         s = (num & 15)*0.0625f + (0.5f / 256.0f);
596                                         t = (num >> 4)*0.0625f + (0.5f / 256.0f);
597                                         u = 0.0625f - (1.0f / 256.0f);
598                                         v = 0.0625f - (1.0f / 256.0f);
599                                         at[ 0] = s  ;at[ 1] = t  ;
600                                         at[ 2] = s+u;at[ 3] = t  ;
601                                         at[ 4] = s+u;at[ 5] = t+v;
602                                         at[ 6] = s  ;at[ 7] = t+v;
603                                         av[ 0] = x  ;av[ 1] = y  ;av[ 2] = 10;
604                                         av[ 3] = x+w;av[ 4] = y  ;av[ 5] = 10;
605                                         av[ 6] = x+w;av[ 7] = y+h;av[ 8] = 10;
606                                         av[ 9] = x  ;av[10] = y+h;av[11] = 10;
607                                         at += 8;
608                                         av += 12;
609                                         batchcount++;
610                                         if (batchcount >= 128)
611                                         {
612                                                 GL_LockArrays(0, batchcount * 4);
613                                                 R_Mesh_Draw(0, batchcount * 4, batchcount * 2, quadelements);
614                                                 GL_LockArrays(0, 0);
615                                                 batchcount = 0;
616                                                 at = varray_texcoord2f[0];
617                                                 av = varray_vertex3f;
618                                         }
619                                 }
620                                 x += w;
621                         }
622                         if (batchcount > 0)
623                         {
624                                 GL_LockArrays(0, batchcount * 4);
625                                 R_Mesh_Draw(0, batchcount * 4, batchcount * 2, quadelements);
626                                 GL_LockArrays(0, 0);
627                         }
628                         break;
629                 case DRAWQUEUE_MESH:
630                         mesh = (drawqueuemesh_t *)(dq + 1);
631                         m.pointer_vertex = mesh->data_vertex3f;
632                         m.pointer_color = mesh->data_color4f;
633                         m.pointer_texcoord[0] = mesh->data_texcoord2f;
634                         m.tex[0] = R_GetTexture(mesh->texture);
635                         if (!m.tex[0])
636                                 m.pointer_texcoord[0] = NULL;
637                         R_Mesh_State(&m);
638                         GL_LockArrays(0, mesh->num_vertices);
639                         R_Mesh_Draw(0, mesh->num_vertices, mesh->num_triangles, mesh->data_element3i);
640                         GL_LockArrays(0, 0);
641                         break;
642                 case DRAWQUEUE_SETCLIP:
643                         {
644                                 // We have to convert the con coords into real coords
645                                 int x , y, width, height;
646                                 x = dq->x * ((float)vid.width / vid_conwidth.integer);
647                                 // OGL uses top to bottom
648                                 y = dq->y * ((float) vid.height / vid_conheight.integer);
649                                 width = dq->scalex * ((float)vid.width / vid_conwidth.integer);
650                                 height = dq->scaley * ((float)vid.height / vid_conheight.integer);
651
652                                 GL_Scissor(x, y, width, height);
653
654                                 GL_ScissorTest(true);
655                         }
656                         break;
657                 case DRAWQUEUE_RESETCLIP:
658                         GL_ScissorTest(false);
659                         break;
660                 }
661         }
662
663         if (!vid_usinghwgamma)
664         {
665                 // all the blends ignore depth
666                 memset(&m, 0, sizeof(m));
667                 m.pointer_vertex = blendvertex3f;
668                 R_Mesh_State(&m);
669                 GL_DepthMask(true);
670                 GL_DepthTest(false);
671                 if (v_color_enable.integer)
672                 {
673                         c[0] = v_color_white_r.value;
674                         c[1] = v_color_white_g.value;
675                         c[2] = v_color_white_b.value;
676                 }
677                 else
678                         c[0] = c[1] = c[2] = v_contrast.value;
679                 if (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f)
680                 {
681                         GL_BlendFunc(GL_DST_COLOR, GL_ONE);
682                         while (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f)
683                         {
684                                 GL_Color(bound(0, c[0] - 1, 1), bound(0, c[1] - 1, 1), bound(0, c[2] - 1, 1), 1);
685                                 R_Mesh_Draw(0, 3, 1, polygonelements);
686                                 VectorScale(c, 0.5, c);
687                         }
688                 }
689                 if (v_color_enable.integer)
690                 {
691                         c[0] = v_color_black_r.value;
692                         c[1] = v_color_black_g.value;
693                         c[2] = v_color_black_b.value;
694                 }
695                 else
696                         c[0] = c[1] = c[2] = v_brightness.value;
697                 if (c[0] >= 0.01f || c[1] >= 0.01f || c[2] >= 0.01f)
698                 {
699                         GL_BlendFunc(GL_ONE, GL_ONE);
700                         GL_Color(c[0], c[1], c[2], 1);
701                         R_Mesh_Draw(0, 3, 1, polygonelements);
702                 }
703         }
704 }
705