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