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