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