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