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.
21 // draw.c -- this is the only file outside the refresh that touches the
26 #define GL_COLOR_INDEX8_EXT 0x80E5
28 extern unsigned char d_15to8table[65536];
30 cvar_t qsg_version = {"qsg_version", "1"};
31 cvar_t gl_conalpha = {"gl_conalpha", "1"};
33 byte *draw_chars; // 8*8 graphic characters
36 //int translate_texture;
45 byte conback_buffer[sizeof(qpic_t) + sizeof(glpic_t)];
46 qpic_t *conback = (qpic_t *)&conback_buffer;
49 =============================================================================
53 Allocate all the little status bar obejcts into a single texture
54 to crutch up stupid hardware / drivers
56 =============================================================================
60 #define BLOCK_WIDTH 256
61 #define BLOCK_HEIGHT 256
63 int scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH];
64 byte scrap_texels[MAX_SCRAPS][BLOCK_WIDTH*BLOCK_HEIGHT*4];
67 // returns a texture number and the position inside it
68 int Scrap_AllocBlock (int w, int h, int *x, int *y)
74 for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++)
78 for (i=0 ; i<BLOCK_WIDTH-w ; i++)
84 if (scrap_allocated[texnum][i+j] >= best)
86 if (scrap_allocated[texnum][i+j] > best2)
87 best2 = scrap_allocated[texnum][i+j];
90 { // this is a valid spot
96 if (best + h > BLOCK_HEIGHT)
100 scrap_allocated[texnum][*x + i] = best + h;
105 Sys_Error ("Scrap_AllocBlock: full");
110 int scraptexnum[MAX_SCRAPS];
112 void Scrap_Upload (void)
118 for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++)
119 scraptexnum[texnum] = GL_LoadTexture (va("scrapslot%d", texnum), BLOCK_WIDTH, BLOCK_HEIGHT, scrap_texels[texnum], false, true, 1);
123 //=============================================================================
124 /* Support Routines */
126 typedef struct cachepic_s
128 char name[MAX_QPATH];
130 byte padding[32]; // for appended glpic
133 #define MAX_CACHED_PICS 128
134 cachepic_t menu_cachepics[MAX_CACHED_PICS];
135 int menu_numcachepics;
137 byte menuplyr_pixels[4096];
142 int GL_LoadPicTexture (qpic_t *pic);
144 qpic_t *Draw_PicFromWad (char *name)
149 p = W_GetLumpName (name);
150 gl = (glpic_t *)p->data;
152 // load little ones into the scrap
153 if (p->width < 64 && p->height < 64)
159 texnum = Scrap_AllocBlock (p->width, p->height, &x, &y);
162 for (i=0 ; i<p->height ; i++)
163 for (j=0 ; j<p->width ; j++, k++)
164 scrap_texels[texnum][(y+i)*BLOCK_WIDTH + x + j] = p->data[k];
165 if (!scraptexnum[texnum])
166 scraptexnum[texnum] = GL_LoadTexture (va("scrapslot%d", texnum), BLOCK_WIDTH, BLOCK_HEIGHT, scrap_texels[texnum], false, true, 1);
167 gl->texnum = scraptexnum[texnum];
168 gl->sl = (x+0.01)/(float)BLOCK_WIDTH;
169 gl->sh = (x+p->width-0.01)/(float)BLOCK_WIDTH;
170 gl->tl = (y+0.01)/(float)BLOCK_WIDTH;
171 gl->th = (y+p->height-0.01)/(float)BLOCK_WIDTH;
174 pic_texels += p->width*p->height;
178 gl->texnum = GL_LoadPicTexture (p);
193 qpic_t *Draw_CachePic (char *path)
200 for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++)
201 if (!strcmp (path, pic->name))
204 if (menu_numcachepics == MAX_CACHED_PICS)
205 Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
207 strcpy (pic->name, path);
210 // load the pic from disk
212 dat = (qpic_t *)COM_LoadTempFile (path, false);
214 Sys_Error ("Draw_CachePic: failed to load %s", path);
217 // HACK HACK HACK --- we need to keep the bytes for
218 // the translatable player picture just for the menu
219 // configuration dialog
220 if (!strcmp (path, "gfx/menuplyr.lmp"))
221 memcpy (menuplyr_pixels, dat->data, dat->width*dat->height);
223 pic->pic.width = dat->width;
224 pic->pic.height = dat->height;
226 gl = (glpic_t *)pic->pic.data;
227 gl->texnum = GL_LoadPicTexture (dat);
237 void Draw_CharToConback (int num, byte *dest)
246 source = draw_chars + (row<<10) + (col<<3);
252 for (x=0 ; x<8 ; x++)
253 if (source[x] != 255)
254 dest[x] = 0x60 + source[x];
262 extern void LoadSky_f(void);
264 extern char *QSG_EXTENSIONS;
271 void rmain_registercvars();
272 extern int buildnumber;
279 // load the console background and the charset
280 // by hand, because we need to write the version
281 // string into the background before turning
283 char_texture = loadtextureimage ("conchars", 0, 0, false, false);
286 draw_chars = W_GetLumpName ("conchars");
287 for (i=0 ; i<256*64 ; i++)
288 if (draw_chars[i] == 0)
289 draw_chars[i] = 255; // proper transparent color
291 // now turn them into textures
292 char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true, 1);
295 gl = (glpic_t *)conback->data;
296 gl->texnum = loadtextureimage("gfx/conback", 0, 0, false, false);
301 conback->width = vid.width;
302 conback->height = vid.height;
304 memset(scraptexnum, 0, sizeof(scraptexnum));
306 // get the other pics we need
307 draw_disc = Draw_PicFromWad ("disc");
310 void gl_draw_shutdown()
314 char engineversion[40];
315 int engineversionx, engineversiony;
317 extern void GL_Textures_Init();
318 void GL_Draw_Init (void)
321 Cvar_RegisterVariable (&qsg_version);
322 Cvar_RegisterVariable (&gl_conalpha);
324 Cmd_AddCommand ("loadsky", &LoadSky_f);
327 #if defined(__linux__)
328 sprintf (engineversion, "DPNehahra Linux GL %.2f build %3i", (float) VERSION, buildnumber);
330 sprintf (engineversion, "DPNehahra Windows GL %.2f build %3i", (float) VERSION, buildnumber);
332 sprintf (engineversion, "DPNehahra Unknown GL %.2f build %3i", (float) VERSION, buildnumber);
335 #if defined(__linux__)
336 sprintf (engineversion, "DarkPlaces Linux GL %.2f build %3i", (float) VERSION, buildnumber);
338 sprintf (engineversion, "DarkPlaces Windows GL %.2f build %3i", (float) VERSION, buildnumber);
340 sprintf (engineversion, "DarkPlaces Unknown GL %.2f build %3i", (float) VERSION, buildnumber);
343 for (i = 0;i < 40 && engineversion[i];i++)
344 engineversion[i] += 0x80; // shift to orange
345 engineversionx = vid.width - strlen(engineversion) * 8 - 8;
346 engineversiony = vid.height - 8;
349 R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown);
356 Draws one 8*8 graphics character with 0 being transparent.
357 It can be clipped to the top of the screen to allow the console to be
358 smoothly scrolled off.
361 void Draw_Character (int x, int y, int num)
364 float frow, fcol, size;
372 return; // totally off screen
381 glBindTexture(GL_TEXTURE_2D, char_texture);
382 // LordHavoc: NEAREST mode on text if not scaling up
383 if ((int) vid.width < glwidth)
385 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
386 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
391 glTexCoord2f (fcol, frow);
393 glTexCoord2f (fcol + size, frow);
395 glTexCoord2f (fcol + size, frow + size);
396 glVertex2f (x+8, y+8);
397 glTexCoord2f (fcol, frow + size);
401 // LordHavoc: revert to LINEAR mode
402 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
403 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
411 // LordHavoc: sped this up a lot, and added maxlen
412 void Draw_String (int x, int y, char *str, int maxlen)
416 if (y <= -8 || y >= (int) vid.height || x >= (int) vid.width || *str == 0) // completely offscreen or no text to print
419 maxlen = strlen(str);
420 else if (maxlen > (int) strlen(str))
421 maxlen = strlen(str);
422 glBindTexture(GL_TEXTURE_2D, char_texture);
424 // LordHavoc: NEAREST mode on text if not scaling up
425 if ((int) vid.width < glwidth)
427 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
428 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
433 while (maxlen-- && x < (int) vid.width) // stop rendering when out of characters or room
435 if ((num = *str++) != 32) // skip spaces
437 frow = (float) ((int) num >> 4)*0.0625;
438 fcol = (float) ((int) num & 15)*0.0625;
439 glTexCoord2f (fcol, frow);
441 glTexCoord2f (fcol + 0.0625, frow);
443 glTexCoord2f (fcol + 0.0625, frow + 0.0625);
444 glVertex2f (x+8, y+8);
445 glTexCoord2f (fcol, frow + 0.0625);
452 // LordHavoc: revert to LINEAR mode
453 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
454 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
457 void Draw_GenericPic (int texnum, float red, float green, float blue, float alpha, float x, float y, float width, float height)
459 glDisable(GL_ALPHA_TEST);
460 // glEnable (GL_BLEND);
461 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
462 // glCullFace(GL_FRONT);
463 glColor4f(red,green,blue,alpha);
464 glBindTexture(GL_TEXTURE_2D, texnum);
465 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
470 glVertex2f (x+width, y);
472 glVertex2f (x+width, y+height);
474 glVertex2f (x, y+height);
477 // glEnable(GL_ALPHA_TEST);
478 // glDisable (GL_BLEND);
486 void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha)
492 gl = (glpic_t *)pic->data;
493 // glDisable(GL_ALPHA_TEST);
494 // glEnable (GL_BLEND);
495 // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
496 // glCullFace(GL_FRONT);
497 glColor4f(0.8,0.8,0.8,alpha);
498 glBindTexture(GL_TEXTURE_2D, gl->texnum);
499 // glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
501 glTexCoord2f (gl->sl, gl->tl);
503 glTexCoord2f (gl->sh, gl->tl);
504 glVertex2f (x+pic->width, y);
505 glTexCoord2f (gl->sh, gl->th);
506 glVertex2f (x+pic->width, y+pic->height);
507 glTexCoord2f (gl->sl, gl->th);
508 glVertex2f (x, y+pic->height);
511 // glEnable(GL_ALPHA_TEST);
512 // glDisable (GL_BLEND);
521 void Draw_Pic (int x, int y, qpic_t *pic)
527 gl = (glpic_t *)pic->data;
528 glColor3f(0.8,0.8,0.8);
529 glBindTexture(GL_TEXTURE_2D, gl->texnum);
531 glTexCoord2f (gl->sl, gl->tl);
533 glTexCoord2f (gl->sh, gl->tl);
534 glVertex2f (x+pic->width, y);
535 glTexCoord2f (gl->sh, gl->th);
536 glVertex2f (x+pic->width, y+pic->height);
537 glTexCoord2f (gl->sl, gl->th);
538 glVertex2f (x, y+pic->height);
548 void Draw_TransPic (int x, int y, qpic_t *pic)
550 if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 || (unsigned)(y + pic->height) > vid.height)
551 Sys_Error ("Draw_TransPic: bad coordinates");
553 // glEnable(GL_BLEND);
554 // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
555 // glDisable(GL_ALPHA_TEST);
556 Draw_Pic (x, y, pic);
557 // glDisable(GL_BLEND);
563 Draw_TransPicTranslate
565 Only used for the player color selection menu
568 void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
571 unsigned trans[64*64], *dest;
575 c = pic->width * pic->height;
578 for (v=0 ; v<64 ; v++, dest += 64)
580 src = &menuplyr_pixels[ ((v*pic->height)>>6) *pic->width];
581 for (u=0 ; u<64 ; u++)
583 p = src[(u*pic->width)>>6];
587 dest[u] = d_8to24table[translation[p]];
591 glBindTexture(GL_TEXTURE_2D, GL_LoadTexture ("translatedplayerpic", 64, 64, (void *) trans, false, true, 1));
593 glColor3f(0.8,0.8,0.8);
598 glVertex2f (x+pic->width, y);
600 glVertex2f (x+pic->width, y+pic->height);
602 glVertex2f (x, y+pic->height);
609 Draw_ConsoleBackground
613 void Draw_ConsoleBackground (int lines)
615 // LordHavoc: changed alpha
616 //int y = (vid.height >> 1);
618 if (lines >= (int) vid.height)
619 Draw_Pic(0, lines - vid.height, conback);
621 Draw_AlphaPic (0, lines - vid.height, conback, gl_conalpha.value*lines/vid.height);
622 // Draw_AlphaPic (0, lines - vid.height, conback, (float)(1.2 * lines)/y);
623 // LordHavoc: draw version
624 Draw_String(engineversionx, lines - vid.height + engineversiony, engineversion, 9999);
631 Fills a box of pixels with a single color
634 void Draw_Fill (int x, int y, int w, int h, int c)
636 glDisable (GL_TEXTURE_2D);
637 glColor3f (host_basepal[c*3]/255.0, host_basepal[c*3+1]/255.0, host_basepal[c*3+2]/255.0);
643 glVertex2f (x+w, y+h);
648 glEnable (GL_TEXTURE_2D);
650 //=============================================================================
652 //=============================================================================
658 Setup as if the screen was 320*200
663 glViewport (glx, gly, glwidth, glheight);
665 glMatrixMode(GL_PROJECTION);
667 glOrtho (0, vid.width, vid.height, 0, -99999, 99999);
669 glMatrixMode(GL_MODELVIEW);
672 glDisable (GL_DEPTH_TEST);
673 glDisable (GL_CULL_FACE);
674 glEnable (GL_BLEND); // was Disable
675 // glEnable (GL_ALPHA_TEST);
676 glDisable (GL_ALPHA_TEST);
677 glEnable(GL_TEXTURE_2D);
679 // LordHavoc: added this
680 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
681 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
686 // LordHavoc: SHOWLMP stuff
687 #define SHOWLMP_MAXLABELS 256
688 typedef struct showlmp_s
697 showlmp_t showlmp[SHOWLMP_MAXLABELS];
699 void SHOWLMP_decodehide()
703 lmplabel = MSG_ReadString();
704 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
705 if (showlmp[i].isactive && strcmp(showlmp[i].label, lmplabel) == 0)
707 showlmp[i].isactive = false;
712 void SHOWLMP_decodeshow()
715 byte lmplabel[256], picname[256];
717 strcpy(lmplabel,MSG_ReadString());
718 strcpy(picname, MSG_ReadString());
722 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
723 if (showlmp[i].isactive)
725 if (strcmp(showlmp[i].label, lmplabel) == 0)
728 break; // drop out to replace it
731 else if (k < 0) // find first empty one to replace
734 return; // none found to replace
735 // change existing one
736 showlmp[k].isactive = true;
737 strcpy(showlmp[k].label, lmplabel);
738 strcpy(showlmp[k].pic, picname);
743 void SHOWLMP_drawall()
746 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
747 if (showlmp[i].isactive)
748 Draw_TransPic(showlmp[i].x, showlmp[i].y, Draw_CachePic(showlmp[i].pic));
754 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
755 showlmp[i].isactive = false;