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