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