]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
made gl_max_size cvar only affect TEXF_PICMIP textures, this prevents it from breakin...
[divverent/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, NULL)))
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         int screenwidth, screenheight;
750         qboolean dobloom;
751         qboolean doblend;
752         rmeshstate_t m;
753
754         // set the (poorly named) screenwidth and screenheight variables to
755         // a power of 2 at least as large as the screen, these will define the
756         // size of the texture to allocate
757         for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
758         for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
759
760         doblend = r_refdef.viewblend[3] >= 0.01f;
761         dobloom = r_bloom.integer && screenwidth <= gl_max_texture_size && screenheight <= gl_max_texture_size && 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;
762
763         if (!dobloom && !doblend)
764                 return;
765
766         GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
767         GL_DepthMask(true);
768         GL_DepthTest(false);
769         R_Mesh_Matrix(&r_identitymatrix);
770         // vertex coordinates for a quad that covers the screen exactly
771         varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
772         varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
773         varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
774         varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
775         if (dobloom)
776         {
777                 int bloomwidth, bloomheight, x, dobloomblend, range;
778                 float xoffset, yoffset, r;
779                 renderstats.bloom++;
780                 // allocate textures as needed
781                 if (!r_bloom_texture_screen)
782                         r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
783                 if (!r_bloom_texture_bloom)
784                         r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
785                 // set bloomwidth and bloomheight to the bloom resolution that will be
786                 // used (often less than the screen resolution for faster rendering)
787                 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
788                 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
789                 // set up a texcoord array for the full resolution screen image
790                 // (we have to keep this around to copy back during final render)
791                 varray_texcoord2f[0][0] = 0;
792                 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
793                 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
794                 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
795                 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
796                 varray_texcoord2f[0][5] = 0;
797                 varray_texcoord2f[0][6] = 0;
798                 varray_texcoord2f[0][7] = 0;
799                 // set up a texcoord array for the reduced resolution bloom image
800                 // (which will be additive blended over the screen image)
801                 varray_texcoord2f[1][0] = 0;
802                 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
803                 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
804                 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
805                 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
806                 varray_texcoord2f[1][5] = 0;
807                 varray_texcoord2f[1][6] = 0;
808                 varray_texcoord2f[1][7] = 0;
809                 memset(&m, 0, sizeof(m));
810                 m.pointer_vertex = varray_vertex3f;
811                 m.pointer_texcoord[0] = varray_texcoord2f[0];
812                 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
813                 R_Mesh_State(&m);
814                 // copy view into the full resolution screen image texture
815                 GL_ActiveTexture(0);
816                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
817                 renderstats.bloom_copypixels += r_view_width * r_view_height;
818                 // now scale it down to the bloom size and raise to a power of itself
819                 // to darken it (this leaves the really bright stuff bright, and
820                 // everything else becomes very dark)
821                 // TODO: optimize with multitexture or GLSL
822                 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
823                 GL_BlendFunc(GL_ONE, GL_ZERO);
824                 GL_Color(1, 1, 1, 1);
825                 R_Mesh_Draw(0, 4, 2, polygonelements);
826                 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
827                 // render multiple times with a multiply blendfunc to raise to a power
828                 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
829                 for (x = 1;x < r_bloom_power.integer;x++)
830                 {
831                         R_Mesh_Draw(0, 4, 2, polygonelements);
832                         renderstats.bloom_drawpixels += bloomwidth * bloomheight;
833                 }
834                 // we now have a darkened bloom image in the framebuffer, copy it into
835                 // the bloom image texture for more processing
836                 memset(&m, 0, sizeof(m));
837                 m.pointer_vertex = varray_vertex3f;
838                 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
839                 m.pointer_texcoord[0] = varray_texcoord2f[2];
840                 R_Mesh_State(&m);
841                 GL_ActiveTexture(0);
842                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
843                 renderstats.bloom_copypixels += bloomwidth * bloomheight;
844                 // blend on at multiple vertical offsets to achieve a vertical blur
845                 // TODO: do offset blends using GLSL
846                 range = r_bloom_blur.integer * bloomwidth / 320;
847                 GL_BlendFunc(GL_ONE, GL_ZERO);
848                 for (x = -range;x <= range;x++)
849                 {
850                         xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
851                         yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
852                         // compute a texcoord array with the specified x and y offset
853                         varray_texcoord2f[2][0] = xoffset+0;
854                         varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
855                         varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
856                         varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
857                         varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
858                         varray_texcoord2f[2][5] = yoffset+0;
859                         varray_texcoord2f[2][6] = xoffset+0;
860                         varray_texcoord2f[2][7] = yoffset+0;
861                         // this r value looks like a 'dot' particle, fading sharply to
862                         // black at the edges
863                         // (probably not realistic but looks good enough)
864                         r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
865                         if (r < 0.01f)
866                                 continue;
867                         GL_Color(r, r, r, 1);
868                         R_Mesh_Draw(0, 4, 2, polygonelements);
869                         renderstats.bloom_drawpixels += bloomwidth * bloomheight;
870                         GL_BlendFunc(GL_ONE, GL_ONE);
871                 }
872                 // copy the vertically blurred bloom view to a texture
873                 GL_ActiveTexture(0);
874                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
875                 renderstats.bloom_copypixels += bloomwidth * bloomheight;
876                 // blend the vertically blurred image at multiple offsets horizontally
877                 // to finish the blur effect
878                 // TODO: do offset blends using GLSL
879                 range = r_bloom_blur.integer * bloomwidth / 320;
880                 GL_BlendFunc(GL_ONE, GL_ZERO);
881                 for (x = -range;x <= range;x++)
882                 {
883                         xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
884                         yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
885                         // compute a texcoord array with the specified x and y offset
886                         varray_texcoord2f[2][0] = xoffset+0;
887                         varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
888                         varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
889                         varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
890                         varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
891                         varray_texcoord2f[2][5] = yoffset+0;
892                         varray_texcoord2f[2][6] = xoffset+0;
893                         varray_texcoord2f[2][7] = yoffset+0;
894                         // this r value looks like a 'dot' particle, fading sharply to
895                         // black at the edges
896                         // (probably not realistic but looks good enough)
897                         r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
898                         if (r < 0.01f)
899                                 continue;
900                         GL_Color(r, r, r, 1);
901                         R_Mesh_Draw(0, 4, 2, polygonelements);
902                         renderstats.bloom_drawpixels += bloomwidth * bloomheight;
903                         GL_BlendFunc(GL_ONE, GL_ONE);
904                 }
905                 // copy the blurred bloom view to a texture
906                 GL_ActiveTexture(0);
907                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
908                 renderstats.bloom_copypixels += bloomwidth * bloomheight;
909                 // go back to full view area
910                 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
911                 // put the original screen image back in place and blend the bloom
912                 // texture on it
913                 memset(&m, 0, sizeof(m));
914                 m.pointer_vertex = varray_vertex3f;
915                 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
916                 m.pointer_texcoord[0] = varray_texcoord2f[0];
917 #if 0
918                 dobloomblend = false;
919 #else
920                 // do both in one pass if possible
921                 if (r_textureunits.integer >= 2 && gl_combine.integer)
922                 {
923                         dobloomblend = false;
924                         m.texcombinergb[1] = GL_ADD;
925                         m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
926                         m.pointer_texcoord[1] = varray_texcoord2f[1];
927                 }
928                 else
929                         dobloomblend = true;
930 #endif
931                 R_Mesh_State(&m);
932                 GL_BlendFunc(GL_ONE, GL_ZERO);
933                 GL_Color(1,1,1,1);
934                 R_Mesh_Draw(0, 4, 2, polygonelements);
935                 renderstats.bloom_drawpixels += r_view_width * r_view_height;
936                 // now blend on the bloom texture if multipass
937                 if (dobloomblend)
938                 {
939                         memset(&m, 0, sizeof(m));
940                         m.pointer_vertex = varray_vertex3f;
941                         m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
942                         m.pointer_texcoord[0] = varray_texcoord2f[1];
943                         R_Mesh_State(&m);
944                         GL_BlendFunc(GL_ONE, GL_ONE);
945                         GL_Color(1,1,1,1);
946                         R_Mesh_Draw(0, 4, 2, polygonelements);
947                         renderstats.bloom_drawpixels += r_view_width * r_view_height;
948                 }
949         }
950         if (doblend)
951         {
952                 // apply a color tint to the whole view
953                 memset(&m, 0, sizeof(m));
954                 m.pointer_vertex = varray_vertex3f;
955                 R_Mesh_State(&m);
956                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
957                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
958                 R_Mesh_Draw(0, 4, 2, polygonelements);
959         }
960 }
961
962 void R_RenderScene(void);
963
964 matrix4x4_t r_waterscrollmatrix;
965
966 /*
967 ================
968 R_RenderView
969 ================
970 */
971 void R_RenderView(void)
972 {
973         if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
974                 return; //Host_Error ("R_RenderView: NULL worldmodel");
975
976         r_view_width = bound(0, r_refdef.width, vid.width);
977         r_view_height = bound(0, r_refdef.height, vid.height);
978         r_view_depth = 1;
979         r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
980         r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
981         r_view_z = 0;
982         r_view_fov_x = bound(1, r_refdef.fov_x, 170);
983         r_view_fov_y = bound(1, r_refdef.fov_y, 170);
984         r_view_matrix = r_refdef.viewentitymatrix;
985         GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
986         r_rtworld = r_shadow_realtime_world.integer;
987         r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
988         r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
989         r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
990         r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
991
992         // GL is weird because it's bottom to top, r_view_y is top to bottom
993         qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
994         GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
995         GL_ScissorTest(true);
996         GL_DepthMask(true);
997         R_ClearScreen();
998         R_Textures_Frame();
999         R_UpdateFog();
1000         R_TimeReport("setup");
1001
1002         qglDepthFunc(GL_LEQUAL);
1003         qglPolygonOffset(0, 0);
1004         qglEnable(GL_POLYGON_OFFSET_FILL);
1005
1006         R_RenderScene();
1007
1008         qglPolygonOffset(0, 0);
1009         qglDisable(GL_POLYGON_OFFSET_FILL);
1010
1011         R_BlendView();
1012         R_TimeReport("blendview");
1013
1014         GL_Scissor(0, 0, vid.width, vid.height);
1015         GL_ScissorTest(false);
1016 }
1017
1018 extern void R_DrawLightningBeams (void);
1019 void R_RenderScene(void)
1020 {
1021         // don't let sound skip if going slow
1022         if (r_refdef.extraupdate)
1023                 S_ExtraUpdate ();
1024
1025         r_framecount++;
1026
1027         R_MeshQueue_BeginScene();
1028
1029         GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1030
1031         R_SetFrustum();
1032
1033         r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1034         if (r_rtworldshadows || r_rtdlightshadows)
1035                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f);
1036         else
1037                 GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip);
1038
1039         GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1040
1041         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);
1042
1043         R_SkyStartFrame();
1044
1045         R_WorldVisibility();
1046         R_TimeReport("worldvis");
1047
1048         R_MarkEntities();
1049         R_TimeReport("markentity");
1050
1051         R_Shadow_UpdateWorldLightSelection();
1052
1053         // don't let sound skip if going slow
1054         if (r_refdef.extraupdate)
1055                 S_ExtraUpdate ();
1056
1057         GL_ShowTrisColor(0.025, 0.025, 0, 1);
1058         if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1059         {
1060                 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1061                 R_TimeReport("worldsky");
1062         }
1063
1064         if (R_DrawBrushModelsSky())
1065                 R_TimeReport("bmodelsky");
1066
1067         GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1068         if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1069         {
1070                 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1071                 R_TimeReport("world");
1072         }
1073
1074         // don't let sound skip if going slow
1075         if (r_refdef.extraupdate)
1076                 S_ExtraUpdate ();
1077
1078         GL_ShowTrisColor(0, 0.015, 0, 1);
1079
1080         R_DrawModels();
1081         R_TimeReport("models");
1082
1083         // don't let sound skip if going slow
1084         if (r_refdef.extraupdate)
1085                 S_ExtraUpdate ();
1086
1087         GL_ShowTrisColor(0, 0, 0.033, 1);
1088         R_ShadowVolumeLighting(false);
1089         R_TimeReport("rtlights");
1090
1091         // don't let sound skip if going slow
1092         if (r_refdef.extraupdate)
1093                 S_ExtraUpdate ();
1094
1095         GL_ShowTrisColor(0.1, 0, 0, 1);
1096
1097         R_DrawLightningBeams();
1098         R_TimeReport("lightning");
1099
1100         R_DrawParticles();
1101         R_TimeReport("particles");
1102
1103         R_DrawExplosions();
1104         R_TimeReport("explosions");
1105
1106         R_MeshQueue_RenderTransparent();
1107         R_TimeReport("drawtrans");
1108
1109         R_DrawCoronas();
1110         R_TimeReport("coronas");
1111
1112         R_DrawWorldCrosshair();
1113         R_TimeReport("crosshair");
1114
1115         R_MeshQueue_Render();
1116         R_MeshQueue_EndScene();
1117
1118         if ((r_shadow_visiblelighting.integer || r_shadow_visiblevolumes.integer) && !r_showtrispass)
1119         {
1120                 R_ShadowVolumeLighting(true);
1121                 R_TimeReport("visiblevolume");
1122         }
1123
1124         GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1125
1126         // don't let sound skip if going slow
1127         if (r_refdef.extraupdate)
1128                 S_ExtraUpdate ();
1129 }
1130
1131 /*
1132 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1133 {
1134         int i;
1135         float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1136         rmeshstate_t m;
1137         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1138         GL_DepthMask(false);
1139         GL_DepthTest(true);
1140         R_Mesh_Matrix(&r_identitymatrix);
1141
1142         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1143         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1144         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1145         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1146         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1147         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1148         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1149         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1150         R_FillColors(color, 8, cr, cg, cb, ca);
1151         if (fogenabled)
1152         {
1153                 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1154                 {
1155                         f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
1156                         f1 = 1 - f2;
1157                         c[0] = c[0] * f1 + fogcolor[0] * f2;
1158                         c[1] = c[1] * f1 + fogcolor[1] * f2;
1159                         c[2] = c[2] * f1 + fogcolor[2] * f2;
1160                 }
1161         }
1162         memset(&m, 0, sizeof(m));
1163         m.pointer_vertex = vertex3f;
1164         m.pointer_color = color;
1165         R_Mesh_State(&m);
1166         R_Mesh_Draw(8, 12);
1167 }
1168 */
1169
1170 int nomodelelements[24] =
1171 {
1172         5, 2, 0,
1173         5, 1, 2,
1174         5, 0, 3,
1175         5, 3, 1,
1176         0, 2, 4,
1177         2, 1, 4,
1178         3, 0, 4,
1179         1, 3, 4
1180 };
1181
1182 float nomodelvertex3f[6*3] =
1183 {
1184         -16,   0,   0,
1185          16,   0,   0,
1186           0, -16,   0,
1187           0,  16,   0,
1188           0,   0, -16,
1189           0,   0,  16
1190 };
1191
1192 float nomodelcolor4f[6*4] =
1193 {
1194         0.0f, 0.0f, 0.5f, 1.0f,
1195         0.0f, 0.0f, 0.5f, 1.0f,
1196         0.0f, 0.5f, 0.0f, 1.0f,
1197         0.0f, 0.5f, 0.0f, 1.0f,
1198         0.5f, 0.0f, 0.0f, 1.0f,
1199         0.5f, 0.0f, 0.0f, 1.0f
1200 };
1201
1202 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1203 {
1204         const entity_render_t *ent = (entity_render_t *)calldata1;
1205         int i;
1206         float f1, f2, *c;
1207         float color4f[6*4];
1208         rmeshstate_t m;
1209         R_Mesh_Matrix(&ent->matrix);
1210
1211         memset(&m, 0, sizeof(m));
1212         m.pointer_vertex = nomodelvertex3f;
1213
1214         if (ent->flags & EF_ADDITIVE)
1215         {
1216                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1217                 GL_DepthMask(false);
1218         }
1219         else if (ent->alpha < 1)
1220         {
1221                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1222                 GL_DepthMask(false);
1223         }
1224         else
1225         {
1226                 GL_BlendFunc(GL_ONE, GL_ZERO);
1227                 GL_DepthMask(true);
1228         }
1229         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1230         if (fogenabled)
1231         {
1232                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1233                 m.pointer_color = color4f;
1234                 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
1235                 f1 = 1 - f2;
1236                 for (i = 0, c = color4f;i < 6;i++, c += 4)
1237                 {
1238                         c[0] = (c[0] * f1 + fogcolor[0] * f2);
1239                         c[1] = (c[1] * f1 + fogcolor[1] * f2);
1240                         c[2] = (c[2] * f1 + fogcolor[2] * f2);
1241                         c[3] *= ent->alpha;
1242                 }
1243         }
1244         else if (ent->alpha != 1)
1245         {
1246                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1247                 m.pointer_color = color4f;
1248                 for (i = 0, c = color4f;i < 6;i++, c += 4)
1249                         c[3] *= ent->alpha;
1250         }
1251         else
1252                 m.pointer_color = nomodelcolor4f;
1253         R_Mesh_State(&m);
1254         R_Mesh_Draw(0, 6, 8, nomodelelements);
1255 }
1256
1257 void R_DrawNoModel(entity_render_t *ent)
1258 {
1259         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1260                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModelCallback, ent, 0);
1261         //else
1262         //      R_DrawNoModelCallback(ent, 0);
1263 }
1264
1265 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1266 {
1267         vec3_t right1, right2, diff, normal;
1268
1269         VectorSubtract (org2, org1, normal);
1270
1271         // calculate 'right' vector for start
1272         VectorSubtract (r_vieworigin, org1, diff);
1273         CrossProduct (normal, diff, right1);
1274         VectorNormalize (right1);
1275
1276         // calculate 'right' vector for end
1277         VectorSubtract (r_vieworigin, org2, diff);
1278         CrossProduct (normal, diff, right2);
1279         VectorNormalize (right2);
1280
1281         vert[ 0] = org1[0] + width * right1[0];
1282         vert[ 1] = org1[1] + width * right1[1];
1283         vert[ 2] = org1[2] + width * right1[2];
1284         vert[ 3] = org1[0] - width * right1[0];
1285         vert[ 4] = org1[1] - width * right1[1];
1286         vert[ 5] = org1[2] - width * right1[2];
1287         vert[ 6] = org2[0] - width * right2[0];
1288         vert[ 7] = org2[1] - width * right2[1];
1289         vert[ 8] = org2[2] - width * right2[2];
1290         vert[ 9] = org2[0] + width * right2[0];
1291         vert[10] = org2[1] + width * right2[1];
1292         vert[11] = org2[2] + width * right2[2];
1293 }
1294
1295 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1296
1297 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)
1298 {
1299         float fog = 0.0f, ifog;
1300         rmeshstate_t m;
1301
1302         if (fogenabled)
1303                 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
1304         ifog = 1 - fog;
1305
1306         R_Mesh_Matrix(&r_identitymatrix);
1307         GL_BlendFunc(blendfunc1, blendfunc2);
1308         GL_DepthMask(false);
1309         GL_DepthTest(!depthdisable);
1310
1311         varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1312         varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1313         varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1314         varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1315         varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1316         varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1317         varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1318         varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1319         varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1320         varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1321         varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1322         varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1323
1324         memset(&m, 0, sizeof(m));
1325         m.tex[0] = R_GetTexture(texture);
1326         m.pointer_texcoord[0] = spritetexcoord2f;
1327         m.pointer_vertex = varray_vertex3f;
1328         R_Mesh_State(&m);
1329         GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
1330         R_Mesh_Draw(0, 4, 2, polygonelements);
1331
1332         if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
1333         {
1334                 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
1335                 GL_BlendFunc(blendfunc1, GL_ONE);
1336                 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
1337                 R_Mesh_Draw(0, 4, 2, polygonelements);
1338         }
1339 }
1340
1341 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1342 {
1343         int i;
1344         float *vertex3f;
1345         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1346                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1347                         break;
1348         if (i == mesh->numvertices)
1349         {
1350                 if (mesh->numvertices < mesh->maxvertices)
1351                 {
1352                         VectorCopy(v, vertex3f);
1353                         mesh->numvertices++;
1354                 }
1355                 return mesh->numvertices;
1356         }
1357         else
1358                 return i;
1359 }
1360
1361 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1362 {
1363         int i;
1364         int *e, element[3];
1365         element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1366         element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1367         e = mesh->element3i + mesh->numtriangles * 3;
1368         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1369         {
1370                 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1371                 if (mesh->numtriangles < mesh->maxtriangles)
1372                 {
1373                         *e++ = element[0];
1374                         *e++ = element[1];
1375                         *e++ = element[2];
1376                         mesh->numtriangles++;
1377                 }
1378                 element[1] = element[2];
1379         }
1380 }
1381
1382 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1383 {
1384         int planenum, planenum2;
1385         int w;
1386         int tempnumpoints;
1387         mplane_t *plane, *plane2;
1388         float temppoints[2][256*3];
1389         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1390         {
1391                 w = 0;
1392                 tempnumpoints = 4;
1393                 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1394                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1395                 {
1396                         if (planenum2 == planenum)
1397                                 continue;
1398                         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);
1399                         w = !w;
1400                 }
1401                 if (tempnumpoints < 3)
1402                         continue;
1403                 // generate elements forming a triangle fan for this polygon
1404                 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1405         }
1406 }
1407
1408 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)
1409 {
1410         texturelayer_t *layer;
1411         layer = t->currentlayers + t->currentnumlayers++;
1412         layer->type = type;
1413         layer->depthmask = depthmask;
1414         layer->blendfunc1 = blendfunc1;
1415         layer->blendfunc2 = blendfunc2;
1416         layer->texture = texture;
1417         layer->texmatrix = *matrix;
1418         layer->color[0] = r;
1419         layer->color[1] = g;
1420         layer->color[2] = b;
1421         layer->color[3] = a;
1422 }
1423
1424 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1425 {
1426         // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1427         //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1428         float currentalpha;
1429
1430         {
1431                 texture_t *texture = t;
1432                 model_t *model = ent->model;
1433                 int s = ent->skinnum;
1434                 if ((unsigned int)s >= (unsigned int)model->numskins)
1435                         s = 0;
1436                 if (model->skinscenes)
1437                 {
1438                         if (model->skinscenes[s].framecount > 1)
1439                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1440                         else
1441                                 s = model->skinscenes[s].firstframe;
1442                 }
1443                 if (s > 0)
1444                         t = t + s * model->num_surfaces;
1445                 if (t->animated)
1446                         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];
1447                 texture->currentframe = t;
1448         }
1449
1450         t->currentmaterialflags = t->basematerialflags;
1451         currentalpha = ent->alpha;
1452         if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1453                 currentalpha *= r_wateralpha.value;
1454         if (!(ent->flags & RENDER_LIGHT))
1455                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1456         if (ent->effects & EF_ADDITIVE)
1457                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1458         else if (currentalpha < 1)
1459                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1460         if (ent->effects & EF_NODEPTHTEST)
1461                 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1462         if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1463                 t->currenttexmatrix = r_waterscrollmatrix;
1464         else
1465                 t->currenttexmatrix = r_identitymatrix;
1466         t->currentnumlayers = 0;
1467         if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
1468         {
1469                 if (gl_lightmaps.integer)
1470                         R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &r_identitymatrix, 1, 1, 1, 1);
1471                 else if (t->currentmaterialflags & MATERIALFLAG_SKY)
1472                 {
1473                         // transparent sky would be ridiculous
1474                         if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1475                                 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
1476                 }
1477                 else
1478                 {
1479                         int blendfunc1, blendfunc2, depthmask;
1480                         if (t->currentmaterialflags & MATERIALFLAG_ADD)
1481                         {
1482                                 blendfunc1 = GL_SRC_ALPHA;
1483                                 blendfunc2 = GL_ONE;
1484                                 depthmask = false;
1485                         }
1486                         else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
1487                         {
1488                                 blendfunc1 = GL_SRC_ALPHA;
1489                                 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1490                                 depthmask = false;
1491                         }
1492                         else
1493                         {
1494                                 blendfunc1 = GL_ONE;
1495                                 blendfunc2 = GL_ZERO;
1496                                 depthmask = true;
1497                         }
1498                         if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1499                         {
1500                                 rtexture_t *currentbasetexture;
1501                                 int layerflags = 0;
1502                                 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1503                                         layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
1504                                 currentbasetexture = (ent->colormap < 0 && t->skin.merged) ? t->skin.merged : t->skin.base;
1505                                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1506                                 {
1507                                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], currentalpha);
1508                                         if (ent->colormap >= 0 && t->skin.pants)
1509                                                 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);
1510                                         if (ent->colormap >= 0 && t->skin.shirt)
1511                                                 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);
1512                                 }
1513                                 else
1514                                 {
1515                                         float colorscale;
1516                                         colorscale = 2;
1517                                         // q3bsp has no lightmap updates, so the lightstylevalue that
1518                                         // would normally be baked into the lightmaptexture must be
1519                                         // applied to the color
1520                                         if (ent->model->type == mod_brushq3)
1521                                                 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
1522                                         // transparent and fullbright are not affected by r_lightmapintensity
1523                                         if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1524                                                 colorscale *= r_lightmapintensity;
1525                                         if (r_textureunits.integer >= 2 && gl_combine.integer)
1526                                                 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);
1527                                         else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
1528                                                 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);
1529                                         else
1530                                                 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);
1531                                         if (r_ambient.value >= (1.0f/64.0f))
1532                                                 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);
1533                                         if (ent->colormap >= 0 && t->skin.pants)
1534                                         {
1535                                                 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);
1536                                                 if (r_ambient.value >= (1.0f/64.0f))
1537                                                         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);
1538                                         }
1539                                         if (ent->colormap >= 0 && t->skin.shirt)
1540                                         {
1541                                                 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);
1542                                                 if (r_ambient.value >= (1.0f/64.0f))
1543                                                         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);
1544                                         }
1545                                 }
1546                                 if (t->skin.glow != NULL)
1547                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, currentalpha);
1548                                 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
1549                                 {
1550                                         // if this is opaque use alpha blend which will darken the earlier
1551                                         // passes cheaply.
1552                                         //
1553                                         // if this is an alpha blended material, all the earlier passes
1554                                         // were darkened by fog already, so we only need to add the fog
1555                                         // color ontop through the fog mask texture
1556                                         //
1557                                         // if this is an additive blended material, all the earlier passes
1558                                         // were darkened by fog already, and we should not add fog color
1559                                         // (because the background was not darkened, there is no fog color
1560                                         // that was lost behind it).
1561                                         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);
1562                                 }
1563                         }
1564                 }
1565         }
1566 }
1567
1568 void R_UpdateAllTextureInfo(entity_render_t *ent)
1569 {
1570         int i;
1571         if (ent->model)
1572                 for (i = 0;i < ent->model->num_textures;i++)
1573                         R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1574 }
1575
1576 float *rsurface_vertex3f;
1577 float *rsurface_svector3f;
1578 float *rsurface_tvector3f;
1579 float *rsurface_normal3f;
1580 float *rsurface_lightmapcolor4f;
1581
1582 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1583 {
1584         int i, j;
1585         float center[3], forward[3], right[3], up[3], v[4][3];
1586         matrix4x4_t matrix1, imatrix1;
1587         if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1588         {
1589                 rsurface_vertex3f = varray_vertex3f;
1590                 rsurface_svector3f = NULL;
1591                 rsurface_tvector3f = NULL;
1592                 rsurface_normal3f = NULL;
1593                 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1594         }
1595         else
1596         {
1597                 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1598                 rsurface_svector3f = surface->groupmesh->data_svector3f;
1599                 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1600                 rsurface_normal3f = surface->groupmesh->data_normal3f;
1601         }
1602         if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1603         {
1604                 if (!rsurface_svector3f)
1605                 {
1606                         rsurface_svector3f = varray_svector3f;
1607                         rsurface_tvector3f = varray_tvector3f;
1608                         rsurface_normal3f = varray_normal3f;
1609                         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);
1610                 }
1611                 // a single autosprite surface can contain multiple sprites...
1612                 VectorClear(forward);
1613                 VectorClear(right);
1614                 VectorSet(up, 0, 0, 1);
1615                 for (j = 0;j < surface->num_vertices - 3;j += 4)
1616                 {
1617                         VectorClear(center);
1618                         for (i = 0;i < 4;i++)
1619                                 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1620                         VectorScale(center, 0.25f, center);
1621                         // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1622                         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);
1623                         Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1624                         for (i = 0;i < 4;i++)
1625                                 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1626                         forward[0] = modelorg[0] - center[0];
1627                         forward[1] = modelorg[1] - center[1];
1628                         VectorNormalize(forward);
1629                         right[0] = forward[1];
1630                         right[1] = -forward[0];
1631                         for (i = 0;i < 4;i++)
1632                                 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1633                 }
1634                 rsurface_vertex3f = varray_vertex3f;
1635                 rsurface_svector3f = NULL;
1636                 rsurface_tvector3f = NULL;
1637                 rsurface_normal3f = NULL;
1638         }
1639         else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1640         {
1641                 if (!rsurface_svector3f)
1642                 {
1643                         rsurface_svector3f = varray_svector3f;
1644                         rsurface_tvector3f = varray_tvector3f;
1645                         rsurface_normal3f = varray_normal3f;
1646                         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);
1647                 }
1648                 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1649                 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1650                 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1651                 // a single autosprite surface can contain multiple sprites...
1652                 for (j = 0;j < surface->num_vertices - 3;j += 4)
1653                 {
1654                         VectorClear(center);
1655                         for (i = 0;i < 4;i++)
1656                                 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1657                         VectorScale(center, 0.25f, center);
1658                         // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1659                         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);
1660                         Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1661                         for (i = 0;i < 4;i++)
1662                                 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1663                         for (i = 0;i < 4;i++)
1664                                 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1665                 }
1666                 rsurface_vertex3f = varray_vertex3f;
1667                 rsurface_svector3f = NULL;
1668                 rsurface_tvector3f = NULL;
1669                 rsurface_normal3f = NULL;
1670         }
1671         R_Mesh_VertexPointer(rsurface_vertex3f);
1672 }
1673
1674 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)
1675 {
1676         int i;
1677         float f;
1678         float *v, *c, *c2;
1679         if (lightmode >= 2)
1680         {
1681                 // model lighting
1682                 vec4_t ambientcolor4f;
1683                 vec3_t diffusecolor;
1684                 vec3_t diffusenormal;
1685                 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1686                 {
1687                         rsurface_lightmapcolor4f = varray_color4f;
1688                         if (rsurface_normal3f == NULL)
1689                         {
1690                                 rsurface_normal3f = varray_normal3f;
1691                                 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);
1692                         }
1693                         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);
1694                         r = 1;
1695                         g = 1;
1696                         b = 1;
1697                         a = 1;
1698                         applycolor = false;
1699                 }
1700                 else
1701                 {
1702                         r = ambientcolor4f[0];
1703                         g = ambientcolor4f[1];
1704                         b = ambientcolor4f[2];
1705                         a = ambientcolor4f[3];
1706                         rsurface_lightmapcolor4f = NULL;
1707                 }
1708         }
1709         else if (lightmode >= 1)
1710         {
1711                 if (surface->lightmapinfo)
1712                 {
1713                         for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1714                         {
1715                                 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1716                                 if (lm)
1717                                 {
1718                                         float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1719                                         VectorScale(lm, scale, c);
1720                                         if (surface->lightmapinfo->styles[1] != 255)
1721                                         {
1722                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1723                                                 lm += size3;
1724                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1725                                                 VectorMA(c, scale, lm, c);
1726                                                 if (surface->lightmapinfo->styles[2] != 255)
1727                                                 {
1728                                                         lm += size3;
1729                                                         scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1730                                                         VectorMA(c, scale, lm, c);
1731                                                         if (surface->lightmapinfo->styles[3] != 255)
1732                                                         {
1733                                                                 lm += size3;
1734                                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1735                                                                 VectorMA(c, scale, lm, c);
1736                                                         }
1737                                                 }
1738                                         }
1739                                 }
1740                                 else
1741                                         VectorClear(c);
1742                         }
1743                         rsurface_lightmapcolor4f = varray_color4f;
1744                 }
1745                 else
1746                         rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1747         }
1748         else
1749                 rsurface_lightmapcolor4f = NULL;
1750         if (applyfog)
1751         {
1752                 if (rsurface_lightmapcolor4f)
1753                 {
1754                         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)
1755                         {
1756                                 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1757                                 c2[0] = c[0] * f;
1758                                 c2[1] = c[1] * f;
1759                                 c2[2] = c[2] * f;
1760                                 c2[3] = c[3];
1761                         }
1762                 }
1763                 else
1764                 {
1765                         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)
1766                         {
1767                                 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1768                                 c2[0] = f;
1769                                 c2[1] = f;
1770                                 c2[2] = f;
1771                                 c2[3] = 1;
1772                         }
1773                 }
1774                 rsurface_lightmapcolor4f = varray_color4f;
1775         }
1776         if (applycolor && rsurface_lightmapcolor4f)
1777         {
1778                 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)
1779                 {
1780                         c2[0] = c[0] * r;
1781                         c2[1] = c[1] * g;
1782                         c2[2] = c[2] * b;
1783                         c2[3] = c[3] * a;
1784                 }
1785                 rsurface_lightmapcolor4f = varray_color4f;
1786         }
1787         R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1788         GL_Color(r, g, b, a);
1789 }
1790
1791
1792 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1793 {
1794         int texturesurfaceindex;
1795         int lightmode;
1796         const msurface_t *surface;
1797         qboolean applycolor;
1798         rmeshstate_t m;
1799         if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1800                 return;
1801         renderstats.entities_surfaces += texturenumsurfaces;
1802         // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1803         lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1804         GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1805         if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1806                 qglDisable(GL_CULL_FACE);
1807         if (texture->currentnumlayers)
1808         {
1809                 int layerindex;
1810                 texturelayer_t *layer;
1811                 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
1812                 {
1813                         vec4_t layercolor;
1814                         int layertexrgbscale;
1815                         GL_DepthMask(layer->depthmask);
1816                         GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
1817                         if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
1818                         {
1819                                 layertexrgbscale = 4;
1820                                 VectorScale(layer->color, 0.25f, layercolor);
1821                         }
1822                         else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
1823                         {
1824                                 layertexrgbscale = 2;
1825                                 VectorScale(layer->color, 0.5f, layercolor);
1826                         }
1827                         else
1828                         {
1829                                 layertexrgbscale = 1;
1830                                 VectorScale(layer->color, 1.0f, layercolor);
1831                         }
1832                         layercolor[3] = layer->color[3];
1833                         GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1834                         applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
1835                         switch (layer->type)
1836                         {
1837                         case TEXTURELAYERTYPE_SKY:
1838                                 if (skyrendernow)
1839                                 {
1840                                         skyrendernow = false;
1841                                         if (skyrendermasked)
1842                                         {
1843                                                 R_Sky();
1844                                                 // restore entity matrix and GL_Color
1845                                                 R_Mesh_Matrix(&ent->matrix);
1846                                                 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1847                                         }
1848                                 }
1849                                 // LordHavoc: HalfLife maps have freaky skypolys...
1850                                 //if (!ent->model->brush.ishlbsp)
1851                                 {
1852                                         if (skyrendermasked)
1853                                         {
1854                                                 // depth-only (masking)
1855                                                 GL_ColorMask(0,0,0,0);
1856                                                 // just to make sure that braindead drivers don't draw anything
1857                                                 // despite that colormask...
1858                                                 GL_BlendFunc(GL_ZERO, GL_ONE);
1859                                         }
1860                                         else
1861                                         {
1862                                                 // fog sky
1863                                                 GL_BlendFunc(GL_ONE, GL_ZERO);
1864                                         }
1865                                         memset(&m, 0, sizeof(m));
1866                                         R_Mesh_State(&m);
1867                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1868                                         {
1869                                                 surface = texturesurfacelist[texturesurfaceindex];
1870                                                 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1871                                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1872                                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1873                                                 GL_LockArrays(0, 0);
1874                                         }
1875                                         if (skyrendermasked)
1876                                                 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1877                                 }
1878                                 break;
1879                         case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
1880                                 memset(&m, 0, sizeof(m));
1881                                 m.tex[1] = R_GetTexture(layer->texture);
1882                                 m.texmatrix[1] = layer->texmatrix;
1883                                 m.texrgbscale[1] = layertexrgbscale;
1884                                 m.pointer_color = varray_color4f;
1885                                 R_Mesh_State(&m);
1886                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1887                                 {
1888                                         surface = texturesurfacelist[texturesurfaceindex];
1889                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1890                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1891                                         R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
1892                                         if (lightmode == 2)
1893                                         {
1894                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1895                                                 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1896                                         }
1897                                         else if (surface->lightmaptexture)
1898                                         {
1899                                                 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1900                                                 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1901                                         }
1902                                         else
1903                                         {
1904                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1905                                                 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1906                                         }
1907                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1908                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1909                                         GL_LockArrays(0, 0);
1910                                 }
1911                                 break;
1912                         case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
1913                                 memset(&m, 0, sizeof(m));
1914                                 m.tex[0] = R_GetTexture(layer->texture);
1915                                 m.texmatrix[0] = layer->texmatrix;
1916                                 m.pointer_color = varray_color4f;
1917                                 m.texrgbscale[0] = layertexrgbscale;
1918                                 R_Mesh_State(&m);
1919                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1920                                 {
1921                                         surface = texturesurfacelist[texturesurfaceindex];
1922                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1923                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1924                                         if (lightmode == 2)
1925                                         {
1926                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1927                                                 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 2, false, false);
1928                                         }
1929                                         else if (surface->lightmaptexture)
1930                                         {
1931                                                 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1932                                                 R_Mesh_ColorPointer(NULL);
1933                                         }
1934                                         else
1935                                         {
1936                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1937                                                 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 1, false, false);
1938                                         }
1939                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1940                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1941                                         GL_LockArrays(0, 0);
1942                                 }
1943                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1944                                 memset(&m, 0, sizeof(m));
1945                                 m.tex[0] = R_GetTexture(layer->texture);
1946                                 m.texmatrix[0] = layer->texmatrix;
1947                                 m.pointer_color = varray_color4f;
1948                                 m.texrgbscale[0] = layertexrgbscale;
1949                                 R_Mesh_State(&m);
1950                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1951                                 {
1952                                         surface = texturesurfacelist[texturesurfaceindex];
1953                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1954                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1955                                         RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1956                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1957                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1958                                         GL_LockArrays(0, 0);
1959                                 }
1960                                 break;
1961                         case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
1962                                 memset(&m, 0, sizeof(m));
1963                                 m.tex[0] = R_GetTexture(layer->texture);
1964                                 m.texmatrix[0] = layer->texmatrix;
1965                                 m.texrgbscale[0] = layertexrgbscale;
1966                                 m.pointer_color = varray_color4f;
1967                                 R_Mesh_State(&m);
1968                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1969                                 {
1970                                         surface = texturesurfacelist[texturesurfaceindex];
1971                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1972                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1973                                         RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode ? lightmode : 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1974                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1975                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1976                                         GL_LockArrays(0, 0);
1977                                 }
1978                                 break;
1979                         case TEXTURELAYERTYPE_TEXTURE:
1980                                 memset(&m, 0, sizeof(m));
1981                                 m.tex[0] = R_GetTexture(layer->texture);
1982                                 m.texmatrix[0] = layer->texmatrix;
1983                                 m.pointer_color = varray_color4f;
1984                                 m.texrgbscale[0] = layertexrgbscale;
1985                                 R_Mesh_State(&m);
1986                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1987                                 {
1988                                         surface = texturesurfacelist[texturesurfaceindex];
1989                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1990                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1991                                         RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1992                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1993                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1994                                         GL_LockArrays(0, 0);
1995                                 }
1996                                 break;
1997                         case TEXTURELAYERTYPE_FOG:
1998                                 memset(&m, 0, sizeof(m));
1999                                 if (layer->texture)
2000                                 {
2001                                         m.tex[0] = R_GetTexture(layer->texture);
2002                                         m.texmatrix[0] = layer->texmatrix;
2003                                 }
2004                                 R_Mesh_State(&m);
2005                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2006                                 {
2007                                         int i;
2008                                         float f, *v, *c;
2009                                         surface = texturesurfacelist[texturesurfaceindex];
2010                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2011                                         if (layer->texture)
2012                                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2013                                         R_Mesh_ColorPointer(varray_color4f);
2014                                         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)
2015                                         {
2016                                                 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
2017                                                 c[0] = layercolor[0];
2018                                                 c[1] = layercolor[1];
2019                                                 c[2] = layercolor[2];
2020                                                 c[3] = f * layercolor[3];
2021                                         }
2022                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2023                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2024                                         GL_LockArrays(0, 0);
2025                                 }
2026                                 break;
2027                         default:
2028                                 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2029                         }
2030                         // if trying to do overbright on first pass of an opaque surface
2031                         // when combine is not supported, brighten as a post process
2032                         if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
2033                         {
2034                                 int scale;
2035                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2036                                 GL_Color(1, 1, 1, 1);
2037                                 memset(&m, 0, sizeof(m));
2038                                 R_Mesh_State(&m);
2039                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2040                                 {
2041                                         surface = texturesurfacelist[texturesurfaceindex];
2042                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2043                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2044                                         for (scale = 1;scale < layertexrgbscale;scale <<= 1)
2045                                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2046                                         GL_LockArrays(0, 0);
2047                                 }
2048                         }
2049                 }
2050         }
2051         if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
2052                 qglEnable(GL_CULL_FACE);
2053 }
2054
2055 static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
2056 {
2057         const entity_render_t *ent = (entity_render_t *)calldata1;
2058         const msurface_t *surface = ent->model->data_surfaces + calldata2;
2059         vec3_t modelorg;
2060         texture_t *texture;
2061
2062         texture = surface->texture;
2063         if (texture->basematerialflags & MATERIALFLAG_SKY)
2064                 return; // transparent sky is too difficult
2065         R_UpdateTextureInfo(ent, texture);
2066
2067         R_Mesh_Matrix(&ent->matrix);
2068         Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2069         R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2070 }
2071
2072 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2073 {
2074         int texturesurfaceindex;
2075         const msurface_t *surface;
2076         vec3_t tempcenter, center;
2077         if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2078         {
2079                 // drawing sky transparently would be too difficult
2080                 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2081                 {
2082                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2083                         {
2084                                 surface = texturesurfacelist[texturesurfaceindex];
2085                                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2086                                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2087                                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2088                                 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2089                                 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->data_surfaces);
2090                         }
2091                 }
2092         }
2093         else
2094                 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2095 }
2096
2097 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2098 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2099 {
2100         int i, j, f, flagsmask;
2101         int counttriangles = 0;
2102         msurface_t *surface, **surfacechain;
2103         texture_t *t, *texture;
2104         model_t *model = ent->model;
2105         vec3_t modelorg;
2106         const int maxsurfacelist = 1024;
2107         int numsurfacelist = 0;
2108         const msurface_t *surfacelist[1024];
2109         if (model == NULL)
2110                 return;
2111         R_Mesh_Matrix(&ent->matrix);
2112         Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2113
2114         // update light styles
2115         if (!skysurfaces && model->brushq1.light_styleupdatechains)
2116         {
2117                 for (i = 0;i < model->brushq1.light_styles;i++)
2118                 {
2119                         if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
2120                         {
2121                                 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
2122                                 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2123                                         for (;(surface = *surfacechain);surfacechain++)
2124                                                 surface->cached_dlight = true;
2125                         }
2126                 }
2127         }
2128
2129         R_UpdateAllTextureInfo(ent);
2130         flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2131         f = 0;
2132         t = NULL;
2133         texture = NULL;
2134         numsurfacelist = 0;
2135         if (ent == r_refdef.worldentity)
2136         {
2137                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2138                 {
2139                         if (!r_worldsurfacevisible[j])
2140                                 continue;
2141                         if (t != surface->texture)
2142                         {
2143                                 if (numsurfacelist)
2144                                 {
2145                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2146                                         numsurfacelist = 0;
2147                                 }
2148                                 t = surface->texture;
2149                                 texture = t->currentframe;
2150                                 f = texture->currentmaterialflags & flagsmask;
2151                         }
2152                         if (f && surface->num_triangles)
2153                         {
2154                                 // if lightmap parameters changed, rebuild lightmap texture
2155                                 if (surface->cached_dlight && surface->lightmapinfo->samples)
2156                                         R_BuildLightMap(ent, surface);
2157                                 // add face to draw list
2158                                 surfacelist[numsurfacelist++] = surface;
2159                                 counttriangles += surface->num_triangles;
2160                                 if (numsurfacelist >= maxsurfacelist)
2161                                 {
2162                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2163                                         numsurfacelist = 0;
2164                                 }
2165                         }
2166                 }
2167         }
2168         else
2169         {
2170                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2171                 {
2172                         if (t != surface->texture)
2173                         {
2174                                 if (numsurfacelist)
2175                                 {
2176                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2177                                         numsurfacelist = 0;
2178                                 }
2179                                 t = surface->texture;
2180                                 texture = t->currentframe;
2181                                 f = texture->currentmaterialflags & flagsmask;
2182                         }
2183                         if (f && surface->num_triangles)
2184                         {
2185                                 // if lightmap parameters changed, rebuild lightmap texture
2186                                 if (surface->cached_dlight && surface->lightmapinfo->samples)
2187                                         R_BuildLightMap(ent, surface);
2188                                 // add face to draw list
2189                                 surfacelist[numsurfacelist++] = surface;
2190                                 counttriangles += surface->num_triangles;
2191                                 if (numsurfacelist >= maxsurfacelist)
2192                                 {
2193                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2194                                         numsurfacelist = 0;
2195                                 }
2196                         }
2197                 }
2198         }
2199         if (numsurfacelist)
2200                 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2201         if (!r_showtrispass)
2202                 renderstats.entities_triangles += counttriangles;
2203 }
2204