]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_draw.c
4518040127b3322a66344ab321ceca2eb40d6509
[xonotic/darkplaces.git] / gl_draw.c
1 /*
2 Copyright (C) 1996-1997 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 #include "quakedef.h"
22
23 //#define GL_COLOR_INDEX8_EXT     0x80E5
24
25 cvar_t scr_conalpha = {CVAR_SAVE, "scr_conalpha", "1"};
26
27 static rtexture_t *char_texture;
28
29 //=============================================================================
30 /* Support Routines */
31
32 #define MAX_CACHED_PICS 256
33 #define CACHEPICHASHSIZE 256
34 static cachepic_t *cachepichash[CACHEPICHASHSIZE];
35 static cachepic_t cachepics[MAX_CACHED_PICS];
36 static int numcachepics;
37
38 static rtexturepool_t *drawtexturepool;
39
40 static byte pointerimage[256] =
41 {
42         "333333332......."
43         "26777761........"
44         "2655541........."
45         "265541.........."
46         "2654561........."
47         "26414561........"
48         "251.14561......."
49         "21...14561......"
50         "1.....141......."
51         ".......1........"
52         "................"
53         "................"
54         "................"
55         "................"
56         "................"
57         "................"
58 };
59
60 static rtexture_t *draw_generatemousepointer(void)
61 {
62         int i;
63         byte buffer[256][4];
64         for (i = 0;i < 256;i++)
65         {
66                 if (pointerimage[i] == '.')
67                 {
68                         buffer[i][0] = 0;
69                         buffer[i][1] = 0;
70                         buffer[i][2] = 0;
71                         buffer[i][3] = 0;
72                 }
73                 else
74                 {
75                         buffer[i][0] = (pointerimage[i] - '0') * 16;
76                         buffer[i][1] = (pointerimage[i] - '0') * 16;
77                         buffer[i][2] = (pointerimage[i] - '0') * 16;
78                         buffer[i][3] = 255;
79                 }
80         }
81         return R_LoadTexture(drawtexturepool, "mousepointer", 16, 16, &buffer[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE);
82 }
83
84 // must match NUMCROSSHAIRS in r_crosshairs.c
85 #define NUMCROSSHAIRS 5
86
87 static byte *crosshairtexdata[NUMCROSSHAIRS] =
88 {
89         "................"
90         "................"
91         "................"
92         "...33......33..."
93         "...355....553..."
94         "....577..775...."
95         ".....77..77....."
96         "................"
97         "................"
98         ".....77..77....."
99         "....577..775...."
100         "...355....553..."
101         "...33......33..."
102         "................"
103         "................"
104         "................"
105         ,
106         "................"
107         "................"
108         "................"
109         "...3........3..."
110         "....5......5...."
111         ".....7....7....."
112         "......7..7......"
113         "................"
114         "................"
115         "......7..7......"
116         ".....7....7....."
117         "....5......5...."
118         "...3........3..."
119         "................"
120         "................"
121         "................"
122         ,
123         "................"
124         ".......77......."
125         ".......77......."
126         "................"
127         "................"
128         ".......44......."
129         ".......44......."
130         ".77..44..44..77."
131         ".77..44..44..77."
132         ".......44......."
133         ".......44......."
134         "................"
135         ".......77......."
136         ".......77......."
137         "................"
138         "................"
139         ,
140         "................"
141         "................"
142         "................"
143         "................"
144         "................"
145         "................"
146         "................"
147         "................"
148         "........7777777."
149         "........752....."
150         "........72......"
151         "........7......."
152         "........7......."
153         "........7......."
154         "................"
155         "................"
156         ,
157         "................"
158         "................"
159         "................"
160         "................"
161         "................"
162         "........7......."
163         "................"
164         "........4......."
165         ".....7.4.4.7...."
166         "........4......."
167         "................"
168         "........7......."
169         "................"
170         "................"
171         "................"
172         "................"
173 };
174
175 static rtexture_t *draw_generatecrosshair(int num)
176 {
177         int i;
178         char *in;
179         byte data[16*16][4];
180         in = crosshairtexdata[num];
181         for (i = 0;i < 16*16;i++)
182         {
183                 if (in[i] == '.')
184                 {
185                         data[i][0] = 255;
186                         data[i][1] = 255;
187                         data[i][2] = 255;
188                         data[i][3] = 0;
189                 }
190                 else
191                 {
192                         data[i][0] = 255;
193                         data[i][1] = 255;
194                         data[i][2] = 255;
195                         data[i][3] = (byte) ((int) (in[i] - '0') * 255 / 7);
196                 }
197         }
198         return R_LoadTexture(drawtexturepool, va("crosshair%i", num), 16, 16, &data[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE);
199 }
200
201 /*
202 ================
203 Draw_CachePic
204 ================
205 */
206 // FIXME: move this to client somehow
207 cachepic_t      *Draw_CachePic (char *path)
208 {
209         int i, crc, hashkey;
210         cachepic_t *pic;
211         qpic_t *p;
212
213         crc = CRC_Block(path, strlen(path));
214         hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
215         for (pic = cachepichash[hashkey];pic;pic = pic->chain)
216                 if (!strcmp (path, pic->name))
217                         return pic;
218         //for (pic = cachepics, i = 0;i < numcachepics;pic++, i++)
219         //      if (!strcmp (path, pic->name))
220         //              return pic;
221
222         if (numcachepics == MAX_CACHED_PICS)
223                 Sys_Error ("numcachepics == MAX_CACHED_PICS");
224         pic = cachepics + (numcachepics++);
225         strcpy (pic->name, path);
226         // link into list
227         pic->chain = cachepichash[hashkey];
228         cachepichash[hashkey] = pic;
229
230         // load the pic from disk
231         pic->tex = loadtextureimage(drawtexturepool, path, 0, 0, false, false, true);
232         if (pic->tex == NULL && (p = W_GetLumpName (path)))
233         {
234                 if (!strcmp(path, "conchars"))
235                 {
236                         byte *pix;
237                         // conchars is a raw image and with the wrong transparent color
238                         pix = (byte *)p;
239                         for (i = 0;i < 128 * 128;i++)
240                                 if (pix[i] == 0)
241                                         pix[i] = 255;
242                         pic->tex = R_LoadTexture (drawtexturepool, path, 128, 128, pix, TEXTYPE_QPALETTE, TEXF_ALPHA | TEXF_PRECACHE);
243                 }
244                 else
245                         pic->tex = R_LoadTexture (drawtexturepool, path, p->width, p->height, p->data, TEXTYPE_QPALETTE, TEXF_ALPHA | TEXF_PRECACHE);
246         }
247         if (pic->tex == NULL && !strcmp(path, "ui/mousepointer.tga"))
248                 pic->tex = draw_generatemousepointer();
249         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair1.tga"))
250                 pic->tex = draw_generatecrosshair(0);
251         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair2.tga"))
252                 pic->tex = draw_generatecrosshair(1);
253         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair3.tga"))
254                 pic->tex = draw_generatecrosshair(2);
255         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair4.tga"))
256                 pic->tex = draw_generatecrosshair(3);
257         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair5.tga"))
258                 pic->tex = draw_generatecrosshair(4);
259         if (pic->tex == NULL)
260                 Sys_Error ("Draw_CachePic: failed to load %s", path);
261
262         pic->width = R_TextureWidth(pic->tex);
263         pic->height = R_TextureHeight(pic->tex);
264         return pic;
265 }
266
267 /*
268 ===============
269 Draw_Init
270 ===============
271 */
272 static void gl_draw_start(void)
273 {
274         drawtexturepool = R_AllocTexturePool();
275
276         numcachepics = 0;
277         memset(cachepichash, 0, sizeof(cachepichash));
278
279         char_texture = Draw_CachePic("conchars")->tex;
280 }
281
282 static void gl_draw_shutdown(void)
283 {
284         R_FreeTexturePool(&drawtexturepool);
285
286         numcachepics = 0;
287         memset(cachepichash, 0, sizeof(cachepichash));
288 }
289
290 static void gl_draw_newmap(void)
291 {
292 }
293
294 void GL_Draw_Init (void)
295 {
296         Cvar_RegisterVariable (&scr_conalpha);
297
298         numcachepics = 0;
299         memset(cachepichash, 0, sizeof(cachepichash));
300
301         R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap);
302 }
303
304 void GL_BrightenScreen(void)
305 {
306         float f;
307
308         if (r_brightness.value < 0.1f)
309                 Cvar_SetValue("r_brightness", 0.1f);
310         if (r_brightness.value > 5.0f)
311                 Cvar_SetValue("r_brightness", 5.0f);
312
313         if (r_contrast.value < 0.2f)
314                 Cvar_SetValue("r_contrast", 0.2f);
315         if (r_contrast.value > 1.0f)
316                 Cvar_SetValue("r_contrast", 1.0f);
317
318         if (!(lighthalf && !hardwaregammasupported) && r_brightness.value < 1.01f && r_contrast.value > 0.99f)
319                 return;
320
321         if (!r_render.integer)
322                 return;
323
324         glDisable(GL_TEXTURE_2D);
325         CHECKGLERROR
326         glEnable(GL_BLEND);
327         CHECKGLERROR
328         f = r_brightness.value;
329         // only apply lighthalf using software color correction if hardware is not available (speed reasons)
330         if (lighthalf && !hardwaregammasupported)
331                 f *= 2;
332         if (f >= 1.01f)
333         {
334                 glBlendFunc (GL_DST_COLOR, GL_ONE);
335                 CHECKGLERROR
336                 glBegin (GL_TRIANGLES);
337                 while (f >= 1.01f)
338                 {
339                         if (f >= 2)
340                                 glColor3f (1, 1, 1);
341                         else
342                                 glColor3f (f-1, f-1, f-1);
343                         glVertex2f (-5000, -5000);
344                         glVertex2f (10000, -5000);
345                         glVertex2f (-5000, 10000);
346                         f *= 0.5;
347                 }
348                 glEnd ();
349                 CHECKGLERROR
350         }
351         if (r_contrast.value <= 0.99f)
352         {
353                 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
354                 CHECKGLERROR
355                 if (lighthalf && hardwaregammasupported)
356                         glColor4f (0.5, 0.5, 0.5, 1 - r_contrast.value);
357                 else
358                         glColor4f (1, 1, 1, 1 - r_contrast.value);
359                 CHECKGLERROR
360                 glBegin (GL_TRIANGLES);
361                 glVertex2f (-5000, -5000);
362                 glVertex2f (10000, -5000);
363                 glVertex2f (-5000, 10000);
364                 glEnd ();
365                 CHECKGLERROR
366         }
367         glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
368         CHECKGLERROR
369
370         glEnable (GL_CULL_FACE);
371         CHECKGLERROR
372         glEnable (GL_DEPTH_TEST);
373         CHECKGLERROR
374         glDisable(GL_BLEND);
375         CHECKGLERROR
376         glEnable(GL_TEXTURE_2D);
377         CHECKGLERROR
378 }
379
380 void R_DrawQueue(void)
381 {
382         int pos, num, chartexnum;
383         float x, y, w, h, s, t, u, v;
384         cachepic_t *pic;
385         drawqueue_t *dq;
386         char *str, *currentpic;
387         int batch, additive;
388         unsigned int color;
389
390         if (!r_render.integer)
391                 return;
392
393         glViewport(vid.realx, vid.realy, vid.realwidth, vid.realheight);
394
395         glMatrixMode(GL_PROJECTION);
396     glLoadIdentity();
397         glOrtho(0, vid.conwidth, vid.conheight, 0, -99999, 99999);
398
399         glMatrixMode(GL_MODELVIEW);
400     glLoadIdentity();
401
402         glDisable(GL_DEPTH_TEST);
403         glDisable(GL_CULL_FACE);
404         glDisable(GL_ALPHA_TEST);
405         glEnable(GL_BLEND);
406         glEnable(GL_TEXTURE_2D);
407         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
408
409         chartexnum = R_GetTexture(char_texture);
410
411         additive = false;
412         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
413         currentpic = "";
414         pic = NULL;
415         glBindTexture(GL_TEXTURE_2D, 0);
416         color = 0;
417         glColor4ub(0,0,0,0);
418
419         // LordHavoc: NEAREST mode on text if not scaling up
420         /*
421         if (vid.realwidth <= (int) vid.conwidth)
422         {
423                 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
424                 CHECKGLERROR
425                 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
426                 CHECKGLERROR
427         }
428         else
429         {
430                 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
431                 CHECKGLERROR
432                 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
433                 CHECKGLERROR
434         }
435         */
436
437         batch = false;
438         for (pos = 0;pos < r_refdef.drawqueuesize;pos += ((drawqueue_t *)(r_refdef.drawqueue + pos))->size)
439         {
440                 dq = (drawqueue_t *)(r_refdef.drawqueue + pos);
441                 if (dq->flags & DRAWFLAG_ADDITIVE)
442                 {
443                         if (!additive)
444                         {
445                                 if (batch)
446                                 {
447                                         batch = false;
448                                         glEnd();
449                                 }
450                                 additive = true;
451                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
452                         }
453                 }
454                 else
455                 {
456                         if (additive)
457                         {
458                                 if (batch)
459                                 {
460                                         batch = false;
461                                         glEnd();
462                                 }
463                                 additive = false;
464                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
465                         }
466                 }
467                 if (color != dq->color)
468                 {
469                         color = dq->color;
470                         if (lighthalf)
471                                 glColor4ub((color >> 25) & 0x7F, (color >> 17) & 0x7F, (color >> 9) & 0x7F, color & 0xFF);
472                         else
473                                 glColor4ub((color >> 24) & 0xFF, (color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF);
474                 }
475                 x = dq->x;
476                 y = dq->y;
477                 w = dq->scalex;
478                 h = dq->scaley;
479                 switch(dq->command)
480                 {
481                 case DRAWQUEUE_PIC:
482                         str = (char *)(dq + 1);
483                         if (*str)
484                         {
485                                 if (strcmp(str, currentpic))
486                                 {
487                                         if (batch)
488                                         {
489                                                 batch = false;
490                                                 glEnd();
491                                         }
492                                         currentpic = str;
493                                         pic = Draw_CachePic(str);
494                                         glBindTexture(GL_TEXTURE_2D, R_GetTexture(pic->tex));
495                                 }
496                                 if (w == 0)
497                                         w = pic->width;
498                                 if (h == 0)
499                                         h = pic->height;
500                                 if (!batch)
501                                 {
502                                         batch = true;
503                                         glBegin(GL_QUADS);
504                                 }
505                                 //DrawQuad(dq->x, dq->y, w, h, 0, 0, 1, 1);
506                                 glTexCoord2f (0, 0);glVertex2f (x  , y  );
507                                 glTexCoord2f (1, 0);glVertex2f (x+w, y  );
508                                 glTexCoord2f (1, 1);glVertex2f (x+w, y+h);
509                                 glTexCoord2f (0, 1);glVertex2f (x  , y+h);
510                         }
511                         else
512                         {
513                                 if (currentpic[0])
514                                 {
515                                         if (batch)
516                                         {
517                                                 batch = false;
518                                                 glEnd();
519                                         }
520                                         currentpic = "";
521                                         glBindTexture(GL_TEXTURE_2D, 0);
522                                 }
523                                 if (!batch)
524                                 {
525                                         batch = true;
526                                         glBegin(GL_QUADS);
527                                 }
528                                 //DrawQuad(dq->x, dq->y, dq->scalex, dq->scaley, 0, 0, 1, 1);
529                                 glTexCoord2f (0, 0);glVertex2f (x  , y  );
530                                 glTexCoord2f (1, 0);glVertex2f (x+w, y  );
531                                 glTexCoord2f (1, 1);glVertex2f (x+w, y+h);
532                                 glTexCoord2f (0, 1);glVertex2f (x  , y+h);
533                         }
534                         break;
535                 case DRAWQUEUE_STRING:
536                         str = (char *)(dq + 1);
537                         if (strcmp("conchars", currentpic))
538                         {
539                                 if (batch)
540                                 {
541                                         batch = false;
542                                         glEnd();
543                                 }
544                                 currentpic = "conchars";
545                                 glBindTexture(GL_TEXTURE_2D, chartexnum);
546                         }
547                         if (!batch)
548                         {
549                                 batch = true;
550                                 glBegin(GL_QUADS);
551                         }
552                         while ((num = *str++) && x < vid.conwidth)
553                         {
554                                 if (num != ' ')
555                                 {
556                                         s = (num & 15)*0.0625f + (0.5f / 256.0f);
557                                         t = (num >> 4)*0.0625f + (0.5f / 256.0f);
558                                         u = 0.0625f - (1.0f / 256.0f);
559                                         v = 0.0625f - (1.0f / 256.0f);
560                                         //DrawQuad(x, y, w, h, (num & 15)*0.0625f + (0.5f / 256.0f), (num >> 4)*0.0625f + (0.5f / 256.0f), 0.0625f - (1.0f / 256.0f), 0.0625f - (1.0f / 256.0f));
561                                         glTexCoord2f (s  , t  );glVertex2f (x  , y  );
562                                         glTexCoord2f (s+u, t  );glVertex2f (x+w, y  );
563                                         glTexCoord2f (s+u, t+v);glVertex2f (x+w, y+h);
564                                         glTexCoord2f (s  , t+v);glVertex2f (x  , y+h);
565                                 }
566                                 x += w;
567                         }
568                         break;
569                 }
570         }
571         if (batch)
572                 glEnd();
573         CHECKGLERROR
574         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
575         CHECKGLERROR
576
577         GL_BrightenScreen();
578
579         glColor3f(1,1,1);
580         CHECKGLERROR
581 }