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));
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));
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);
599 floats[12] = 0;floats[13] = 0;
600 floats[14] = 1;floats[15] = 0;
601 floats[16] = 1;floats[17] = 1;
602 floats[18] = 0;floats[19] = 1;
605 floats[2] = floats[5] = floats[8] = floats[11] = 0;
606 floats[0] = floats[9] = x;
607 floats[1] = floats[4] = y;
608 floats[3] = floats[6] = x + width;
609 floats[7] = floats[10] = y + height;
611 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
614 void DrawQ_Fill(float x, float y, float width, float height, float red, float green, float blue, float alpha, int flags)
618 _DrawQ_ProcessDrawFlag(flags);
619 GL_Color(red, green, blue, alpha);
621 R_Mesh_VertexPointer(floats, 0, 0);
622 R_Mesh_ColorPointer(NULL, 0, 0);
623 R_Mesh_ResetTextureState();
625 floats[2] = floats[5] = floats[8] = floats[11] = 0;
626 floats[0] = floats[9] = x;
627 floats[1] = floats[4] = y;
628 floats[3] = floats[6] = x + width;
629 floats[7] = floats[10] = y + height;
631 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
634 // color tag printing
635 static vec4_t string_colors[] =
638 // LordHavoc: why on earth is cyan before magenta in Quake3?
639 // LordHavoc: note: Doom3 uses white for [0] and [7]
640 {0.0, 0.0, 0.0, 1.0}, // black
641 {1.0, 0.0, 0.0, 1.0}, // red
642 {0.0, 1.0, 0.0, 1.0}, // green
643 {1.0, 1.0, 0.0, 1.0}, // yellow
644 {0.0, 0.0, 1.0, 1.0}, // blue
645 {0.0, 1.0, 1.0, 1.0}, // cyan
646 {1.0, 0.0, 1.0, 1.0}, // magenta
647 {1.0, 1.0, 1.0, 1.0}, // white
648 // [515]'s BX_COLOREDTEXT extension
649 {1.0, 1.0, 1.0, 0.5}, // half transparent
650 {0.5, 0.5, 0.5, 1.0} // half brightness
651 // Black's color table
652 //{1.0, 1.0, 1.0, 1.0},
653 //{1.0, 0.0, 0.0, 1.0},
654 //{0.0, 1.0, 0.0, 1.0},
655 //{0.0, 0.0, 1.0, 1.0},
656 //{1.0, 1.0, 0.0, 1.0},
657 //{0.0, 1.0, 1.0, 1.0},
658 //{1.0, 0.0, 1.0, 1.0},
659 //{0.1, 0.1, 0.1, 1.0}
662 #define STRING_COLORS_COUNT (sizeof(string_colors) / sizeof(vec4_t))
664 static void DrawQ_GetTextColor(float color[4], int colorindex, float r, float g, float b, float a, qboolean shadow)
666 float v = r_textbrightness.value;
667 Vector4Copy(string_colors[colorindex], color);
668 Vector4Set(color, (color[0] * (1-v) + v) * r, (color[1] * (1-v) + v) * g, (color[2] * (1-v) + v) * b, color[3] * a);
671 float shadowalpha = color[0]+color[1]+color[2] * 0.8;
672 Vector4Set(color, 0, 0, 0, color[3] * bound(0, shadowalpha, 1));
676 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)
678 int i, num, shadow, colorindex = STRING_COLOR_DEFAULT;
679 float x = startx, y, s, t, u, v;
683 float vertex3f[QUADELEMENTS_MAXQUADS*4*3];
684 float texcoord2f[QUADELEMENTS_MAXQUADS*4*2];
685 float color4f[QUADELEMENTS_MAXQUADS*4*4];
690 _DrawQ_ProcessDrawFlag(flags);
692 R_Mesh_ColorPointer(color4f, 0, 0);
693 R_Mesh_ResetTextureState();
694 R_Mesh_TexBind(0, R_GetTexture(char_texture));
695 R_Mesh_TexCoordPointer(0, 2, texcoord2f, 0, 0);
696 R_Mesh_VertexPointer(vertex3f, 0, 0);
703 for (shadow = r_textshadow.value != 0;shadow >= 0;shadow--)
705 if (!outcolor || *outcolor == -1)
706 colorindex = STRING_COLOR_DEFAULT;
708 colorindex = *outcolor;
709 DrawQ_GetTextColor(color, colorindex, basered, basegreen, baseblue, basealpha, shadow);
715 x += r_textshadow.value;
716 y += r_textshadow.value;
718 for (i = 0;i < maxlen && text[i];i++, x += w)
722 if (text[i] == STRING_COLOR_TAG && !ignorecolorcodes && i + 1 < maxlen)
724 if (text[i+1] == STRING_COLOR_TAG)
730 else if (text[i+1] >= '0' && text[i+1] <= '9')
732 colorindex = text[i+1] - '0';
733 DrawQ_GetTextColor(color, colorindex, basered, basegreen, baseblue, basealpha, shadow);
740 s = (num & 15)*0.0625f + (0.5f / 256.0f);
741 t = (num >> 4)*0.0625f + (0.5f / 256.0f);
742 u = 0.0625f - (1.0f / 256.0f);
743 v = 0.0625f - (1.0f / 256.0f);
744 ac[ 0] = color[0];ac[ 1] = color[1];ac[ 2] = color[2];ac[ 3] = color[3];
745 ac[ 4] = color[0];ac[ 5] = color[1];ac[ 6] = color[2];ac[ 7] = color[3];
746 ac[ 8] = color[0];ac[ 9] = color[1];ac[10] = color[2];ac[11] = color[3];
747 ac[12] = color[0];ac[13] = color[1];ac[14] = color[2];ac[15] = color[3];
748 at[ 0] = s ;at[ 1] = t ;
749 at[ 2] = s+u;at[ 3] = t ;
750 at[ 4] = s+u;at[ 5] = t+v;
751 at[ 6] = s ;at[ 7] = t+v;
752 av[ 0] = x ;av[ 1] = y ;av[ 2] = 10;
753 av[ 3] = x+w;av[ 4] = y ;av[ 5] = 10;
754 av[ 6] = x+w;av[ 7] = y+h;av[ 8] = 10;
755 av[ 9] = x ;av[10] = y+h;av[11] = 10;
760 if (batchcount >= QUADELEMENTS_MAXQUADS)
762 if (basealpha >= (1.0f / 255.0f))
764 GL_LockArrays(0, batchcount * 4);
765 R_Mesh_Draw(0, batchcount * 4, batchcount * 2, quadelements, 0, 0);
777 if (basealpha >= (1.0f / 255.0f))
779 GL_LockArrays(0, batchcount * 4);
780 R_Mesh_Draw(0, batchcount * 4, batchcount * 2, quadelements, 0, 0);
786 *outcolor = colorindex;
788 // note: this relies on the proper text (not shadow) being drawn last
794 static int DrawQ_BuildColoredText(char *output2c, size_t maxoutchars, const char *text, int maxreadchars, qboolean ignorecolorcodes, int *outcolor)
796 int color, numchars = 0;
797 char *outputend2c = output2c + maxoutchars - 2;
798 if (!outcolor || *outcolor == -1)
799 color = STRING_COLOR_DEFAULT;
803 maxreadchars = 1<<30;
804 textend = text + maxreadchars;
805 while (text != textend && *text)
807 if (*text == STRING_COLOR_TAG && !ignorecolorcodes && text + 1 != textend)
809 if (text[1] == STRING_COLOR_TAG)
811 else if (text[1] >= '0' && text[1] <= '9')
813 color = text[1] - '0';
818 if (output2c >= outputend2c)
820 *output2c++ = *text++;
824 output2c[0] = output2c[1] = 0;
831 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)
835 _DrawQ_ProcessDrawFlag(flags);
837 R_Mesh_VertexPointer(floats, 0, 0);
838 R_Mesh_ColorPointer(floats + 20, 0, 0);
839 R_Mesh_ResetTextureState();
845 height = pic->height;
846 R_Mesh_TexBind(0, R_GetTexture(pic->tex));
847 R_Mesh_TexCoordPointer(0, 2, floats + 12, 0, 0);
848 floats[12] = s1;floats[13] = t1;
849 floats[14] = s2;floats[15] = t2;
850 floats[16] = s4;floats[17] = t4;
851 floats[18] = s3;floats[19] = t3;
854 floats[2] = floats[5] = floats[8] = floats[11] = 0;
855 floats[0] = floats[9] = x;
856 floats[1] = floats[4] = y;
857 floats[3] = floats[6] = x + width;
858 floats[7] = floats[10] = y + height;
859 floats[20] = r1;floats[21] = g1;floats[22] = b1;floats[23] = a1;
860 floats[24] = r2;floats[25] = g2;floats[26] = b2;floats[27] = a2;
861 floats[28] = r4;floats[29] = g4;floats[30] = b4;floats[31] = a4;
862 floats[32] = r3;floats[33] = g3;floats[34] = b3;floats[35] = a3;
864 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
867 void DrawQ_Mesh (drawqueuemesh_t *mesh, int flags)
869 _DrawQ_ProcessDrawFlag(flags);
871 R_Mesh_VertexPointer(mesh->data_vertex3f, 0, 0);
872 R_Mesh_ColorPointer(mesh->data_color4f, 0, 0);
873 R_Mesh_ResetTextureState();
874 R_Mesh_TexBind(0, R_GetTexture(mesh->texture));
875 R_Mesh_TexCoordPointer(0, 2, mesh->data_texcoord2f, 0, 0);
877 GL_LockArrays(0, mesh->num_vertices);
878 R_Mesh_Draw(0, mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, 0, 0);
882 void DrawQ_LineLoop (drawqueuemesh_t *mesh, int flags)
886 _DrawQ_ProcessDrawFlag(flags);
890 qglBegin(GL_LINE_LOOP);
891 for (num = 0;num < mesh->num_vertices;num++)
893 if (mesh->data_color4f)
894 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]);
895 qglVertex2f(mesh->data_vertex3f[num*3+0], mesh->data_vertex3f[num*3+1]);
901 //[515]: this is old, delete
902 void DrawQ_Line (float width, float x1, float y1, float x2, float y2, float r, float g, float b, float alpha, int flags)
904 _DrawQ_ProcessDrawFlag(flags);
907 qglLineWidth(width);CHECKGLERROR
909 GL_Color(r,g,b,alpha);
918 void DrawQ_SetClipArea(float x, float y, float width, float height)
922 // We have to convert the con coords into real coords
923 // OGL uses top to bottom
924 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)));
926 GL_ScissorTest(true);
929 void DrawQ_ResetClipArea(void)
932 GL_ScissorTest(false);
935 void DrawQ_Finish(void)
937 r_refdef.draw2dstage = false;
940 static float blendvertex3f[9] = {-5000, -5000, 10, 10000, -5000, 10, -5000, 10000, 10};
941 void R_DrawGamma(void)
944 if (!vid_usinghwgamma)
946 // all the blends ignore depth
947 R_Mesh_VertexPointer(blendvertex3f, 0, 0);
948 R_Mesh_ColorPointer(NULL, 0, 0);
949 R_Mesh_ResetTextureState();
952 GL_PolygonOffset(0, 0);
954 if (v_color_enable.integer)
956 c[0] = v_color_white_r.value;
957 c[1] = v_color_white_g.value;
958 c[2] = v_color_white_b.value;
961 c[0] = c[1] = c[2] = v_contrast.value;
962 if (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f)
964 GL_BlendFunc(GL_DST_COLOR, GL_ONE);
965 while (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f)
967 GL_Color(bound(0, c[0] - 1, 1), bound(0, c[1] - 1, 1), bound(0, c[2] - 1, 1), 1);
968 R_Mesh_Draw(0, 3, 1, polygonelements, 0, 0);
969 VectorScale(c, 0.5, c);
972 if (v_color_enable.integer)
974 c[0] = v_color_black_r.value;
975 c[1] = v_color_black_g.value;
976 c[2] = v_color_black_b.value;
979 c[0] = c[1] = c[2] = v_brightness.value;
980 if (c[0] >= 0.01f || c[1] >= 0.01f || c[2] >= 0.01f)
982 GL_BlendFunc(GL_ONE, GL_ONE);
983 GL_Color(c[0], c[1], c[2], 1);
984 R_Mesh_Draw(0, 3, 1, polygonelements, 0, 0);