1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3
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.
8
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.
12
13 See the GNU General Public License for more details.
14
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.
18
19 */
20
21 // draw.c
22
23 #include "gl_local.h"
24
25 image_t *draw_chars;
26
27 // vertex arrays
28 float tex_array[MAX_ARRAY][2];
29 float vert_array[MAX_ARRAY][3];
30 float col_array[MAX_ARRAY][4];
31
32 extern qboolean scrap_dirty;
33 void Scrap_Upload (void);
34
RefreshFont(void)35 void RefreshFont (void)
36 {
37
38 draw_chars = GL_FindImage (va("fonts/%s.pcx", con_font->string), it_pic);
39 if (!draw_chars)
40 {
41 draw_chars = GL_FindImage ("fonts/default.pcx", it_pic);
42 ri.Cvar_Set( "con_font", "default" );
43 }
44
45 GL_Bind( draw_chars->texnum );
46
47 con_font->modified = false;
48 }
49
50
51 /*
52 ===============
53 Draw_InitLocal
54 ===============
55 */
Draw_InitLocal(void)56 void Draw_InitLocal (void)
57 {
58 image_t *Draw_FindPic (char *name);
59
60 // load console characters (don't bilerp characters)
61 draw_chars = Draw_FindPic ("conchars");
62
63 GL_Bind( draw_chars->texnum );
64
65 qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
66 qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
67
68 //RefreshFont();
69 }
70
71
72
73 /*
74 ================
75 Draw_Char
76
77 Draws one 8*8 graphics character with 0 being transparent.
78 It can be clipped to the top of the screen to allow the console to be
79 smoothly scrolled off.
80 ================
81 */
82
CharMapScale(void)83 float CharMapScale (void)
84 {
85 return (draw_chars->width/128.0); //current width / original width
86 }
87
Draw_NoAlphaChar(int x,int y,int num)88 void Draw_NoAlphaChar (int x, int y, int num)
89 {
90 int row, col;
91 float frow, fcol, size;
92
93 num &= 255;
94
95 if ( (num&127) == 32 )
96 return; // space
97
98 if (y <= -8)
99 return; // totally off screen
100
101 row = num>>4;
102 col = num&15;
103
104 frow = row*0.0625;
105 fcol = col*0.0625;
106 size = 0.0625;
107
108 GL_Bind (draw_chars->texnum);
109
110 qglBegin (GL_QUADS);
111 qglTexCoord2f (fcol, frow);
112 qglVertex2f (x, y);
113 qglTexCoord2f (fcol + size, frow);
114 qglVertex2f (x+8, y);
115 qglTexCoord2f (fcol + size, frow + size);
116 qglVertex2f (x+8, y+8);
117 qglTexCoord2f (fcol, frow + size);
118 qglVertex2f (x, y+8);
119 qglEnd ();
120 }
121
Draw_Char(int x,int y,int num,int alpha)122 void Draw_Char (int x, int y, int num, int alpha)
123 {
124 Draw_NoAlphaChar(x, y, num);
125 /* we don't need no stinkin' alpha chars...
126 int row, col;
127 float frow, fcol, size, scale;
128
129 num &= 255;
130
131
132 if (alpha >= 254)
133 alpha = 254;
134 else if (alpha <= 1)
135 alpha = 1;
136
137 if ( (num&127) == 32 )
138 return; // space
139
140 if (y <= -8)
141 return; // totally off screen
142
143 row = num>>4;
144 col = num&15;
145
146 frow = row*0.0625;
147 fcol = col*0.0625;
148 size = 0.0625;
149 scale = 8;
150
151 {
152 qglDisable (GL_ALPHA_TEST);
153 GL_TexEnv( GL_MODULATE );
154 qglColor4ub( 255, 255, 255, alpha);
155 qglEnable( GL_BLEND );
156 qglDepthMask (false);
157 }
158
159 GL_Bind(draw_chars->texnum);
160
161 qglBegin (GL_QUADS);
162 qglTexCoord2f (fcol, frow);
163 qglVertex2f (x, y);
164 qglTexCoord2f (fcol + size, frow);
165 qglVertex2f (x+scale, y);
166 qglTexCoord2f (fcol + size, frow + size);
167 qglVertex2f (x+scale, y+scale);
168 qglTexCoord2f (fcol, frow + size);
169 qglVertex2f (x, y+scale);
170 qglEnd ();
171
172 {
173 qglDepthMask (true);
174 GL_TexEnv( GL_REPLACE );
175 qglDisable ( GL_BLEND );
176 qglColor4f (1,1,1,1);
177
178 qglEnable (GL_ALPHA_TEST);
179 }
180 */
181 }
182
183
184 /*
185 =============
186 Draw_FindPic
187 =============
188 */
Draw_FindPic(char * name)189 image_t *Draw_FindPic (char *name)
190 {
191 image_t *gl;
192 char fullname[MAX_QPATH];
193
194 if (name[0] != '/' && name[0] != '\\')
195 {
196 Com_sprintf (fullname, sizeof(fullname), "pics/%s.pcx", name);
197 gl = GL_FindImage (fullname, it_pic);
198 }
199 else
200 gl = GL_FindImage (name+1, it_pic);
201
202 return gl;
203 }
204
205 /*
206 =============
207 Draw_GetPicSize
208 =============
209 */
Draw_GetPicSize(int * w,int * h,char * pic)210 void Draw_GetPicSize (int *w, int *h, char *pic)
211 {
212 image_t *gl;
213
214 gl = Draw_FindPic (pic);
215 if (!gl)
216 {
217 *w = *h = -1;
218 return;
219 }
220 *w = gl->width;
221 *h = gl->height;
222 }
223
224 /*
225 =============
226 Draw_StretchPic -- only used for drawing console...
227 =============
228 */
Draw_StretchPic(int x,int y,int w,int h,char * pic,float alpha)229 void Draw_StretchPic (int x, int y, int w, int h, char *pic, float alpha)
230 {
231 image_t *gl;
232
233 gl = Draw_FindPic (pic);
234 if (!gl)
235 {
236 ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", pic);
237 return;
238 }
239
240 if (scrap_dirty)
241 Scrap_Upload ();
242
243 if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) )
244 && !gl->has_alpha)
245 qglDisable (GL_ALPHA_TEST);
246
247 //add alpha support
248 if (gl->has_alpha || alpha<1)
249 {
250 qglDisable (GL_ALPHA_TEST);
251
252 GL_Bind( gl->texnum);
253
254 GL_TexEnv( GL_MODULATE );
255 qglColor4f(1,1,1,alpha);
256 qglEnable( GL_BLEND );
257 qglDepthMask (false);
258 }
259 else
260 GL_Bind (gl->texnum);
261
262 qglBegin (GL_QUADS);
263 qglTexCoord2f (gl->sl, gl->tl);
264 qglVertex2f (x, y);
265 qglTexCoord2f (gl->sh, gl->tl);
266 qglVertex2f (x+w, y);
267 qglTexCoord2f (gl->sh, gl->th);
268 qglVertex2f (x+w, y+h);
269 qglTexCoord2f (gl->sl, gl->th);
270 qglVertex2f (x, y+h);
271 qglEnd ();
272
273 //add alpha support
274 if (gl->has_alpha || alpha<1)
275 {
276 qglDepthMask (true);
277 GL_TexEnv( GL_REPLACE );
278 qglDisable ( GL_BLEND );
279 qglColor4f (1,1,1,1);
280
281 qglEnable (GL_ALPHA_TEST);
282 }
283
284 if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) )
285 && !gl->has_alpha)
286 qglEnable (GL_ALPHA_TEST);
287 }
288
289 /*
290 =============
291 Draw_ScaledPic
292 =============
293 */
294
Draw_ScaledPic(int x,int y,float scale,float alpha,char * pic)295 void Draw_ScaledPic (int x, int y, float scale, float alpha, char *pic)
296 {
297 float xoff, yoff;
298 image_t *gl;
299
300 gl = Draw_FindPic (pic);
301 if (!gl)
302 {
303 ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", pic);
304 return;
305 }
306 if (scrap_dirty)
307 Scrap_Upload ();
308
309 if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) ) && !gl->has_alpha)
310 qglDisable (GL_ALPHA_TEST);
311
312 //add alpha support
313 {
314 qglDisable (GL_ALPHA_TEST);
315
316 qglBindTexture (GL_TEXTURE_2D, gl->texnum);
317
318 GL_TexEnv( GL_MODULATE );
319 qglColor4f(1,1,1, alpha); //need <1 for trans to work
320 qglEnable( GL_BLEND );
321 qglDepthMask (false);
322 }
323
324 xoff = (gl->width*scale-gl->width)/2;
325 yoff = (gl->height*scale-gl->height)/2;
326
327 GL_Bind (gl->texnum);
328 qglBegin (GL_QUADS);
329 qglTexCoord2f (gl->sl, gl->tl);
330 qglVertex2f (x-xoff, y-yoff);
331 qglTexCoord2f (gl->sh, gl->tl);
332 qglVertex2f (x+gl->width+xoff, y-yoff);
333 qglTexCoord2f (gl->sh, gl->th);
334 qglVertex2f (x+gl->width+xoff, y+gl->height+yoff);
335 qglTexCoord2f (gl->sl, gl->th);
336 qglVertex2f (x-xoff, y+gl->height+yoff);
337 qglEnd ();
338
339 //add alpha support
340 {
341 qglDepthMask (true);
342 GL_TexEnv( GL_REPLACE );
343 qglDisable ( GL_BLEND );
344 qglColor4f (1,1,1,1);
345
346 qglEnable (GL_ALPHA_TEST);
347 }
348
349 if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) ) && !gl->has_alpha)
350 qglEnable (GL_ALPHA_TEST);
351 }
352
353 /*
354 =============
355 Draw_Pic
356 =============
357 */
Draw_Pic(int x,int y,char * pic)358 void Draw_Pic (int x, int y, char *pic)
359 {
360 image_t *gl;
361
362 gl = Draw_FindPic (pic);
363 if (!gl)
364 {
365 ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", pic);
366 return;
367 }
368 if (scrap_dirty)
369 Scrap_Upload ();
370
371 if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) ) && !gl->has_alpha)
372 qglDisable (GL_ALPHA_TEST);
373
374 //add alpha support
375 {
376 qglDisable (GL_ALPHA_TEST);
377
378 qglBindTexture (GL_TEXTURE_2D, gl->texnum);
379
380 GL_TexEnv( GL_MODULATE );
381 qglColor4f(1,1,1,0.999); //need <1 for trans to work
382 qglEnable( GL_BLEND );
383 qglDepthMask (false);
384 }
385
386 GL_Bind (gl->texnum);
387 qglBegin (GL_QUADS);
388 qglTexCoord2f (gl->sl, gl->tl);
389 qglVertex2f (x, y);
390 qglTexCoord2f (gl->sh, gl->tl);
391 qglVertex2f (x+gl->width, y);
392 qglTexCoord2f (gl->sh, gl->th);
393 qglVertex2f (x+gl->width, y+gl->height);
394 qglTexCoord2f (gl->sl, gl->th);
395 qglVertex2f (x, y+gl->height);
396 qglEnd ();
397
398 //add alpha support
399 {
400 qglDepthMask (true);
401 GL_TexEnv( GL_REPLACE );
402 qglDisable ( GL_BLEND );
403 qglColor4f (1,1,1,1);
404
405 qglEnable (GL_ALPHA_TEST);
406 }
407
408 if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) ) && !gl->has_alpha)
409 qglEnable (GL_ALPHA_TEST);
410 }
411
412 /*
413 =============
414 Draw_TileClear
415
416 This repeats a 64*64 tile graphic to fill the screen around a sized down
417 refresh window.
418 =============
419 */
Draw_TileClear(int x,int y,int w,int h,char * pic)420 void Draw_TileClear (int x, int y, int w, int h, char *pic)
421 {
422 image_t *image;
423
424 image = Draw_FindPic (pic);
425 if (!image)
426 {
427 ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", pic);
428 return;
429 }
430
431 if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) ) && !image->has_alpha)
432 qglDisable (GL_ALPHA_TEST);
433
434 GL_Bind (image->texnum);
435 qglBegin (GL_QUADS);
436 qglTexCoord2f (x/64.0, y/64.0);
437 qglVertex2f (x, y);
438 qglTexCoord2f ( (x+w)/64.0, y/64.0);
439 qglVertex2f (x+w, y);
440 qglTexCoord2f ( (x+w)/64.0, (y+h)/64.0);
441 qglVertex2f (x+w, y+h);
442 qglTexCoord2f ( x/64.0, (y+h)/64.0 );
443 qglVertex2f (x, y+h);
444 qglEnd ();
445
446 if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) ) && !image->has_alpha)
447 qglEnable (GL_ALPHA_TEST);
448 }
449
450
451 /*
452 =============
453 Draw_Fill
454
455 Fills a box of pixels with a single color
456 =============
457 */
Draw_Fill(int x,int y,int w,int h,int c)458 void Draw_Fill (int x, int y, int w, int h, int c)
459 {
460 union
461 {
462 unsigned c;
463 byte v[4];
464 } color;
465
466 if ( (unsigned)c > 255)
467 ri.Sys_Error (ERR_FATAL, "Draw_Fill: bad color");
468
469 qglDisable (GL_TEXTURE_2D);
470
471 color.c = d_8to24table[c];
472 qglColor3f (color.v[0]*DIV255,
473 color.v[1]*DIV255,
474 color.v[2]*DIV255);
475
476 qglBegin (GL_QUADS);
477
478 qglVertex2f (x,y);
479 qglVertex2f (x+w, y);
480 qglVertex2f (x+w, y+h);
481 qglVertex2f (x, y+h);
482
483 qglEnd ();
484 qglColor3f (1,1,1);
485 qglEnable (GL_TEXTURE_2D);
486 }
487
488 //=============================================================================
489
490 /*
491 ================
492 Draw_FadeScreen
493
494 ================
495 */
Draw_FadeScreen(void)496 void Draw_FadeScreen (void)
497 {
498 qglEnable (GL_BLEND);
499 qglDisable (GL_TEXTURE_2D);
500 qglColor4f (0, 0, 0, 0.8);
501 qglBegin (GL_QUADS);
502
503 qglVertex2f (0,0);
504 qglVertex2f (vid.width, 0);
505 qglVertex2f (vid.width, vid.height);
506 qglVertex2f (0, vid.height);
507
508 qglEnd ();
509 qglColor4f (1,1,1,1);
510 qglEnable (GL_TEXTURE_2D);
511 qglDisable (GL_BLEND);
512 }
513
514
515 //====================================================================
516
517
518 /*
519 =============
520 Draw_StretchRaw
521 =============
522 */
523 extern unsigned r_rawpalette[256];
524
Draw_StretchRaw(int x,int y,int w,int h,int cols,int rows,byte * data)525 void Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data)
526 {
527 unsigned image32[256*256];
528 unsigned char image8[256*256];
529 int i, j, trows;
530 byte *source;
531 int frac, fracstep;
532 float hscale;
533 int row;
534 float t;
535
536 GL_Bind (0);
537
538 if (rows<=256)
539 {
540 hscale = 1;
541 trows = rows;
542 }
543 else
544 {
545 hscale = rows*DIV256;
546 trows = 256;
547 }
548 t = rows*hscale / 256;
549
550 if ( !qglColorTableEXT )
551 {
552 unsigned *dest;
553
554 for (i=0 ; i<trows ; i++)
555 {
556 row = (int)(i*hscale);
557 if (row > rows)
558 break;
559 source = data + cols*row;
560 dest = &image32[i*256];
561 fracstep = cols*0x10000*DIV256;
562 frac = fracstep >> 1;
563 for (j=0 ; j<256 ; j++)
564 {
565 dest[j] = r_rawpalette[source[frac>>16]];
566 frac += fracstep;
567 }
568 }
569
570 qglTexImage2D (GL_TEXTURE_2D, 0, gl_tex_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, image32);
571 }
572 else
573 {
574 unsigned char *dest;
575
576 for (i=0 ; i<trows ; i++)
577 {
578 row = (int)(i*hscale);
579 if (row > rows)
580 break;
581 source = data + cols*row;
582 dest = &image8[i*256];
583 fracstep = cols*0x10000*DIV256;
584 frac = fracstep >> 1;
585 for (j=0 ; j<256 ; j++)
586 {
587 dest[j] = source[frac>>16];
588 frac += fracstep;
589 }
590 }
591
592 qglTexImage2D( GL_TEXTURE_2D,
593 0,
594 GL_COLOR_INDEX8_EXT,
595 256, 256,
596 0,
597 GL_COLOR_INDEX,
598 GL_UNSIGNED_BYTE,
599 image8 );
600 }
601 qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
602 qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
603
604 if ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) )
605 qglDisable (GL_ALPHA_TEST);
606
607 qglBegin (GL_QUADS);
608 qglTexCoord2f (0, 0);
609 qglVertex2f (x, y);
610 qglTexCoord2f (1, 0);
611 qglVertex2f (x+w, y);
612 qglTexCoord2f (1, t);
613 qglVertex2f (x+w, y+h);
614 qglTexCoord2f (0, t);
615 qglVertex2f (x, y+h);
616 qglEnd ();
617
618 if ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) )
619 qglEnable (GL_ALPHA_TEST);
620 }
621
622