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