the beginnings of texture fog support (to cure the vertex artifacts and simplify...
[xonotic/darkplaces.git] / gl_rmain.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 // r_main.c
21
22 #include "quakedef.h"
23 #include "r_shadow.h"
24 #include "polygon.h"
25
26 // used for dlight push checking and other things
27 int r_framecount;
28
29 mplane_t frustum[5];
30
31 matrix4x4_t r_identitymatrix;
32
33 renderstats_t renderstats;
34
35 // true during envmap command capture
36 qboolean envmap;
37
38 // maximum visible distance (recalculated from world box each frame)
39 float r_farclip;
40 // brightness of world lightmaps and related lighting
41 // (often reduced when world rtlights are enabled)
42 float r_lightmapintensity;
43 // whether to draw world lights realtime, dlights realtime, and their shadows
44 qboolean r_rtworld;
45 qboolean r_rtworldshadows;
46 qboolean r_rtdlight;
47 qboolean r_rtdlightshadows;
48
49
50 // forces all rendering to draw triangle outlines
51 int r_showtrispass;
52
53 // view origin
54 vec3_t r_vieworigin;
55 vec3_t r_viewforward;
56 vec3_t r_viewleft;
57 vec3_t r_viewright;
58 vec3_t r_viewup;
59 int r_view_x;
60 int r_view_y;
61 int r_view_z;
62 int r_view_width;
63 int r_view_height;
64 int r_view_depth;
65 float r_view_fov_x;
66 float r_view_fov_y;
67 matrix4x4_t r_view_matrix;
68
69 //
70 // screen size info
71 //
72 refdef_t r_refdef;
73
74 cvar_t r_showtris = {0, "r_showtris", "0"};
75 cvar_t r_drawentities = {0, "r_drawentities","1"};
76 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
77 cvar_t r_speeds = {0, "r_speeds","0"};
78 cvar_t r_fullbright = {0, "r_fullbright","0"};
79 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
80 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
81 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
82 cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0"};
83
84 cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
85 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"};
86 cvar_t gl_fogred = {0, "gl_fogred","0.3"};
87 cvar_t gl_foggreen = {0, "gl_foggreen","0.3"};
88 cvar_t gl_fogblue = {0, "gl_fogblue","0.3"};
89 cvar_t gl_fogstart = {0, "gl_fogstart", "0"};
90 cvar_t gl_fogend = {0, "gl_fogend","0"};
91
92 cvar_t r_textureunits = {0, "r_textureunits", "32"};
93
94 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"};
95 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"};
96 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"};
97
98 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0"};
99 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "2"};
100 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "8"};
101 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320"};
102 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "4"};
103
104 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1"};
105
106 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0"};
107
108 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0"};
109
110 cvar_t r_test = {0, "r_test", "0"}; // used for testing renderer code changes, otherwise does nothing
111
112 rtexturepool_t *r_main_texturepool;
113 rtexture_t *r_bloom_texture_screen;
114 rtexture_t *r_bloom_texture_bloom;
115 rtexture_t *r_texture_blanknormalmap;
116 rtexture_t *r_texture_white;
117 rtexture_t *r_texture_black;
118 rtexture_t *r_texture_notexture;
119 rtexture_t *r_texture_whitecube;
120 rtexture_t *r_texture_normalizationcube;
121 rtexture_t *r_texture_fogattenuation;
122 rtexture_t *r_texture_fogintensity;
123
124 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
125 {
126         int i;
127         for (i = 0;i < verts;i++)
128         {
129                 out[0] = in[0] * r;
130                 out[1] = in[1] * g;
131                 out[2] = in[2] * b;
132                 out[3] = in[3];
133                 in += 4;
134                 out += 4;
135         }
136 }
137
138 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
139 {
140         int i;
141         for (i = 0;i < verts;i++)
142         {
143                 out[0] = r;
144                 out[1] = g;
145                 out[2] = b;
146                 out[3] = a;
147                 out += 4;
148         }
149 }
150
151 vec3_t fogcolor;
152 vec_t fogdensity;
153 vec_t fogrange;
154 vec_t fograngerecip;
155 float fog_density, fog_red, fog_green, fog_blue;
156 qboolean fogenabled;
157 qboolean oldgl_fogenable;
158 void R_UpdateFog(void)
159 {
160         if (gamemode == GAME_NEHAHRA)
161         {
162                 if (gl_fogenable.integer)
163                 {
164                         oldgl_fogenable = true;
165                         fog_density = gl_fogdensity.value;
166                         fog_red = gl_fogred.value;
167                         fog_green = gl_foggreen.value;
168                         fog_blue = gl_fogblue.value;
169                 }
170                 else if (oldgl_fogenable)
171                 {
172                         oldgl_fogenable = false;
173                         fog_density = 0;
174                         fog_red = 0;
175                         fog_green = 0;
176                         fog_blue = 0;
177                 }
178         }
179         if (fog_density)
180         {
181                 fogcolor[0] = fog_red   = bound(0.0f, fog_red  , 1.0f);
182                 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
183                 fogcolor[2] = fog_blue  = bound(0.0f, fog_blue , 1.0f);
184         }
185         if (fog_density)
186         {
187                 fogenabled = true;
188                 fogdensity = -4000.0f / (fog_density * fog_density);
189                 // this is the point where the fog reaches 0.991373 alpha, which we
190                 // consider a good enough cutoff point for the texture
191                 fogrange = 400 / fog_density;
192                 fograngerecip = 1.0f / fogrange;
193                 // fog color was already set
194         }
195         else
196                 fogenabled = false;
197 }
198
199 // FIXME: move this to client?
200 void FOG_clear(void)
201 {
202         if (gamemode == GAME_NEHAHRA)
203         {
204                 Cvar_Set("gl_fogenable", "0");
205                 Cvar_Set("gl_fogdensity", "0.2");
206                 Cvar_Set("gl_fogred", "0.3");
207                 Cvar_Set("gl_foggreen", "0.3");
208                 Cvar_Set("gl_fogblue", "0.3");
209         }
210         fog_density = fog_red = fog_green = fog_blue = 0.0f;
211 }
212
213 // FIXME: move this to client?
214 void FOG_registercvars(void)
215 {
216         if (gamemode == GAME_NEHAHRA)
217         {
218                 Cvar_RegisterVariable (&gl_fogenable);
219                 Cvar_RegisterVariable (&gl_fogdensity);
220                 Cvar_RegisterVariable (&gl_fogred);
221                 Cvar_RegisterVariable (&gl_foggreen);
222                 Cvar_RegisterVariable (&gl_fogblue);
223                 Cvar_RegisterVariable (&gl_fogstart);
224                 Cvar_RegisterVariable (&gl_fogend);
225         }
226 }
227
228 static void R_BuildBlankTextures(void)
229 {
230         qbyte data[4];
231         data[0] = 128; // normal X
232         data[1] = 128; // normal Y
233         data[2] = 255; // normal Z
234         data[3] = 128; // height
235         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
236         data[0] = 255;
237         data[1] = 255;
238         data[2] = 255;
239         data[3] = 255;
240         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
241         data[0] = 0;
242         data[1] = 0;
243         data[2] = 0;
244         data[3] = 255;
245         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
246 }
247
248 static void R_BuildNoTexture(void)
249 {
250         int x, y;
251         qbyte pix[16][16][4];
252         // this makes a light grey/dark grey checkerboard texture
253         for (y = 0;y < 16;y++)
254         {
255                 for (x = 0;x < 16;x++)
256                 {
257                         if ((y < 8) ^ (x < 8))
258                         {
259                                 pix[y][x][0] = 128;
260                                 pix[y][x][1] = 128;
261                                 pix[y][x][2] = 128;
262                                 pix[y][x][3] = 255;
263                         }
264                         else
265                         {
266                                 pix[y][x][0] = 64;
267                                 pix[y][x][1] = 64;
268                                 pix[y][x][2] = 64;
269                                 pix[y][x][3] = 255;
270                         }
271                 }
272         }
273         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
274 }
275
276 static void R_BuildWhiteCube(void)
277 {
278         qbyte data[6*1*1*4];
279         data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
280         data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
281         data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
282         data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
283         data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
284         data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
285         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
286 }
287
288 static void R_BuildNormalizationCube(void)
289 {
290         int x, y, side;
291         vec3_t v;
292         vec_t s, t, intensity;
293 #define NORMSIZE 64
294         qbyte data[6][NORMSIZE][NORMSIZE][4];
295         for (side = 0;side < 6;side++)
296         {
297                 for (y = 0;y < NORMSIZE;y++)
298                 {
299                         for (x = 0;x < NORMSIZE;x++)
300                         {
301                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
302                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
303                                 switch(side)
304                                 {
305                                 default:
306                                 case 0:
307                                         v[0] = 1;
308                                         v[1] = -t;
309                                         v[2] = -s;
310                                         break;
311                                 case 1:
312                                         v[0] = -1;
313                                         v[1] = -t;
314                                         v[2] = s;
315                                         break;
316                                 case 2:
317                                         v[0] = s;
318                                         v[1] = 1;
319                                         v[2] = t;
320                                         break;
321                                 case 3:
322                                         v[0] = s;
323                                         v[1] = -1;
324                                         v[2] = -t;
325                                         break;
326                                 case 4:
327                                         v[0] = s;
328                                         v[1] = -t;
329                                         v[2] = 1;
330                                         break;
331                                 case 5:
332                                         v[0] = -s;
333                                         v[1] = -t;
334                                         v[2] = -1;
335                                         break;
336                                 }
337                                 intensity = 127.0f / sqrt(DotProduct(v, v));
338                                 data[side][y][x][0] = 128.0f + intensity * v[0];
339                                 data[side][y][x][1] = 128.0f + intensity * v[1];
340                                 data[side][y][x][2] = 128.0f + intensity * v[2];
341                                 data[side][y][x][3] = 255;
342                         }
343                 }
344         }
345         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
346 }
347
348 static void R_BuildFogTexture(void)
349 {
350 #define FOGWIDTH 64
351         int x, b;
352         double r;
353         qbyte data1[FOGWIDTH][4];
354         qbyte data2[FOGWIDTH][4];
355         r = (-65536.0 / (FOGWIDTH*FOGWIDTH));
356         for (x = 0;x < FOGWIDTH;x++)
357         {
358                 b = (int)(256.0 * exp(r / ((double)x*(double)x)));
359                 b = bound(0, b, 255);
360                 data1[x][0] = 255 - b;
361                 data1[x][1] = 255 - b;
362                 data1[x][2] = 255 - b;
363                 data1[x][3] = 255;
364                 data2[x][0] = b;
365                 data2[x][1] = b;
366                 data2[x][2] = b;
367                 data2[x][3] = 255;
368         }
369         r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
370         r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
371 }
372
373 void gl_main_start(void)
374 {
375         r_main_texturepool = R_AllocTexturePool();
376         r_bloom_texture_screen = NULL;
377         r_bloom_texture_bloom = NULL;
378         R_BuildBlankTextures();
379         R_BuildNoTexture();
380         if (gl_texturecubemap)
381         {
382                 R_BuildWhiteCube();
383                 R_BuildNormalizationCube();
384         }
385         R_BuildFogTexture();
386 }
387
388 void gl_main_shutdown(void)
389 {
390         R_FreeTexturePool(&r_main_texturepool);
391         r_bloom_texture_screen = NULL;
392         r_bloom_texture_bloom = NULL;
393         r_texture_blanknormalmap = NULL;
394         r_texture_white = NULL;
395         r_texture_black = NULL;
396         r_texture_whitecube = NULL;
397         r_texture_normalizationcube = NULL;
398 }
399
400 extern void CL_ParseEntityLump(char *entitystring);
401 void gl_main_newmap(void)
402 {
403         // FIXME: move this code to client
404         int l;
405         char *entities, entname[MAX_QPATH];
406         r_framecount = 1;
407         if (cl.worldmodel)
408         {
409                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
410                 l = (int)strlen(entname) - 4;
411                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
412                 {
413                         strcpy(entname + l, ".ent");
414                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true)))
415                         {
416                                 CL_ParseEntityLump(entities);
417                                 Mem_Free(entities);
418                                 return;
419                         }
420                 }
421                 if (cl.worldmodel->brush.entities)
422                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
423         }
424 }
425
426 void GL_Main_Init(void)
427 {
428         Matrix4x4_CreateIdentity(&r_identitymatrix);
429 // FIXME: move this to client?
430         FOG_registercvars();
431         Cvar_RegisterVariable(&r_showtris);
432         Cvar_RegisterVariable(&r_drawentities);
433         Cvar_RegisterVariable(&r_drawviewmodel);
434         Cvar_RegisterVariable(&r_speeds);
435         Cvar_RegisterVariable(&r_fullbrights);
436         Cvar_RegisterVariable(&r_wateralpha);
437         Cvar_RegisterVariable(&r_dynamic);
438         Cvar_RegisterVariable(&r_fullbright);
439         Cvar_RegisterVariable(&r_textureunits);
440         Cvar_RegisterVariable(&r_lerpsprites);
441         Cvar_RegisterVariable(&r_lerpmodels);
442         Cvar_RegisterVariable(&r_waterscroll);
443         Cvar_RegisterVariable(&r_drawcollisionbrushes);
444         Cvar_RegisterVariable(&r_bloom);
445         Cvar_RegisterVariable(&r_bloom_intensity);
446         Cvar_RegisterVariable(&r_bloom_blur);
447         Cvar_RegisterVariable(&r_bloom_resolution);
448         Cvar_RegisterVariable(&r_bloom_power);
449         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
450         Cvar_RegisterVariable(&developer_texturelogging);
451         Cvar_RegisterVariable(&gl_lightmaps);
452         Cvar_RegisterVariable(&r_test);
453         if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
454                 Cvar_SetValue("r_fullbrights", 0);
455         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
456 }
457
458 static vec3_t r_farclip_origin;
459 static vec3_t r_farclip_direction;
460 static vec_t r_farclip_directiondist;
461 static vec_t r_farclip_meshfarclip;
462 static int r_farclip_directionbit0;
463 static int r_farclip_directionbit1;
464 static int r_farclip_directionbit2;
465
466 // enlarge farclip to accomodate box
467 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
468 {
469         float d;
470         d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
471           + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
472           + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
473         if (r_farclip_meshfarclip < d)
474                 r_farclip_meshfarclip = d;
475 }
476
477 // return farclip value
478 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
479 {
480         int i;
481
482         VectorCopy(origin, r_farclip_origin);
483         VectorCopy(direction, r_farclip_direction);
484         r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
485         r_farclip_directionbit0 = r_farclip_direction[0] < 0;
486         r_farclip_directionbit1 = r_farclip_direction[1] < 0;
487         r_farclip_directionbit2 = r_farclip_direction[2] < 0;
488         r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
489
490         if (r_refdef.worldmodel)
491                 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
492         for (i = 0;i < r_refdef.numentities;i++)
493                 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
494
495         return r_farclip_meshfarclip - r_farclip_directiondist;
496 }
497
498 extern void R_Textures_Init(void);
499 extern void GL_Draw_Init(void);
500 extern void GL_Main_Init(void);
501 extern void R_Shadow_Init(void);
502 extern void R_Sky_Init(void);
503 extern void GL_Surf_Init(void);
504 extern void R_Crosshairs_Init(void);
505 extern void R_Light_Init(void);
506 extern void R_Particles_Init(void);
507 extern void R_Explosion_Init(void);
508 extern void gl_backend_init(void);
509 extern void Sbar_Init(void);
510 extern void R_LightningBeams_Init(void);
511 extern void Mod_RenderInit(void);
512
513 void Render_Init(void)
514 {
515         gl_backend_init();
516         R_Textures_Init();
517         R_MeshQueue_Init();
518         GL_Main_Init();
519         GL_Draw_Init();
520         R_Shadow_Init();
521         R_Sky_Init();
522         GL_Surf_Init();
523         R_Crosshairs_Init();
524         R_Light_Init();
525         R_Particles_Init();
526         R_Explosion_Init();
527         UI_Init();
528         Sbar_Init();
529         R_LightningBeams_Init();
530         Mod_RenderInit();
531 }
532
533 /*
534 ===============
535 GL_Init
536 ===============
537 */
538 extern char *ENGINE_EXTENSIONS;
539 void GL_Init (void)
540 {
541         VID_CheckExtensions();
542
543         // LordHavoc: report supported extensions
544         Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
545
546         // clear to black (loading plaque will be seen over this)
547         qglClearColor(0,0,0,1);
548         qglClear(GL_COLOR_BUFFER_BIT);
549 }
550
551 int R_CullBox(const vec3_t mins, const vec3_t maxs)
552 {
553         int i;
554         mplane_t *p;
555         for (i = 0;i < 4;i++)
556         {
557                 p = frustum + i;
558                 switch(p->signbits)
559                 {
560                 default:
561                 case 0:
562                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
563                                 return true;
564                         break;
565                 case 1:
566                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
567                                 return true;
568                         break;
569                 case 2:
570                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
571                                 return true;
572                         break;
573                 case 3:
574                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
575                                 return true;
576                         break;
577                 case 4:
578                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
579                                 return true;
580                         break;
581                 case 5:
582                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
583                                 return true;
584                         break;
585                 case 6:
586                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
587                                 return true;
588                         break;
589                 case 7:
590                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
591                                 return true;
592                         break;
593                 }
594         }
595         return false;
596 }
597
598 //==================================================================================
599
600 static void R_MarkEntities (void)
601 {
602         int i, renderimask;
603         entity_render_t *ent;
604
605         if (!r_drawentities.integer)
606                 return;
607
608         r_refdef.worldentity->visframe = r_framecount;
609         renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
610         if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
611         {
612                 // worldmodel can check visibility
613                 for (i = 0;i < r_refdef.numentities;i++)
614                 {
615                         ent = r_refdef.entities[i];
616                         // some of the renderer still relies on origin...
617                         Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
618                         // some of the renderer still relies on scale...
619                         ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
620                         if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_worldleafvisible, ent->mins, ent->maxs)))
621                         {
622                                 R_UpdateEntLights(ent);
623                                 ent->visframe = r_framecount;
624                         }
625                 }
626         }
627         else
628         {
629                 // no worldmodel or it can't check visibility
630                 for (i = 0;i < r_refdef.numentities;i++)
631                 {
632                         ent = r_refdef.entities[i];
633                         // some of the renderer still relies on origin...
634                         Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
635                         // some of the renderer still relies on scale...
636                         ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
637                         if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
638                         {
639                                 R_UpdateEntLights(ent);
640                                 ent->visframe = r_framecount;
641                         }
642                 }
643         }
644 }
645
646 // only used if skyrendermasked, and normally returns false
647 int R_DrawBrushModelsSky (void)
648 {
649         int i, sky;
650         entity_render_t *ent;
651
652         if (!r_drawentities.integer)
653                 return false;
654
655         sky = false;
656         for (i = 0;i < r_refdef.numentities;i++)
657         {
658                 ent = r_refdef.entities[i];
659                 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
660                 {
661                         ent->model->DrawSky(ent);
662                         sky = true;
663                 }
664         }
665         return sky;
666 }
667
668 void R_DrawNoModel(entity_render_t *ent);
669 void R_DrawModels(void)
670 {
671         int i;
672         entity_render_t *ent;
673
674         if (!r_drawentities.integer)
675                 return;
676
677         for (i = 0;i < r_refdef.numentities;i++)
678         {
679                 ent = r_refdef.entities[i];
680                 if (ent->visframe == r_framecount)
681                 {
682                         renderstats.entities++;
683                         if (ent->model && ent->model->Draw != NULL)
684                                 ent->model->Draw(ent);
685                         else
686                                 R_DrawNoModel(ent);
687                 }
688         }
689 }
690
691 static void R_SetFrustum(void)
692 {
693         // break apart the view matrix into vectors for various purposes
694         Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
695         VectorNegate(r_viewleft, r_viewright);
696
697         // LordHavoc: note to all quake engine coders, the special case for 90
698         // degrees assumed a square view (wrong), so I removed it, Quake2 has it
699         // disabled as well.
700
701         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
702         RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_view_fov_x / 2));
703         frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
704         PlaneClassify(&frustum[0]);
705
706         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
707         RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_view_fov_x / 2));
708         frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
709         PlaneClassify(&frustum[1]);
710
711         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
712         RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_view_fov_y / 2));
713         frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
714         PlaneClassify(&frustum[2]);
715
716         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
717         RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_view_fov_y / 2));
718         frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
719         PlaneClassify(&frustum[3]);
720
721         // nearclip plane
722         VectorCopy(r_viewforward, frustum[4].normal);
723         frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
724         PlaneClassify(&frustum[4]);
725 }
726
727 static void R_BlendView(void)
728 {
729         rmeshstate_t m;
730
731         if (r_refdef.viewblend[3] < 0.01f && !r_bloom.integer)
732                 return;
733
734         GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
735         GL_DepthMask(true);
736         GL_DepthTest(false);
737         R_Mesh_Matrix(&r_identitymatrix);
738         // vertex coordinates for a quad that covers the screen exactly
739         varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
740         varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
741         varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
742         varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
743         if (r_bloom.integer && r_bloom_resolution.value >= 32 && r_bloom_power.integer >= 1 && r_bloom_power.integer < 100 && r_bloom_blur.value >= 0 && r_bloom_blur.value < 512)
744         {
745                 int screenwidth, screenheight, bloomwidth, bloomheight, x, dobloomblend, range;
746                 float xoffset, yoffset, r;
747                 renderstats.bloom++;
748                 // set the (poorly named) screenwidth and screenheight variables to
749                 // a power of 2 at least as large as the screen, these will define the
750                 // size of the texture to allocate
751                 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
752                 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
753                 // allocate textures as needed
754                 if (!r_bloom_texture_screen)
755                         r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
756                 if (!r_bloom_texture_bloom)
757                         r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
758                 // set bloomwidth and bloomheight to the bloom resolution that will be
759                 // used (often less than the screen resolution for faster rendering)
760                 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
761                 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
762                 // set up a texcoord array for the full resolution screen image
763                 // (we have to keep this around to copy back during final render)
764                 varray_texcoord2f[0][0] = 0;
765                 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
766                 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
767                 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
768                 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
769                 varray_texcoord2f[0][5] = 0;
770                 varray_texcoord2f[0][6] = 0;
771                 varray_texcoord2f[0][7] = 0;
772                 // set up a texcoord array for the reduced resolution bloom image
773                 // (which will be additive blended over the screen image)
774                 varray_texcoord2f[1][0] = 0;
775                 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
776                 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
777                 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
778                 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
779                 varray_texcoord2f[1][5] = 0;
780                 varray_texcoord2f[1][6] = 0;
781                 varray_texcoord2f[1][7] = 0;
782                 memset(&m, 0, sizeof(m));
783                 m.pointer_vertex = varray_vertex3f;
784                 m.pointer_texcoord[0] = varray_texcoord2f[0];
785                 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
786                 R_Mesh_State(&m);
787                 // copy view into the full resolution screen image texture
788                 GL_ActiveTexture(0);
789                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
790                 renderstats.bloom_copypixels += r_view_width * r_view_height;
791                 // now scale it down to the bloom size and raise to a power of itself
792                 // to darken it (this leaves the really bright stuff bright, and
793                 // everything else becomes very dark)
794                 // TODO: optimize with multitexture or GLSL
795                 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
796                 GL_BlendFunc(GL_ONE, GL_ZERO);
797                 GL_Color(1, 1, 1, 1);
798                 R_Mesh_Draw(0, 4, 2, polygonelements);
799                 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
800                 // render multiple times with a multiply blendfunc to raise to a power
801                 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
802                 for (x = 1;x < r_bloom_power.integer;x++)
803                 {
804                         R_Mesh_Draw(0, 4, 2, polygonelements);
805                         renderstats.bloom_drawpixels += bloomwidth * bloomheight;
806                 }
807                 // we now have a darkened bloom image in the framebuffer, copy it into
808                 // the bloom image texture for more processing
809                 memset(&m, 0, sizeof(m));
810                 m.pointer_vertex = varray_vertex3f;
811                 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
812                 m.pointer_texcoord[0] = varray_texcoord2f[2];
813                 R_Mesh_State(&m);
814                 GL_ActiveTexture(0);
815                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
816                 renderstats.bloom_copypixels += bloomwidth * bloomheight;
817                 // blend on at multiple vertical offsets to achieve a vertical blur
818                 // TODO: do offset blends using GLSL
819                 range = r_bloom_blur.integer * bloomwidth / 320;
820                 GL_BlendFunc(GL_ONE, GL_ZERO);
821                 for (x = -range;x <= range;x++)
822                 {
823                         xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
824                         yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
825                         // compute a texcoord array with the specified x and y offset
826                         varray_texcoord2f[2][0] = xoffset+0;
827                         varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
828                         varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
829                         varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
830                         varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
831                         varray_texcoord2f[2][5] = yoffset+0;
832                         varray_texcoord2f[2][6] = xoffset+0;
833                         varray_texcoord2f[2][7] = yoffset+0;
834                         // this r value looks like a 'dot' particle, fading sharply to
835                         // black at the edges
836                         // (probably not realistic but looks good enough)
837                         r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
838                         if (r < 0.01f)
839                                 continue;
840                         GL_Color(r, r, r, 1);
841                         R_Mesh_Draw(0, 4, 2, polygonelements);
842                         renderstats.bloom_drawpixels += bloomwidth * bloomheight;
843                         GL_BlendFunc(GL_ONE, GL_ONE);
844                 }
845                 // copy the vertically blurred bloom view to a texture
846                 GL_ActiveTexture(0);
847                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
848                 renderstats.bloom_copypixels += bloomwidth * bloomheight;
849                 // blend the vertically blurred image at multiple offsets horizontally
850                 // to finish the blur effect
851                 // TODO: do offset blends using GLSL
852                 range = r_bloom_blur.integer * bloomwidth / 320;
853                 GL_BlendFunc(GL_ONE, GL_ZERO);
854                 for (x = -range;x <= range;x++)
855                 {
856                         xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
857                         yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
858                         // compute a texcoord array with the specified x and y offset
859                         varray_texcoord2f[2][0] = xoffset+0;
860                         varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
861                         varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
862                         varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
863                         varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
864                         varray_texcoord2f[2][5] = yoffset+0;
865                         varray_texcoord2f[2][6] = xoffset+0;
866                         varray_texcoord2f[2][7] = yoffset+0;
867                         // this r value looks like a 'dot' particle, fading sharply to
868                         // black at the edges
869                         // (probably not realistic but looks good enough)
870                         r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
871                         if (r < 0.01f)
872                                 continue;
873                         GL_Color(r, r, r, 1);
874                         R_Mesh_Draw(0, 4, 2, polygonelements);
875                         renderstats.bloom_drawpixels += bloomwidth * bloomheight;
876                         GL_BlendFunc(GL_ONE, GL_ONE);
877                 }
878                 // copy the blurred bloom view to a texture
879                 GL_ActiveTexture(0);
880                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
881                 renderstats.bloom_copypixels += bloomwidth * bloomheight;
882                 // go back to full view area
883                 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
884                 // put the original screen image back in place and blend the bloom
885                 // texture on it
886                 memset(&m, 0, sizeof(m));
887                 m.pointer_vertex = varray_vertex3f;
888                 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
889                 m.pointer_texcoord[0] = varray_texcoord2f[0];
890 #if 0
891                 dobloomblend = false;
892 #else
893                 // do both in one pass if possible
894                 if (r_textureunits.integer >= 2 && gl_combine.integer)
895                 {
896                         dobloomblend = false;
897                         m.texcombinergb[1] = GL_ADD;
898                         m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
899                         m.pointer_texcoord[1] = varray_texcoord2f[1];
900                 }
901                 else
902                         dobloomblend = true;
903 #endif
904                 R_Mesh_State(&m);
905                 GL_BlendFunc(GL_ONE, GL_ZERO);
906                 GL_Color(1,1,1,1);
907                 R_Mesh_Draw(0, 4, 2, polygonelements);
908                 renderstats.bloom_drawpixels += r_view_width * r_view_height;
909                 // now blend on the bloom texture if multipass
910                 if (dobloomblend)
911                 {
912                         memset(&m, 0, sizeof(m));
913                         m.pointer_vertex = varray_vertex3f;
914                         m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
915                         m.pointer_texcoord[0] = varray_texcoord2f[1];
916                         R_Mesh_State(&m);
917                         GL_BlendFunc(GL_ONE, GL_ONE);
918                         GL_Color(1,1,1,1);
919                         R_Mesh_Draw(0, 4, 2, polygonelements);
920                         renderstats.bloom_drawpixels += r_view_width * r_view_height;
921                 }
922         }
923         if (r_refdef.viewblend[3] >= 0.01f)
924         {
925                 // apply a color tint to the whole view
926                 memset(&m, 0, sizeof(m));
927                 m.pointer_vertex = varray_vertex3f;
928                 R_Mesh_State(&m);
929                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
930                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
931                 R_Mesh_Draw(0, 4, 2, polygonelements);
932         }
933 }
934
935 void R_RenderScene(void);
936
937 matrix4x4_t r_waterscrollmatrix;
938
939 /*
940 ================
941 R_RenderView
942 ================
943 */
944 void R_RenderView(void)
945 {
946         if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
947                 return; //Host_Error ("R_RenderView: NULL worldmodel");
948
949         r_view_width = bound(0, r_refdef.width, vid.width);
950         r_view_height = bound(0, r_refdef.height, vid.height);
951         r_view_depth = 1;
952         r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
953         r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
954         r_view_z = 0;
955         r_view_fov_x = bound(1, r_refdef.fov_x, 170);
956         r_view_fov_y = bound(1, r_refdef.fov_y, 170);
957         r_view_matrix = r_refdef.viewentitymatrix;
958         GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
959         r_rtworld = r_shadow_realtime_world.integer;
960         r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
961         r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
962         r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
963         r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
964
965         // GL is weird because it's bottom to top, r_view_y is top to bottom
966         qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
967         GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
968         GL_ScissorTest(true);
969         GL_DepthMask(true);
970         R_ClearScreen();
971         R_Textures_Frame();
972         R_UpdateFog();
973         R_TimeReport("setup");
974
975         qglDepthFunc(GL_LEQUAL);
976         qglPolygonOffset(0, 0);
977         qglEnable(GL_POLYGON_OFFSET_FILL);
978
979         R_RenderScene();
980
981         qglPolygonOffset(0, 0);
982         qglDisable(GL_POLYGON_OFFSET_FILL);
983
984         R_BlendView();
985         R_TimeReport("blendview");
986
987         GL_Scissor(0, 0, vid.width, vid.height);
988         GL_ScissorTest(false);
989 }
990
991 extern void R_DrawLightningBeams (void);
992 void R_RenderScene(void)
993 {
994         // don't let sound skip if going slow
995         if (r_refdef.extraupdate)
996                 S_ExtraUpdate ();
997
998         r_framecount++;
999
1000         R_MeshQueue_BeginScene();
1001
1002         GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1003
1004         R_SetFrustum();
1005
1006         r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1007         if (r_rtworldshadows || r_rtdlightshadows)
1008                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f);
1009         else
1010                 GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip);
1011
1012         GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1013
1014         Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.time) * 0.025 * r_waterscroll.value, sin(r_refdef.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
1015
1016         R_SkyStartFrame();
1017
1018         R_WorldVisibility();
1019         R_TimeReport("worldvis");
1020
1021         R_MarkEntities();
1022         R_TimeReport("markentity");
1023
1024         R_Shadow_UpdateWorldLightSelection();
1025
1026         // don't let sound skip if going slow
1027         if (r_refdef.extraupdate)
1028                 S_ExtraUpdate ();
1029
1030         GL_ShowTrisColor(0.025, 0.025, 0, 1);
1031         if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1032         {
1033                 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1034                 R_TimeReport("worldsky");
1035         }
1036
1037         if (R_DrawBrushModelsSky())
1038                 R_TimeReport("bmodelsky");
1039
1040         GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1041         if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1042         {
1043                 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1044                 R_TimeReport("world");
1045         }
1046
1047         // don't let sound skip if going slow
1048         if (r_refdef.extraupdate)
1049                 S_ExtraUpdate ();
1050
1051         GL_ShowTrisColor(0, 0.015, 0, 1);
1052
1053         R_DrawModels();
1054         R_TimeReport("models");
1055
1056         // don't let sound skip if going slow
1057         if (r_refdef.extraupdate)
1058                 S_ExtraUpdate ();
1059
1060         GL_ShowTrisColor(0, 0, 0.033, 1);
1061         R_ShadowVolumeLighting(false);
1062         R_TimeReport("rtlights");
1063
1064         // don't let sound skip if going slow
1065         if (r_refdef.extraupdate)
1066                 S_ExtraUpdate ();
1067
1068         GL_ShowTrisColor(0.1, 0, 0, 1);
1069
1070         R_DrawLightningBeams();
1071         R_TimeReport("lightning");
1072
1073         R_DrawParticles();
1074         R_TimeReport("particles");
1075
1076         R_DrawExplosions();
1077         R_TimeReport("explosions");
1078
1079         R_MeshQueue_RenderTransparent();
1080         R_TimeReport("drawtrans");
1081
1082         R_DrawCoronas();
1083         R_TimeReport("coronas");
1084
1085         R_DrawWorldCrosshair();
1086         R_TimeReport("crosshair");
1087
1088         R_MeshQueue_Render();
1089         R_MeshQueue_EndScene();
1090
1091         if ((r_shadow_visiblelighting.integer || r_shadow_visiblevolumes.integer) && !r_showtrispass)
1092         {
1093                 R_ShadowVolumeLighting(true);
1094                 R_TimeReport("visiblevolume");
1095         }
1096
1097         GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1098
1099         // don't let sound skip if going slow
1100         if (r_refdef.extraupdate)
1101                 S_ExtraUpdate ();
1102 }
1103
1104 /*
1105 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1106 {
1107         int i;
1108         float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1109         rmeshstate_t m;
1110         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1111         GL_DepthMask(false);
1112         GL_DepthTest(true);
1113         R_Mesh_Matrix(&r_identitymatrix);
1114
1115         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1116         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1117         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1118         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1119         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1120         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1121         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1122         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1123         R_FillColors(color, 8, cr, cg, cb, ca);
1124         if (fogenabled)
1125         {
1126                 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1127                 {
1128                         VectorSubtract(v, r_vieworigin, diff);
1129                         f2 = exp(fogdensity/DotProduct(diff, diff));
1130                         f1 = 1 - f2;
1131                         c[0] = c[0] * f1 + fogcolor[0] * f2;
1132                         c[1] = c[1] * f1 + fogcolor[1] * f2;
1133                         c[2] = c[2] * f1 + fogcolor[2] * f2;
1134                 }
1135         }
1136         memset(&m, 0, sizeof(m));
1137         m.pointer_vertex = vertex3f;
1138         m.pointer_color = color;
1139         R_Mesh_State(&m);
1140         R_Mesh_Draw(8, 12);
1141 }
1142 */
1143
1144 int nomodelelements[24] =
1145 {
1146         5, 2, 0,
1147         5, 1, 2,
1148         5, 0, 3,
1149         5, 3, 1,
1150         0, 2, 4,
1151         2, 1, 4,
1152         3, 0, 4,
1153         1, 3, 4
1154 };
1155
1156 float nomodelvertex3f[6*3] =
1157 {
1158         -16,   0,   0,
1159          16,   0,   0,
1160           0, -16,   0,
1161           0,  16,   0,
1162           0,   0, -16,
1163           0,   0,  16
1164 };
1165
1166 float nomodelcolor4f[6*4] =
1167 {
1168         0.0f, 0.0f, 0.5f, 1.0f,
1169         0.0f, 0.0f, 0.5f, 1.0f,
1170         0.0f, 0.5f, 0.0f, 1.0f,
1171         0.0f, 0.5f, 0.0f, 1.0f,
1172         0.5f, 0.0f, 0.0f, 1.0f,
1173         0.5f, 0.0f, 0.0f, 1.0f
1174 };
1175
1176 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1177 {
1178         const entity_render_t *ent = (entity_render_t *)calldata1;
1179         int i;
1180         float f1, f2, *c, diff[3];
1181         float color4f[6*4];
1182         rmeshstate_t m;
1183         R_Mesh_Matrix(&ent->matrix);
1184
1185         memset(&m, 0, sizeof(m));
1186         m.pointer_vertex = nomodelvertex3f;
1187
1188         if (ent->flags & EF_ADDITIVE)
1189         {
1190                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1191                 GL_DepthMask(false);
1192         }
1193         else if (ent->alpha < 1)
1194         {
1195                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1196                 GL_DepthMask(false);
1197         }
1198         else
1199         {
1200                 GL_BlendFunc(GL_ONE, GL_ZERO);
1201                 GL_DepthMask(true);
1202         }
1203         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1204         if (fogenabled)
1205         {
1206                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1207                 m.pointer_color = color4f;
1208                 VectorSubtract(ent->origin, r_vieworigin, diff);
1209                 f2 = exp(fogdensity/DotProduct(diff, diff));
1210                 f1 = 1 - f2;
1211                 for (i = 0, c = color4f;i < 6;i++, c += 4)
1212                 {
1213                         c[0] = (c[0] * f1 + fogcolor[0] * f2);
1214                         c[1] = (c[1] * f1 + fogcolor[1] * f2);
1215                         c[2] = (c[2] * f1 + fogcolor[2] * f2);
1216                         c[3] *= ent->alpha;
1217                 }
1218         }
1219         else if (ent->alpha != 1)
1220         {
1221                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1222                 m.pointer_color = color4f;
1223                 for (i = 0, c = color4f;i < 6;i++, c += 4)
1224                         c[3] *= ent->alpha;
1225         }
1226         else
1227                 m.pointer_color = nomodelcolor4f;
1228         R_Mesh_State(&m);
1229         R_Mesh_Draw(0, 6, 8, nomodelelements);
1230 }
1231
1232 void R_DrawNoModel(entity_render_t *ent)
1233 {
1234         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1235                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModelCallback, ent, 0);
1236         //else
1237         //      R_DrawNoModelCallback(ent, 0);
1238 }
1239
1240 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1241 {
1242         vec3_t right1, right2, diff, normal;
1243
1244         VectorSubtract (org2, org1, normal);
1245
1246         // calculate 'right' vector for start
1247         VectorSubtract (r_vieworigin, org1, diff);
1248         CrossProduct (normal, diff, right1);
1249         VectorNormalize (right1);
1250
1251         // calculate 'right' vector for end
1252         VectorSubtract (r_vieworigin, org2, diff);
1253         CrossProduct (normal, diff, right2);
1254         VectorNormalize (right2);
1255
1256         vert[ 0] = org1[0] + width * right1[0];
1257         vert[ 1] = org1[1] + width * right1[1];
1258         vert[ 2] = org1[2] + width * right1[2];
1259         vert[ 3] = org1[0] - width * right1[0];
1260         vert[ 4] = org1[1] - width * right1[1];
1261         vert[ 5] = org1[2] - width * right1[2];
1262         vert[ 6] = org2[0] - width * right2[0];
1263         vert[ 7] = org2[1] - width * right2[1];
1264         vert[ 8] = org2[2] - width * right2[2];
1265         vert[ 9] = org2[0] + width * right2[0];
1266         vert[10] = org2[1] + width * right2[1];
1267         vert[11] = org2[2] + width * right2[2];
1268 }
1269
1270 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1271
1272 void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, int depthdisable, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2, float cr, float cg, float cb, float ca)
1273 {
1274         float diff[3];
1275         rmeshstate_t m;
1276
1277         if (fogenabled)
1278         {
1279                 VectorSubtract(origin, r_vieworigin, diff);
1280                 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1281         }
1282
1283         R_Mesh_Matrix(&r_identitymatrix);
1284         GL_BlendFunc(blendfunc1, blendfunc2);
1285         GL_DepthMask(false);
1286         GL_DepthTest(!depthdisable);
1287
1288         varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1289         varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1290         varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1291         varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1292         varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1293         varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1294         varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1295         varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1296         varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1297         varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1298         varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1299         varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1300
1301         memset(&m, 0, sizeof(m));
1302         m.tex[0] = R_GetTexture(texture);
1303         m.pointer_texcoord[0] = spritetexcoord2f;
1304         m.pointer_vertex = varray_vertex3f;
1305         R_Mesh_State(&m);
1306         GL_Color(cr, cg, cb, ca);
1307         R_Mesh_Draw(0, 4, 2, polygonelements);
1308 }
1309
1310 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1311 {
1312         int i;
1313         float *vertex3f;
1314         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1315                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1316                         break;
1317         if (i == mesh->numvertices)
1318         {
1319                 if (mesh->numvertices < mesh->maxvertices)
1320                 {
1321                         VectorCopy(v, vertex3f);
1322                         mesh->numvertices++;
1323                 }
1324                 return mesh->numvertices;
1325         }
1326         else
1327                 return i;
1328 }
1329
1330 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1331 {
1332         int i;
1333         int *e, element[3];
1334         element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1335         element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1336         e = mesh->element3i + mesh->numtriangles * 3;
1337         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1338         {
1339                 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1340                 if (mesh->numtriangles < mesh->maxtriangles)
1341                 {
1342                         *e++ = element[0];
1343                         *e++ = element[1];
1344                         *e++ = element[2];
1345                         mesh->numtriangles++;
1346                 }
1347                 element[1] = element[2];
1348         }
1349 }
1350
1351 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1352 {
1353         int planenum, planenum2;
1354         int w;
1355         int tempnumpoints;
1356         mplane_t *plane, *plane2;
1357         float temppoints[2][256*3];
1358         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1359         {
1360                 w = 0;
1361                 tempnumpoints = 4;
1362                 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1363                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1364                 {
1365                         if (planenum2 == planenum)
1366                                 continue;
1367                         PolygonF_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, 1.0/32.0, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints);
1368                         w = !w;
1369                 }
1370                 if (tempnumpoints < 3)
1371                         continue;
1372                 // generate elements forming a triangle fan for this polygon
1373                 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1374         }
1375 }
1376
1377 void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, matrix4x4_t *matrix, float r, float g, float b, float a)
1378 {
1379         texturelayer_t *layer;
1380         layer = t->currentlayers + t->currentnumlayers++;
1381         layer->type = type;
1382         layer->depthmask = depthmask;
1383         layer->blendfunc1 = blendfunc1;
1384         layer->blendfunc2 = blendfunc2;
1385         layer->texture = texture;
1386         layer->texmatrix = *matrix;
1387         layer->color[0] = r;
1388         layer->color[1] = g;
1389         layer->color[2] = b;
1390         layer->color[3] = a;
1391 }
1392
1393 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1394 {
1395         // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1396         //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1397         float currentalpha;
1398
1399         {
1400                 texture_t *texture = t;
1401                 model_t *model = ent->model;
1402                 int s = ent->skinnum;
1403                 if ((unsigned int)s >= (unsigned int)model->numskins)
1404                         s = 0;
1405                 if (model->skinscenes)
1406                 {
1407                         if (model->skinscenes[s].framecount > 1)
1408                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1409                         else
1410                                 s = model->skinscenes[s].firstframe;
1411                 }
1412                 if (s > 0)
1413                         t = t + s * model->num_surfaces;
1414                 if (t->animated)
1415                         t = t->anim_frames[ent->frame != 0][(t->anim_total[ent->frame != 0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[ent->frame != 0]) : 0];
1416                 texture->currentframe = t;
1417         }
1418
1419         t->currentmaterialflags = t->basematerialflags;
1420         currentalpha = ent->alpha;
1421         if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1422                 currentalpha *= r_wateralpha.value;
1423         if (!(ent->flags & RENDER_LIGHT))
1424                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1425         if (ent->effects & EF_ADDITIVE)
1426                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1427         else if (currentalpha < 1)
1428                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1429         if (ent->effects & EF_NODEPTHTEST)
1430                 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1431         if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1432                 t->currenttexmatrix = r_waterscrollmatrix;
1433         else
1434                 t->currenttexmatrix = r_identitymatrix;
1435         t->currentnumlayers = 0;
1436         if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
1437         {
1438                 if (gl_lightmaps.integer)
1439                         R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &r_identitymatrix, 1, 1, 1, 1);
1440                 else if (t->currentmaterialflags & MATERIALFLAG_SKY)
1441                 {
1442                         // transparent sky would be ridiculous
1443                         if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1444                                 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
1445                 }
1446                 else
1447                 {
1448                         int blendfunc1, blendfunc2, depthmask;
1449                         if (t->currentmaterialflags & MATERIALFLAG_ADD)
1450                         {
1451                                 blendfunc1 = GL_SRC_ALPHA;
1452                                 blendfunc2 = GL_ONE;
1453                                 depthmask = false;
1454                         }
1455                         else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
1456                         {
1457                                 blendfunc1 = GL_SRC_ALPHA;
1458                                 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1459                                 depthmask = false;
1460                         }
1461                         else
1462                         {
1463                                 blendfunc1 = GL_ONE;
1464                                 blendfunc2 = GL_ZERO;
1465                                 depthmask = true;
1466                         }
1467                         if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1468                         {
1469                                 rtexture_t *currentbasetexture;
1470                                 int layerflags = 0;
1471                                 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1472                                         layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
1473                                 currentbasetexture = (ent->colormap < 0 && t->skin.merged) ? t->skin.merged : t->skin.base;
1474                                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1475                                 {
1476                                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], currentalpha);
1477                                         if (ent->colormap >= 0 && t->skin.pants)
1478                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2], currentalpha);
1479                                         if (ent->colormap >= 0 && t->skin.shirt)
1480                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2], currentalpha);
1481                                 }
1482                                 else
1483                                 {
1484                                         float colorscale;
1485                                         colorscale = 2;
1486                                         // q3bsp has no lightmap updates, so the lightstylevalue that
1487                                         // would normally be baked into the lightmaptexture must be
1488                                         // applied to the color
1489                                         if (ent->model->type == mod_brushq3)
1490                                                 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
1491                                         // transparent and fullbright are not affected by r_lightmapintensity
1492                                         if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1493                                                 colorscale *= r_lightmapintensity;
1494                                         if (r_textureunits.integer >= 2 && gl_combine.integer)
1495                                                 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE_COMBINE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, currentalpha);
1496                                         else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
1497                                                 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale * 0.5f, ent->colormod[1] * colorscale * 0.5f, ent->colormod[2] * colorscale * 0.5f, currentalpha);
1498                                         else
1499                                                 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, currentalpha);
1500                                         if (r_ambient.value >= (1.0f/64.0f))
1501                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), currentalpha);
1502                                         if (ent->colormap >= 0 && t->skin.pants)
1503                                         {
1504                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * colorscale, ent->colormap_pantscolor[1] * colorscale, ent->colormap_pantscolor[2] * colorscale, currentalpha);
1505                                                 if (r_ambient.value >= (1.0f/64.0f))
1506                                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[2] * r_ambient.value * (1.0f / 64.0f), currentalpha);
1507                                         }
1508                                         if (ent->colormap >= 0 && t->skin.shirt)
1509                                         {
1510                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * colorscale, ent->colormap_shirtcolor[1] * colorscale, ent->colormap_shirtcolor[2] * colorscale, currentalpha);
1511                                                 if (r_ambient.value >= (1.0f/64.0f))
1512                                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[2] * r_ambient.value * (1.0f / 64.0f), currentalpha);
1513                                         }
1514                                 }
1515                                 if (t->skin.glow != NULL)
1516                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, currentalpha);
1517                                 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
1518                                 {
1519                                         // if this is opaque use alpha blend which will darken the earlier
1520                                         // passes cheaply.
1521                                         //
1522                                         // if this is an alpha blended material, all the earlier passes
1523                                         // were darkened by fog already, so we only need to add the fog
1524                                         // color ontop through the fog mask texture
1525                                         //
1526                                         // if this is an additive blended material, all the earlier passes
1527                                         // were darkened by fog already, and we should not add fog color
1528                                         // (because the background was not darkened, there is no fog color
1529                                         // that was lost behind it).
1530                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->skin.fog, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], currentalpha);
1531                                 }
1532                         }
1533                 }
1534         }
1535 }
1536
1537 void R_UpdateAllTextureInfo(entity_render_t *ent)
1538 {
1539         int i;
1540         if (ent->model)
1541                 for (i = 0;i < ent->model->num_textures;i++)
1542                         R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1543 }
1544
1545 float *rsurface_vertex3f;
1546 float *rsurface_svector3f;
1547 float *rsurface_tvector3f;
1548 float *rsurface_normal3f;
1549 float *rsurface_lightmapcolor4f;
1550
1551 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1552 {
1553         int i, j;
1554         float center[3], forward[3], right[3], up[3], v[4][3];
1555         matrix4x4_t matrix1, imatrix1;
1556         if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1557         {
1558                 rsurface_vertex3f = varray_vertex3f;
1559                 rsurface_svector3f = NULL;
1560                 rsurface_tvector3f = NULL;
1561                 rsurface_normal3f = NULL;
1562                 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1563         }
1564         else
1565         {
1566                 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1567                 rsurface_svector3f = surface->groupmesh->data_svector3f;
1568                 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1569                 rsurface_normal3f = surface->groupmesh->data_normal3f;
1570         }
1571         if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1572         {
1573                 if (!rsurface_svector3f)
1574                 {
1575                         rsurface_svector3f = varray_svector3f;
1576                         rsurface_tvector3f = varray_tvector3f;
1577                         rsurface_normal3f = varray_normal3f;
1578                         Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
1579                 }
1580                 // a single autosprite surface can contain multiple sprites...
1581                 VectorClear(forward);
1582                 VectorClear(right);
1583                 VectorSet(up, 0, 0, 1);
1584                 for (j = 0;j < surface->num_vertices - 3;j += 4)
1585                 {
1586                         VectorClear(center);
1587                         for (i = 0;i < 4;i++)
1588                                 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1589                         VectorScale(center, 0.25f, center);
1590                         // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1591                         Matrix4x4_FromVectors(&matrix1, (rsurface_normal3f + 3 * surface->num_firstvertex) + j*3, (rsurface_svector3f + 3 * surface->num_firstvertex) + j*3, (rsurface_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
1592                         Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1593                         for (i = 0;i < 4;i++)
1594                                 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1595                         forward[0] = modelorg[0] - center[0];
1596                         forward[1] = modelorg[1] - center[1];
1597                         VectorNormalize(forward);
1598                         right[0] = forward[1];
1599                         right[1] = -forward[0];
1600                         for (i = 0;i < 4;i++)
1601                                 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1602                 }
1603                 rsurface_vertex3f = varray_vertex3f;
1604                 rsurface_svector3f = NULL;
1605                 rsurface_tvector3f = NULL;
1606                 rsurface_normal3f = NULL;
1607         }
1608         else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1609         {
1610                 if (!rsurface_svector3f)
1611                 {
1612                         rsurface_svector3f = varray_svector3f;
1613                         rsurface_tvector3f = varray_tvector3f;
1614                         rsurface_normal3f = varray_normal3f;
1615                         Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
1616                 }
1617                 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1618                 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1619                 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1620                 // a single autosprite surface can contain multiple sprites...
1621                 for (j = 0;j < surface->num_vertices - 3;j += 4)
1622                 {
1623                         VectorClear(center);
1624                         for (i = 0;i < 4;i++)
1625                                 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1626                         VectorScale(center, 0.25f, center);
1627                         // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1628                         Matrix4x4_FromVectors(&matrix1, (rsurface_normal3f + 3 * surface->num_firstvertex) + j*3, (rsurface_svector3f + 3 * surface->num_firstvertex) + j*3, (rsurface_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
1629                         Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1630                         for (i = 0;i < 4;i++)
1631                                 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1632                         for (i = 0;i < 4;i++)
1633                                 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1634                 }
1635                 rsurface_vertex3f = varray_vertex3f;
1636                 rsurface_svector3f = NULL;
1637                 rsurface_tvector3f = NULL;
1638                 rsurface_normal3f = NULL;
1639         }
1640         R_Mesh_VertexPointer(rsurface_vertex3f);
1641 }
1642
1643 void RSurf_SetColorPointer(const entity_render_t *ent, const msurface_t *surface, const vec3_t modelorg, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
1644 {
1645         int i;
1646         float f;
1647         float *v, *c, *c2;
1648         vec3_t diff;
1649         if (lightmode >= 2)
1650         {
1651                 // model lighting
1652                 vec4_t ambientcolor4f;
1653                 vec3_t diffusecolor;
1654                 vec3_t diffusenormal;
1655                 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1656                 {
1657                         rsurface_lightmapcolor4f = varray_color4f;
1658                         if (rsurface_normal3f == NULL)
1659                         {
1660                                 rsurface_normal3f = varray_normal3f;
1661                                 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
1662                         }
1663                         R_LightModel_CalcVertexColors(ambientcolor4f, diffusecolor, diffusenormal, surface->groupmesh->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, rsurface_lightmapcolor4f + 4 * surface->num_firstvertex);
1664                         r = 1;
1665                         g = 1;
1666                         b = 1;
1667                         a = 1;
1668                         applycolor = false;
1669                 }
1670                 else
1671                 {
1672                         r = ambientcolor4f[0];
1673                         g = ambientcolor4f[1];
1674                         b = ambientcolor4f[2];
1675                         a = ambientcolor4f[3];
1676                         rsurface_lightmapcolor4f = NULL;
1677                 }
1678         }
1679         else if (lightmode >= 1)
1680         {
1681                 if (surface->lightmapinfo)
1682                 {
1683                         for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1684                         {
1685                                 const qbyte *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1686                                 if (lm)
1687                                 {
1688                                         float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1689                                         VectorScale(lm, scale, c);
1690                                         if (surface->lightmapinfo->styles[1] != 255)
1691                                         {
1692                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1693                                                 lm += size3;
1694                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1695                                                 VectorMA(c, scale, lm, c);
1696                                                 if (surface->lightmapinfo->styles[2] != 255)
1697                                                 {
1698                                                         lm += size3;
1699                                                         scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1700                                                         VectorMA(c, scale, lm, c);
1701                                                         if (surface->lightmapinfo->styles[3] != 255)
1702                                                         {
1703                                                                 lm += size3;
1704                                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1705                                                                 VectorMA(c, scale, lm, c);
1706                                                         }
1707                                                 }
1708                                         }
1709                                 }
1710                                 else
1711                                         VectorClear(c);
1712                         }
1713                         rsurface_lightmapcolor4f = varray_color4f;
1714                 }
1715                 else
1716                         rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1717         }
1718         else
1719                 rsurface_lightmapcolor4f = NULL;
1720         if (applyfog)
1721         {
1722                 if (rsurface_lightmapcolor4f)
1723                 {
1724                         for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
1725                         {
1726                                 VectorSubtract(v, modelorg, diff);
1727                                 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1728                                 c2[0] = c[0] * f;
1729                                 c2[1] = c[1] * f;
1730                                 c2[2] = c[2] * f;
1731                                 c2[3] = c[3];
1732                         }
1733                 }
1734                 else
1735                 {
1736                         for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
1737                         {
1738                                 VectorSubtract(v, modelorg, diff);
1739                                 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1740                                 c2[0] = f;
1741                                 c2[1] = f;
1742                                 c2[2] = f;
1743                                 c2[3] = 1;
1744                         }
1745                 }
1746                 rsurface_lightmapcolor4f = varray_color4f;
1747         }
1748         if (applycolor && rsurface_lightmapcolor4f)
1749         {
1750                 for (i = 0, c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
1751                 {
1752                         c2[0] = c[0] * r;
1753                         c2[1] = c[1] * g;
1754                         c2[2] = c[2] * b;
1755                         c2[3] = c[3] * a;
1756                 }
1757                 rsurface_lightmapcolor4f = varray_color4f;
1758         }
1759         R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1760         GL_Color(r, g, b, a);
1761 }
1762
1763
1764 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1765 {
1766         int texturesurfaceindex;
1767         int lightmode;
1768         const msurface_t *surface;
1769         qboolean applycolor;
1770         rmeshstate_t m;
1771         if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1772                 return;
1773         renderstats.entities_surfaces += texturenumsurfaces;
1774         // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1775         lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1776         GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1777         if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1778                 qglDisable(GL_CULL_FACE);
1779         if (texture->currentnumlayers)
1780         {
1781                 int layerindex;
1782                 texturelayer_t *layer;
1783                 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
1784                 {
1785                         vec4_t layercolor;
1786                         int layertexrgbscale;
1787                         GL_DepthMask(layer->depthmask);
1788                         GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
1789                         if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
1790                         {
1791                                 layertexrgbscale = 4;
1792                                 VectorScale(layer->color, 0.25f, layercolor);
1793                         }
1794                         else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
1795                         {
1796                                 layertexrgbscale = 2;
1797                                 VectorScale(layer->color, 0.5f, layercolor);
1798                         }
1799                         else
1800                         {
1801                                 layertexrgbscale = 1;
1802                                 VectorScale(layer->color, 1.0f, layercolor);
1803                         }
1804                         layercolor[3] = layer->color[3];
1805                         GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1806                         applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
1807                         switch (layer->type)
1808                         {
1809                         case TEXTURELAYERTYPE_SKY:
1810                                 if (skyrendernow)
1811                                 {
1812                                         skyrendernow = false;
1813                                         if (skyrendermasked)
1814                                         {
1815                                                 R_Sky();
1816                                                 // restore entity matrix and GL_Color
1817                                                 R_Mesh_Matrix(&ent->matrix);
1818                                                 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1819                                         }
1820                                 }
1821                                 // LordHavoc: HalfLife maps have freaky skypolys...
1822                                 //if (!ent->model->brush.ishlbsp)
1823                                 {
1824                                         if (skyrendermasked)
1825                                         {
1826                                                 // depth-only (masking)
1827                                                 GL_ColorMask(0,0,0,0);
1828                                                 // just to make sure that braindead drivers don't draw anything
1829                                                 // despite that colormask...
1830                                                 GL_BlendFunc(GL_ZERO, GL_ONE);
1831                                         }
1832                                         else
1833                                         {
1834                                                 // fog sky
1835                                                 GL_BlendFunc(GL_ONE, GL_ZERO);
1836                                         }
1837                                         memset(&m, 0, sizeof(m));
1838                                         R_Mesh_State(&m);
1839                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1840                                         {
1841                                                 surface = texturesurfacelist[texturesurfaceindex];
1842                                                 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1843                                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1844                                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1845                                                 GL_LockArrays(0, 0);
1846                                         }
1847                                         if (skyrendermasked)
1848                                                 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1849                                 }
1850                                 break;
1851                         case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
1852                                 memset(&m, 0, sizeof(m));
1853                                 m.tex[1] = R_GetTexture(layer->texture);
1854                                 m.texmatrix[1] = layer->texmatrix;
1855                                 m.texrgbscale[1] = layertexrgbscale;
1856                                 m.pointer_color = varray_color4f;
1857                                 R_Mesh_State(&m);
1858                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1859                                 {
1860                                         surface = texturesurfacelist[texturesurfaceindex];
1861                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1862                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1863                                         R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
1864                                         if (lightmode == 2)
1865                                         {
1866                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1867                                                 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1868                                         }
1869                                         else if (surface->lightmaptexture)
1870                                         {
1871                                                 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1872                                                 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1873                                         }
1874                                         else
1875                                         {
1876                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1877                                                 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1878                                         }
1879                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1880                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1881                                         GL_LockArrays(0, 0);
1882                                 }
1883                                 break;
1884                         case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
1885                                 memset(&m, 0, sizeof(m));
1886                                 m.tex[0] = R_GetTexture(layer->texture);
1887                                 m.texmatrix[0] = layer->texmatrix;
1888                                 m.pointer_color = varray_color4f;
1889                                 m.texrgbscale[0] = layertexrgbscale;
1890                                 R_Mesh_State(&m);
1891                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1892                                 {
1893                                         surface = texturesurfacelist[texturesurfaceindex];
1894                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1895                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1896                                         if (lightmode == 2)
1897                                         {
1898                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1899                                                 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 2, false, false);
1900                                         }
1901                                         else if (surface->lightmaptexture)
1902                                         {
1903                                                 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1904                                                 R_Mesh_ColorPointer(NULL);
1905                                         }
1906                                         else
1907                                         {
1908                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1909                                                 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 1, false, false);
1910                                         }
1911                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1912                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1913                                         GL_LockArrays(0, 0);
1914                                 }
1915                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1916                                 memset(&m, 0, sizeof(m));
1917                                 m.tex[0] = R_GetTexture(layer->texture);
1918                                 m.texmatrix[0] = layer->texmatrix;
1919                                 m.pointer_color = varray_color4f;
1920                                 m.texrgbscale[0] = layertexrgbscale;
1921                                 R_Mesh_State(&m);
1922                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1923                                 {
1924                                         surface = texturesurfacelist[texturesurfaceindex];
1925                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1926                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1927                                         RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1928                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1929                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1930                                         GL_LockArrays(0, 0);
1931                                 }
1932                                 break;
1933                         case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
1934                                 memset(&m, 0, sizeof(m));
1935                                 m.tex[0] = R_GetTexture(layer->texture);
1936                                 m.texmatrix[0] = layer->texmatrix;
1937                                 m.texrgbscale[0] = layertexrgbscale;
1938                                 m.pointer_color = varray_color4f;
1939                                 R_Mesh_State(&m);
1940                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1941                                 {
1942                                         surface = texturesurfacelist[texturesurfaceindex];
1943                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1944                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1945                                         RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode ? lightmode : 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1946                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1947                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1948                                         GL_LockArrays(0, 0);
1949                                 }
1950                                 break;
1951                         case TEXTURELAYERTYPE_TEXTURE:
1952                                 memset(&m, 0, sizeof(m));
1953                                 m.tex[0] = R_GetTexture(layer->texture);
1954                                 m.texmatrix[0] = layer->texmatrix;
1955                                 m.pointer_color = varray_color4f;
1956                                 m.texrgbscale[0] = layertexrgbscale;
1957                                 R_Mesh_State(&m);
1958                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1959                                 {
1960                                         surface = texturesurfacelist[texturesurfaceindex];
1961                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1962                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1963                                         RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1964                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1965                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1966                                         GL_LockArrays(0, 0);
1967                                 }
1968                                 break;
1969                         case TEXTURELAYERTYPE_FOG:
1970                                 memset(&m, 0, sizeof(m));
1971                                 if (layer->texture)
1972                                 {
1973                                         m.tex[0] = R_GetTexture(layer->texture);
1974                                         m.texmatrix[0] = layer->texmatrix;
1975                                 }
1976                                 R_Mesh_State(&m);
1977                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1978                                 {
1979                                         int i;
1980                                         float diff[3];
1981                                         float f, *v, *c;
1982                                         surface = texturesurfacelist[texturesurfaceindex];
1983                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1984                                         if (layer->texture)
1985                                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1986                                         R_Mesh_ColorPointer(varray_color4f);
1987                                         for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
1988                                         {
1989                                                 VectorSubtract(v, modelorg, diff);
1990                                                 f = exp(fogdensity/DotProduct(diff, diff));
1991                                                 c[0] = layercolor[0];
1992                                                 c[1] = layercolor[1];
1993                                                 c[2] = layercolor[2];
1994                                                 c[3] = f * layercolor[3];
1995                                         }
1996                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1997                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1998                                         GL_LockArrays(0, 0);
1999                                 }
2000                                 break;
2001                         default:
2002                                 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2003                         }
2004                         // if trying to do overbright on first pass of an opaque surface
2005                         // when combine is not supported, brighten as a post process
2006                         if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
2007                         {
2008                                 int scale;
2009                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2010                                 GL_Color(1, 1, 1, 1);
2011                                 memset(&m, 0, sizeof(m));
2012                                 R_Mesh_State(&m);
2013                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2014                                 {
2015                                         surface = texturesurfacelist[texturesurfaceindex];
2016                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2017                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2018                                         for (scale = 1;scale < layertexrgbscale;scale <<= 1)
2019                                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2020                                         GL_LockArrays(0, 0);
2021                                 }
2022                         }
2023                 }
2024         }
2025         if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
2026                 qglEnable(GL_CULL_FACE);
2027 }
2028
2029 static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
2030 {
2031         const entity_render_t *ent = (entity_render_t *)calldata1;
2032         const msurface_t *surface = ent->model->data_surfaces + calldata2;
2033         vec3_t modelorg;
2034         texture_t *texture;
2035
2036         texture = surface->texture;
2037         if (texture->basematerialflags & MATERIALFLAG_SKY)
2038                 return; // transparent sky is too difficult
2039         R_UpdateTextureInfo(ent, texture);
2040
2041         R_Mesh_Matrix(&ent->matrix);
2042         Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2043         R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2044 }
2045
2046 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2047 {
2048         int texturesurfaceindex;
2049         const msurface_t *surface;
2050         vec3_t tempcenter, center;
2051         if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2052         {
2053                 // drawing sky transparently would be too difficult
2054                 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2055                 {
2056                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2057                         {
2058                                 surface = texturesurfacelist[texturesurfaceindex];
2059                                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2060                                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2061                                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2062                                 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2063                                 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->data_surfaces);
2064                         }
2065                 }
2066         }
2067         else
2068                 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2069 }
2070
2071 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2072 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2073 {
2074         int i, j, f, flagsmask;
2075         int counttriangles = 0;
2076         msurface_t *surface, **surfacechain;
2077         texture_t *t, *texture;
2078         model_t *model = ent->model;
2079         vec3_t modelorg;
2080         const int maxsurfacelist = 1024;
2081         int numsurfacelist = 0;
2082         const msurface_t *surfacelist[1024];
2083         if (model == NULL)
2084                 return;
2085         R_Mesh_Matrix(&ent->matrix);
2086         Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2087
2088         // update light styles
2089         if (!skysurfaces && model->brushq1.light_styleupdatechains)
2090         {
2091                 for (i = 0;i < model->brushq1.light_styles;i++)
2092                 {
2093                         if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
2094                         {
2095                                 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
2096                                 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2097                                         for (;(surface = *surfacechain);surfacechain++)
2098                                                 surface->cached_dlight = true;
2099                         }
2100                 }
2101         }
2102
2103         R_UpdateAllTextureInfo(ent);
2104         flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2105         f = 0;
2106         t = NULL;
2107         texture = NULL;
2108         numsurfacelist = 0;
2109         if (ent == r_refdef.worldentity)
2110         {
2111                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2112                 {
2113                         if (!r_worldsurfacevisible[j])
2114                                 continue;
2115                         if (t != surface->texture)
2116                         {
2117                                 if (numsurfacelist)
2118                                 {
2119                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2120                                         numsurfacelist = 0;
2121                                 }
2122                                 t = surface->texture;
2123                                 texture = t->currentframe;
2124                                 f = texture->currentmaterialflags & flagsmask;
2125                         }
2126                         if (f && surface->num_triangles)
2127                         {
2128                                 // if lightmap parameters changed, rebuild lightmap texture
2129                                 if (surface->cached_dlight && surface->lightmapinfo->samples)
2130                                         R_BuildLightMap(ent, surface);
2131                                 // add face to draw list
2132                                 surfacelist[numsurfacelist++] = surface;
2133                                 counttriangles += surface->num_triangles;
2134                                 if (numsurfacelist >= maxsurfacelist)
2135                                 {
2136                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2137                                         numsurfacelist = 0;
2138                                 }
2139                         }
2140                 }
2141         }
2142         else
2143         {
2144                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2145                 {
2146                         if (t != surface->texture)
2147                         {
2148                                 if (numsurfacelist)
2149                                 {
2150                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2151                                         numsurfacelist = 0;
2152                                 }
2153                                 t = surface->texture;
2154                                 texture = t->currentframe;
2155                                 f = texture->currentmaterialflags & flagsmask;
2156                         }
2157                         if (f && surface->num_triangles)
2158                         {
2159                                 // if lightmap parameters changed, rebuild lightmap texture
2160                                 if (surface->cached_dlight && surface->lightmapinfo->samples)
2161                                         R_BuildLightMap(ent, surface);
2162                                 // add face to draw list
2163                                 surfacelist[numsurfacelist++] = surface;
2164                                 counttriangles += surface->num_triangles;
2165                                 if (numsurfacelist >= maxsurfacelist)
2166                                 {
2167                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2168                                         numsurfacelist = 0;
2169                                 }
2170                         }
2171                 }
2172         }
2173         if (numsurfacelist)
2174                 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2175         if (!r_showtrispass)
2176                 renderstats.entities_triangles += counttriangles;
2177 }
2178