]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_draw.c
reduced skysphere from 2048 triangles to 1024
[divverent/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 qbyte 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         qbyte 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 qbyte *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         qbyte 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] = (qbyte) ((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                         qbyte *pix;
237                         // conchars is a raw image and with the wrong transparent color
238                         pix = (qbyte *)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 R_DrawQueue(void)
305 {
306         int pos, num, chartexnum, overbright;
307         float x, y, w, h, s, t, u, v;
308         cachepic_t *pic;
309         drawqueue_t *dq;
310         char *str, *currentpic;
311         int batch, batchcount, additive;
312         unsigned int color;
313
314         if (!r_render.integer)
315                 return;
316
317         qglViewport(vid.realx, vid.realy, vid.realwidth, vid.realheight);
318
319         qglMatrixMode(GL_PROJECTION);
320     qglLoadIdentity();
321         qglOrtho(0, vid.conwidth, vid.conheight, 0, -99999, 99999);
322
323         qglMatrixMode(GL_MODELVIEW);
324     qglLoadIdentity();
325
326         qglDisable(GL_DEPTH_TEST);
327         qglDisable(GL_CULL_FACE);
328         qglEnable(GL_BLEND);
329         qglEnable(GL_TEXTURE_2D);
330         qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
331
332         chartexnum = R_GetTexture(char_texture);
333
334         additive = false;
335         qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
336         currentpic = "";
337         pic = NULL;
338         qglBindTexture(GL_TEXTURE_2D, 0);
339         color = 0;
340         qglColor4ub(0,0,0,0);
341
342         // LordHavoc: NEAREST mode on text if not scaling up
343         /*
344         if (vid.realwidth <= (int) vid.conwidth)
345         {
346                 qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
347                 CHECKGLERROR
348                 qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
349                 CHECKGLERROR
350         }
351         else
352         {
353                 qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
354                 CHECKGLERROR
355                 qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
356                 CHECKGLERROR
357         }
358         */
359
360         overbright = v_overbrightbits.integer;
361         batch = false;
362         batchcount = 0;
363         for (pos = 0;pos < r_refdef.drawqueuesize;pos += ((drawqueue_t *)(r_refdef.drawqueue + pos))->size)
364         {
365                 dq = (drawqueue_t *)(r_refdef.drawqueue + pos);
366                 if (dq->flags & DRAWFLAG_ADDITIVE)
367                 {
368                         if (!additive)
369                         {
370                                 if (batch)
371                                 {
372                                         batch = false;
373                                         qglEnd();
374                                 }
375                                 additive = true;
376                                 qglBlendFunc(GL_SRC_ALPHA, GL_ONE);
377                         }
378                 }
379                 else
380                 {
381                         if (additive)
382                         {
383                                 if (batch)
384                                 {
385                                         batch = false;
386                                         qglEnd();
387                                 }
388                                 additive = false;
389                                 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
390                         }
391                 }
392                 if (color != dq->color)
393                 {
394                         color = dq->color;
395                         qglColor4ub((qbyte)(((color >> 24) & 0xFF) >> overbright), (qbyte)(((color >> 16) & 0xFF) >> overbright), (qbyte)(((color >> 8) & 0xFF) >> overbright), (qbyte)(color & 0xFF));
396                 }
397                 if (batch && batchcount > 128)
398                 {
399                         batch = false;
400                         qglEnd();
401                 }
402                 x = dq->x;
403                 y = dq->y;
404                 w = dq->scalex;
405                 h = dq->scaley;
406                 switch(dq->command)
407                 {
408                 case DRAWQUEUE_PIC:
409                         str = (char *)(dq + 1);
410                         if (*str)
411                         {
412                                 if (strcmp(str, currentpic))
413                                 {
414                                         if (batch)
415                                         {
416                                                 batch = false;
417                                                 qglEnd();
418                                         }
419                                         currentpic = str;
420                                         pic = Draw_CachePic(str);
421                                         qglBindTexture(GL_TEXTURE_2D, R_GetTexture(pic->tex));
422                                 }
423                                 if (w == 0)
424                                         w = pic->width;
425                                 if (h == 0)
426                                         h = pic->height;
427                                 if (!batch)
428                                 {
429                                         batch = true;
430                                         qglBegin(GL_QUADS);
431                                         batchcount = 0;
432                                 }
433                                 //DrawQuad(dq->x, dq->y, w, h, 0, 0, 1, 1);
434                                 qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
435                                 qglTexCoord2f (1, 0);qglVertex2f (x+w, y  );
436                                 qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
437                                 qglTexCoord2f (0, 1);qglVertex2f (x  , y+h);
438                                 batchcount++;
439                         }
440                         else
441                         {
442                                 if (currentpic[0])
443                                 {
444                                         if (batch)
445                                         {
446                                                 batch = false;
447                                                 qglEnd();
448                                         }
449                                         currentpic = "";
450                                         qglBindTexture(GL_TEXTURE_2D, 0);
451                                 }
452                                 if (!batch)
453                                 {
454                                         batch = true;
455                                         qglBegin(GL_QUADS);
456                                         batchcount = 0;
457                                 }
458                                 //DrawQuad(dq->x, dq->y, dq->scalex, dq->scaley, 0, 0, 1, 1);
459                                 qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
460                                 qglTexCoord2f (1, 0);qglVertex2f (x+w, y  );
461                                 qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
462                                 qglTexCoord2f (0, 1);qglVertex2f (x  , y+h);
463                                 batchcount++;
464                         }
465                         break;
466                 case DRAWQUEUE_STRING:
467                         str = (char *)(dq + 1);
468                         if (strcmp("conchars", currentpic))
469                         {
470                                 if (batch)
471                                 {
472                                         batch = false;
473                                         qglEnd();
474                                 }
475                                 currentpic = "conchars";
476                                 qglBindTexture(GL_TEXTURE_2D, chartexnum);
477                         }
478                         if (!batch)
479                         {
480                                 batch = true;
481                                 qglBegin(GL_QUADS);
482                                 batchcount = 0;
483                         }
484                         while ((num = *str++) && x < vid.conwidth)
485                         {
486                                 if (num != ' ')
487                                 {
488                                         s = (num & 15)*0.0625f + (0.5f / 256.0f);
489                                         t = (num >> 4)*0.0625f + (0.5f / 256.0f);
490                                         u = 0.0625f - (1.0f / 256.0f);
491                                         v = 0.0625f - (1.0f / 256.0f);
492                                         //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));
493                                         qglTexCoord2f (s  , t  );qglVertex2f (x  , y  );
494                                         qglTexCoord2f (s+u, t  );qglVertex2f (x+w, y  );
495                                         qglTexCoord2f (s+u, t+v);qglVertex2f (x+w, y+h);
496                                         qglTexCoord2f (s  , t+v);qglVertex2f (x  , y+h);
497                                         batchcount++;
498                                 }
499                                 x += w;
500                         }
501                         break;
502                 }
503         }
504         if (batch)
505                 qglEnd();
506         CHECKGLERROR
507
508         if (!v_hwgamma.integer)
509         {
510                 qglDisable(GL_TEXTURE_2D);
511                 CHECKGLERROR
512                 t = v_contrast.value * (float) (1 << v_overbrightbits.integer);
513                 if (t >= 1.01f)
514                 {
515                         qglBlendFunc (GL_DST_COLOR, GL_ONE);
516                         CHECKGLERROR
517                         qglBegin (GL_TRIANGLES);
518                         while (t >= 1.01f)
519                         {
520                                 num = (int) ((t - 1.0f) * 255.0f);
521                                 if (num > 255)
522                                         num = 255;
523                                 qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
524                                 qglVertex2f (-5000, -5000);
525                                 qglVertex2f (10000, -5000);
526                                 qglVertex2f (-5000, 10000);
527                                 t *= 0.5;
528                         }
529                         qglEnd ();
530                         CHECKGLERROR
531                 }
532                 else if (t <= 0.99f)
533                 {
534                         qglBlendFunc(GL_ZERO, GL_SRC_COLOR);
535                         CHECKGLERROR
536                         qglBegin(GL_TRIANGLES);
537                         num = (int) (t * 255.0f);
538                         qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
539                         qglVertex2f (-5000, -5000);
540                         qglVertex2f (10000, -5000);
541                         qglVertex2f (-5000, 10000);
542                         qglEnd();
543                         CHECKGLERROR
544                 }
545                 if (v_brightness.value >= 0.01f)
546                 {
547                         qglBlendFunc (GL_ONE, GL_ONE);
548                         CHECKGLERROR
549                         num = (int) (v_brightness.value * 255.0f);
550                         qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
551                         CHECKGLERROR
552                         qglBegin (GL_TRIANGLES);
553                         qglVertex2f (-5000, -5000);
554                         qglVertex2f (10000, -5000);
555                         qglVertex2f (-5000, 10000);
556                         qglEnd ();
557                         CHECKGLERROR
558                 }
559                 qglEnable(GL_TEXTURE_2D);
560                 CHECKGLERROR
561         }
562
563         qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
564         CHECKGLERROR
565         qglEnable (GL_CULL_FACE);
566         CHECKGLERROR
567         qglEnable (GL_DEPTH_TEST);
568         CHECKGLERROR
569         qglDisable (GL_BLEND);
570         CHECKGLERROR
571         qglColor4ub (255, 255, 255, 255);
572         CHECKGLERROR
573 }