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)"};
28 cvar_t r_textbrightness = {CVAR_SAVE, "r_textbrightness", "0", "additional brightness for text color codes (0 keeps colors as is, 1 makes them all white)"};
30 static rtexture_t *char_texture;
31 cachepic_t *r_crosshairs[NUMCROSSHAIRS+1];
33 //=============================================================================
34 /* Support Routines */
36 #define FONT_FILESIZE 13468
37 #define MAX_CACHED_PICS 1024
38 #define CACHEPICHASHSIZE 256
39 static cachepic_t *cachepichash[CACHEPICHASHSIZE];
40 static cachepic_t cachepics[MAX_CACHED_PICS];
41 static int numcachepics;
43 static rtexturepool_t *drawtexturepool;
45 static unsigned char concharimage[FONT_FILESIZE] =
50 static rtexture_t *draw_generateconchars(void)
53 unsigned char buffer[65536][4], *data = NULL;
56 data = LoadTGA (concharimage, FONT_FILESIZE, 256, 256);
58 for (i = 0;i < 8192;i++)
60 random = lhrandom (0.0,1.0);
61 buffer[i][0] = 83 + (unsigned char)(random * 64);
62 buffer[i][1] = 71 + (unsigned char)(random * 32);
63 buffer[i][2] = 23 + (unsigned char)(random * 16);
64 buffer[i][3] = data[i*4+0];
67 for (i = 8192;i < 32768;i++)
69 random = lhrandom (0.0,1.0);
70 buffer[i][0] = 95 + (unsigned char)(random * 64);
71 buffer[i][1] = 95 + (unsigned char)(random * 64);
72 buffer[i][2] = 95 + (unsigned char)(random * 64);
73 buffer[i][3] = data[i*4+0];
76 for (i = 32768;i < 40960;i++)
78 random = lhrandom (0.0,1.0);
79 buffer[i][0] = 83 + (unsigned char)(random * 64);
80 buffer[i][1] = 71 + (unsigned char)(random * 32);
81 buffer[i][2] = 23 + (unsigned char)(random * 16);
82 buffer[i][3] = data[i*4+0];
85 for (i = 40960;i < 65536;i++)
87 random = lhrandom (0.0,1.0);
88 buffer[i][0] = 96 + (unsigned char)(random * 64);
89 buffer[i][1] = 43 + (unsigned char)(random * 32);
90 buffer[i][2] = 27 + (unsigned char)(random * 32);
91 buffer[i][3] = data[i*4+0];
95 Image_WriteTGARGBA ("gfx/generated_conchars.tga", 256, 256, &buffer[0][0]);
99 return R_LoadTexture2D(drawtexturepool, "conchars", 256, 256, &buffer[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
102 static char *pointerimage =
121 static rtexture_t *draw_generatemousepointer(void)
124 unsigned char buffer[256][4];
125 for (i = 0;i < 256;i++)
127 if (pointerimage[i] == '.')
136 buffer[i][0] = (pointerimage[i] - '0') * 16;
137 buffer[i][1] = (pointerimage[i] - '0') * 16;
138 buffer[i][2] = (pointerimage[i] - '0') * 16;
142 return R_LoadTexture2D(drawtexturepool, "mousepointer", 16, 16, &buffer[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
145 static char *crosshairtexdata[NUMCROSSHAIRS] =
250 static rtexture_t *draw_generatecrosshair(int num)
254 unsigned char data[16*16][4];
255 in = crosshairtexdata[num];
256 for (i = 0;i < 16*16;i++)
267 data[i][0] = data[i][1] = data[i][2] = (unsigned char) ((int) (in[i] - '0') * 127 / 7 + 128);
271 return R_LoadTexture2D(drawtexturepool, va("crosshair%i", num+1), 16, 16, &data[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
274 static rtexture_t *draw_generateditherpattern(void)
278 unsigned char data[8*8*4];
279 for (y = 0;y < 8;y++)
281 for (x = 0;x < 8;x++)
283 data[(y*8+x)*4+0] = data[(y*8+x)*4+1] = data[(y*8+x)*4+2] = ((x^y) & 4) ? 255 : 0;
284 data[(y*8+x)*4+3] = 255;
287 return R_LoadTexture2D(drawtexturepool, "ditherpattern", 8, 8, data, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_PRECACHE, NULL);
289 unsigned char data[16];
290 memset(data, 255, sizeof(data));
291 data[0] = data[1] = data[2] = data[12] = data[13] = data[14] = 0;
292 return R_LoadTexture2D(drawtexturepool, "ditherpattern", 2, 2, data, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_PRECACHE, NULL);
301 // FIXME: move this to client somehow
302 cachepic_t *Draw_CachePic (const char *path, qboolean persistent)
308 unsigned char *lmpdata;
309 char lmpname[MAX_QPATH];
311 if (!strncmp(CLVIDEOPREFIX, path, sizeof(CLVIDEOPREFIX) - 1))
315 video = CL_GetVideoByName(path);
320 crc = CRC_Block((unsigned char *)path, strlen(path));
321 hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
322 for (pic = cachepichash[hashkey];pic;pic = pic->chain)
323 if (!strcmp (path, pic->name))
326 if (numcachepics == MAX_CACHED_PICS)
328 Con_Printf ("Draw_CachePic: numcachepics == MAX_CACHED_PICS\n");
329 // FIXME: support NULL in callers?
330 return cachepics; // return the first one
332 pic = cachepics + (numcachepics++);
333 strlcpy (pic->name, path, sizeof(pic->name));
335 pic->chain = cachepichash[hashkey];
336 cachepichash[hashkey] = pic;
340 flags |= TEXF_PRECACHE;
341 if (!strcmp(path, "gfx/colorcontrol/ditherpattern"))
344 // load a high quality image from disk if possible
345 pic->tex = loadtextureimage(drawtexturepool, path, 0, 0, false, flags | (gl_texturecompression_2d.integer ? TEXF_COMPRESS : 0), true);
346 if (pic->tex == NULL && !strncmp(path, "gfx/", 4))
348 // compatibility with older versions which did not require gfx/ prefix
349 pic->tex = loadtextureimage(drawtexturepool, path + 4, 0, 0, false, flags | (gl_texturecompression_2d.integer ? TEXF_COMPRESS : 0), true);
351 // if a high quality image was loaded, set the pic's size to match it, just
352 // in case there's no low quality version to get the size from
355 pic->width = R_TextureWidth(pic->tex);
356 pic->height = R_TextureHeight(pic->tex);
359 // now read the low quality version (wad or lmp file), and take the pic
360 // size from that even if we don't upload the texture, this way the pics
361 // show up the right size in the menu even if they were replaced with
362 // higher or lower resolution versions
363 dpsnprintf(lmpname, sizeof(lmpname), "%s.lmp", path);
364 if (!strncmp(path, "gfx/", 4) && (lmpdata = FS_LoadFile(lmpname, tempmempool, false, &lmpsize)))
368 pic->width = lmpdata[0] + lmpdata[1] * 256 + lmpdata[2] * 65536 + lmpdata[3] * 16777216;
369 pic->height = lmpdata[4] + lmpdata[5] * 256 + lmpdata[6] * 65536 + lmpdata[7] * 16777216;
370 // if no high quality replacement image was found, upload the original low quality texture
372 pic->tex = R_LoadTexture2D(drawtexturepool, path, pic->width, pic->height, lmpdata + 8, TEXTYPE_PALETTE, flags, palette_transparent);
376 else if ((lmpdata = W_GetLumpName (path + 4)))
378 if (!strcmp(path, "gfx/conchars"))
380 // conchars is a raw image and with color 0 as transparent instead of 255
383 // if no high quality replacement image was found, upload the original low quality texture
385 pic->tex = R_LoadTexture2D(drawtexturepool, path, 128, 128, lmpdata, TEXTYPE_PALETTE, flags, palette_font);
389 pic->width = lmpdata[0] + lmpdata[1] * 256 + lmpdata[2] * 65536 + lmpdata[3] * 16777216;
390 pic->height = lmpdata[4] + lmpdata[5] * 256 + lmpdata[6] * 65536 + lmpdata[7] * 16777216;
391 // if no high quality replacement image was found, upload the original low quality texture
393 pic->tex = R_LoadTexture2D(drawtexturepool, path, pic->width, pic->height, lmpdata + 8, TEXTYPE_PALETTE, flags, palette_transparent);
397 // if it's not found on disk, check if it's one of the builtin images
398 if (pic->tex == NULL)
400 if (pic->tex == NULL && !strcmp(path, "gfx/conchars"))
401 pic->tex = draw_generateconchars();
402 if (pic->tex == NULL && !strcmp(path, "ui/mousepointer"))
403 pic->tex = draw_generatemousepointer();
404 if (pic->tex == NULL && !strcmp(path, "gfx/prydoncursor001"))
405 pic->tex = draw_generatemousepointer();
406 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair1"))
407 pic->tex = draw_generatecrosshair(0);
408 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair2"))
409 pic->tex = draw_generatecrosshair(1);
410 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair3"))
411 pic->tex = draw_generatecrosshair(2);
412 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair4"))
413 pic->tex = draw_generatecrosshair(3);
414 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair5"))
415 pic->tex = draw_generatecrosshair(4);
416 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair6"))
417 pic->tex = draw_generatecrosshair(5);
418 if (pic->tex == NULL && !strcmp(path, "gfx/colorcontrol/ditherpattern"))
419 pic->tex = draw_generateditherpattern();
420 if (pic->tex == NULL)
422 // don't complain about missing gfx/crosshair images
423 if (strncmp(path, "gfx/crosshair", 13))
424 Con_Printf("Draw_CachePic: failed to load %s\n", path);
425 pic->tex = r_texture_notexture;
427 pic->width = R_TextureWidth(pic->tex);
428 pic->height = R_TextureHeight(pic->tex);
434 cachepic_t *Draw_NewPic(const char *picname, int width, int height, int alpha, unsigned char *pixels)
439 crc = CRC_Block((unsigned char *)picname, strlen(picname));
440 hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
441 for (pic = cachepichash[hashkey];pic;pic = pic->chain)
442 if (!strcmp (picname, pic->name))
447 if (pic->tex && pic->width == width && pic->height == height)
449 R_UpdateTexture(pic->tex, pixels, 0, 0, width, height);
457 if (numcachepics == MAX_CACHED_PICS)
459 Con_Printf ("Draw_NewPic: numcachepics == MAX_CACHED_PICS\n");
460 // FIXME: support NULL in callers?
461 return cachepics; // return the first one
463 pic = cachepics + (numcachepics++);
464 strlcpy (pic->name, picname, sizeof(pic->name));
466 pic->chain = cachepichash[hashkey];
467 cachepichash[hashkey] = pic;
472 pic->height = height;
474 R_FreeTexture(pic->tex);
475 pic->tex = R_LoadTexture2D(drawtexturepool, picname, width, height, pixels, TEXTYPE_RGBA, alpha ? TEXF_ALPHA : 0, NULL);
479 void Draw_FreePic(const char *picname)
484 // this doesn't really free the pic, but does free it's texture
485 crc = CRC_Block((unsigned char *)picname, strlen(picname));
486 hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
487 for (pic = cachepichash[hashkey];pic;pic = pic->chain)
489 if (!strcmp (picname, pic->name) && pic->tex)
491 R_FreeTexture(pic->tex);
504 static void gl_draw_start(void)
507 drawtexturepool = R_AllocTexturePool();
510 memset(cachepichash, 0, sizeof(cachepichash));
512 char_texture = Draw_CachePic("gfx/conchars", true)->tex;
513 for (i = 1;i <= NUMCROSSHAIRS;i++)
514 r_crosshairs[i] = Draw_CachePic(va("gfx/crosshair%i", i), true);
516 // draw the loading screen so people have something to see in the newly opened window
517 SCR_UpdateLoadingScreen(true);
520 static void gl_draw_shutdown(void)
522 R_FreeTexturePool(&drawtexturepool);
525 memset(cachepichash, 0, sizeof(cachepichash));
528 static void gl_draw_newmap(void)
532 void GL_Draw_Init (void)
534 Cvar_RegisterVariable(&r_textshadow);
535 Cvar_RegisterVariable(&r_textbrightness);
536 R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap);
539 static void _DrawQ_Setup(void)
541 if (r_refdef.draw2dstage)
543 r_refdef.draw2dstage = true;
545 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
546 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
547 GL_SetupView_Mode_Ortho(0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100);
548 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
549 qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
550 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
551 R_Mesh_Matrix(&identitymatrix);
555 GL_PolygonOffset(0, 0);
559 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
561 if (gl_support_fragment_shader)
563 qglUseProgramObjectARB(0);CHECKGLERROR
567 static void _DrawQ_ProcessDrawFlag(int flags)
571 if(flags == DRAWFLAG_ADDITIVE)
572 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
573 else if(flags == DRAWFLAG_MODULATE)
574 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
575 else if(flags == DRAWFLAG_2XMODULATE)
576 GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
578 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
581 void DrawQ_Pic(float x, float y, cachepic_t *pic, float width, float height, float red, float green, float blue, float alpha, int flags)
585 _DrawQ_ProcessDrawFlag(flags);
586 GL_Color(red, green, blue, alpha);
588 R_Mesh_VertexPointer(floats, 0, 0);
589 R_Mesh_ColorPointer(NULL, 0, 0);
590 R_Mesh_ResetTextureState();
596 height = pic->height;
597 R_Mesh_TexBind(0, R_GetTexture(pic->tex));
598 R_Mesh_TexCoordPointer(0, 2, floats + 12, 0, 0);
600 // AK07: lets be texel correct on the corners
602 float horz_offset = 0.5f / pic->width;
603 float vert_offset = 0.5f / pic->height;
605 floats[12] = 0.0f + horz_offset;floats[13] = 0.0f + vert_offset;
606 floats[14] = 1.0f - horz_offset;floats[15] = 0.0f + vert_offset;
607 floats[16] = 1.0f - horz_offset;floats[17] = 1.0f - vert_offset;
608 floats[18] = 0.0f + horz_offset;floats[19] = 1.0f - vert_offset;
612 floats[2] = floats[5] = floats[8] = floats[11] = 0;
613 floats[0] = floats[9] = x;
614 floats[1] = floats[4] = y;
615 floats[3] = floats[6] = x + width;
616 floats[7] = floats[10] = y + height;
618 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
621 void DrawQ_Fill(float x, float y, float width, float height, float red, float green, float blue, float alpha, int flags)
625 _DrawQ_ProcessDrawFlag(flags);
626 GL_Color(red, green, blue, alpha);
628 R_Mesh_VertexPointer(floats, 0, 0);
629 R_Mesh_ColorPointer(NULL, 0, 0);
630 R_Mesh_ResetTextureState();
632 floats[2] = floats[5] = floats[8] = floats[11] = 0;
633 floats[0] = floats[9] = x;
634 floats[1] = floats[4] = y;
635 floats[3] = floats[6] = x + width;
636 floats[7] = floats[10] = y + height;
638 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
641 // color tag printing
642 static vec4_t string_colors[] =
645 // LordHavoc: why on earth is cyan before magenta in Quake3?
646 // LordHavoc: note: Doom3 uses white for [0] and [7]
647 {0.0, 0.0, 0.0, 1.0}, // black
648 {1.0, 0.0, 0.0, 1.0}, // red
649 {0.0, 1.0, 0.0, 1.0}, // green
650 {1.0, 1.0, 0.0, 1.0}, // yellow
651 {0.0, 0.0, 1.0, 1.0}, // blue
652 {0.0, 1.0, 1.0, 1.0}, // cyan
653 {1.0, 0.0, 1.0, 1.0}, // magenta
654 {1.0, 1.0, 1.0, 1.0}, // white
655 // [515]'s BX_COLOREDTEXT extension
656 {1.0, 1.0, 1.0, 0.5}, // half transparent
657 {0.5, 0.5, 0.5, 1.0} // half brightness
658 // Black's color table
659 //{1.0, 1.0, 1.0, 1.0},
660 //{1.0, 0.0, 0.0, 1.0},
661 //{0.0, 1.0, 0.0, 1.0},
662 //{0.0, 0.0, 1.0, 1.0},
663 //{1.0, 1.0, 0.0, 1.0},
664 //{0.0, 1.0, 1.0, 1.0},
665 //{1.0, 0.0, 1.0, 1.0},
666 //{0.1, 0.1, 0.1, 1.0}
669 #define STRING_COLORS_COUNT (sizeof(string_colors) / sizeof(vec4_t))
671 static void DrawQ_GetTextColor(float color[4], int colorindex, float r, float g, float b, float a, qboolean shadow)
673 float v = r_textbrightness.value;
674 Vector4Copy(string_colors[colorindex], color);
675 Vector4Set(color, (color[0] * (1-v) + v) * r, (color[1] * (1-v) + v) * g, (color[2] * (1-v) + v) * b, color[3] * a);
678 float shadowalpha = color[0]+color[1]+color[2] * 0.8;
679 Vector4Set(color, 0, 0, 0, color[3] * bound(0, shadowalpha, 1));
683 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)
685 int i, num, shadow, colorindex = STRING_COLOR_DEFAULT;
686 float x = startx, y, s, t, u, v;
690 float vertex3f[QUADELEMENTS_MAXQUADS*4*3];
691 float texcoord2f[QUADELEMENTS_MAXQUADS*4*2];
692 float color4f[QUADELEMENTS_MAXQUADS*4*4];
697 _DrawQ_ProcessDrawFlag(flags);
699 R_Mesh_ColorPointer(color4f, 0, 0);
700 R_Mesh_ResetTextureState();
701 R_Mesh_TexBind(0, R_GetTexture(char_texture));
702 R_Mesh_TexCoordPointer(0, 2, texcoord2f, 0, 0);
703 R_Mesh_VertexPointer(vertex3f, 0, 0);
710 for (shadow = r_textshadow.value != 0;shadow >= 0;shadow--)
712 if (!outcolor || *outcolor == -1)
713 colorindex = STRING_COLOR_DEFAULT;
715 colorindex = *outcolor;
716 DrawQ_GetTextColor(color, colorindex, basered, basegreen, baseblue, basealpha, shadow);
722 x += r_textshadow.value;
723 y += r_textshadow.value;
725 for (i = 0;i < maxlen && text[i];i++, x += w)
729 if (text[i] == STRING_COLOR_TAG && !ignorecolorcodes && i + 1 < maxlen)
731 if (text[i+1] == STRING_COLOR_TAG)
737 else if (text[i+1] >= '0' && text[i+1] <= '9')
739 colorindex = text[i+1] - '0';
740 DrawQ_GetTextColor(color, colorindex, basered, basegreen, baseblue, basealpha, shadow);
747 s = (num & 15)*0.0625f + (0.5f / 256.0f);
748 t = (num >> 4)*0.0625f + (0.5f / 256.0f);
749 u = 0.0625f - (1.0f / 256.0f);
750 v = 0.0625f - (1.0f / 256.0f);
751 ac[ 0] = color[0];ac[ 1] = color[1];ac[ 2] = color[2];ac[ 3] = color[3];
752 ac[ 4] = color[0];ac[ 5] = color[1];ac[ 6] = color[2];ac[ 7] = color[3];
753 ac[ 8] = color[0];ac[ 9] = color[1];ac[10] = color[2];ac[11] = color[3];
754 ac[12] = color[0];ac[13] = color[1];ac[14] = color[2];ac[15] = color[3];
755 at[ 0] = s ;at[ 1] = t ;
756 at[ 2] = s+u;at[ 3] = t ;
757 at[ 4] = s+u;at[ 5] = t+v;
758 at[ 6] = s ;at[ 7] = t+v;
759 av[ 0] = x ;av[ 1] = y ;av[ 2] = 10;
760 av[ 3] = x+w;av[ 4] = y ;av[ 5] = 10;
761 av[ 6] = x+w;av[ 7] = y+h;av[ 8] = 10;
762 av[ 9] = x ;av[10] = y+h;av[11] = 10;
767 if (batchcount >= QUADELEMENTS_MAXQUADS)
769 if (basealpha >= (1.0f / 255.0f))
771 GL_LockArrays(0, batchcount * 4);
772 R_Mesh_Draw(0, batchcount * 4, batchcount * 2, quadelements, 0, 0);
784 if (basealpha >= (1.0f / 255.0f))
786 GL_LockArrays(0, batchcount * 4);
787 R_Mesh_Draw(0, batchcount * 4, batchcount * 2, quadelements, 0, 0);
793 *outcolor = colorindex;
795 // note: this relies on the proper text (not shadow) being drawn last
801 static int DrawQ_BuildColoredText(char *output2c, size_t maxoutchars, const char *text, int maxreadchars, qboolean ignorecolorcodes, int *outcolor)
803 int color, numchars = 0;
804 char *outputend2c = output2c + maxoutchars - 2;
805 if (!outcolor || *outcolor == -1)
806 color = STRING_COLOR_DEFAULT;
810 maxreadchars = 1<<30;
811 textend = text + maxreadchars;
812 while (text != textend && *text)
814 if (*text == STRING_COLOR_TAG && !ignorecolorcodes && text + 1 != textend)
816 if (text[1] == STRING_COLOR_TAG)
818 else if (text[1] >= '0' && text[1] <= '9')
820 color = text[1] - '0';
825 if (output2c >= outputend2c)
827 *output2c++ = *text++;
831 output2c[0] = output2c[1] = 0;
838 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)
842 _DrawQ_ProcessDrawFlag(flags);
844 R_Mesh_VertexPointer(floats, 0, 0);
845 R_Mesh_ColorPointer(floats + 20, 0, 0);
846 R_Mesh_ResetTextureState();
852 height = pic->height;
853 R_Mesh_TexBind(0, R_GetTexture(pic->tex));
854 R_Mesh_TexCoordPointer(0, 2, floats + 12, 0, 0);
855 floats[12] = s1;floats[13] = t1;
856 floats[14] = s2;floats[15] = t2;
857 floats[16] = s4;floats[17] = t4;
858 floats[18] = s3;floats[19] = t3;
861 floats[2] = floats[5] = floats[8] = floats[11] = 0;
862 floats[0] = floats[9] = x;
863 floats[1] = floats[4] = y;
864 floats[3] = floats[6] = x + width;
865 floats[7] = floats[10] = y + height;
866 floats[20] = r1;floats[21] = g1;floats[22] = b1;floats[23] = a1;
867 floats[24] = r2;floats[25] = g2;floats[26] = b2;floats[27] = a2;
868 floats[28] = r4;floats[29] = g4;floats[30] = b4;floats[31] = a4;
869 floats[32] = r3;floats[33] = g3;floats[34] = b3;floats[35] = a3;
871 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
874 void DrawQ_Mesh (drawqueuemesh_t *mesh, int flags)
876 _DrawQ_ProcessDrawFlag(flags);
878 R_Mesh_VertexPointer(mesh->data_vertex3f, 0, 0);
879 R_Mesh_ColorPointer(mesh->data_color4f, 0, 0);
880 R_Mesh_ResetTextureState();
881 R_Mesh_TexBind(0, R_GetTexture(mesh->texture));
882 R_Mesh_TexCoordPointer(0, 2, mesh->data_texcoord2f, 0, 0);
884 GL_LockArrays(0, mesh->num_vertices);
885 R_Mesh_Draw(0, mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, 0, 0);
889 void DrawQ_LineLoop (drawqueuemesh_t *mesh, int flags)
893 _DrawQ_ProcessDrawFlag(flags);
897 qglBegin(GL_LINE_LOOP);
898 for (num = 0;num < mesh->num_vertices;num++)
900 if (mesh->data_color4f)
901 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]);
902 qglVertex2f(mesh->data_vertex3f[num*3+0], mesh->data_vertex3f[num*3+1]);
908 //[515]: this is old, delete
909 void DrawQ_Line (float width, float x1, float y1, float x2, float y2, float r, float g, float b, float alpha, int flags)
911 _DrawQ_ProcessDrawFlag(flags);
914 qglLineWidth(width);CHECKGLERROR
916 GL_Color(r,g,b,alpha);
925 void DrawQ_SetClipArea(float x, float y, float width, float height)
929 // We have to convert the con coords into real coords
930 // OGL uses top to bottom
931 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)));
933 GL_ScissorTest(true);
936 void DrawQ_ResetClipArea(void)
939 GL_ScissorTest(false);
942 void DrawQ_Finish(void)
944 r_refdef.draw2dstage = false;
947 static float blendvertex3f[9] = {-5000, -5000, 10, 10000, -5000, 10, -5000, 10000, 10};
948 void R_DrawGamma(void)
951 if (!vid_usinghwgamma)
953 // all the blends ignore depth
954 R_Mesh_VertexPointer(blendvertex3f, 0, 0);
955 R_Mesh_ColorPointer(NULL, 0, 0);
956 R_Mesh_ResetTextureState();
959 GL_PolygonOffset(0, 0);
961 if (v_color_enable.integer)
963 c[0] = v_color_white_r.value;
964 c[1] = v_color_white_g.value;
965 c[2] = v_color_white_b.value;
968 c[0] = c[1] = c[2] = v_contrast.value;
969 if (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f)
971 GL_BlendFunc(GL_DST_COLOR, GL_ONE);
972 while (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f)
974 GL_Color(bound(0, c[0] - 1, 1), bound(0, c[1] - 1, 1), bound(0, c[2] - 1, 1), 1);
975 R_Mesh_Draw(0, 3, 1, polygonelements, 0, 0);
976 VectorScale(c, 0.5, c);
979 if (v_color_enable.integer)
981 c[0] = v_color_black_r.value;
982 c[1] = v_color_black_g.value;
983 c[2] = v_color_black_b.value;
986 c[0] = c[1] = c[2] = v_brightness.value;
987 if (c[0] >= 0.01f || c[1] >= 0.01f || c[2] >= 0.01f)
989 GL_BlendFunc(GL_ONE, GL_ONE);
990 GL_Color(c[0], c[1], c[2], 1);
991 R_Mesh_Draw(0, 3, 1, polygonelements, 0, 0);