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