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