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.
26 #include "cl_dyntexture.h"
28 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 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)"};
31 static rtexture_t *char_texture;
32 cachepic_t *r_crosshairs[NUMCROSSHAIRS+1];
34 //=============================================================================
35 /* Support Routines */
37 #define FONT_FILESIZE 13468
38 #define MAX_CACHED_PICS 1024
39 #define CACHEPICHASHSIZE 256
40 static cachepic_t *cachepichash[CACHEPICHASHSIZE];
41 static cachepic_t cachepics[MAX_CACHED_PICS];
42 static int numcachepics;
44 static rtexturepool_t *drawtexturepool;
46 static unsigned char concharimage[FONT_FILESIZE] =
51 static rtexture_t *draw_generateconchars(void)
54 unsigned char buffer[65536][4], *data = NULL;
57 data = LoadTGA_BGRA (concharimage, FONT_FILESIZE);
59 for (i = 0;i < 8192;i++)
61 random = lhrandom (0.0,1.0);
62 buffer[i][2] = 83 + (unsigned char)(random * 64);
63 buffer[i][1] = 71 + (unsigned char)(random * 32);
64 buffer[i][0] = 23 + (unsigned char)(random * 16);
65 buffer[i][3] = data[i*4+0];
68 for (i = 8192;i < 32768;i++)
70 random = lhrandom (0.0,1.0);
71 buffer[i][2] = 95 + (unsigned char)(random * 64);
72 buffer[i][1] = 95 + (unsigned char)(random * 64);
73 buffer[i][0] = 95 + (unsigned char)(random * 64);
74 buffer[i][3] = data[i*4+0];
77 for (i = 32768;i < 40960;i++)
79 random = lhrandom (0.0,1.0);
80 buffer[i][2] = 83 + (unsigned char)(random * 64);
81 buffer[i][1] = 71 + (unsigned char)(random * 32);
82 buffer[i][0] = 23 + (unsigned char)(random * 16);
83 buffer[i][3] = data[i*4+0];
86 for (i = 40960;i < 65536;i++)
88 random = lhrandom (0.0,1.0);
89 buffer[i][2] = 96 + (unsigned char)(random * 64);
90 buffer[i][1] = 43 + (unsigned char)(random * 32);
91 buffer[i][0] = 27 + (unsigned char)(random * 32);
92 buffer[i][3] = data[i*4+0];
96 Image_WriteTGABGRA ("gfx/generated_conchars.tga", 256, 256, &buffer[0][0]);
100 return R_LoadTexture2D(drawtexturepool, "conchars", 256, 256, &buffer[0][0], TEXTYPE_BGRA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
103 static char *pointerimage =
122 static rtexture_t *draw_generatemousepointer(void)
125 unsigned char buffer[256][4];
126 for (i = 0;i < 256;i++)
128 if (pointerimage[i] == '.')
137 buffer[i][0] = (pointerimage[i] - '0') * 16;
138 buffer[i][1] = (pointerimage[i] - '0') * 16;
139 buffer[i][2] = (pointerimage[i] - '0') * 16;
143 return R_LoadTexture2D(drawtexturepool, "mousepointer", 16, 16, &buffer[0][0], TEXTYPE_BGRA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
146 static char *crosshairtexdata[NUMCROSSHAIRS] =
251 static rtexture_t *draw_generatecrosshair(int num)
255 unsigned char data[16*16][4];
256 in = crosshairtexdata[num];
257 for (i = 0;i < 16*16;i++)
268 data[i][0] = data[i][1] = data[i][2] = (unsigned char) ((int) (in[i] - '0') * 127 / 7 + 128);
272 return R_LoadTexture2D(drawtexturepool, va("crosshair%i", num+1), 16, 16, &data[0][0], TEXTYPE_BGRA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
275 static rtexture_t *draw_generateditherpattern(void)
279 unsigned char data[8*8*4];
280 for (y = 0;y < 8;y++)
282 for (x = 0;x < 8;x++)
284 data[(y*8+x)*4+0] = data[(y*8+x)*4+1] = data[(y*8+x)*4+2] = ((x^y) & 4) ? 255 : 0;
285 data[(y*8+x)*4+3] = 255;
288 return R_LoadTexture2D(drawtexturepool, "ditherpattern", 8, 8, data, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_PRECACHE, NULL);
290 unsigned char data[16];
291 memset(data, 255, sizeof(data));
292 data[0] = data[1] = data[2] = data[12] = data[13] = data[14] = 0;
293 return R_LoadTexture2D(drawtexturepool, "ditherpattern", 2, 2, data, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_PRECACHE, NULL);
302 // FIXME: move this to client somehow
303 cachepic_t *Draw_CachePic (const char *path, qboolean persistent)
309 unsigned char *lmpdata;
310 char lmpname[MAX_QPATH];
312 // check whether the picture has already been cached
313 crc = CRC_Block((unsigned char *)path, strlen(path));
314 hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
315 for (pic = cachepichash[hashkey];pic;pic = pic->chain)
316 if (!strcmp (path, pic->name))
319 if (numcachepics == MAX_CACHED_PICS)
321 Con_Printf ("Draw_CachePic: numcachepics == MAX_CACHED_PICS\n");
322 // FIXME: support NULL in callers?
323 return cachepics; // return the first one
325 pic = cachepics + (numcachepics++);
326 strlcpy (pic->name, path, sizeof(pic->name));
328 pic->chain = cachepichash[hashkey];
329 cachepichash[hashkey] = pic;
331 // check whether it is an dynamic texture (if so, we can directly use its texture handler)
332 pic->tex = CL_GetDynTexture( path );
333 // if so, set the width/height, too
335 pic->width = R_TextureWidth(pic->tex);
336 pic->height = R_TextureHeight(pic->tex);
337 // we're done now (early-out)
343 flags |= TEXF_PRECACHE;
344 if (!strcmp(path, "gfx/colorcontrol/ditherpattern"))
347 // load a high quality image from disk if possible
348 pic->tex = loadtextureimage(drawtexturepool, path, false, flags | (gl_texturecompression_2d.integer ? TEXF_COMPRESS : 0), true);
349 if (pic->tex == NULL && !strncmp(path, "gfx/", 4))
351 // compatibility with older versions which did not require gfx/ prefix
352 pic->tex = loadtextureimage(drawtexturepool, path + 4, false, flags | (gl_texturecompression_2d.integer ? TEXF_COMPRESS : 0), true);
354 // if a high quality image was loaded, set the pic's size to match it, just
355 // in case there's no low quality version to get the size from
358 pic->width = R_TextureWidth(pic->tex);
359 pic->height = R_TextureHeight(pic->tex);
362 // now read the low quality version (wad or lmp file), and take the pic
363 // size from that even if we don't upload the texture, this way the pics
364 // show up the right size in the menu even if they were replaced with
365 // higher or lower resolution versions
366 dpsnprintf(lmpname, sizeof(lmpname), "%s.lmp", path);
367 if (!strncmp(path, "gfx/", 4) && (lmpdata = FS_LoadFile(lmpname, tempmempool, false, &lmpsize)))
371 pic->width = lmpdata[0] + lmpdata[1] * 256 + lmpdata[2] * 65536 + lmpdata[3] * 16777216;
372 pic->height = lmpdata[4] + lmpdata[5] * 256 + lmpdata[6] * 65536 + lmpdata[7] * 16777216;
373 // if no high quality replacement image was found, upload the original low quality texture
375 pic->tex = R_LoadTexture2D(drawtexturepool, path, pic->width, pic->height, lmpdata + 8, TEXTYPE_PALETTE, flags, palette_bgra_transparent);
379 else if ((lmpdata = W_GetLumpName (path + 4)))
381 if (!strcmp(path, "gfx/conchars"))
383 // conchars is a raw image and with color 0 as transparent instead of 255
386 // if no high quality replacement image was found, upload the original low quality texture
388 pic->tex = R_LoadTexture2D(drawtexturepool, path, 128, 128, lmpdata, TEXTYPE_PALETTE, flags, palette_bgra_font);
392 pic->width = lmpdata[0] + lmpdata[1] * 256 + lmpdata[2] * 65536 + lmpdata[3] * 16777216;
393 pic->height = lmpdata[4] + lmpdata[5] * 256 + lmpdata[6] * 65536 + lmpdata[7] * 16777216;
394 // if no high quality replacement image was found, upload the original low quality texture
396 pic->tex = R_LoadTexture2D(drawtexturepool, path, pic->width, pic->height, lmpdata + 8, TEXTYPE_PALETTE, flags, palette_bgra_transparent);
400 // if it's not found on disk, check if it's one of the builtin images
401 if (pic->tex == NULL)
403 if (pic->tex == NULL && !strcmp(path, "gfx/conchars"))
404 pic->tex = draw_generateconchars();
405 if (pic->tex == NULL && !strcmp(path, "ui/mousepointer"))
406 pic->tex = draw_generatemousepointer();
407 if (pic->tex == NULL && !strcmp(path, "gfx/prydoncursor001"))
408 pic->tex = draw_generatemousepointer();
409 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair1"))
410 pic->tex = draw_generatecrosshair(0);
411 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair2"))
412 pic->tex = draw_generatecrosshair(1);
413 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair3"))
414 pic->tex = draw_generatecrosshair(2);
415 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair4"))
416 pic->tex = draw_generatecrosshair(3);
417 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair5"))
418 pic->tex = draw_generatecrosshair(4);
419 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair6"))
420 pic->tex = draw_generatecrosshair(5);
421 if (pic->tex == NULL && !strcmp(path, "gfx/colorcontrol/ditherpattern"))
422 pic->tex = draw_generateditherpattern();
423 if (pic->tex == NULL)
425 // don't complain about missing gfx/crosshair images
426 if (strncmp(path, "gfx/crosshair", 13))
427 Con_Printf("Draw_CachePic: failed to load %s\n", path);
428 pic->tex = r_texture_notexture;
430 pic->width = R_TextureWidth(pic->tex);
431 pic->height = R_TextureHeight(pic->tex);
437 cachepic_t *Draw_NewPic(const char *picname, int width, int height, int alpha, unsigned char *pixels_bgra)
442 crc = CRC_Block((unsigned char *)picname, strlen(picname));
443 hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
444 for (pic = cachepichash[hashkey];pic;pic = pic->chain)
445 if (!strcmp (picname, pic->name))
450 if (pic->tex && pic->width == width && pic->height == height)
452 R_UpdateTexture(pic->tex, pixels_bgra, 0, 0, width, height);
460 if (numcachepics == MAX_CACHED_PICS)
462 Con_Printf ("Draw_NewPic: numcachepics == MAX_CACHED_PICS\n");
463 // FIXME: support NULL in callers?
464 return cachepics; // return the first one
466 pic = cachepics + (numcachepics++);
467 strlcpy (pic->name, picname, sizeof(pic->name));
469 pic->chain = cachepichash[hashkey];
470 cachepichash[hashkey] = pic;
475 pic->height = height;
477 R_FreeTexture(pic->tex);
478 pic->tex = R_LoadTexture2D(drawtexturepool, picname, width, height, pixels_bgra, TEXTYPE_BGRA, alpha ? TEXF_ALPHA : 0, NULL);
482 void Draw_FreePic(const char *picname)
487 // this doesn't really free the pic, but does free it's texture
488 crc = CRC_Block((unsigned char *)picname, strlen(picname));
489 hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
490 for (pic = cachepichash[hashkey];pic;pic = pic->chain)
492 if (!strcmp (picname, pic->name) && pic->tex)
494 R_FreeTexture(pic->tex);
507 static void gl_draw_start(void)
510 drawtexturepool = R_AllocTexturePool();
513 memset(cachepichash, 0, sizeof(cachepichash));
515 char_texture = Draw_CachePic("gfx/conchars", true)->tex;
516 for (i = 1;i <= NUMCROSSHAIRS;i++)
517 r_crosshairs[i] = Draw_CachePic(va("gfx/crosshair%i", i), true);
519 // draw the loading screen so people have something to see in the newly opened window
520 SCR_UpdateLoadingScreen(true);
523 static void gl_draw_shutdown(void)
525 R_FreeTexturePool(&drawtexturepool);
528 memset(cachepichash, 0, sizeof(cachepichash));
531 static void gl_draw_newmap(void)
535 void GL_Draw_Init (void)
537 Cvar_RegisterVariable(&r_textshadow);
538 Cvar_RegisterVariable(&r_textbrightness);
539 R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap);
542 static void _DrawQ_Setup(void)
544 if (r_refdef.draw2dstage)
546 r_refdef.draw2dstage = true;
548 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
549 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
550 GL_SetupView_Mode_Ortho(0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100);
551 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
552 qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
553 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
554 R_Mesh_Matrix(&identitymatrix);
558 GL_PolygonOffset(0, 0);
562 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
564 if (gl_support_fragment_shader)
566 qglUseProgramObjectARB(0);CHECKGLERROR
570 static void _DrawQ_ProcessDrawFlag(int flags)
574 if(flags == DRAWFLAG_ADDITIVE)
575 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
576 else if(flags == DRAWFLAG_MODULATE)
577 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
578 else if(flags == DRAWFLAG_2XMODULATE)
579 GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
581 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
584 void DrawQ_Pic(float x, float y, cachepic_t *pic, float width, float height, float red, float green, float blue, float alpha, int flags)
588 _DrawQ_ProcessDrawFlag(flags);
589 GL_Color(red, green, blue, alpha);
591 R_Mesh_VertexPointer(floats, 0, 0);
592 R_Mesh_ColorPointer(NULL, 0, 0);
593 R_Mesh_ResetTextureState();
599 height = pic->height;
600 R_Mesh_TexBind(0, R_GetTexture(pic->tex));
601 R_Mesh_TexCoordPointer(0, 2, floats + 12, 0, 0);
603 // AK07: lets be texel correct on the corners
605 float horz_offset = 0.5f / pic->width;
606 float vert_offset = 0.5f / pic->height;
608 floats[12] = 0.0f + horz_offset;floats[13] = 0.0f + vert_offset;
609 floats[14] = 1.0f - horz_offset;floats[15] = 0.0f + vert_offset;
610 floats[16] = 1.0f - horz_offset;floats[17] = 1.0f - vert_offset;
611 floats[18] = 0.0f + horz_offset;floats[19] = 1.0f - vert_offset;
615 floats[2] = floats[5] = floats[8] = floats[11] = 0;
616 floats[0] = floats[9] = x;
617 floats[1] = floats[4] = y;
618 floats[3] = floats[6] = x + width;
619 floats[7] = floats[10] = y + height;
621 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
624 void DrawQ_Fill(float x, float y, float width, float height, float red, float green, float blue, float alpha, int flags)
628 _DrawQ_ProcessDrawFlag(flags);
629 GL_Color(red, green, blue, alpha);
631 R_Mesh_VertexPointer(floats, 0, 0);
632 R_Mesh_ColorPointer(NULL, 0, 0);
633 R_Mesh_ResetTextureState();
635 floats[2] = floats[5] = floats[8] = floats[11] = 0;
636 floats[0] = floats[9] = x;
637 floats[1] = floats[4] = y;
638 floats[3] = floats[6] = x + width;
639 floats[7] = floats[10] = y + height;
641 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
644 // color tag printing
645 static vec4_t string_colors[] =
648 // LordHavoc: why on earth is cyan before magenta in Quake3?
649 // LordHavoc: note: Doom3 uses white for [0] and [7]
650 {0.0, 0.0, 0.0, 1.0}, // black
651 {1.0, 0.0, 0.0, 1.0}, // red
652 {0.0, 1.0, 0.0, 1.0}, // green
653 {1.0, 1.0, 0.0, 1.0}, // yellow
654 {0.0, 0.0, 1.0, 1.0}, // blue
655 {0.0, 1.0, 1.0, 1.0}, // cyan
656 {1.0, 0.0, 1.0, 1.0}, // magenta
657 {1.0, 1.0, 1.0, 1.0}, // white
658 // [515]'s BX_COLOREDTEXT extension
659 {1.0, 1.0, 1.0, 0.5}, // half transparent
660 {0.5, 0.5, 0.5, 1.0} // half brightness
661 // Black's color table
662 //{1.0, 1.0, 1.0, 1.0},
663 //{1.0, 0.0, 0.0, 1.0},
664 //{0.0, 1.0, 0.0, 1.0},
665 //{0.0, 0.0, 1.0, 1.0},
666 //{1.0, 1.0, 0.0, 1.0},
667 //{0.0, 1.0, 1.0, 1.0},
668 //{1.0, 0.0, 1.0, 1.0},
669 //{0.1, 0.1, 0.1, 1.0}
672 #define STRING_COLORS_COUNT (sizeof(string_colors) / sizeof(vec4_t))
674 static void DrawQ_GetTextColor(float color[4], int colorindex, float r, float g, float b, float a, qboolean shadow)
676 float v = r_textbrightness.value;
677 Vector4Copy(string_colors[colorindex], color);
678 Vector4Set(color, (color[0] * (1-v) + v) * r, (color[1] * (1-v) + v) * g, (color[2] * (1-v) + v) * b, color[3] * a);
681 float shadowalpha = color[0]+color[1]+color[2] * 0.8;
682 Vector4Set(color, 0, 0, 0, color[3] * bound(0, shadowalpha, 1));
686 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)
688 int i, num, shadow, colorindex = STRING_COLOR_DEFAULT;
689 float x = startx, y, s, t, u, v;
693 float vertex3f[QUADELEMENTS_MAXQUADS*4*3];
694 float texcoord2f[QUADELEMENTS_MAXQUADS*4*2];
695 float color4f[QUADELEMENTS_MAXQUADS*4*4];
700 _DrawQ_ProcessDrawFlag(flags);
702 R_Mesh_ColorPointer(color4f, 0, 0);
703 R_Mesh_ResetTextureState();
704 R_Mesh_TexBind(0, R_GetTexture(char_texture));
705 R_Mesh_TexCoordPointer(0, 2, texcoord2f, 0, 0);
706 R_Mesh_VertexPointer(vertex3f, 0, 0);
713 for (shadow = r_textshadow.value != 0;shadow >= 0;shadow--)
715 if (!outcolor || *outcolor == -1)
716 colorindex = STRING_COLOR_DEFAULT;
718 colorindex = *outcolor;
719 DrawQ_GetTextColor(color, colorindex, basered, basegreen, baseblue, basealpha, shadow);
725 x += r_textshadow.value;
726 y += r_textshadow.value;
728 for (i = 0;i < maxlen && text[i];i++, x += w)
732 if (text[i] == STRING_COLOR_TAG && !ignorecolorcodes && i + 1 < maxlen)
734 if (text[i+1] == STRING_COLOR_TAG)
740 else if (text[i+1] >= '0' && text[i+1] <= '9')
742 colorindex = text[i+1] - '0';
743 DrawQ_GetTextColor(color, colorindex, basered, basegreen, baseblue, basealpha, shadow);
750 s = (num & 15)*0.0625f + (0.5f / 256.0f);
751 t = (num >> 4)*0.0625f + (0.5f / 256.0f);
752 u = 0.0625f - (1.0f / 256.0f);
753 v = 0.0625f - (1.0f / 256.0f);
754 ac[ 0] = color[0];ac[ 1] = color[1];ac[ 2] = color[2];ac[ 3] = color[3];
755 ac[ 4] = color[0];ac[ 5] = color[1];ac[ 6] = color[2];ac[ 7] = color[3];
756 ac[ 8] = color[0];ac[ 9] = color[1];ac[10] = color[2];ac[11] = color[3];
757 ac[12] = color[0];ac[13] = color[1];ac[14] = color[2];ac[15] = color[3];
758 at[ 0] = s ;at[ 1] = t ;
759 at[ 2] = s+u;at[ 3] = t ;
760 at[ 4] = s+u;at[ 5] = t+v;
761 at[ 6] = s ;at[ 7] = t+v;
762 av[ 0] = x ;av[ 1] = y ;av[ 2] = 10;
763 av[ 3] = x+w;av[ 4] = y ;av[ 5] = 10;
764 av[ 6] = x+w;av[ 7] = y+h;av[ 8] = 10;
765 av[ 9] = x ;av[10] = y+h;av[11] = 10;
770 if (batchcount >= QUADELEMENTS_MAXQUADS)
772 if (basealpha >= (1.0f / 255.0f))
774 GL_LockArrays(0, batchcount * 4);
775 R_Mesh_Draw(0, batchcount * 4, batchcount * 2, quadelements, 0, 0);
787 if (basealpha >= (1.0f / 255.0f))
789 GL_LockArrays(0, batchcount * 4);
790 R_Mesh_Draw(0, batchcount * 4, batchcount * 2, quadelements, 0, 0);
796 *outcolor = colorindex;
798 // note: this relies on the proper text (not shadow) being drawn last
804 static int DrawQ_BuildColoredText(char *output2c, size_t maxoutchars, const char *text, int maxreadchars, qboolean ignorecolorcodes, int *outcolor)
806 int color, numchars = 0;
807 char *outputend2c = output2c + maxoutchars - 2;
808 if (!outcolor || *outcolor == -1)
809 color = STRING_COLOR_DEFAULT;
813 maxreadchars = 1<<30;
814 textend = text + maxreadchars;
815 while (text != textend && *text)
817 if (*text == STRING_COLOR_TAG && !ignorecolorcodes && text + 1 != textend)
819 if (text[1] == STRING_COLOR_TAG)
821 else if (text[1] >= '0' && text[1] <= '9')
823 color = text[1] - '0';
828 if (output2c >= outputend2c)
830 *output2c++ = *text++;
834 output2c[0] = output2c[1] = 0;
841 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)
845 _DrawQ_ProcessDrawFlag(flags);
847 R_Mesh_VertexPointer(floats, 0, 0);
848 R_Mesh_ColorPointer(floats + 20, 0, 0);
849 R_Mesh_ResetTextureState();
855 height = pic->height;
856 R_Mesh_TexBind(0, R_GetTexture(pic->tex));
857 R_Mesh_TexCoordPointer(0, 2, floats + 12, 0, 0);
858 floats[12] = s1;floats[13] = t1;
859 floats[14] = s2;floats[15] = t2;
860 floats[16] = s4;floats[17] = t4;
861 floats[18] = s3;floats[19] = t3;
864 floats[2] = floats[5] = floats[8] = floats[11] = 0;
865 floats[0] = floats[9] = x;
866 floats[1] = floats[4] = y;
867 floats[3] = floats[6] = x + width;
868 floats[7] = floats[10] = y + height;
869 floats[20] = r1;floats[21] = g1;floats[22] = b1;floats[23] = a1;
870 floats[24] = r2;floats[25] = g2;floats[26] = b2;floats[27] = a2;
871 floats[28] = r4;floats[29] = g4;floats[30] = b4;floats[31] = a4;
872 floats[32] = r3;floats[33] = g3;floats[34] = b3;floats[35] = a3;
874 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
877 void DrawQ_Mesh (drawqueuemesh_t *mesh, int flags)
879 _DrawQ_ProcessDrawFlag(flags);
881 R_Mesh_VertexPointer(mesh->data_vertex3f, 0, 0);
882 R_Mesh_ColorPointer(mesh->data_color4f, 0, 0);
883 R_Mesh_ResetTextureState();
884 R_Mesh_TexBind(0, R_GetTexture(mesh->texture));
885 R_Mesh_TexCoordPointer(0, 2, mesh->data_texcoord2f, 0, 0);
887 GL_LockArrays(0, mesh->num_vertices);
888 R_Mesh_Draw(0, mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, 0, 0);
892 void DrawQ_LineLoop (drawqueuemesh_t *mesh, int flags)
896 _DrawQ_ProcessDrawFlag(flags);
900 qglBegin(GL_LINE_LOOP);
901 for (num = 0;num < mesh->num_vertices;num++)
903 if (mesh->data_color4f)
904 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]);
905 qglVertex2f(mesh->data_vertex3f[num*3+0], mesh->data_vertex3f[num*3+1]);
911 //[515]: this is old, delete
912 void DrawQ_Line (float width, float x1, float y1, float x2, float y2, float r, float g, float b, float alpha, int flags)
914 _DrawQ_ProcessDrawFlag(flags);
917 qglLineWidth(width);CHECKGLERROR
919 GL_Color(r,g,b,alpha);
928 void DrawQ_SetClipArea(float x, float y, float width, float height)
932 // We have to convert the con coords into real coords
933 // OGL uses top to bottom
934 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)));
936 GL_ScissorTest(true);
939 void DrawQ_ResetClipArea(void)
942 GL_ScissorTest(false);
945 void DrawQ_Finish(void)
947 r_refdef.draw2dstage = false;
950 static float blendvertex3f[9] = {-5000, -5000, 10, 10000, -5000, 10, -5000, 10000, 10};
951 void R_DrawGamma(void)
954 if (!vid_usinghwgamma)
956 // all the blends ignore depth
957 R_Mesh_VertexPointer(blendvertex3f, 0, 0);
958 R_Mesh_ColorPointer(NULL, 0, 0);
959 R_Mesh_ResetTextureState();
962 GL_PolygonOffset(0, 0);
964 if (v_color_enable.integer)
966 c[0] = v_color_white_r.value;
967 c[1] = v_color_white_g.value;
968 c[2] = v_color_white_b.value;
971 c[0] = c[1] = c[2] = v_contrast.value;
972 if (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f)
974 GL_BlendFunc(GL_DST_COLOR, GL_ONE);
975 while (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f)
977 GL_Color(bound(0, c[0] - 1, 1), bound(0, c[1] - 1, 1), bound(0, c[2] - 1, 1), 1);
978 R_Mesh_Draw(0, 3, 1, polygonelements, 0, 0);
979 VectorScale(c, 0.5, c);
982 if (v_color_enable.integer)
984 c[0] = v_color_black_r.value;
985 c[1] = v_color_black_g.value;
986 c[2] = v_color_black_b.value;
989 c[0] = c[1] = c[2] = v_brightness.value;
990 if (c[0] >= 0.01f || c[1] >= 0.01f || c[2] >= 0.01f)
992 GL_BlendFunc(GL_ONE, GL_ONE);
993 GL_Color(c[0], c[1], c[2], 1);
994 R_Mesh_Draw(0, 3, 1, polygonelements, 0, 0);