]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_draw.c
massive coding has been done on shadow volumes (some scrapped code which will be...
[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 cvar_t scr_conalpha = {CVAR_SAVE, "scr_conalpha", "1"};
24
25 static rtexture_t *char_texture;
26
27 //=============================================================================
28 /* Support Routines */
29
30 #define MAX_CACHED_PICS 256
31 #define CACHEPICHASHSIZE 256
32 static cachepic_t *cachepichash[CACHEPICHASHSIZE];
33 static cachepic_t cachepics[MAX_CACHED_PICS];
34 static int numcachepics;
35
36 static rtexturepool_t *drawtexturepool;
37
38 static qbyte pointerimage[256] =
39 {
40         "333333332......."
41         "26777761........"
42         "2655541........."
43         "265541.........."
44         "2654561........."
45         "26414561........"
46         "251.14561......."
47         "21...14561......"
48         "1.....141......."
49         ".......1........"
50         "................"
51         "................"
52         "................"
53         "................"
54         "................"
55         "................"
56 };
57
58 static rtexture_t *draw_generatemousepointer(void)
59 {
60         int i;
61         qbyte buffer[256][4];
62         for (i = 0;i < 256;i++)
63         {
64                 if (pointerimage[i] == '.')
65                 {
66                         buffer[i][0] = 0;
67                         buffer[i][1] = 0;
68                         buffer[i][2] = 0;
69                         buffer[i][3] = 0;
70                 }
71                 else
72                 {
73                         buffer[i][0] = (pointerimage[i] - '0') * 16;
74                         buffer[i][1] = (pointerimage[i] - '0') * 16;
75                         buffer[i][2] = (pointerimage[i] - '0') * 16;
76                         buffer[i][3] = 255;
77                 }
78         }
79         return R_LoadTexture(drawtexturepool, "mousepointer", 16, 16, &buffer[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE);
80 }
81
82 // must match NUMCROSSHAIRS in r_crosshairs.c
83 #define NUMCROSSHAIRS 5
84
85 static qbyte *crosshairtexdata[NUMCROSSHAIRS] =
86 {
87         "................"
88         "................"
89         "................"
90         "...33......33..."
91         "...355....553..."
92         "....577..775...."
93         ".....77..77....."
94         "................"
95         "................"
96         ".....77..77....."
97         "....577..775...."
98         "...355....553..."
99         "...33......33..."
100         "................"
101         "................"
102         "................"
103         ,
104         "................"
105         "................"
106         "................"
107         "...3........3..."
108         "....5......5...."
109         ".....7....7....."
110         "......7..7......"
111         "................"
112         "................"
113         "......7..7......"
114         ".....7....7....."
115         "....5......5...."
116         "...3........3..."
117         "................"
118         "................"
119         "................"
120         ,
121         "................"
122         ".......77......."
123         ".......77......."
124         "................"
125         "................"
126         ".......44......."
127         ".......44......."
128         ".77..44..44..77."
129         ".77..44..44..77."
130         ".......44......."
131         ".......44......."
132         "................"
133         ".......77......."
134         ".......77......."
135         "................"
136         "................"
137         ,
138         "................"
139         "................"
140         "................"
141         "................"
142         "................"
143         "................"
144         "................"
145         "................"
146         "........7777777."
147         "........752....."
148         "........72......"
149         "........7......."
150         "........7......."
151         "........7......."
152         "................"
153         "................"
154         ,
155         "................"
156         "................"
157         "................"
158         "................"
159         "................"
160         "........7......."
161         "................"
162         "........4......."
163         ".....7.4.4.7...."
164         "........4......."
165         "................"
166         "........7......."
167         "................"
168         "................"
169         "................"
170         "................"
171 };
172
173 static rtexture_t *draw_generatecrosshair(int num)
174 {
175         int i;
176         char *in;
177         qbyte data[16*16][4];
178         in = crosshairtexdata[num];
179         for (i = 0;i < 16*16;i++)
180         {
181                 if (in[i] == '.')
182                 {
183                         data[i][0] = 255;
184                         data[i][1] = 255;
185                         data[i][2] = 255;
186                         data[i][3] = 0;
187                 }
188                 else
189                 {
190                         data[i][0] = 255;
191                         data[i][1] = 255;
192                         data[i][2] = 255;
193                         data[i][3] = (qbyte) ((int) (in[i] - '0') * 255 / 7);
194                 }
195         }
196         return R_LoadTexture(drawtexturepool, va("crosshair%i", num), 16, 16, &data[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE);
197 }
198
199 /*
200 ================
201 Draw_CachePic
202 ================
203 */
204 // FIXME: move this to client somehow
205 cachepic_t      *Draw_CachePic (char *path)
206 {
207         int i, crc, hashkey;
208         cachepic_t *pic;
209         qpic_t *p;
210
211         crc = CRC_Block(path, strlen(path));
212         hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
213         for (pic = cachepichash[hashkey];pic;pic = pic->chain)
214                 if (!strcmp (path, pic->name))
215                         return pic;
216
217         if (numcachepics == MAX_CACHED_PICS)
218                 Sys_Error ("numcachepics == MAX_CACHED_PICS");
219         pic = cachepics + (numcachepics++);
220         strcpy (pic->name, path);
221         // link into list
222         pic->chain = cachepichash[hashkey];
223         cachepichash[hashkey] = pic;
224
225         // load the pic from disk
226         pic->tex = loadtextureimage(drawtexturepool, path, 0, 0, false, false, true);
227         if (pic->tex == NULL && !strncmp(path, "gfx/", 4))
228         {
229                 // compatibility with older versions
230                 pic->tex = loadtextureimage(drawtexturepool, path + 4, 0, 0, false, false, true);
231                 // failed to find gfx/whatever.tga or similar, try the wad
232                 if (pic->tex == NULL && (p = W_GetLumpName (path + 4)))
233                 {
234                         if (!strcmp(path, "gfx/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         }
248         if (pic->tex == NULL && !strcmp(path, "ui/mousepointer.tga"))
249                 pic->tex = draw_generatemousepointer();
250         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair1.tga"))
251                 pic->tex = draw_generatecrosshair(0);
252         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair2.tga"))
253                 pic->tex = draw_generatecrosshair(1);
254         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair3.tga"))
255                 pic->tex = draw_generatecrosshair(2);
256         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair4.tga"))
257                 pic->tex = draw_generatecrosshair(3);
258         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair5.tga"))
259                 pic->tex = draw_generatecrosshair(4);
260         if (pic->tex == NULL)
261         {
262                 Con_Printf ("Draw_CachePic: failed to load %s\n", path);
263                 pic->tex = r_notexture;
264         }
265
266         pic->width = R_TextureWidth(pic->tex);
267         pic->height = R_TextureHeight(pic->tex);
268         return pic;
269 }
270
271 cachepic_t *Draw_NewPic(char *picname, int width, int height, int alpha, qbyte *pixels)
272 {
273         int crc, hashkey;
274         cachepic_t *pic;
275
276         crc = CRC_Block(picname, strlen(picname));
277         hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
278         for (pic = cachepichash[hashkey];pic;pic = pic->chain)
279                 if (!strcmp (picname, pic->name))
280                         break;
281
282         if (pic)
283         {
284                 if (pic->tex && pic->width == width && pic->height == height)
285                 {
286                         R_UpdateTexture(pic->tex, pixels);
287                         return pic;
288                 }
289         }
290         else
291         {
292                 if (pic == NULL)
293                 {
294                         if (numcachepics == MAX_CACHED_PICS)
295                                 Sys_Error ("numcachepics == MAX_CACHED_PICS");
296                         pic = cachepics + (numcachepics++);
297                         strcpy (pic->name, picname);
298                         // link into list
299                         pic->chain = cachepichash[hashkey];
300                         cachepichash[hashkey] = pic;
301                 }
302         }
303
304         pic->width = width;
305         pic->height = height;
306         if (pic->tex)
307                 R_FreeTexture(pic->tex);
308         pic->tex = R_LoadTexture (drawtexturepool, picname, width, height, pixels, TEXTYPE_RGBA, alpha ? TEXF_ALPHA : 0);
309         return pic;
310 }
311
312 void Draw_FreePic(char *picname)
313 {
314         int crc;
315         int hashkey;
316         cachepic_t *pic;
317         // this doesn't really free the pic, but does free it's texture
318         crc = CRC_Block(picname, strlen(picname));
319         hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
320         for (pic = cachepichash[hashkey];pic;pic = pic->chain)
321         {
322                 if (!strcmp (picname, pic->name))
323                 {
324                         R_FreeTexture(pic->tex);
325                         pic->width = 0;
326                         pic->height = 0;
327                         return;
328                 }
329         }
330 }
331
332 /*
333 ===============
334 Draw_Init
335 ===============
336 */
337 static void gl_draw_start(void)
338 {
339         drawtexturepool = R_AllocTexturePool();
340
341         numcachepics = 0;
342         memset(cachepichash, 0, sizeof(cachepichash));
343
344         char_texture = Draw_CachePic("gfx/conchars")->tex;
345 }
346
347 static void gl_draw_shutdown(void)
348 {
349         R_FreeTexturePool(&drawtexturepool);
350
351         numcachepics = 0;
352         memset(cachepichash, 0, sizeof(cachepichash));
353 }
354
355 static void gl_draw_newmap(void)
356 {
357 }
358
359 void GL_Draw_Init (void)
360 {
361         Cvar_RegisterVariable (&scr_conalpha);
362
363         numcachepics = 0;
364         memset(cachepichash, 0, sizeof(cachepichash));
365
366         R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap);
367 }
368
369 int quadelements[768];
370 void R_DrawQueue(void)
371 {
372         int pos, num, chartexnum, overbright, texnum, additive, batch;
373         float x, y, w, h, s, t, u, v, cr, cg, cb, ca, *av, *at;
374         cachepic_t *pic;
375         drawqueue_t *dq;
376         char *str, *currentpic;
377         int batchcount;
378         unsigned int color;
379         drawqueuemesh_t *mesh;
380         rmeshstate_t m;
381
382         if (!r_render.integer)
383                 return;
384
385         if (!quadelements[1])
386         {
387                 // elements for rendering a series of quads as triangles
388                 for (batch = 0, pos = 0, num = 0;batch < 128;batch++, num += 4)
389                 {
390                         quadelements[pos++] = num;
391                         quadelements[pos++] = num + 1;
392                         quadelements[pos++] = num + 2;
393                         quadelements[pos++] = num;
394                         quadelements[pos++] = num + 2;
395                         quadelements[pos++] = num + 3;
396                 }
397         }
398         GL_SetupView_ViewPort(vid.realx, vid.realy, vid.realwidth, vid.realheight);
399         GL_SetupView_Mode_Ortho(0, 0, vid.conwidth, vid.conheight, -10, 100);
400         qglDepthFunc(GL_LEQUAL);
401         R_Mesh_Start();
402         R_Mesh_Matrix(&r_identitymatrix);
403
404         memset(&m, 0, sizeof(m));
405         chartexnum = R_GetTexture(char_texture);
406         m.tex[0] = chartexnum;
407         R_Mesh_TextureState(&m);
408
409         currentpic = "";
410         pic = NULL;
411         texnum = 0;
412         color = 0;
413
414         overbright = v_overbrightbits.integer;
415         batch = false;
416         batchcount = 0;
417         for (pos = 0;pos < r_refdef.drawqueuesize;pos += ((drawqueue_t *)(r_refdef.drawqueue + pos))->size)
418         {
419                 dq = (drawqueue_t *)(r_refdef.drawqueue + pos);
420                 additive = (dq->flags & DRAWFLAG_ADDITIVE) != 0;
421                 color = dq->color;
422                 m.blendfunc1 = GL_SRC_ALPHA;
423                 if (additive)
424                         m.blendfunc2 = GL_ONE;
425                 else
426                         m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
427                 m.depthdisable = true;
428                 R_Mesh_MainState(&m);
429
430                 cr = (float) ((color >> 24) & 0xFF) * (1.0f / 255.0f) * r_colorscale;
431                 cg = (float) ((color >> 16) & 0xFF) * (1.0f / 255.0f) * r_colorscale;
432                 cb = (float) ((color >>  8) & 0xFF) * (1.0f / 255.0f) * r_colorscale;
433                 ca = (float) ( color        & 0xFF) * (1.0f / 255.0f);
434                 x = dq->x;
435                 y = dq->y;
436                 w = dq->scalex;
437                 h = dq->scaley;
438
439                 switch(dq->command)
440                 {
441                 case DRAWQUEUE_PIC:
442                         str = (char *)(dq + 1);
443                         if (strcmp(str, currentpic))
444                         {
445                                 currentpic = str;
446                                 if (*str)
447                                 {
448                                         pic = Draw_CachePic(str);
449                                         m.tex[0] = R_GetTexture(pic->tex);
450                                 }
451                                 else
452                                         m.tex[0] = 0;
453                                 R_Mesh_TextureState(&m);
454                         }
455                         if (*str)
456                         {
457                                 if (w == 0)
458                                         w = pic->width;
459                                 if (h == 0)
460                                         h = pic->height;
461                         }
462                         varray_texcoord[0][0] = 0;varray_texcoord[0][1] = 0;
463                         varray_texcoord[0][2] = 1;varray_texcoord[0][3] = 0;
464                         varray_texcoord[0][4] = 1;varray_texcoord[0][5] = 1;
465                         varray_texcoord[0][6] = 0;varray_texcoord[0][7] = 1;
466                         varray_vertex[ 0] = x  ;varray_vertex[ 1] = y  ;varray_vertex[ 2] = 10;
467                         varray_vertex[ 4] = x+w;varray_vertex[ 5] = y  ;varray_vertex[ 6] = 10;
468                         varray_vertex[ 8] = x+w;varray_vertex[ 9] = y+h;varray_vertex[10] = 10;
469                         varray_vertex[12] = x  ;varray_vertex[13] = y+h;varray_vertex[14] = 10;
470                         GL_Color(cr, cg, cb, ca);
471                         R_Mesh_Draw(4, 2, quadelements);
472                         break;
473                 case DRAWQUEUE_STRING:
474                         str = (char *)(dq + 1);
475                         if (strcmp("gfx/conchars", currentpic))
476                         {
477                                 currentpic = "gfx/conchars";
478                                 m.tex[0] = chartexnum;
479                                 R_Mesh_TextureState(&m);
480                         }
481                         batchcount = 0;
482                         at = varray_texcoord[0];
483                         av = varray_vertex;
484                         GL_Color(cr, cg, cb, ca);
485                         while ((num = *str++) && x < vid.conwidth)
486                         {
487                                 if (num != ' ')
488                                 {
489                                         s = (num & 15)*0.0625f + (0.5f / 256.0f);
490                                         t = (num >> 4)*0.0625f + (0.5f / 256.0f);
491                                         u = 0.0625f - (1.0f / 256.0f);
492                                         v = 0.0625f - (1.0f / 256.0f);
493                                         at[0] = s  ;at[1] = t  ;
494                                         at[2] = s+u;at[3] = t  ;
495                                         at[4] = s+u;at[5] = t+v;
496                                         at[6] = s  ;at[7] = t+v;
497                                         av[ 0] = x  ;av[ 1] = y  ;av[ 2] = 10;
498                                         av[ 4] = x+w;av[ 5] = y  ;av[ 6] = 10;
499                                         av[ 8] = x+w;av[ 9] = y+h;av[10] = 10;
500                                         av[12] = x  ;av[13] = y+h;av[14] = 10;
501                                         at += 8;
502                                         av += 16;
503                                         batchcount++;
504                                         if (batchcount >= 128)
505                                         {
506                                                 R_Mesh_Draw(batchcount * 4, batchcount * 2, quadelements);
507                                                 batchcount = 0;
508                                                 at = varray_texcoord[0];
509                                                 av = varray_vertex;
510                                         }
511                                 }
512                                 x += w;
513                         }
514                         if (batchcount > 0)
515                                 R_Mesh_Draw(batchcount * 4, batchcount * 2, quadelements);
516                         break;
517                 case DRAWQUEUE_MESH:
518                         mesh = (void *)(dq + 1);
519                         m.tex[0] = R_GetTexture(mesh->texture);
520                         R_Mesh_TextureState(&m);
521                         R_Mesh_ResizeCheck(mesh->numvertices);
522                         memcpy(varray_vertex, mesh->vertices, sizeof(float[4]) * mesh->numvertices);
523                         memcpy(varray_texcoord[0], mesh->texcoords, sizeof(float[2]) * mesh->numvertices);
524                         memcpy(varray_color, mesh->colors, sizeof(float[4]) * mesh->numvertices);
525                         GL_UseColorArray();
526                         R_Mesh_Draw(mesh->numvertices, mesh->numtriangles, mesh->indices);
527                         currentpic = "\0";
528                         break;
529                 }
530         }
531
532         if (!v_hwgamma.integer)
533         {
534                 // we use one big triangle for all the screen blends
535                 varray_texcoord[0][0] = 0;varray_texcoord[0][1] = 0;
536                 varray_texcoord[0][2] = 0;varray_texcoord[0][3] = 0;
537                 varray_texcoord[0][4] = 0;varray_texcoord[0][5] = 0;
538                 varray_vertex[0] = -5000;varray_vertex[1] = -5000;varray_vertex[2] = 10;
539                 varray_vertex[4] = 10000;varray_vertex[5] = -5000;varray_vertex[6] = 10;
540                 varray_vertex[8] = -5000;varray_vertex[9] = 10000;varray_vertex[10] = 10;
541                 // all the blends ignore depth
542                 memset(&m, 0, sizeof(m));
543                 m.depthdisable = true;
544                 t = v_contrast.value * (float) (1 << v_overbrightbits.integer);
545                 if (t >= 1.01f)
546                 {
547                         m.blendfunc1 = GL_DST_COLOR;
548                         m.blendfunc2 = GL_ONE;
549                         R_Mesh_State(&m);
550                         while (t >= 1.01f)
551                         {
552                                 cr = t - 1.0f;
553                                 if (cr > 1.0f)
554                                         cr = 1.0f;
555                                 GL_Color(cr, cr, cr, 1);
556                                 R_Mesh_Draw(3, 1, polygonelements);
557                                 t *= 0.5;
558                         }
559                 }
560                 else if (t <= 0.99f)
561                 {
562                         m.blendfunc1 = GL_ZERO;
563                         m.blendfunc2 = GL_SRC_COLOR;
564                         R_Mesh_State(&m);
565                         GL_Color(t, t, t, 1);
566                         R_Mesh_Draw(3, 1, polygonelements);
567                 }
568                 if (v_brightness.value >= 0.01f)
569                 {
570                         m.blendfunc1 = GL_ONE;
571                         m.blendfunc2 = GL_ONE;
572                         R_Mesh_State(&m);
573                         GL_Color(v_brightness.value, v_brightness.value, v_brightness.value, 1);
574                         R_Mesh_Draw(3, 1, polygonelements);
575                 }
576         }
577         R_Mesh_Finish();
578 }
579