2 Copyright (C) 1996-1997 Id Software, Inc.
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.
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.
13 See the GNU General Public License for more details.
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.
27 cvar_t r_textshadow = {CVAR_SAVE, "r_textshadow", "0", "draws a shadow on all text to improve readability (note: value controls offset, 1 = 1 pixel, 1.5 = 1.5 pixels, etc)"};
29 static rtexture_t *char_texture;
30 cachepic_t *r_crosshairs[NUMCROSSHAIRS+1];
32 //=============================================================================
33 /* Support Routines */
35 #define FONT_FILESIZE 13468
36 #define MAX_CACHED_PICS 1024
37 #define CACHEPICHASHSIZE 256
38 static cachepic_t *cachepichash[CACHEPICHASHSIZE];
39 static cachepic_t cachepics[MAX_CACHED_PICS];
40 static int numcachepics;
42 static rtexturepool_t *drawtexturepool;
44 static unsigned char concharimage[FONT_FILESIZE] =
49 static rtexture_t *draw_generateconchars(void)
52 unsigned char buffer[65536][4], *data = NULL;
55 data = LoadTGA (concharimage, FONT_FILESIZE, 256, 256);
57 for (i = 0;i < 8192;i++)
59 random = lhrandom (0.0,1.0);
60 buffer[i][0] = 83 + (unsigned char)(random * 64);
61 buffer[i][1] = 71 + (unsigned char)(random * 32);
62 buffer[i][2] = 23 + (unsigned char)(random * 16);
63 buffer[i][3] = data[i*4+0];
66 for (i = 8192;i < 32768;i++)
68 random = lhrandom (0.0,1.0);
69 buffer[i][0] = 95 + (unsigned char)(random * 64);
70 buffer[i][1] = 95 + (unsigned char)(random * 64);
71 buffer[i][2] = 95 + (unsigned char)(random * 64);
72 buffer[i][3] = data[i*4+0];
75 for (i = 32768;i < 40960;i++)
77 random = lhrandom (0.0,1.0);
78 buffer[i][0] = 83 + (unsigned char)(random * 64);
79 buffer[i][1] = 71 + (unsigned char)(random * 32);
80 buffer[i][2] = 23 + (unsigned char)(random * 16);
81 buffer[i][3] = data[i*4+0];
84 for (i = 40960;i < 65536;i++)
86 random = lhrandom (0.0,1.0);
87 buffer[i][0] = 96 + (unsigned char)(random * 64);
88 buffer[i][1] = 43 + (unsigned char)(random * 32);
89 buffer[i][2] = 27 + (unsigned char)(random * 32);
90 buffer[i][3] = data[i*4+0];
94 Image_WriteTGARGBA ("gfx/generated_conchars.tga", 256, 256, &buffer[0][0]);
98 return R_LoadTexture2D(drawtexturepool, "conchars", 256, 256, &buffer[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
101 static char *pointerimage =
120 static rtexture_t *draw_generatemousepointer(void)
123 unsigned char buffer[256][4];
124 for (i = 0;i < 256;i++)
126 if (pointerimage[i] == '.')
135 buffer[i][0] = (pointerimage[i] - '0') * 16;
136 buffer[i][1] = (pointerimage[i] - '0') * 16;
137 buffer[i][2] = (pointerimage[i] - '0') * 16;
141 return R_LoadTexture2D(drawtexturepool, "mousepointer", 16, 16, &buffer[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
144 static char *crosshairtexdata[NUMCROSSHAIRS] =
249 static rtexture_t *draw_generatecrosshair(int num)
253 unsigned char data[16*16][4];
254 in = crosshairtexdata[num];
255 for (i = 0;i < 16*16;i++)
266 data[i][0] = data[i][1] = data[i][2] = (unsigned char) ((int) (in[i] - '0') * 127 / 7 + 128);
270 return R_LoadTexture2D(drawtexturepool, va("crosshair%i", num+1), 16, 16, &data[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
273 static rtexture_t *draw_generateditherpattern(void)
277 unsigned char data[8*8*4];
278 for (y = 0;y < 8;y++)
280 for (x = 0;x < 8;x++)
282 data[(y*8+x)*4+0] = data[(y*8+x)*4+1] = data[(y*8+x)*4+2] = ((x^y) & 4) ? 255 : 0;
283 data[(y*8+x)*4+3] = 255;
286 return R_LoadTexture2D(drawtexturepool, "ditherpattern", 8, 8, data, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_PRECACHE, NULL);
288 unsigned char data[16];
289 memset(data, 255, sizeof(data));
290 data[0] = data[1] = data[2] = data[12] = data[13] = data[14] = 0;
291 return R_LoadTexture2D(drawtexturepool, "ditherpattern", 2, 2, data, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_PRECACHE, NULL);
300 // FIXME: move this to client somehow
301 cachepic_t *Draw_CachePic (const char *path, qboolean persistent)
307 unsigned char *lmpdata;
308 char lmpname[MAX_QPATH];
310 if (!strncmp(CLVIDEOPREFIX, path, sizeof(CLVIDEOPREFIX) - 1))
314 video = CL_GetVideoByName(path);
319 crc = CRC_Block((unsigned char *)path, strlen(path));
320 hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
321 for (pic = cachepichash[hashkey];pic;pic = pic->chain)
322 if (!strcmp (path, pic->name))
325 if (numcachepics == MAX_CACHED_PICS)
327 Con_Printf ("Draw_CachePic: numcachepics == MAX_CACHED_PICS\n");
328 // FIXME: support NULL in callers?
329 return cachepics; // return the first one
331 pic = cachepics + (numcachepics++);
332 strlcpy (pic->name, path, sizeof(pic->name));
334 pic->chain = cachepichash[hashkey];
335 cachepichash[hashkey] = pic;
339 flags |= TEXF_PRECACHE;
340 if (!strcmp(path, "gfx/colorcontrol/ditherpattern"))
343 // load a high quality image from disk if possible
344 pic->tex = loadtextureimage(drawtexturepool, path, 0, 0, false, flags | (gl_texturecompression_2d.integer ? TEXF_COMPRESS : 0));
345 if (pic->tex == NULL && !strncmp(path, "gfx/", 4))
347 // compatibility with older versions which did not require gfx/ prefix
348 pic->tex = loadtextureimage(drawtexturepool, path + 4, 0, 0, false, flags | (gl_texturecompression_2d.integer ? TEXF_COMPRESS : 0));
350 // if a high quality image was loaded, set the pic's size to match it, just
351 // in case there's no low quality version to get the size from
354 pic->width = R_TextureWidth(pic->tex);
355 pic->height = R_TextureHeight(pic->tex);
358 // now read the low quality version (wad or lmp file), and take the pic
359 // size from that even if we don't upload the texture, this way the pics
360 // show up the right size in the menu even if they were replaced with
361 // higher or lower resolution versions
362 dpsnprintf(lmpname, sizeof(lmpname), "%s.lmp", path);
363 if (!strncmp(path, "gfx/", 4) && (lmpdata = FS_LoadFile(lmpname, tempmempool, false, &lmpsize)))
367 pic->width = lmpdata[0] + lmpdata[1] * 256 + lmpdata[2] * 65536 + lmpdata[3] * 16777216;
368 pic->height = lmpdata[4] + lmpdata[5] * 256 + lmpdata[6] * 65536 + lmpdata[7] * 16777216;
369 // if no high quality replacement image was found, upload the original low quality texture
371 pic->tex = R_LoadTexture2D(drawtexturepool, path, pic->width, pic->height, lmpdata + 8, TEXTYPE_PALETTE, flags, palette_transparent);
375 else if ((lmpdata = W_GetLumpName (path + 4)))
377 if (!strcmp(path, "gfx/conchars"))
379 // conchars is a raw image and with color 0 as transparent instead of 255
382 // if no high quality replacement image was found, upload the original low quality texture
384 pic->tex = R_LoadTexture2D(drawtexturepool, path, 128, 128, lmpdata, TEXTYPE_PALETTE, flags, palette_font);
388 pic->width = lmpdata[0] + lmpdata[1] * 256 + lmpdata[2] * 65536 + lmpdata[3] * 16777216;
389 pic->height = lmpdata[4] + lmpdata[5] * 256 + lmpdata[6] * 65536 + lmpdata[7] * 16777216;
390 // if no high quality replacement image was found, upload the original low quality texture
392 pic->tex = R_LoadTexture2D(drawtexturepool, path, pic->width, pic->height, lmpdata + 8, TEXTYPE_PALETTE, flags, palette_transparent);
396 // if it's not found on disk, check if it's one of the builtin images
397 if (pic->tex == NULL)
399 if (pic->tex == NULL && !strcmp(path, "gfx/conchars"))
400 pic->tex = draw_generateconchars();
401 if (pic->tex == NULL && !strcmp(path, "ui/mousepointer"))
402 pic->tex = draw_generatemousepointer();
403 if (pic->tex == NULL && !strcmp(path, "gfx/prydoncursor001"))
404 pic->tex = draw_generatemousepointer();
405 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair1"))
406 pic->tex = draw_generatecrosshair(0);
407 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair2"))
408 pic->tex = draw_generatecrosshair(1);
409 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair3"))
410 pic->tex = draw_generatecrosshair(2);
411 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair4"))
412 pic->tex = draw_generatecrosshair(3);
413 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair5"))
414 pic->tex = draw_generatecrosshair(4);
415 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair6"))
416 pic->tex = draw_generatecrosshair(5);
417 if (pic->tex == NULL && !strcmp(path, "gfx/colorcontrol/ditherpattern"))
418 pic->tex = draw_generateditherpattern();
419 if (pic->tex == NULL)
421 // don't complain about missing gfx/crosshair images
422 if (strncmp(path, "gfx/crosshair", 13))
423 Con_Printf("Draw_CachePic: failed to load %s\n", path);
424 pic->tex = r_texture_notexture;
426 pic->width = R_TextureWidth(pic->tex);
427 pic->height = R_TextureHeight(pic->tex);
433 cachepic_t *Draw_NewPic(const char *picname, int width, int height, int alpha, unsigned char *pixels)
438 crc = CRC_Block((unsigned char *)picname, strlen(picname));
439 hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
440 for (pic = cachepichash[hashkey];pic;pic = pic->chain)
441 if (!strcmp (picname, pic->name))
446 if (pic->tex && pic->width == width && pic->height == height)
448 R_UpdateTexture(pic->tex, pixels, 0, 0, width, height);
456 if (numcachepics == MAX_CACHED_PICS)
458 Con_Printf ("Draw_NewPic: numcachepics == MAX_CACHED_PICS\n");
459 // FIXME: support NULL in callers?
460 return cachepics; // return the first one
462 pic = cachepics + (numcachepics++);
463 strlcpy (pic->name, picname, sizeof(pic->name));
465 pic->chain = cachepichash[hashkey];
466 cachepichash[hashkey] = pic;
471 pic->height = height;
473 R_FreeTexture(pic->tex);
474 pic->tex = R_LoadTexture2D(drawtexturepool, picname, width, height, pixels, TEXTYPE_RGBA, alpha ? TEXF_ALPHA : 0, NULL);
478 void Draw_FreePic(const char *picname)
483 // this doesn't really free the pic, but does free it's texture
484 crc = CRC_Block((unsigned char *)picname, strlen(picname));
485 hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
486 for (pic = cachepichash[hashkey];pic;pic = pic->chain)
488 if (!strcmp (picname, pic->name) && pic->tex)
490 R_FreeTexture(pic->tex);
503 static void gl_draw_start(void)
506 drawtexturepool = R_AllocTexturePool();
509 memset(cachepichash, 0, sizeof(cachepichash));
511 char_texture = Draw_CachePic("gfx/conchars", true)->tex;
512 for (i = 1;i <= NUMCROSSHAIRS;i++)
513 r_crosshairs[i] = Draw_CachePic(va("gfx/crosshair%i", i), true);
515 // draw the loading screen so people have something to see in the newly opened window
516 SCR_UpdateLoadingScreen(true);
519 static void gl_draw_shutdown(void)
521 R_FreeTexturePool(&drawtexturepool);
524 memset(cachepichash, 0, sizeof(cachepichash));
527 static void gl_draw_newmap(void)
531 void GL_Draw_Init (void)
533 Cvar_RegisterVariable(&r_textshadow);
534 R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap);
537 static void _DrawQ_Setup(void)
539 if (r_refdef.draw2dstage)
541 r_refdef.draw2dstage = true;
543 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
544 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
545 GL_SetupView_Mode_Ortho(0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100);
546 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
547 qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
548 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
549 R_Mesh_Matrix(&identitymatrix);
553 GL_PolygonOffset(0, 0);
557 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
559 if (gl_support_fragment_shader)
561 qglUseProgramObjectARB(0);CHECKGLERROR
565 static void _DrawQ_ProcessDrawFlag(int flags)
569 if(flags == DRAWFLAG_ADDITIVE)
570 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
571 else if(flags == DRAWFLAG_MODULATE)
572 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
573 else if(flags == DRAWFLAG_2XMODULATE)
574 GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
576 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
579 void DrawQ_Pic(float x, float y, cachepic_t *pic, float width, float height, float red, float green, float blue, float alpha, int flags)
583 _DrawQ_ProcessDrawFlag(flags);
584 GL_Color(red, green, blue, alpha);
586 R_Mesh_VertexPointer(floats, 0, 0);
587 R_Mesh_ColorPointer(NULL, 0, 0);
588 R_Mesh_ResetTextureState();
594 height = pic->height;
595 R_Mesh_TexBind(0, R_GetTexture(pic->tex));
596 R_Mesh_TexCoordPointer(0, 2, floats + 12, 0, 0);
597 floats[12] = 0;floats[13] = 0;
598 floats[14] = 1;floats[15] = 0;
599 floats[16] = 1;floats[17] = 1;
600 floats[18] = 0;floats[19] = 1;
603 floats[2] = floats[5] = floats[8] = floats[11] = 0;
604 floats[0] = floats[9] = x;
605 floats[1] = floats[4] = y;
606 floats[3] = floats[6] = x + width;
607 floats[7] = floats[10] = y + height;
609 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
612 void DrawQ_Fill(float x, float y, float width, float height, float red, float green, float blue, float alpha, int flags)
616 _DrawQ_ProcessDrawFlag(flags);
617 GL_Color(red, green, blue, alpha);
619 R_Mesh_VertexPointer(floats, 0, 0);
620 R_Mesh_ColorPointer(NULL, 0, 0);
621 R_Mesh_ResetTextureState();
623 floats[2] = floats[5] = floats[8] = floats[11] = 0;
624 floats[0] = floats[9] = x;
625 floats[1] = floats[4] = y;
626 floats[3] = floats[6] = x + width;
627 floats[7] = floats[10] = y + height;
629 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
632 // color tag printing
633 static vec4_t string_colors[] =
636 // LordHavoc: why on earth is cyan before magenta in Quake3?
637 // LordHavoc: note: Doom3 uses white for [0] and [7]
638 {0.0, 0.0, 0.0, 1.0}, // black
639 {1.0, 0.0, 0.0, 1.0}, // red
640 {0.0, 1.0, 0.0, 1.0}, // green
641 {1.0, 1.0, 0.0, 1.0}, // yellow
642 {0.0, 0.0, 1.0, 1.0}, // blue
643 {0.0, 1.0, 1.0, 1.0}, // cyan
644 {1.0, 0.0, 1.0, 1.0}, // magenta
645 {1.0, 1.0, 1.0, 1.0}, // white
646 // [515]'s BX_COLOREDTEXT extension
647 {1.0, 1.0, 1.0, 0.5}, // half transparent
648 {0.5, 0.5, 0.5, 1.0} // half brightness
649 // Black's color table
650 //{1.0, 1.0, 1.0, 1.0},
651 //{1.0, 0.0, 0.0, 1.0},
652 //{0.0, 1.0, 0.0, 1.0},
653 //{0.0, 0.0, 1.0, 1.0},
654 //{1.0, 1.0, 0.0, 1.0},
655 //{0.0, 1.0, 1.0, 1.0},
656 //{1.0, 0.0, 1.0, 1.0},
657 //{0.1, 0.1, 0.1, 1.0}
660 #define STRING_COLORS_COUNT (sizeof(string_colors) / sizeof(vec4_t))
662 static void DrawQ_GetTextColor(float color[4], int colorindex, float r, float g, float b, float a, qboolean shadow)
664 Vector4Copy(string_colors[colorindex], color);
665 Vector4Set(color, color[0] * r, color[1] * g, color[2] * b, color[3] * a);
668 float shadowalpha = color[0]+color[1]+color[2] * 0.8;
669 Vector4Set(color, 0, 0, 0, color[3] * bound(0, shadowalpha, 1));
673 float DrawQ_String(float startx, float starty, const char *text, int maxlen, float w, float h, float basered, float basegreen, float baseblue, float basealpha, int flags, int *outcolor, qboolean ignorecolorcodes)
675 int i, num, shadow, colorindex = STRING_COLOR_DEFAULT;
676 float x = startx, y, s, t, u, v;
680 float vertex3f[QUADELEMENTS_MAXQUADS*4*3];
681 float texcoord2f[QUADELEMENTS_MAXQUADS*4*2];
682 float color4f[QUADELEMENTS_MAXQUADS*4*4];
687 _DrawQ_ProcessDrawFlag(flags);
689 R_Mesh_ColorPointer(color4f, 0, 0);
690 R_Mesh_ResetTextureState();
691 R_Mesh_TexBind(0, R_GetTexture(char_texture));
692 R_Mesh_TexCoordPointer(0, 2, texcoord2f, 0, 0);
693 R_Mesh_VertexPointer(vertex3f, 0, 0);
700 for (shadow = r_textshadow.value != 0;shadow >= 0;shadow--)
702 if (!outcolor || *outcolor == -1)
703 colorindex = STRING_COLOR_DEFAULT;
705 colorindex = *outcolor;
706 DrawQ_GetTextColor(color, colorindex, basered, basegreen, baseblue, basealpha, shadow);
712 x += r_textshadow.value;
713 y += r_textshadow.value;
715 for (i = 0;i < maxlen && text[i];i++, x += w)
719 if (text[i] == STRING_COLOR_TAG && !ignorecolorcodes && i + 1 < maxlen)
721 if (text[i+1] == STRING_COLOR_TAG)
727 else if (text[i+1] >= '0' && text[i+1] <= '9')
729 colorindex = text[i+1] - '0';
730 DrawQ_GetTextColor(color, colorindex, basered, basegreen, baseblue, basealpha, shadow);
737 s = (num & 15)*0.0625f + (0.5f / 256.0f);
738 t = (num >> 4)*0.0625f + (0.5f / 256.0f);
739 u = 0.0625f - (1.0f / 256.0f);
740 v = 0.0625f - (1.0f / 256.0f);
741 ac[ 0] = color[0];ac[ 1] = color[1];ac[ 2] = color[2];ac[ 3] = color[3];
742 ac[ 4] = color[0];ac[ 5] = color[1];ac[ 6] = color[2];ac[ 7] = color[3];
743 ac[ 8] = color[0];ac[ 9] = color[1];ac[10] = color[2];ac[11] = color[3];
744 ac[12] = color[0];ac[13] = color[1];ac[14] = color[2];ac[15] = color[3];
745 at[ 0] = s ;at[ 1] = t ;
746 at[ 2] = s+u;at[ 3] = t ;
747 at[ 4] = s+u;at[ 5] = t+v;
748 at[ 6] = s ;at[ 7] = t+v;
749 av[ 0] = x ;av[ 1] = y ;av[ 2] = 10;
750 av[ 3] = x+w;av[ 4] = y ;av[ 5] = 10;
751 av[ 6] = x+w;av[ 7] = y+h;av[ 8] = 10;
752 av[ 9] = x ;av[10] = y+h;av[11] = 10;
757 if (batchcount >= QUADELEMENTS_MAXQUADS)
759 if (basealpha >= (1.0f / 255.0f))
761 GL_LockArrays(0, batchcount * 4);
762 R_Mesh_Draw(0, batchcount * 4, batchcount * 2, quadelements, 0, 0);
774 if (basealpha >= (1.0f / 255.0f))
776 GL_LockArrays(0, batchcount * 4);
777 R_Mesh_Draw(0, batchcount * 4, batchcount * 2, quadelements, 0, 0);
783 *outcolor = colorindex;
785 // note: this relies on the proper text (not shadow) being drawn last
791 static int DrawQ_BuildColoredText(char *output2c, size_t maxoutchars, const char *text, int maxreadchars, qboolean ignorecolorcodes, int *outcolor)
793 int color, numchars = 0;
794 char *outputend2c = output2c + maxoutchars - 2;
795 if (!outcolor || *outcolor == -1)
796 color = STRING_COLOR_DEFAULT;
800 maxreadchars = 1<<30;
801 textend = text + maxreadchars;
802 while (text != textend && *text)
804 if (*text == STRING_COLOR_TAG && !ignorecolorcodes && text + 1 != textend)
806 if (text[1] == STRING_COLOR_TAG)
808 else if (text[1] >= '0' && text[1] <= '9')
810 color = text[1] - '0';
815 if (output2c >= outputend2c)
817 *output2c++ = *text++;
821 output2c[0] = output2c[1] = 0;
828 void DrawQ_SuperPic(float x, float y, cachepic_t *pic, float width, float height, float s1, float t1, float r1, float g1, float b1, float a1, float s2, float t2, float r2, float g2, float b2, float a2, float s3, float t3, float r3, float g3, float b3, float a3, float s4, float t4, float r4, float g4, float b4, float a4, int flags)
832 _DrawQ_ProcessDrawFlag(flags);
834 R_Mesh_VertexPointer(floats, 0, 0);
835 R_Mesh_ColorPointer(floats + 20, 0, 0);
836 R_Mesh_ResetTextureState();
842 height = pic->height;
843 R_Mesh_TexBind(0, R_GetTexture(pic->tex));
844 R_Mesh_TexCoordPointer(0, 2, floats + 12, 0, 0);
845 floats[12] = s1;floats[13] = t1;
846 floats[14] = s2;floats[15] = t2;
847 floats[16] = s4;floats[17] = t4;
848 floats[18] = s3;floats[19] = t3;
851 floats[2] = floats[5] = floats[8] = floats[11] = 0;
852 floats[0] = floats[9] = x;
853 floats[1] = floats[4] = y;
854 floats[3] = floats[6] = x + width;
855 floats[7] = floats[10] = y + height;
856 floats[20] = r1;floats[21] = g1;floats[22] = b1;floats[23] = a1;
857 floats[24] = r2;floats[25] = g2;floats[26] = b2;floats[27] = a2;
858 floats[28] = r4;floats[29] = g4;floats[30] = b4;floats[31] = a4;
859 floats[32] = r3;floats[33] = g3;floats[34] = b3;floats[35] = a3;
861 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
864 void DrawQ_Mesh (drawqueuemesh_t *mesh, int flags)
866 _DrawQ_ProcessDrawFlag(flags);
868 R_Mesh_VertexPointer(mesh->data_vertex3f, 0, 0);
869 R_Mesh_ColorPointer(mesh->data_color4f, 0, 0);
870 R_Mesh_ResetTextureState();
871 R_Mesh_TexBind(0, R_GetTexture(mesh->texture));
872 R_Mesh_TexCoordPointer(0, 2, mesh->data_texcoord2f, 0, 0);
874 GL_LockArrays(0, mesh->num_vertices);
875 R_Mesh_Draw(0, mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, 0, 0);
879 void DrawQ_LineLoop (drawqueuemesh_t *mesh, int flags)
883 _DrawQ_ProcessDrawFlag(flags);
887 qglBegin(GL_LINE_LOOP);
888 for (num = 0;num < mesh->num_vertices;num++)
890 if (mesh->data_color4f)
891 GL_Color(mesh->data_color4f[num*4+0], mesh->data_color4f[num*4+1], mesh->data_color4f[num*4+2], mesh->data_color4f[num*4+3]);
892 qglVertex2f(mesh->data_vertex3f[num*3+0], mesh->data_vertex3f[num*3+1]);
898 //[515]: this is old, delete
899 void DrawQ_Line (float width, float x1, float y1, float x2, float y2, float r, float g, float b, float alpha, int flags)
901 _DrawQ_ProcessDrawFlag(flags);
904 qglLineWidth(width);CHECKGLERROR
906 GL_Color(r,g,b,alpha);
915 void DrawQ_SetClipArea(float x, float y, float width, float height)
919 // We have to convert the con coords into real coords
920 // OGL uses top to bottom
921 GL_Scissor((int)(x * ((float)vid.width / vid_conwidth.integer)), (int)(y * ((float) vid.height / vid_conheight.integer)), (int)(width * ((float)vid.width / vid_conwidth.integer)), (int)(height * ((float)vid.height / vid_conheight.integer)));
923 GL_ScissorTest(true);
926 void DrawQ_ResetClipArea(void)
929 GL_ScissorTest(false);
932 void DrawQ_Finish(void)
934 r_refdef.draw2dstage = false;
937 static float blendvertex3f[9] = {-5000, -5000, 10, 10000, -5000, 10, -5000, 10000, 10};
938 void R_DrawGamma(void)
941 if (!vid_usinghwgamma)
943 // all the blends ignore depth
944 R_Mesh_VertexPointer(blendvertex3f, 0, 0);
945 R_Mesh_ColorPointer(NULL, 0, 0);
946 R_Mesh_ResetTextureState();
949 GL_PolygonOffset(0, 0);
951 if (v_color_enable.integer)
953 c[0] = v_color_white_r.value;
954 c[1] = v_color_white_g.value;
955 c[2] = v_color_white_b.value;
958 c[0] = c[1] = c[2] = v_contrast.value;
959 if (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f)
961 GL_BlendFunc(GL_DST_COLOR, GL_ONE);
962 while (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f)
964 GL_Color(bound(0, c[0] - 1, 1), bound(0, c[1] - 1, 1), bound(0, c[2] - 1, 1), 1);
965 R_Mesh_Draw(0, 3, 1, polygonelements, 0, 0);
966 VectorScale(c, 0.5, c);
969 if (v_color_enable.integer)
971 c[0] = v_color_black_r.value;
972 c[1] = v_color_black_g.value;
973 c[2] = v_color_black_b.value;
976 c[0] = c[1] = c[2] = v_brightness.value;
977 if (c[0] >= 0.01f || c[1] >= 0.01f || c[2] >= 0.01f)
979 GL_BlendFunc(GL_ONE, GL_ONE);
980 GL_Color(c[0], c[1], c[2], 1);
981 R_Mesh_Draw(0, 3, 1, polygonelements, 0, 0);