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