]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
fix a line I forgot to commit
[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 #include "image.h"
26
27 mempool_t *r_main_mempool;
28 rtexturepool_t *r_main_texturepool;
29
30 //
31 // screen size info
32 //
33 r_refdef_t r_refdef;
34 r_view_t r_view;
35 r_viewcache_t r_viewcache;
36
37 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
38 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
39 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
40 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
41 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
42 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"};
43 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"};
44 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
45 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"};
46 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"};
47 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"};
48 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
49 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
50 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
51 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
52 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
53 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
54 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
55 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
56 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
57 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
58 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
59 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
60 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
61 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
62 cvar_t r_q1bsp_skymasking = {0, "r_qb1sp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
63
64 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
65 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
66 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
67 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
68 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
69 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
70 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
71
72 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)"};
73
74 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
75 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
76 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
77 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
78 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
79
80 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
81 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
82 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
83
84 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
85 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
86 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
87 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
88 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
89 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
90 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
91
92 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
93 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
94 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
95 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
96
97 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"};
98
99 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"};
100
101 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
102
103 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
104 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
105
106 typedef struct r_glsl_bloomshader_s
107 {
108         int program;
109         int loc_Texture_Bloom;
110 }
111 r_glsl_bloomshader_t;
112
113 static struct r_bloomstate_s
114 {
115         qboolean enabled;
116         qboolean hdr;
117
118         int bloomwidth, bloomheight;
119
120         int screentexturewidth, screentextureheight;
121         rtexture_t *texture_screen;
122
123         int bloomtexturewidth, bloomtextureheight;
124         rtexture_t *texture_bloom;
125
126         r_glsl_bloomshader_t *shader;
127
128         // arrays for rendering the screen passes
129         float screentexcoord2f[8];
130         float bloomtexcoord2f[8];
131         float offsettexcoord2f[8];
132 }
133 r_bloomstate;
134
135 // shadow volume bsp struct with automatically growing nodes buffer
136 svbsp_t r_svbsp;
137
138 rtexture_t *r_texture_blanknormalmap;
139 rtexture_t *r_texture_white;
140 rtexture_t *r_texture_black;
141 rtexture_t *r_texture_notexture;
142 rtexture_t *r_texture_whitecube;
143 rtexture_t *r_texture_normalizationcube;
144 rtexture_t *r_texture_fogattenuation;
145 //rtexture_t *r_texture_fogintensity;
146
147 // information about each possible shader permutation
148 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_MAX];
149 // currently selected permutation
150 r_glsl_permutation_t *r_glsl_permutation;
151
152 // vertex coordinates for a quad that covers the screen exactly
153 const static float r_screenvertex3f[12] =
154 {
155         0, 0, 0,
156         1, 0, 0,
157         1, 1, 0,
158         0, 1, 0
159 };
160
161 extern void R_DrawModelShadows(void);
162
163 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
164 {
165         int i;
166         for (i = 0;i < verts;i++)
167         {
168                 out[0] = in[0] * r;
169                 out[1] = in[1] * g;
170                 out[2] = in[2] * b;
171                 out[3] = in[3];
172                 in += 4;
173                 out += 4;
174         }
175 }
176
177 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
178 {
179         int i;
180         for (i = 0;i < verts;i++)
181         {
182                 out[0] = r;
183                 out[1] = g;
184                 out[2] = b;
185                 out[3] = a;
186                 out += 4;
187         }
188 }
189
190 // FIXME: move this to client?
191 void FOG_clear(void)
192 {
193         if (gamemode == GAME_NEHAHRA)
194         {
195                 Cvar_Set("gl_fogenable", "0");
196                 Cvar_Set("gl_fogdensity", "0.2");
197                 Cvar_Set("gl_fogred", "0.3");
198                 Cvar_Set("gl_foggreen", "0.3");
199                 Cvar_Set("gl_fogblue", "0.3");
200         }
201         r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
202 }
203
204 float FogPoint_World(const vec3_t p)
205 {
206         int fogmasktableindex = (int)(VectorDistance((p), r_view.origin) * r_refdef.fogmasktabledistmultiplier);
207         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
208 }
209
210 float FogPoint_Model(const vec3_t p)
211 {
212         int fogmasktableindex = (int)(VectorDistance((p), rsurface_modelorg) * r_refdef.fogmasktabledistmultiplier);
213         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
214 }
215
216 static void R_BuildBlankTextures(void)
217 {
218         unsigned char data[4];
219         data[0] = 128; // normal X
220         data[1] = 128; // normal Y
221         data[2] = 255; // normal Z
222         data[3] = 128; // height
223         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
224         data[0] = 255;
225         data[1] = 255;
226         data[2] = 255;
227         data[3] = 255;
228         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
229         data[0] = 0;
230         data[1] = 0;
231         data[2] = 0;
232         data[3] = 255;
233         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
234 }
235
236 static void R_BuildNoTexture(void)
237 {
238         int x, y;
239         unsigned char pix[16][16][4];
240         // this makes a light grey/dark grey checkerboard texture
241         for (y = 0;y < 16;y++)
242         {
243                 for (x = 0;x < 16;x++)
244                 {
245                         if ((y < 8) ^ (x < 8))
246                         {
247                                 pix[y][x][0] = 128;
248                                 pix[y][x][1] = 128;
249                                 pix[y][x][2] = 128;
250                                 pix[y][x][3] = 255;
251                         }
252                         else
253                         {
254                                 pix[y][x][0] = 64;
255                                 pix[y][x][1] = 64;
256                                 pix[y][x][2] = 64;
257                                 pix[y][x][3] = 255;
258                         }
259                 }
260         }
261         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
262 }
263
264 static void R_BuildWhiteCube(void)
265 {
266         unsigned char data[6*1*1*4];
267         data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
268         data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
269         data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
270         data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
271         data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
272         data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
273         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
274 }
275
276 static void R_BuildNormalizationCube(void)
277 {
278         int x, y, side;
279         vec3_t v;
280         vec_t s, t, intensity;
281 #define NORMSIZE 64
282         unsigned char data[6][NORMSIZE][NORMSIZE][4];
283         for (side = 0;side < 6;side++)
284         {
285                 for (y = 0;y < NORMSIZE;y++)
286                 {
287                         for (x = 0;x < NORMSIZE;x++)
288                         {
289                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
290                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
291                                 switch(side)
292                                 {
293                                 default:
294                                 case 0:
295                                         v[0] = 1;
296                                         v[1] = -t;
297                                         v[2] = -s;
298                                         break;
299                                 case 1:
300                                         v[0] = -1;
301                                         v[1] = -t;
302                                         v[2] = s;
303                                         break;
304                                 case 2:
305                                         v[0] = s;
306                                         v[1] = 1;
307                                         v[2] = t;
308                                         break;
309                                 case 3:
310                                         v[0] = s;
311                                         v[1] = -1;
312                                         v[2] = -t;
313                                         break;
314                                 case 4:
315                                         v[0] = s;
316                                         v[1] = -t;
317                                         v[2] = 1;
318                                         break;
319                                 case 5:
320                                         v[0] = -s;
321                                         v[1] = -t;
322                                         v[2] = -1;
323                                         break;
324                                 }
325                                 intensity = 127.0f / sqrt(DotProduct(v, v));
326                                 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
327                                 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
328                                 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
329                                 data[side][y][x][3] = 255;
330                         }
331                 }
332         }
333         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
334 }
335
336 static void R_BuildFogTexture(void)
337 {
338         int x, b;
339 #define FOGWIDTH 64
340         unsigned char data1[FOGWIDTH][4];
341         //unsigned char data2[FOGWIDTH][4];
342         for (x = 0;x < FOGWIDTH;x++)
343         {
344                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
345                 data1[x][0] = b;
346                 data1[x][1] = b;
347                 data1[x][2] = b;
348                 data1[x][3] = 255;
349                 //data2[x][0] = 255 - b;
350                 //data2[x][1] = 255 - b;
351                 //data2[x][2] = 255 - b;
352                 //data2[x][3] = 255;
353         }
354         r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
355         //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
356 }
357
358 static const char *builtinshaderstring =
359 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
360 "// written by Forest 'LordHavoc' Hale\n"
361 "\n"
362 "// common definitions between vertex shader and fragment shader:\n"
363 "\n"
364 "#ifdef __GLSL_CG_DATA_TYPES\n"
365 "#define myhalf half\n"
366 "#define myhvec2 hvec2\n"
367 "#define myhvec3 hvec3\n"
368 "#define myhvec4 hvec4\n"
369 "#else\n"
370 "#define myhalf float\n"
371 "#define myhvec2 vec2\n"
372 "#define myhvec3 vec3\n"
373 "#define myhvec4 vec4\n"
374 "#endif\n"
375 "\n"
376 "varying vec2 TexCoord;\n"
377 "varying vec2 TexCoordLightmap;\n"
378 "\n"
379 "varying vec3 CubeVector;\n"
380 "varying vec3 LightVector;\n"
381 "varying vec3 EyeVector;\n"
382 "#ifdef USEFOG\n"
383 "varying vec3 EyeVectorModelSpace;\n"
384 "#endif\n"
385 "\n"
386 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
387 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
388 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
389 "\n"
390 "\n"
391 "\n"
392 "\n"
393 "// vertex shader specific:\n"
394 "#ifdef VERTEX_SHADER\n"
395 "\n"
396 "uniform vec3 LightPosition;\n"
397 "uniform vec3 EyePosition;\n"
398 "uniform vec3 LightDir;\n"
399 "\n"
400 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
401 "\n"
402 "void main(void)\n"
403 "{\n"
404 "       gl_FrontColor = gl_Color;\n"
405 "       // copy the surface texcoord\n"
406 "       TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
407 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
408 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
409 "#endif\n"
410 "\n"
411 "#ifdef MODE_LIGHTSOURCE\n"
412 "       // transform vertex position into light attenuation/cubemap space\n"
413 "       // (-1 to +1 across the light box)\n"
414 "       CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
415 "\n"
416 "       // transform unnormalized light direction into tangent space\n"
417 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
418 "       //  normalize it per pixel)\n"
419 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
420 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
421 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
422 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
423 "#endif\n"
424 "\n"
425 "#ifdef MODE_LIGHTDIRECTION\n"
426 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
427 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
428 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
429 "#endif\n"
430 "\n"
431 "       // transform unnormalized eye direction into tangent space\n"
432 "#ifndef USEFOG\n"
433 "       vec3 EyeVectorModelSpace;\n"
434 "#endif\n"
435 "       EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
436 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
437 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
438 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
439 "\n"
440 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
441 "       VectorS = gl_MultiTexCoord1.xyz;\n"
442 "       VectorT = gl_MultiTexCoord2.xyz;\n"
443 "       VectorR = gl_MultiTexCoord3.xyz;\n"
444 "#endif\n"
445 "\n"
446 "       // transform vertex to camera space, using ftransform to match non-VS\n"
447 "       // rendering\n"
448 "       gl_Position = ftransform();\n"
449 "}\n"
450 "\n"
451 "#endif // VERTEX_SHADER\n"
452 "\n"
453 "\n"
454 "\n"
455 "\n"
456 "// fragment shader specific:\n"
457 "#ifdef FRAGMENT_SHADER\n"
458 "\n"
459 "// 11 textures, we can only use up to 16 on DX9-class hardware\n"
460 "uniform sampler2D Texture_Normal;\n"
461 "uniform sampler2D Texture_Color;\n"
462 "uniform sampler2D Texture_Gloss;\n"
463 "uniform samplerCube Texture_Cube;\n"
464 "uniform sampler2D Texture_Attenuation;\n"
465 "uniform sampler2D Texture_FogMask;\n"
466 "uniform sampler2D Texture_Pants;\n"
467 "uniform sampler2D Texture_Shirt;\n"
468 "uniform sampler2D Texture_Lightmap;\n"
469 "uniform sampler2D Texture_Deluxemap;\n"
470 "uniform sampler2D Texture_Glow;\n"
471 "\n"
472 "uniform myhvec3 LightColor;\n"
473 "uniform myhvec3 AmbientColor;\n"
474 "uniform myhvec3 DiffuseColor;\n"
475 "uniform myhvec3 SpecularColor;\n"
476 "uniform myhvec3 Color_Pants;\n"
477 "uniform myhvec3 Color_Shirt;\n"
478 "uniform myhvec3 FogColor;\n"
479 "\n"
480 "uniform myhalf GlowScale;\n"
481 "uniform myhalf SceneBrightness;\n"
482 "\n"
483 "uniform float OffsetMapping_Scale;\n"
484 "uniform float OffsetMapping_Bias;\n"
485 "uniform float FogRangeRecip;\n"
486 "\n"
487 "uniform myhalf AmbientScale;\n"
488 "uniform myhalf DiffuseScale;\n"
489 "uniform myhalf SpecularScale;\n"
490 "uniform myhalf SpecularPower;\n"
491 "\n"
492 "#ifdef USEOFFSETMAPPING\n"
493 "vec2 OffsetMapping(vec2 TexCoord)\n"
494 "{\n"
495 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
496 "       // 14 sample relief mapping: linear search and then binary search\n"
497 "       // this basically steps forward a small amount repeatedly until it finds\n"
498 "       // itself inside solid, then jitters forward and back using decreasing\n"
499 "       // amounts to find the impact\n"
500 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
501 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
502 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
503 "       vec3 RT = vec3(TexCoord, 1);\n"
504 "       OffsetVector *= 0.1;\n"
505 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
506 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
507 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
508 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
509 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
510 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
511 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
512 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
513 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
514 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
515 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
516 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
517 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
518 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
519 "       return RT.xy;\n"
520 "#else\n"
521 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
522 "       // this basically moves forward the full distance, and then backs up based\n"
523 "       // on height of samples\n"
524 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
525 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
526 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
527 "       TexCoord += OffsetVector;\n"
528 "       OffsetVector *= 0.333;\n"
529 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
530 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
531 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
532 "       return TexCoord;\n"
533 "#endif\n"
534 "}\n"
535 "#endif\n"
536 "\n"
537 "void main(void)\n"
538 "{\n"
539 "#ifdef USEOFFSETMAPPING\n"
540 "       // apply offsetmapping\n"
541 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
542 "#define TexCoord TexCoordOffset\n"
543 "#endif\n"
544 "\n"
545 "       // combine the diffuse textures (base, pants, shirt)\n"
546 "       myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
547 "#ifdef USECOLORMAPPING\n"
548 "       color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
549 "#endif\n"
550 "\n"
551 "\n"
552 "\n"
553 "\n"
554 "#ifdef MODE_LIGHTSOURCE\n"
555 "       // light source\n"
556 "\n"
557 "       // calculate surface normal, light normal, and specular normal\n"
558 "       // compute color intensity for the two textures (colormap and glossmap)\n"
559 "       // scale by light color and attenuation as efficiently as possible\n"
560 "       // (do as much scalar math as possible rather than vector math)\n"
561 "#ifdef USESPECULAR\n"
562 "       myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
563 "       myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
564 "       myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
565 "\n"
566 "       // calculate directional shading\n"
567 "       color.rgb = LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * myhvec3(texture2D(Texture_Gloss, TexCoord)));\n"
568 "#else\n"
569 "#ifdef USEDIFFUSE\n"
570 "       myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
571 "       myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
572 "\n"
573 "       // calculate directional shading\n"
574 "       color.rgb = color.rgb * LightColor * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
575 "#else\n"
576 "       // calculate directionless shading\n"
577 "       color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
578 "#endif\n"
579 "#endif\n"
580 "\n"
581 "#ifdef USECUBEFILTER\n"
582 "       // apply light cubemap filter\n"
583 "       //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
584 "       color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
585 "#endif\n"
586 "\n"
587 "\n"
588 "\n"
589 "\n"
590 "#elif defined(MODE_LIGHTDIRECTION)\n"
591 "       // directional model lighting\n"
592 "\n"
593 "       // get the surface normal and light normal\n"
594 "       myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
595 "       myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
596 "\n"
597 "       // calculate directional shading\n"
598 "       color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
599 "#ifdef USESPECULAR\n"
600 "       myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
601 "       color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
602 "#endif\n"
603 "\n"
604 "\n"
605 "\n"
606 "\n"
607 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
608 "       // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
609 "\n"
610 "       // get the surface normal and light normal\n"
611 "       myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
612 "\n"
613 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
614 "       myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
615 "       myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
616 "#else\n"
617 "       myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
618 "#endif\n"
619 "       // calculate directional shading\n"
620 "       myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
621 "#ifdef USESPECULAR\n"
622 "       myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
623 "       tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
624 "#endif\n"
625 "\n"
626 "       // apply lightmap color\n"
627 "       color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * AmbientScale;\n"
628 "\n"
629 "\n"
630 "#else // MODE none (lightmap)\n"
631 "       // apply lightmap color\n"
632 "       color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
633 "#endif // MODE\n"
634 "\n"
635 "       color *= myhvec4(gl_Color);\n"
636 "\n"
637 "#ifdef USEGLOW\n"
638 "       color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
639 "#endif\n"
640 "\n"
641 "#ifdef USEFOG\n"
642 "       // apply fog\n"
643 "       color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
644 "#endif\n"
645 "\n"
646 "       color.rgb *= SceneBrightness;\n"
647 "\n"
648 "       gl_FragColor = vec4(color);\n"
649 "}\n"
650 "\n"
651 "#endif // FRAGMENT_SHADER\n"
652 ;
653
654 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
655 const char *permutationinfo[][2] =
656 {
657         {"#define MODE_LIGHTSOURCE\n", " lightsource"},
658         {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
659         {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
660         {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
661         {"#define USEGLOW\n", " glow"},
662         {"#define USEFOG\n", " fog"},
663         {"#define USECOLORMAPPING\n", " colormapping"},
664         {"#define USEDIFFUSE\n", " diffuse"},
665         {"#define USESPECULAR\n", " specular"},
666         {"#define USECUBEFILTER\n", " cubefilter"},
667         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
668         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
669         {NULL, NULL}
670 };
671
672 void R_GLSL_CompilePermutation(const char *filename, int permutation)
673 {
674         int i;
675         qboolean shaderfound;
676         r_glsl_permutation_t *p = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
677         int vertstrings_count;
678         int geomstrings_count;
679         int fragstrings_count;
680         char *shaderstring;
681         const char *vertstrings_list[32+1];
682         const char *geomstrings_list[32+1];
683         const char *fragstrings_list[32+1];
684         char permutationname[256];
685         if (p->compiled)
686                 return;
687         p->compiled = true;
688         p->program = 0;
689         vertstrings_list[0] = "#define VERTEX_SHADER\n";
690         geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
691         fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
692         vertstrings_count = 1;
693         geomstrings_count = 1;
694         fragstrings_count = 1;
695         permutationname[0] = 0;
696         for (i = 0;permutationinfo[i][0];i++)
697         {
698                 if (permutation & (1<<i))
699                 {
700                         vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
701                         geomstrings_list[geomstrings_count++] = permutationinfo[i][0];
702                         fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
703                         strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
704                 }
705                 else
706                 {
707                         // keep line numbers correct
708                         vertstrings_list[vertstrings_count++] = "\n";
709                         geomstrings_list[geomstrings_count++] = "\n";
710                         fragstrings_list[fragstrings_count++] = "\n";
711                 }
712         }
713         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
714         shaderfound = false;
715         if (shaderstring)
716         {
717                 Con_DPrintf("GLSL shader text for \"%s\" loaded from disk\n", filename);
718                 vertstrings_list[vertstrings_count++] = shaderstring;
719                 geomstrings_list[geomstrings_count++] = shaderstring;
720                 fragstrings_list[fragstrings_count++] = shaderstring;
721                 shaderfound = true;
722         }
723         else if (!strcmp(filename, "glsl/default.glsl"))
724         {
725                 Con_DPrintf("GLSL shader text for \"%s\" loaded from engine\n", filename);
726                 vertstrings_list[vertstrings_count++] = builtinshaderstring;
727                 geomstrings_list[geomstrings_count++] = builtinshaderstring;
728                 fragstrings_list[fragstrings_count++] = builtinshaderstring;
729                 shaderfound = true;
730         }
731         // clear any lists that are not needed by this shader
732         if (!(permutation & SHADERPERMUTATION_USES_VERTEXSHADER))
733                 vertstrings_count = 0;
734         if (!(permutation & SHADERPERMUTATION_USES_GEOMETRYSHADER))
735                 geomstrings_count = 0;
736         if (!(permutation & SHADERPERMUTATION_USES_FRAGMENTSHADER))
737                 fragstrings_count = 0;
738         // compile the shader program
739         if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
740                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
741         if (p->program)
742         {
743                 CHECKGLERROR
744                 qglUseProgramObjectARB(p->program);CHECKGLERROR
745                 // look up all the uniform variable names we care about, so we don't
746                 // have to look them up every time we set them
747                 p->loc_Texture_Normal      = qglGetUniformLocationARB(p->program, "Texture_Normal");
748                 p->loc_Texture_Color       = qglGetUniformLocationARB(p->program, "Texture_Color");
749                 p->loc_Texture_Gloss       = qglGetUniformLocationARB(p->program, "Texture_Gloss");
750                 p->loc_Texture_Cube        = qglGetUniformLocationARB(p->program, "Texture_Cube");
751                 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
752                 p->loc_Texture_FogMask     = qglGetUniformLocationARB(p->program, "Texture_FogMask");
753                 p->loc_Texture_Pants       = qglGetUniformLocationARB(p->program, "Texture_Pants");
754                 p->loc_Texture_Shirt       = qglGetUniformLocationARB(p->program, "Texture_Shirt");
755                 p->loc_Texture_Lightmap    = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
756                 p->loc_Texture_Deluxemap   = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
757                 p->loc_Texture_Glow        = qglGetUniformLocationARB(p->program, "Texture_Glow");
758                 p->loc_FogColor            = qglGetUniformLocationARB(p->program, "FogColor");
759                 p->loc_LightPosition       = qglGetUniformLocationARB(p->program, "LightPosition");
760                 p->loc_EyePosition         = qglGetUniformLocationARB(p->program, "EyePosition");
761                 p->loc_LightColor          = qglGetUniformLocationARB(p->program, "LightColor");
762                 p->loc_Color_Pants         = qglGetUniformLocationARB(p->program, "Color_Pants");
763                 p->loc_Color_Shirt         = qglGetUniformLocationARB(p->program, "Color_Shirt");
764                 p->loc_FogRangeRecip       = qglGetUniformLocationARB(p->program, "FogRangeRecip");
765                 p->loc_AmbientScale        = qglGetUniformLocationARB(p->program, "AmbientScale");
766                 p->loc_DiffuseScale        = qglGetUniformLocationARB(p->program, "DiffuseScale");
767                 p->loc_SpecularPower       = qglGetUniformLocationARB(p->program, "SpecularPower");
768                 p->loc_SpecularScale       = qglGetUniformLocationARB(p->program, "SpecularScale");
769                 p->loc_GlowScale           = qglGetUniformLocationARB(p->program, "GlowScale");
770                 p->loc_SceneBrightness     = qglGetUniformLocationARB(p->program, "SceneBrightness");
771                 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
772                 p->loc_AmbientColor        = qglGetUniformLocationARB(p->program, "AmbientColor");
773                 p->loc_DiffuseColor        = qglGetUniformLocationARB(p->program, "DiffuseColor");
774                 p->loc_SpecularColor       = qglGetUniformLocationARB(p->program, "SpecularColor");
775                 p->loc_LightDir            = qglGetUniformLocationARB(p->program, "LightDir");
776                 // initialize the samplers to refer to the texture units we use
777                 if (p->loc_Texture_Normal >= 0)    qglUniform1iARB(p->loc_Texture_Normal, 0);
778                 if (p->loc_Texture_Color >= 0)     qglUniform1iARB(p->loc_Texture_Color, 1);
779                 if (p->loc_Texture_Gloss >= 0)     qglUniform1iARB(p->loc_Texture_Gloss, 2);
780                 if (p->loc_Texture_Cube >= 0)      qglUniform1iARB(p->loc_Texture_Cube, 3);
781                 if (p->loc_Texture_FogMask >= 0)   qglUniform1iARB(p->loc_Texture_FogMask, 4);
782                 if (p->loc_Texture_Pants >= 0)     qglUniform1iARB(p->loc_Texture_Pants, 5);
783                 if (p->loc_Texture_Shirt >= 0)     qglUniform1iARB(p->loc_Texture_Shirt, 6);
784                 if (p->loc_Texture_Lightmap >= 0)  qglUniform1iARB(p->loc_Texture_Lightmap, 7);
785                 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
786                 if (p->loc_Texture_Glow >= 0)      qglUniform1iARB(p->loc_Texture_Glow, 9);
787                 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
788                 CHECKGLERROR
789                 qglUseProgramObjectARB(0);CHECKGLERROR
790         }
791         else
792                 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
793         if (shaderstring)
794                 Mem_Free(shaderstring);
795 }
796
797 void R_GLSL_Restart_f(void)
798 {
799         int i;
800         for (i = 0;i < SHADERPERMUTATION_MAX;i++)
801                 if (r_glsl_permutations[i].program)
802                         GL_Backend_FreeProgram(r_glsl_permutations[i].program);
803         memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
804 }
805
806 extern rtexture_t *r_shadow_attenuationgradienttexture;
807 extern rtexture_t *r_shadow_attenuation2dtexture;
808 extern rtexture_t *r_shadow_attenuation3dtexture;
809 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale)
810 {
811         // select a permutation of the lighting shader appropriate to this
812         // combination of texture, entity, light source, and fogging, only use the
813         // minimum features necessary to avoid wasting rendering time in the
814         // fragment shader on features that are not being used
815         const char *shaderfilename = NULL;
816         unsigned int permutation = 0;
817         r_glsl_permutation = NULL;
818         // TODO: implement geometry-shader based shadow volumes someday
819         if (r_shadow_rtlight)
820         {
821                 // light source
822                 shaderfilename = "glsl/default.glsl";
823                 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
824                 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
825                         permutation |= SHADERPERMUTATION_CUBEFILTER;
826                 if (diffusescale > 0)
827                         permutation |= SHADERPERMUTATION_DIFFUSE;
828                 if (specularscale > 0)
829                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
830                 if (r_refdef.fogenabled)
831                         permutation |= SHADERPERMUTATION_FOG;
832                 if (rsurface_texture->colormapping)
833                         permutation |= SHADERPERMUTATION_COLORMAPPING;
834                 if (r_glsl_offsetmapping.integer)
835                 {
836                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
837                         if (r_glsl_offsetmapping_reliefmapping.integer)
838                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
839                 }
840         }
841         else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
842         {
843                 // bright unshaded geometry
844                 shaderfilename = "glsl/default.glsl";
845                 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
846                 if (rsurface_texture->currentskinframe->glow)
847                         permutation |= SHADERPERMUTATION_GLOW;
848                 if (r_refdef.fogenabled)
849                         permutation |= SHADERPERMUTATION_FOG;
850                 if (rsurface_texture->colormapping)
851                         permutation |= SHADERPERMUTATION_COLORMAPPING;
852                 if (r_glsl_offsetmapping.integer)
853                 {
854                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
855                         if (r_glsl_offsetmapping_reliefmapping.integer)
856                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
857                 }
858         }
859         else if (modellighting)
860         {
861                 // directional model lighting
862                 shaderfilename = "glsl/default.glsl";
863                 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
864                 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
865                 if (rsurface_texture->currentskinframe->glow)
866                         permutation |= SHADERPERMUTATION_GLOW;
867                 if (specularscale > 0)
868                         permutation |= SHADERPERMUTATION_SPECULAR;
869                 if (r_refdef.fogenabled)
870                         permutation |= SHADERPERMUTATION_FOG;
871                 if (rsurface_texture->colormapping)
872                         permutation |= SHADERPERMUTATION_COLORMAPPING;
873                 if (r_glsl_offsetmapping.integer)
874                 {
875                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
876                         if (r_glsl_offsetmapping_reliefmapping.integer)
877                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
878                 }
879         }
880         else
881         {
882                 // lightmapped wall
883                 shaderfilename = "glsl/default.glsl";
884                 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
885                 if (r_glsl_deluxemapping.integer >= 1 && rsurface_lightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
886                 {
887                         // deluxemapping (light direction texture)
888                         if (rsurface_lightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
889                                 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
890                         else
891                                 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
892                         if (specularscale > 0)
893                                 permutation |= SHADERPERMUTATION_SPECULAR;
894                 }
895                 else if (r_glsl_deluxemapping.integer >= 2)
896                 {
897                         // fake deluxemapping (uniform light direction in tangentspace)
898                         permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
899                         if (specularscale > 0)
900                                 permutation |= SHADERPERMUTATION_SPECULAR;
901                 }
902                 else
903                 {
904                         // ordinary lightmapping
905                         permutation |= 0;
906                 }
907                 if (rsurface_texture->currentskinframe->glow)
908                         permutation |= SHADERPERMUTATION_GLOW;
909                 if (r_refdef.fogenabled)
910                         permutation |= SHADERPERMUTATION_FOG;
911                 if (rsurface_texture->colormapping)
912                         permutation |= SHADERPERMUTATION_COLORMAPPING;
913                 if (r_glsl_offsetmapping.integer)
914                 {
915                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
916                         if (r_glsl_offsetmapping_reliefmapping.integer)
917                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
918                 }
919         }
920         if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
921         {
922                 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
923                         R_GLSL_CompilePermutation(shaderfilename, permutation);
924                 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
925                 {
926                         // remove features until we find a valid permutation
927                         unsigned int i;
928                         for (i = SHADERPERMUTATION_MASK;;i>>=1)
929                         {
930                                 if (!i)
931                                         return 0; // utterly failed
932                                 // reduce i more quickly whenever it would not remove any bits
933                                 if (permutation < i)
934                                         continue;
935                                 permutation &= i;
936                                 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
937                                         R_GLSL_CompilePermutation(shaderfilename, permutation);
938                                 if (r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
939                                         break;
940                         }
941                 }
942         }
943         r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
944         CHECKGLERROR
945         qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
946         R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
947         if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
948         {
949                 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
950                 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, r_shadow_entitylightorigin[0], r_shadow_entitylightorigin[1], r_shadow_entitylightorigin[2]);
951                 if (permutation & SHADERPERMUTATION_DIFFUSE)
952                 {
953                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
954                         if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
955                         if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
956                         if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
957                 }
958                 else
959                 {
960                         // ambient only is simpler
961                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
962                         if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
963                         if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
964                         if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
965                 }
966         }
967         else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
968         {
969                 if (r_glsl_permutation->loc_AmbientColor >= 0)
970                         qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0] * ambientscale, rsurface_entity->modellight_ambient[1] * ambientscale, rsurface_entity->modellight_ambient[2] * ambientscale);
971                 if (r_glsl_permutation->loc_DiffuseColor >= 0)
972                         qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0] * diffusescale, rsurface_entity->modellight_diffuse[1] * diffusescale, rsurface_entity->modellight_diffuse[2] * diffusescale);
973                 if (r_glsl_permutation->loc_SpecularColor >= 0)
974                         qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface_entity->modellight_diffuse[0] * specularscale, rsurface_entity->modellight_diffuse[1] * specularscale, rsurface_entity->modellight_diffuse[2] * specularscale);
975                 if (r_glsl_permutation->loc_LightDir >= 0)
976                         qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
977         }
978         else
979         {
980                 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
981                 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
982                 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
983         }
984         if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->currentskinframe->nmap));
985         if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
986         if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
987         //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
988         if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(10, R_GetTexture(r_shadow_attenuationgradienttexture));
989         if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
990         if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->currentskinframe->pants));
991         if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->currentskinframe->shirt));
992         //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
993         //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
994         if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->currentskinframe->glow));
995         if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
996         if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
997         if (r_glsl_permutation->loc_FogColor >= 0)
998         {
999                 // additive passes are only darkened by fog, not tinted
1000                 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
1001                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1002                 else
1003                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1004         }
1005         if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
1006         if (r_glsl_permutation->loc_Color_Pants >= 0)
1007         {
1008                 if (rsurface_texture->currentskinframe->pants)
1009                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
1010                 else
1011                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1012         }
1013         if (r_glsl_permutation->loc_Color_Shirt >= 0)
1014         {
1015                 if (rsurface_texture->currentskinframe->shirt)
1016                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
1017                 else
1018                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1019         }
1020         if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1021         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
1022         if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1023         CHECKGLERROR
1024         return permutation;
1025 }
1026
1027 void R_SwitchSurfaceShader(int permutation)
1028 {
1029         if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK))
1030         {
1031                 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1032                 CHECKGLERROR
1033                 qglUseProgramObjectARB(r_glsl_permutation->program);
1034                 CHECKGLERROR
1035         }
1036 }
1037
1038 #define SKINFRAME_HASH 1024
1039
1040 struct
1041 {
1042         int loadsequence; // incremented each level change
1043         memexpandablearray_t array;
1044         skinframe_t *hash[SKINFRAME_HASH];
1045 }
1046 r_skinframe;
1047
1048 void R_SkinFrame_PrepareForPurge(void)
1049 {
1050         r_skinframe.loadsequence++;
1051         // wrap it without hitting zero
1052         if (r_skinframe.loadsequence >= 200)
1053                 r_skinframe.loadsequence = 1;
1054 }
1055
1056 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1057 {
1058         // mark the skinframe as used for the purging code
1059         skinframe->loadsequence = r_skinframe.loadsequence;
1060 }
1061
1062 void R_SkinFrame_Purge(void)
1063 {
1064         int i;
1065         skinframe_t *s;
1066         for (i = 0;i < SKINFRAME_HASH;i++)
1067         {
1068                 for (s = r_skinframe.hash[i];s;s = s->next)
1069                 {
1070                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1071                         {
1072                                 if (s->base == r_texture_notexture)     s->base   = NULL;
1073                                 if (s->nmap == r_texture_blanknormalmap)s->nmap   = NULL;
1074                                 if (s->merged == s->base)               s->merged = NULL;
1075                                 if (s->stain ) R_FreeTexture(s->stain );s->stain  = NULL;
1076                                 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1077                                 if (s->base  ) R_FreeTexture(s->base  );s->base   = NULL;
1078                                 if (s->pants ) R_FreeTexture(s->pants );s->pants  = NULL;
1079                                 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt  = NULL;
1080                                 if (s->nmap  ) R_FreeTexture(s->nmap  );s->nmap   = NULL;
1081                                 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss  = NULL;
1082                                 if (s->glow  ) R_FreeTexture(s->glow  );s->glow   = NULL;
1083                                 if (s->fog   ) R_FreeTexture(s->fog   );s->fog    = NULL;
1084                                 s->loadsequence = 0;
1085                         }
1086                 }
1087         }
1088 }
1089
1090 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1091 {
1092         skinframe_t *item;
1093         int hashindex;
1094         char basename[MAX_QPATH];
1095
1096         Image_StripImageExtension(name, basename, sizeof(basename));
1097
1098         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1099         for (item = r_skinframe.hash[hashindex];item;item = item->next)
1100                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1101                         break;
1102         if (!item)
1103         {
1104                 if (!add)
1105                         return NULL;
1106                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1107                 memset(item, 0, sizeof(*item));
1108                 strlcpy(item->basename, basename, sizeof(item->basename));
1109                 item->textureflags = textureflags;
1110                 item->comparewidth = comparewidth;
1111                 item->compareheight = compareheight;
1112                 item->comparecrc = comparecrc;
1113                 item->next = r_skinframe.hash[hashindex];
1114                 r_skinframe.hash[hashindex] = item;
1115         }
1116         R_SkinFrame_MarkUsed(item);
1117         return item;
1118 }
1119
1120 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags)
1121 {
1122         // FIXME: it should be possible to disable loading various layers using
1123         // cvars, to prevent wasted loading time and memory usage if the user does
1124         // not want them
1125         qboolean loadnormalmap = true;
1126         qboolean loadgloss = true;
1127         qboolean loadpantsandshirt = true;
1128         qboolean loadglow = true;
1129         int j;
1130         unsigned char *pixels;
1131         unsigned char *bumppixels;
1132         unsigned char *basepixels = NULL;
1133         int basepixels_width;
1134         int basepixels_height;
1135         skinframe_t *skinframe;
1136
1137         if (cls.state == ca_dedicated)
1138                 return NULL;
1139
1140         // return an existing skinframe if already loaded
1141         // if loading of the first image fails, don't make a new skinframe as it
1142         // would cause all future lookups of this to be missing
1143         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1144         if (skinframe && skinframe->base)
1145                 return skinframe;
1146
1147         basepixels = loadimagepixels(name, false, 0, 0);
1148         if (basepixels == NULL)
1149                 return NULL;
1150
1151         // we've got some pixels to store, so really allocate this new texture now
1152         if (!skinframe)
1153                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1154         skinframe->stain = NULL;
1155         skinframe->merged = NULL;
1156         skinframe->base = r_texture_notexture;
1157         skinframe->pants = NULL;
1158         skinframe->shirt = NULL;
1159         skinframe->nmap = r_texture_blanknormalmap;
1160         skinframe->gloss = NULL;
1161         skinframe->glow = NULL;
1162         skinframe->fog = NULL;
1163
1164         basepixels_width = image_width;
1165         basepixels_height = image_height;
1166         skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1167
1168         if (textureflags & TEXF_ALPHA)
1169         {
1170                 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1171                         if (basepixels[j] < 255)
1172                                 break;
1173                 if (j < basepixels_width * basepixels_height * 4)
1174                 {
1175                         // has transparent pixels
1176                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1177                         for (j = 0;j < image_width * image_height * 4;j += 4)
1178                         {
1179                                 pixels[j+0] = 255;
1180                                 pixels[j+1] = 255;
1181                                 pixels[j+2] = 255;
1182                                 pixels[j+3] = basepixels[j+3];
1183                         }
1184                         skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1185                         Mem_Free(pixels);
1186                 }
1187         }
1188
1189         // _norm is the name used by tenebrae and has been adopted as standard
1190         if (loadnormalmap)
1191         {
1192                 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0)) != NULL)
1193                 {
1194                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1195                         Mem_Free(pixels);
1196                         pixels = NULL;
1197                 }
1198                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0)) != NULL)
1199                 {
1200                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1201                         Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1202                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1203                         Mem_Free(pixels);
1204                         Mem_Free(bumppixels);
1205                 }
1206                 else if (r_shadow_bumpscale_basetexture.value > 0)
1207                 {
1208                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1209                         Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1210                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1211                         Mem_Free(pixels);
1212                 }
1213         }
1214         // _luma is supported for tenebrae compatibility
1215         // (I think it's a very stupid name, but oh well)
1216         // _glow is the preferred name
1217         if (loadglow          && ((pixels = loadimagepixels(va("%s_glow", skinframe->basename), false, 0, 0)) != NULL || (pixels = loadimagepixels(va("%s_luma", skinframe->basename), false, 0, 0)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);Mem_Free(pixels);pixels = NULL;}
1218         if (loadgloss         && (pixels = loadimagepixels(va("%s_gloss", skinframe->basename), false, 0, 0)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);Mem_Free(pixels);pixels = NULL;}
1219         if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_pants", skinframe->basename), false, 0, 0)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);Mem_Free(pixels);pixels = NULL;}
1220         if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_shirt", skinframe->basename), false, 0, 0)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);Mem_Free(pixels);pixels = NULL;}
1221
1222         if (basepixels)
1223                 Mem_Free(basepixels);
1224
1225         return skinframe;
1226 }
1227
1228 static rtexture_t *R_SkinFrame_TextureForSkinLayer(const unsigned char *in, int width, int height, const char *name, const unsigned int *palette, int textureflags, qboolean force)
1229 {
1230         int i;
1231         if (!force)
1232         {
1233                 for (i = 0;i < width*height;i++)
1234                         if (((unsigned char *)&palette[in[i]])[3] > 0)
1235                                 break;
1236                 if (i == width*height)
1237                         return NULL;
1238         }
1239         return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1240 }
1241
1242 skinframe_t *R_SkinFrame_LoadInternal(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height, int bitsperpixel, const unsigned int *palette, const unsigned int *alphapalette)
1243 {
1244         int i;
1245         unsigned char *temp1, *temp2;
1246         skinframe_t *skinframe;
1247
1248         if (cls.state == ca_dedicated)
1249                 return NULL;
1250
1251         // if already loaded just return it, otherwise make a new skinframe
1252         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1253         if (skinframe && skinframe->base)
1254                 return skinframe;
1255
1256         skinframe->stain = NULL;
1257         skinframe->merged = NULL;
1258         skinframe->base = r_texture_notexture;
1259         skinframe->pants = NULL;
1260         skinframe->shirt = NULL;
1261         skinframe->nmap = r_texture_blanknormalmap;
1262         skinframe->gloss = NULL;
1263         skinframe->glow = NULL;
1264         skinframe->fog = NULL;
1265
1266         // if no data was provided, then clearly the caller wanted to get a blank skinframe
1267         if (!skindata)
1268                 return NULL;
1269
1270         if (bitsperpixel == 32)
1271         {
1272                 if (r_shadow_bumpscale_basetexture.value > 0)
1273                 {
1274                         temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1275                         temp2 = temp1 + width * height * 4;
1276                         Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1277                         skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL);
1278                         Mem_Free(temp1);
1279                 }
1280                 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, textureflags, NULL);
1281                 if (textureflags & TEXF_ALPHA)
1282                 {
1283                         for (i = 3;i < width * height * 4;i += 4)
1284                                 if (skindata[i] < 255)
1285                                         break;
1286                         if (i < width * height * 4)
1287                         {
1288                                 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1289                                 memcpy(fogpixels, skindata, width * height * 4);
1290                                 for (i = 0;i < width * height * 4;i += 4)
1291                                         fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1292                                 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, textureflags, NULL);
1293                                 Mem_Free(fogpixels);
1294                         }
1295                 }
1296         }
1297         else if (bitsperpixel == 8)
1298         {
1299                 if (r_shadow_bumpscale_basetexture.value > 0)
1300                 {
1301                         temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1302                         temp2 = temp1 + width * height * 4;
1303                         if (bitsperpixel == 32)
1304                                 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1305                         else
1306                         {
1307                                 // use either a custom palette or the quake palette
1308                                 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1309                                 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1310                         }
1311                         skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL);
1312                         Mem_Free(temp1);
1313                 }
1314                 // use either a custom palette, or the quake palette
1315                 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette ? palette : (loadglowtexture ? palette_nofullbrights : ((textureflags & TEXF_ALPHA) ? palette_transparent : palette_complete)), textureflags, true); // all
1316                 if (!palette && loadglowtexture)
1317                         skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, textureflags, false); // glow
1318                 if (!palette && loadpantsandshirt)
1319                 {
1320                         skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, textureflags, false); // pants
1321                         skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, textureflags, false); // shirt
1322                 }
1323                 if (skinframe->pants || skinframe->shirt)
1324                         skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, textureflags, false); // no special colors
1325                 if (textureflags & TEXF_ALPHA)
1326                 {
1327                         // if not using a custom alphapalette, use the quake one
1328                         if (!alphapalette)
1329                                 alphapalette = palette_alpha;
1330                         for (i = 0;i < width * height;i++)
1331                                 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1332                                         break;
1333                         if (i < width * height)
1334                                 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, textureflags, true); // fog mask
1335                 }
1336         }
1337
1338         return skinframe;
1339 }
1340
1341 skinframe_t *R_SkinFrame_LoadMissing(void)
1342 {
1343         skinframe_t *skinframe;
1344
1345         if (cls.state == ca_dedicated)
1346                 return NULL;
1347
1348         skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1349         skinframe->stain = NULL;
1350         skinframe->merged = NULL;
1351         skinframe->base = r_texture_notexture;
1352         skinframe->pants = NULL;
1353         skinframe->shirt = NULL;
1354         skinframe->nmap = r_texture_blanknormalmap;
1355         skinframe->gloss = NULL;
1356         skinframe->glow = NULL;
1357         skinframe->fog = NULL;
1358
1359         return skinframe;
1360 }
1361
1362 void gl_main_start(void)
1363 {
1364         int x;
1365         double r, alpha;
1366
1367         r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1368         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1369         {
1370                 alpha = 1 - exp(r / ((double)x*(double)x));
1371                 if (x == FOGMASKTABLEWIDTH - 1)
1372                         alpha = 0;
1373                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1374         }
1375
1376         // set up r_skinframe loading system for textures
1377         memset(&r_skinframe, 0, sizeof(r_skinframe));
1378         r_skinframe.loadsequence = 1;
1379         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1380
1381         r_main_texturepool = R_AllocTexturePool();
1382         R_BuildBlankTextures();
1383         R_BuildNoTexture();
1384         if (gl_texturecubemap)
1385         {
1386                 R_BuildWhiteCube();
1387                 R_BuildNormalizationCube();
1388         }
1389         R_BuildFogTexture();
1390         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1391         memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1392         memset(&r_svbsp, 0, sizeof (r_svbsp));
1393 }
1394
1395 void gl_main_shutdown(void)
1396 {
1397         // clear out the r_skinframe state
1398         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1399         memset(&r_skinframe, 0, sizeof(r_skinframe));
1400
1401         if (r_svbsp.nodes)
1402                 Mem_Free(r_svbsp.nodes);
1403         memset(&r_svbsp, 0, sizeof (r_svbsp));
1404         R_FreeTexturePool(&r_main_texturepool);
1405         r_texture_blanknormalmap = NULL;
1406         r_texture_white = NULL;
1407         r_texture_black = NULL;
1408         r_texture_whitecube = NULL;
1409         r_texture_normalizationcube = NULL;
1410         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1411         R_GLSL_Restart_f();
1412 }
1413
1414 extern void CL_ParseEntityLump(char *entitystring);
1415 void gl_main_newmap(void)
1416 {
1417         // FIXME: move this code to client
1418         int l;
1419         char *entities, entname[MAX_QPATH];
1420         if (cl.worldmodel)
1421         {
1422                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1423                 l = (int)strlen(entname) - 4;
1424                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1425                 {
1426                         memcpy(entname + l, ".ent", 5);
1427                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1428                         {
1429                                 CL_ParseEntityLump(entities);
1430                                 Mem_Free(entities);
1431                                 return;
1432                         }
1433                 }
1434                 if (cl.worldmodel->brush.entities)
1435                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
1436         }
1437 }
1438
1439 void GL_Main_Init(void)
1440 {
1441         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1442
1443         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1444         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1445         if (gamemode == GAME_NEHAHRA)
1446         {
1447                 Cvar_RegisterVariable (&gl_fogenable);
1448                 Cvar_RegisterVariable (&gl_fogdensity);
1449                 Cvar_RegisterVariable (&gl_fogred);
1450                 Cvar_RegisterVariable (&gl_foggreen);
1451                 Cvar_RegisterVariable (&gl_fogblue);
1452                 Cvar_RegisterVariable (&gl_fogstart);
1453                 Cvar_RegisterVariable (&gl_fogend);
1454         }
1455         Cvar_RegisterVariable(&r_nearclip);
1456         Cvar_RegisterVariable(&r_showbboxes);
1457         Cvar_RegisterVariable(&r_showsurfaces);
1458         Cvar_RegisterVariable(&r_showtris);
1459         Cvar_RegisterVariable(&r_shownormals);
1460         Cvar_RegisterVariable(&r_showlighting);
1461         Cvar_RegisterVariable(&r_showshadowvolumes);
1462         Cvar_RegisterVariable(&r_showcollisionbrushes);
1463         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1464         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1465         Cvar_RegisterVariable(&r_showdisabledepthtest);
1466         Cvar_RegisterVariable(&r_drawportals);
1467         Cvar_RegisterVariable(&r_drawentities);
1468         Cvar_RegisterVariable(&r_cullentities_trace);
1469         Cvar_RegisterVariable(&r_cullentities_trace_samples);
1470         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1471         Cvar_RegisterVariable(&r_cullentities_trace_delay);
1472         Cvar_RegisterVariable(&r_drawviewmodel);
1473         Cvar_RegisterVariable(&r_speeds);
1474         Cvar_RegisterVariable(&r_fullbrights);
1475         Cvar_RegisterVariable(&r_wateralpha);
1476         Cvar_RegisterVariable(&r_dynamic);
1477         Cvar_RegisterVariable(&r_fullbright);
1478         Cvar_RegisterVariable(&r_shadows);
1479         Cvar_RegisterVariable(&r_shadows_throwdistance);
1480         Cvar_RegisterVariable(&r_q1bsp_skymasking);
1481         Cvar_RegisterVariable(&r_textureunits);
1482         Cvar_RegisterVariable(&r_glsl);
1483         Cvar_RegisterVariable(&r_glsl_offsetmapping);
1484         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1485         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1486         Cvar_RegisterVariable(&r_glsl_deluxemapping);
1487         Cvar_RegisterVariable(&r_lerpsprites);
1488         Cvar_RegisterVariable(&r_lerpmodels);
1489         Cvar_RegisterVariable(&r_waterscroll);
1490         Cvar_RegisterVariable(&r_bloom);
1491         Cvar_RegisterVariable(&r_bloom_colorscale);
1492         Cvar_RegisterVariable(&r_bloom_brighten);
1493         Cvar_RegisterVariable(&r_bloom_blur);
1494         Cvar_RegisterVariable(&r_bloom_resolution);
1495         Cvar_RegisterVariable(&r_bloom_colorexponent);
1496         Cvar_RegisterVariable(&r_bloom_colorsubtract);
1497         Cvar_RegisterVariable(&r_hdr);
1498         Cvar_RegisterVariable(&r_hdr_scenebrightness);
1499         Cvar_RegisterVariable(&r_hdr_glowintensity);
1500         Cvar_RegisterVariable(&r_hdr_range);
1501         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1502         Cvar_RegisterVariable(&developer_texturelogging);
1503         Cvar_RegisterVariable(&gl_lightmaps);
1504         Cvar_RegisterVariable(&r_test);
1505         Cvar_RegisterVariable(&r_batchmode);
1506         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1507                 Cvar_SetValue("r_fullbrights", 0);
1508         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1509 }
1510
1511 extern void R_Textures_Init(void);
1512 extern void GL_Draw_Init(void);
1513 extern void GL_Main_Init(void);
1514 extern void R_Shadow_Init(void);
1515 extern void R_Sky_Init(void);
1516 extern void GL_Surf_Init(void);
1517 extern void R_Light_Init(void);
1518 extern void R_Particles_Init(void);
1519 extern void R_Explosion_Init(void);
1520 extern void gl_backend_init(void);
1521 extern void Sbar_Init(void);
1522 extern void R_LightningBeams_Init(void);
1523 extern void Mod_RenderInit(void);
1524
1525 void Render_Init(void)
1526 {
1527         gl_backend_init();
1528         R_Textures_Init();
1529         GL_Main_Init();
1530         GL_Draw_Init();
1531         R_Shadow_Init();
1532         R_Sky_Init();
1533         GL_Surf_Init();
1534         Sbar_Init();
1535         R_Light_Init();
1536         R_Particles_Init();
1537         R_Explosion_Init();
1538         R_LightningBeams_Init();
1539         Mod_RenderInit();
1540 }
1541
1542 /*
1543 ===============
1544 GL_Init
1545 ===============
1546 */
1547 extern char *ENGINE_EXTENSIONS;
1548 void GL_Init (void)
1549 {
1550         VID_CheckExtensions();
1551
1552         // LordHavoc: report supported extensions
1553         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1554
1555         // clear to black (loading plaque will be seen over this)
1556         CHECKGLERROR
1557         qglClearColor(0,0,0,1);CHECKGLERROR
1558         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1559 }
1560
1561 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1562 {
1563         int i;
1564         mplane_t *p;
1565         for (i = 0;i < 4;i++)
1566         {
1567                 p = r_view.frustum + i;
1568                 switch(p->signbits)
1569                 {
1570                 default:
1571                 case 0:
1572                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1573                                 return true;
1574                         break;
1575                 case 1:
1576                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1577                                 return true;
1578                         break;
1579                 case 2:
1580                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1581                                 return true;
1582                         break;
1583                 case 3:
1584                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1585                                 return true;
1586                         break;
1587                 case 4:
1588                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1589                                 return true;
1590                         break;
1591                 case 5:
1592                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1593                                 return true;
1594                         break;
1595                 case 6:
1596                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1597                                 return true;
1598                         break;
1599                 case 7:
1600                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1601                                 return true;
1602                         break;
1603                 }
1604         }
1605         return false;
1606 }
1607
1608 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1609 {
1610         int i;
1611         const mplane_t *p;
1612         for (i = 0;i < numplanes;i++)
1613         {
1614                 p = planes + i;
1615                 switch(p->signbits)
1616                 {
1617                 default:
1618                 case 0:
1619                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1620                                 return true;
1621                         break;
1622                 case 1:
1623                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1624                                 return true;
1625                         break;
1626                 case 2:
1627                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1628                                 return true;
1629                         break;
1630                 case 3:
1631                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1632                                 return true;
1633                         break;
1634                 case 4:
1635                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1636                                 return true;
1637                         break;
1638                 case 5:
1639                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1640                                 return true;
1641                         break;
1642                 case 6:
1643                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1644                                 return true;
1645                         break;
1646                 case 7:
1647                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1648                                 return true;
1649                         break;
1650                 }
1651         }
1652         return false;
1653 }
1654
1655 //==================================================================================
1656
1657 static void R_UpdateEntityLighting(entity_render_t *ent)
1658 {
1659         vec3_t tempdiffusenormal;
1660
1661         // fetch the lighting from the worldmodel data
1662         VectorSet(ent->modellight_ambient, r_ambient.value * (2.0f / 128.0f), r_ambient.value * (2.0f / 128.0f), r_ambient.value * (2.0f / 128.0f));
1663         VectorClear(ent->modellight_diffuse);
1664         VectorClear(tempdiffusenormal);
1665         if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1666         {
1667                 vec3_t org;
1668                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1669                 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1670         }
1671         else // highly rare
1672                 VectorSet(ent->modellight_ambient, 1, 1, 1);
1673
1674         // move the light direction into modelspace coordinates for lighting code
1675         Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1676         VectorNormalize(ent->modellight_lightdir);
1677
1678         // scale ambient and directional light contributions according to rendering variables
1679         ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1680         ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1681         ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1682         ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1683         ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1684         ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1685 }
1686
1687 static void R_View_UpdateEntityVisible (void)
1688 {
1689         int i, renderimask;
1690         entity_render_t *ent;
1691
1692         if (!r_drawentities.integer)
1693                 return;
1694
1695         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1696         if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1697         {
1698                 // worldmodel can check visibility
1699                 for (i = 0;i < r_refdef.numentities;i++)
1700                 {
1701                         ent = r_refdef.entities[i];
1702                         r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_viewcache.world_leafvisible, ent->mins, ent->maxs));
1703                 }
1704                 if(r_cullentities_trace.integer)
1705                 {
1706                         for (i = 0;i < r_refdef.numentities;i++)
1707                         {
1708                                 ent = r_refdef.entities[i];
1709                                 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
1710                                 {
1711                                         if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
1712                                                 ent->last_trace_visibility = realtime;
1713                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
1714                                                 r_viewcache.entityvisible[i] = 0;
1715                                 }
1716                         }
1717                 }
1718         }
1719         else
1720         {
1721                 // no worldmodel or it can't check visibility
1722                 for (i = 0;i < r_refdef.numentities;i++)
1723                 {
1724                         ent = r_refdef.entities[i];
1725                         r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1726                 }
1727         }
1728
1729         // update entity lighting (even on hidden entities for r_shadows)
1730         for (i = 0;i < r_refdef.numentities;i++)
1731                 R_UpdateEntityLighting(r_refdef.entities[i]);
1732 }
1733
1734 // only used if skyrendermasked, and normally returns false
1735 int R_DrawBrushModelsSky (void)
1736 {
1737         int i, sky;
1738         entity_render_t *ent;
1739
1740         if (!r_drawentities.integer)
1741                 return false;
1742
1743         sky = false;
1744         for (i = 0;i < r_refdef.numentities;i++)
1745         {
1746                 if (!r_viewcache.entityvisible[i])
1747                         continue;
1748                 ent = r_refdef.entities[i];
1749                 if (!ent->model || !ent->model->DrawSky)
1750                         continue;
1751                 ent->model->DrawSky(ent);
1752                 sky = true;
1753         }
1754         return sky;
1755 }
1756
1757 void R_DrawNoModel(entity_render_t *ent);
1758 void R_DrawModels(void)
1759 {
1760         int i;
1761         entity_render_t *ent;
1762
1763         if (!r_drawentities.integer)
1764                 return;
1765
1766         for (i = 0;i < r_refdef.numentities;i++)
1767         {
1768                 if (!r_viewcache.entityvisible[i])
1769                         continue;
1770                 ent = r_refdef.entities[i];
1771                 r_refdef.stats.entities++;
1772                 if (ent->model && ent->model->Draw != NULL)
1773                         ent->model->Draw(ent);
1774                 else
1775                         R_DrawNoModel(ent);
1776         }
1777 }
1778
1779 static void R_View_SetFrustum(void)
1780 {
1781         double slopex, slopey;
1782
1783         // break apart the view matrix into vectors for various purposes
1784         Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1785         VectorNegate(r_view.left, r_view.right);
1786
1787 #if 0
1788         r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1789         r_view.frustum[0].normal[1] = 0 - 0;
1790         r_view.frustum[0].normal[2] = -1 - 0;
1791         r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1792         r_view.frustum[1].normal[1] = 0 + 0;
1793         r_view.frustum[1].normal[2] = -1 + 0;
1794         r_view.frustum[2].normal[0] = 0 - 0;
1795         r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1796         r_view.frustum[2].normal[2] = -1 - 0;
1797         r_view.frustum[3].normal[0] = 0 + 0;
1798         r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1799         r_view.frustum[3].normal[2] = -1 + 0;
1800 #endif
1801
1802 #if 0
1803         zNear = r_refdef.nearclip;
1804         nudge = 1.0 - 1.0 / (1<<23);
1805         r_view.frustum[4].normal[0] = 0 - 0;
1806         r_view.frustum[4].normal[1] = 0 - 0;
1807         r_view.frustum[4].normal[2] = -1 - -nudge;
1808         r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1809         r_view.frustum[5].normal[0] = 0 + 0;
1810         r_view.frustum[5].normal[1] = 0 + 0;
1811         r_view.frustum[5].normal[2] = -1 + -nudge;
1812         r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1813 #endif
1814
1815
1816
1817 #if 0
1818         r_view.frustum[0].normal[0] = m[3] - m[0];
1819         r_view.frustum[0].normal[1] = m[7] - m[4];
1820         r_view.frustum[0].normal[2] = m[11] - m[8];
1821         r_view.frustum[0].dist = m[15] - m[12];
1822
1823         r_view.frustum[1].normal[0] = m[3] + m[0];
1824         r_view.frustum[1].normal[1] = m[7] + m[4];
1825         r_view.frustum[1].normal[2] = m[11] + m[8];
1826         r_view.frustum[1].dist = m[15] + m[12];
1827
1828         r_view.frustum[2].normal[0] = m[3] - m[1];
1829         r_view.frustum[2].normal[1] = m[7] - m[5];
1830         r_view.frustum[2].normal[2] = m[11] - m[9];
1831         r_view.frustum[2].dist = m[15] - m[13];
1832
1833         r_view.frustum[3].normal[0] = m[3] + m[1];
1834         r_view.frustum[3].normal[1] = m[7] + m[5];
1835         r_view.frustum[3].normal[2] = m[11] + m[9];
1836         r_view.frustum[3].dist = m[15] + m[13];
1837
1838         r_view.frustum[4].normal[0] = m[3] - m[2];
1839         r_view.frustum[4].normal[1] = m[7] - m[6];
1840         r_view.frustum[4].normal[2] = m[11] - m[10];
1841         r_view.frustum[4].dist = m[15] - m[14];
1842
1843         r_view.frustum[5].normal[0] = m[3] + m[2];
1844         r_view.frustum[5].normal[1] = m[7] + m[6];
1845         r_view.frustum[5].normal[2] = m[11] + m[10];
1846         r_view.frustum[5].dist = m[15] + m[14];
1847 #endif
1848
1849
1850
1851         slopex = 1.0 / r_view.frustum_x;
1852         slopey = 1.0 / r_view.frustum_y;
1853         VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
1854         VectorMA(r_view.forward,  slopex, r_view.left, r_view.frustum[1].normal);
1855         VectorMA(r_view.forward, -slopey, r_view.up  , r_view.frustum[2].normal);
1856         VectorMA(r_view.forward,  slopey, r_view.up  , r_view.frustum[3].normal);
1857         VectorCopy(r_view.forward, r_view.frustum[4].normal);
1858         VectorNormalize(r_view.frustum[0].normal);
1859         VectorNormalize(r_view.frustum[1].normal);
1860         VectorNormalize(r_view.frustum[2].normal);
1861         VectorNormalize(r_view.frustum[3].normal);
1862         r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1863         r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1864         r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1865         r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1866         r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1867         PlaneClassify(&r_view.frustum[0]);
1868         PlaneClassify(&r_view.frustum[1]);
1869         PlaneClassify(&r_view.frustum[2]);
1870         PlaneClassify(&r_view.frustum[3]);
1871         PlaneClassify(&r_view.frustum[4]);
1872
1873         // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
1874         VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
1875         VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward,  1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
1876         VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left,  1024 * slopey, r_view.up, r_view.frustumcorner[2]);
1877         VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward,  1024 * slopex, r_view.left,  1024 * slopey, r_view.up, r_view.frustumcorner[3]);
1878
1879         // LordHavoc: note to all quake engine coders, Quake had a special case
1880         // for 90 degrees which assumed a square view (wrong), so I removed it,
1881         // Quake2 has it disabled as well.
1882
1883         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1884         //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1885         //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1886         //PlaneClassify(&frustum[0]);
1887
1888         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1889         //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1890         //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1891         //PlaneClassify(&frustum[1]);
1892
1893         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1894         //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1895         //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1896         //PlaneClassify(&frustum[2]);
1897
1898         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1899         //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1900         //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1901         //PlaneClassify(&frustum[3]);
1902
1903         // nearclip plane
1904         //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1905         //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1906         //PlaneClassify(&frustum[4]);
1907 }
1908
1909 void R_View_Update(void)
1910 {
1911         R_View_SetFrustum();
1912         R_View_WorldVisibility();
1913         R_View_UpdateEntityVisible();
1914 }
1915
1916 void R_SetupView(const matrix4x4_t *matrix)
1917 {
1918         if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1919                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1920         else
1921                 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1922
1923         GL_SetupView_Orientation_FromEntity(matrix);
1924 }
1925
1926 void R_ResetViewRendering2D(void)
1927 {
1928         if (gl_support_fragment_shader)
1929         {
1930                 qglUseProgramObjectARB(0);CHECKGLERROR
1931         }
1932
1933         DrawQ_Finish();
1934
1935         // GL is weird because it's bottom to top, r_view.y is top to bottom
1936         qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1937         GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1938         GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1939         GL_Color(1, 1, 1, 1);
1940         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1941         GL_BlendFunc(GL_ONE, GL_ZERO);
1942         GL_AlphaTest(false);
1943         GL_ScissorTest(false);
1944         GL_DepthMask(false);
1945         GL_DepthRange(0, 1);
1946         GL_DepthTest(false);
1947         R_Mesh_Matrix(&identitymatrix);
1948         R_Mesh_ResetTextureState();
1949         qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1950         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1951         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1952         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1953         qglStencilMask(~0);CHECKGLERROR
1954         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1955         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1956         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1957 }
1958
1959 void R_ResetViewRendering3D(void)
1960 {
1961         if (gl_support_fragment_shader)
1962         {
1963                 qglUseProgramObjectARB(0);CHECKGLERROR
1964         }
1965
1966         DrawQ_Finish();
1967
1968         // GL is weird because it's bottom to top, r_view.y is top to bottom
1969         qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1970         R_SetupView(&r_view.matrix);
1971         GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1972         GL_Color(1, 1, 1, 1);
1973         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1974         GL_BlendFunc(GL_ONE, GL_ZERO);
1975         GL_AlphaTest(false);
1976         GL_ScissorTest(true);
1977         GL_DepthMask(true);
1978         GL_DepthRange(0, 1);
1979         GL_DepthTest(true);
1980         R_Mesh_Matrix(&identitymatrix);
1981         R_Mesh_ResetTextureState();
1982         qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1983         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1984         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1985         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1986         qglStencilMask(~0);CHECKGLERROR
1987         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1988         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1989         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1990 }
1991
1992 /*
1993         R_Bloom_SetupShader(
1994 "// bloom shader\n"
1995 "// written by Forest 'LordHavoc' Hale\n"
1996 "\n"
1997 "// common definitions between vertex shader and fragment shader:\n"
1998 "\n"
1999 "#ifdef __GLSL_CG_DATA_TYPES\n"
2000 "#define myhalf half\n"
2001 "#define myhvec2 hvec2\n"
2002 "#define myhvec3 hvec3\n"
2003 "#define myhvec4 hvec4\n"
2004 "#else\n"
2005 "#define myhalf float\n"
2006 "#define myhvec2 vec2\n"
2007 "#define myhvec3 vec3\n"
2008 "#define myhvec4 vec4\n"
2009 "#endif\n"
2010 "\n"
2011 "varying vec2 ScreenTexCoord;\n"
2012 "varying vec2 BloomTexCoord;\n"
2013 "\n"
2014 "\n"
2015 "\n"
2016 "\n"
2017 "// vertex shader specific:\n"
2018 "#ifdef VERTEX_SHADER\n"
2019 "\n"
2020 "void main(void)\n"
2021 "{\n"
2022 "       ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2023 "       BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2024 "       // transform vertex to camera space, using ftransform to match non-VS\n"
2025 "       // rendering\n"
2026 "       gl_Position = ftransform();\n"
2027 "}\n"
2028 "\n"
2029 "#endif // VERTEX_SHADER\n"
2030 "\n"
2031 "\n"
2032 "\n"
2033 "\n"
2034 "// fragment shader specific:\n"
2035 "#ifdef FRAGMENT_SHADER\n"
2036 "\n"
2037 "void main(void)\n"
2038 "{\n"
2039 "       int x, y;
2040 "       myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2041 "       for (x = -BLUR_X;x <= BLUR_X;x++)
2042 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2043 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2044 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2045 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2046
2047 "       gl_FragColor = vec4(color);\n"
2048 "}\n"
2049 "\n"
2050 "#endif // FRAGMENT_SHADER\n"
2051 */
2052
2053 void R_RenderScene(void);
2054
2055 void R_Bloom_StartFrame(void)
2056 {
2057         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2058
2059         // set bloomwidth and bloomheight to the bloom resolution that will be
2060         // used (often less than the screen resolution for faster rendering)
2061         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2062         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2063         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2064
2065         // calculate desired texture sizes
2066         if (gl_support_arb_texture_non_power_of_two)
2067         {
2068                 screentexturewidth = r_view.width;
2069                 screentextureheight = r_view.height;
2070                 bloomtexturewidth = r_bloomstate.bloomwidth;
2071                 bloomtextureheight = r_bloomstate.bloomheight;
2072         }
2073         else
2074         {
2075                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
2076                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
2077                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
2078                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
2079         }
2080
2081         if (r_hdr.integer)
2082         {
2083                 screentexturewidth = screentextureheight = 0;
2084         }
2085         else if (r_bloom.integer)
2086         {
2087         }
2088         else
2089         {
2090                 screentexturewidth = screentextureheight = 0;
2091                 bloomtexturewidth = bloomtextureheight = 0;
2092         }
2093
2094         if ((!bloomtexturewidth && !bloomtextureheight) || r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512 || screentexturewidth > gl_max_texture_size || screentextureheight > gl_max_texture_size || bloomtexturewidth > gl_max_texture_size || bloomtextureheight > gl_max_texture_size)
2095         {
2096                 // can't use bloom if the parameters are too weird
2097                 // can't use bloom if the card does not support the texture size
2098                 if (r_bloomstate.texture_screen)
2099                         R_FreeTexture(r_bloomstate.texture_screen);
2100                 if (r_bloomstate.texture_bloom)
2101                         R_FreeTexture(r_bloomstate.texture_bloom);
2102                 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2103                 return;
2104         }
2105
2106         r_bloomstate.enabled = true;
2107         r_bloomstate.hdr = r_hdr.integer != 0;
2108
2109         // allocate textures as needed
2110         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2111         {
2112                 if (r_bloomstate.texture_screen)
2113                         R_FreeTexture(r_bloomstate.texture_screen);
2114                 r_bloomstate.texture_screen = NULL;
2115                 r_bloomstate.screentexturewidth = screentexturewidth;
2116                 r_bloomstate.screentextureheight = screentextureheight;
2117                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2118                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2119         }
2120         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2121         {
2122                 if (r_bloomstate.texture_bloom)
2123                         R_FreeTexture(r_bloomstate.texture_bloom);
2124                 r_bloomstate.texture_bloom = NULL;
2125                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2126                 r_bloomstate.bloomtextureheight = bloomtextureheight;
2127                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2128                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2129         }
2130
2131         // set up a texcoord array for the full resolution screen image
2132         // (we have to keep this around to copy back during final render)
2133         r_bloomstate.screentexcoord2f[0] = 0;
2134         r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2135         r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2136         r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2137         r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2138         r_bloomstate.screentexcoord2f[5] = 0;
2139         r_bloomstate.screentexcoord2f[6] = 0;
2140         r_bloomstate.screentexcoord2f[7] = 0;
2141
2142         // set up a texcoord array for the reduced resolution bloom image
2143         // (which will be additive blended over the screen image)
2144         r_bloomstate.bloomtexcoord2f[0] = 0;
2145         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2146         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2147         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2148         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2149         r_bloomstate.bloomtexcoord2f[5] = 0;
2150         r_bloomstate.bloomtexcoord2f[6] = 0;
2151         r_bloomstate.bloomtexcoord2f[7] = 0;
2152 }
2153
2154 void R_Bloom_CopyScreenTexture(float colorscale)
2155 {
2156         r_refdef.stats.bloom++;
2157
2158         R_ResetViewRendering2D();
2159         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2160         R_Mesh_ColorPointer(NULL, 0, 0);
2161         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2162         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2163
2164         // copy view into the screen texture
2165         GL_ActiveTexture(0);
2166         CHECKGLERROR
2167         qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2168         r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2169
2170         // now scale it down to the bloom texture size
2171         CHECKGLERROR
2172         qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2173         GL_BlendFunc(GL_ONE, GL_ZERO);
2174         GL_Color(colorscale, colorscale, colorscale, 1);
2175         // TODO: optimize with multitexture or GLSL
2176         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2177         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2178
2179         // we now have a bloom image in the framebuffer
2180         // copy it into the bloom image texture for later processing
2181         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2182         GL_ActiveTexture(0);
2183         CHECKGLERROR
2184         qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2185         r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2186 }
2187
2188 void R_Bloom_CopyHDRTexture(void)
2189 {
2190         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2191         GL_ActiveTexture(0);
2192         CHECKGLERROR
2193         qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2194         r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2195 }
2196
2197 void R_Bloom_MakeTexture(void)
2198 {
2199         int x, range, dir;
2200         float xoffset, yoffset, r, brighten;
2201
2202         r_refdef.stats.bloom++;
2203
2204         R_ResetViewRendering2D();
2205         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2206         R_Mesh_ColorPointer(NULL, 0, 0);
2207
2208         // we have a bloom image in the framebuffer
2209         CHECKGLERROR
2210         qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2211
2212         for (x = 1;x < r_bloom_colorexponent.value;)
2213         {
2214                 x *= 2;
2215                 r = bound(0, r_bloom_colorexponent.value / x, 1);
2216                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2217                 GL_Color(r, r, r, 1);
2218                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2219                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2220                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2221                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2222
2223                 // copy the vertically blurred bloom view to a texture
2224                 GL_ActiveTexture(0);
2225                 CHECKGLERROR
2226                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2227                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2228         }
2229
2230         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2231         brighten = r_bloom_brighten.value;
2232         if (r_hdr.integer)
2233                 brighten *= r_hdr_range.value;
2234         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2235         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2236
2237         for (dir = 0;dir < 2;dir++)
2238         {
2239                 // blend on at multiple vertical offsets to achieve a vertical blur
2240                 // TODO: do offset blends using GLSL
2241                 GL_BlendFunc(GL_ONE, GL_ZERO);
2242                 for (x = -range;x <= range;x++)
2243                 {
2244                         if (!dir){xoffset = 0;yoffset = x;}
2245                         else {xoffset = x;yoffset = 0;}
2246                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
2247                         yoffset /= (float)r_bloomstate.bloomtextureheight;
2248                         // compute a texcoord array with the specified x and y offset
2249                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2250                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2251                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2252                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2253                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2254                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2255                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2256                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2257                         // this r value looks like a 'dot' particle, fading sharply to
2258                         // black at the edges
2259                         // (probably not realistic but looks good enough)
2260                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2261                         //r = (dir ? 1.0f : brighten)/(range*2+1);
2262                         r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2263                         GL_Color(r, r, r, 1);
2264                         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2265                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2266                         GL_BlendFunc(GL_ONE, GL_ONE);
2267                 }
2268
2269                 // copy the vertically blurred bloom view to a texture
2270                 GL_ActiveTexture(0);
2271                 CHECKGLERROR
2272                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2273                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2274         }
2275
2276         // apply subtract last
2277         // (just like it would be in a GLSL shader)
2278         if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
2279         {
2280                 GL_BlendFunc(GL_ONE, GL_ZERO);
2281                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2282                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2283                 GL_Color(1, 1, 1, 1);
2284                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2285                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2286
2287                 GL_BlendFunc(GL_ONE, GL_ONE);
2288                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2289                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2290                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2291                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
2292                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2293                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2294                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2295
2296                 // copy the darkened bloom view to a texture
2297                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2298                 GL_ActiveTexture(0);
2299                 CHECKGLERROR
2300                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2301                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2302         }
2303 }
2304
2305 void R_HDR_RenderBloomTexture(void)
2306 {
2307         int oldwidth, oldheight;
2308
2309         oldwidth = r_view.width;
2310         oldheight = r_view.height;
2311         r_view.width = r_bloomstate.bloomwidth;
2312         r_view.height = r_bloomstate.bloomheight;
2313
2314         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
2315         // TODO: add exposure compensation features
2316         // TODO: add fp16 framebuffer support
2317
2318         r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
2319         if (r_hdr.integer)
2320                 r_view.colorscale /= r_hdr_range.value;
2321         R_RenderScene();
2322
2323         R_ResetViewRendering2D();
2324
2325         R_Bloom_CopyHDRTexture();
2326         R_Bloom_MakeTexture();
2327
2328         R_ResetViewRendering3D();
2329
2330         R_ClearScreen();
2331         if (r_timereport_active)
2332                 R_TimeReport("clear");
2333
2334
2335         // restore the view settings
2336         r_view.width = oldwidth;
2337         r_view.height = oldheight;
2338 }
2339
2340 static void R_BlendView(void)
2341 {
2342         if (r_bloomstate.enabled && r_bloomstate.hdr)
2343         {
2344                 // render high dynamic range bloom effect
2345                 // the bloom texture was made earlier this render, so we just need to
2346                 // blend it onto the screen...
2347                 R_ResetViewRendering2D();
2348                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2349                 R_Mesh_ColorPointer(NULL, 0, 0);
2350                 GL_Color(1, 1, 1, 1);
2351                 GL_BlendFunc(GL_ONE, GL_ONE);
2352                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2353                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2354                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2355                 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2356         }
2357         else if (r_bloomstate.enabled)
2358         {
2359                 // render simple bloom effect
2360                 // copy the screen and shrink it and darken it for the bloom process
2361                 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2362                 // make the bloom texture
2363                 R_Bloom_MakeTexture();
2364                 // put the original screen image back in place and blend the bloom
2365                 // texture on it
2366                 R_ResetViewRendering2D();
2367                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2368                 R_Mesh_ColorPointer(NULL, 0, 0);
2369                 GL_Color(1, 1, 1, 1);
2370                 GL_BlendFunc(GL_ONE, GL_ZERO);
2371                 // do both in one pass if possible
2372                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2373                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2374                 if (r_textureunits.integer >= 2 && gl_combine.integer)
2375                 {
2376                         R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2377                         R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2378                         R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
2379                 }
2380                 else
2381                 {
2382                         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2383                         r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2384                         // now blend on the bloom texture
2385                         GL_BlendFunc(GL_ONE, GL_ONE);
2386                         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2387                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2388                 }
2389                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2390                 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2391         }
2392         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
2393         {
2394                 // apply a color tint to the whole view
2395                 R_ResetViewRendering2D();
2396                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2397                 R_Mesh_ColorPointer(NULL, 0, 0);
2398                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2399                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
2400                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2401         }
2402 }
2403
2404 void R_RenderScene(void);
2405
2406 matrix4x4_t r_waterscrollmatrix;
2407
2408 void R_UpdateVariables(void)
2409 {
2410         R_Textures_Frame();
2411
2412         r_refdef.farclip = 4096;
2413         if (r_refdef.worldmodel)
2414                 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
2415         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
2416
2417         r_refdef.polygonfactor = 0;
2418         r_refdef.polygonoffset = 0;
2419         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
2420         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
2421
2422         r_refdef.rtworld = r_shadow_realtime_world.integer;
2423         r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
2424         r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
2425         r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
2426         r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
2427         if (r_showsurfaces.integer)
2428         {
2429                 r_refdef.rtworld = false;
2430                 r_refdef.rtworldshadows = false;
2431                 r_refdef.rtdlight = false;
2432                 r_refdef.rtdlightshadows = false;
2433                 r_refdef.lightmapintensity = 0;
2434         }
2435
2436         if (gamemode == GAME_NEHAHRA)
2437         {
2438                 if (gl_fogenable.integer)
2439                 {
2440                         r_refdef.oldgl_fogenable = true;
2441                         r_refdef.fog_density = gl_fogdensity.value;
2442                         r_refdef.fog_red = gl_fogred.value;
2443                         r_refdef.fog_green = gl_foggreen.value;
2444                         r_refdef.fog_blue = gl_fogblue.value;
2445                 }
2446                 else if (r_refdef.oldgl_fogenable)
2447                 {
2448                         r_refdef.oldgl_fogenable = false;
2449                         r_refdef.fog_density = 0;
2450                         r_refdef.fog_red = 0;
2451                         r_refdef.fog_green = 0;
2452                         r_refdef.fog_blue = 0;
2453                 }
2454         }
2455         if (r_refdef.fog_density)
2456         {
2457                 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red  , 1.0f);
2458                 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
2459                 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
2460         }
2461         if (r_refdef.fog_density)
2462         {
2463                 r_refdef.fogenabled = true;
2464                 // this is the point where the fog reaches 0.9986 alpha, which we
2465                 // consider a good enough cutoff point for the texture
2466                 // (0.9986 * 256 == 255.6)
2467                 r_refdef.fogrange = 400 / r_refdef.fog_density;
2468                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
2469                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
2470                 // fog color was already set
2471         }
2472         else
2473                 r_refdef.fogenabled = false;
2474 }
2475
2476 /*
2477 ================
2478 R_RenderView
2479 ================
2480 */
2481 void R_RenderView(void)
2482 {
2483         if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
2484                 return; //Host_Error ("R_RenderView: NULL worldmodel");
2485
2486         R_Shadow_UpdateWorldLightSelection();
2487
2488         CHECKGLERROR
2489         if (r_timereport_active)
2490                 R_TimeReport("setup");
2491
2492         R_View_Update();
2493         if (r_timereport_active)
2494                 R_TimeReport("visibility");
2495
2496         R_ResetViewRendering3D();
2497
2498         R_ClearScreen();
2499         if (r_timereport_active)
2500                 R_TimeReport("clear");
2501
2502         R_Bloom_StartFrame();
2503
2504         // this produces a bloom texture to be used in R_BlendView() later
2505         if (r_hdr.integer)
2506                 R_HDR_RenderBloomTexture();
2507
2508         r_view.colorscale = r_hdr_scenebrightness.value;
2509         R_RenderScene();
2510
2511         R_BlendView();
2512         if (r_timereport_active)
2513                 R_TimeReport("blendview");
2514
2515         GL_Scissor(0, 0, vid.width, vid.height);
2516         GL_ScissorTest(false);
2517         CHECKGLERROR
2518 }
2519
2520 extern void R_DrawLightningBeams (void);
2521 extern void VM_CL_AddPolygonsToMeshQueue (void);
2522 extern void R_DrawPortals (void);
2523 extern cvar_t cl_locs_show;
2524 static void R_DrawLocs(void);
2525 static void R_DrawEntityBBoxes(void);
2526 void R_RenderScene(void)
2527 {
2528         // don't let sound skip if going slow
2529         if (r_refdef.extraupdate)
2530                 S_ExtraUpdate ();
2531
2532         R_ResetViewRendering3D();
2533
2534         R_MeshQueue_BeginScene();
2535
2536         R_SkyStartFrame();
2537
2538         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);
2539
2540         if (cl.csqc_vidvars.drawworld)
2541         {
2542                 // don't let sound skip if going slow
2543                 if (r_refdef.extraupdate)
2544                         S_ExtraUpdate ();
2545
2546                 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2547                 {
2548                         r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2549                         if (r_timereport_active)
2550                                 R_TimeReport("worldsky");
2551                 }
2552
2553                 if (R_DrawBrushModelsSky() && r_timereport_active)
2554                         R_TimeReport("bmodelsky");
2555
2556                 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2557                 {
2558                         r_refdef.worldmodel->Draw(r_refdef.worldentity);
2559                         if (r_timereport_active)
2560                                 R_TimeReport("world");
2561                 }
2562         }
2563
2564         // don't let sound skip if going slow
2565         if (r_refdef.extraupdate)
2566                 S_ExtraUpdate ();
2567
2568         R_DrawModels();
2569         if (r_timereport_active)
2570                 R_TimeReport("models");
2571
2572         // don't let sound skip if going slow
2573         if (r_refdef.extraupdate)
2574                 S_ExtraUpdate ();
2575
2576         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2577         {
2578                 R_DrawModelShadows();
2579
2580                 R_ResetViewRendering3D();
2581
2582                 // don't let sound skip if going slow
2583                 if (r_refdef.extraupdate)
2584                         S_ExtraUpdate ();
2585         }
2586
2587         R_ShadowVolumeLighting(false);
2588         if (r_timereport_active)
2589                 R_TimeReport("rtlights");
2590
2591         // don't let sound skip if going slow
2592         if (r_refdef.extraupdate)
2593                 S_ExtraUpdate ();
2594
2595         if (cl.csqc_vidvars.drawworld)
2596         {
2597                 R_DrawLightningBeams();
2598                 if (r_timereport_active)
2599                         R_TimeReport("lightning");
2600
2601                 R_DrawParticles();
2602                 if (r_timereport_active)
2603                         R_TimeReport("particles");
2604
2605                 R_DrawExplosions();
2606                 if (r_timereport_active)
2607                         R_TimeReport("explosions");
2608         }
2609
2610         if (gl_support_fragment_shader)
2611         {
2612                 qglUseProgramObjectARB(0);CHECKGLERROR
2613         }
2614         VM_CL_AddPolygonsToMeshQueue();
2615
2616         if (cl_locs_show.integer)
2617         {
2618                 R_DrawLocs();
2619                 if (r_timereport_active)
2620                         R_TimeReport("showlocs");
2621         }
2622
2623         if (r_drawportals.integer)
2624         {
2625                 R_DrawPortals();
2626                 if (r_timereport_active)
2627                         R_TimeReport("portals");
2628         }
2629
2630         if (r_showbboxes.value > 0)
2631         {
2632                 R_DrawEntityBBoxes();
2633                 if (r_timereport_active)
2634                         R_TimeReport("bboxes");
2635         }
2636
2637         if (gl_support_fragment_shader)
2638         {
2639                 qglUseProgramObjectARB(0);CHECKGLERROR
2640         }
2641         R_MeshQueue_RenderTransparent();
2642         if (r_timereport_active)
2643                 R_TimeReport("drawtrans");
2644
2645         if (gl_support_fragment_shader)
2646         {
2647                 qglUseProgramObjectARB(0);CHECKGLERROR
2648         }
2649
2650         if (cl.csqc_vidvars.drawworld)
2651         {
2652                 R_DrawCoronas();
2653                 if (r_timereport_active)
2654                         R_TimeReport("coronas");
2655         }
2656
2657         // don't let sound skip if going slow
2658         if (r_refdef.extraupdate)
2659                 S_ExtraUpdate ();
2660
2661         R_ResetViewRendering2D();
2662 }
2663
2664 static const int bboxelements[36] =
2665 {
2666         5, 1, 3, 5, 3, 7,
2667         6, 2, 0, 6, 0, 4,
2668         7, 3, 2, 7, 2, 6,
2669         4, 0, 1, 4, 1, 5,
2670         4, 5, 7, 4, 7, 6,
2671         1, 0, 2, 1, 2, 3,
2672 };
2673
2674 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2675 {
2676         int i;
2677         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
2678         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2679         GL_DepthMask(false);
2680         GL_DepthRange(0, 1);
2681         R_Mesh_Matrix(&identitymatrix);
2682         R_Mesh_ResetTextureState();
2683
2684         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
2685         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2686         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2687         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2688         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2689         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2690         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2691         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2692         R_FillColors(color4f, 8, cr, cg, cb, ca);
2693         if (r_refdef.fogenabled)
2694         {
2695                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
2696                 {
2697                         f1 = FogPoint_World(v);
2698                         f2 = 1 - f1;
2699                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2700                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2701                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2702                 }
2703         }
2704         R_Mesh_VertexPointer(vertex3f, 0, 0);
2705         R_Mesh_ColorPointer(color4f, 0, 0);
2706         R_Mesh_ResetTextureState();
2707         R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
2708 }
2709
2710 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2711 {
2712         int i;
2713         float color[4];
2714         prvm_edict_t *edict;
2715         // this function draws bounding boxes of server entities
2716         if (!sv.active)
2717                 return;
2718         SV_VM_Begin();
2719         for (i = 0;i < numsurfaces;i++)
2720         {
2721                 edict = PRVM_EDICT_NUM(surfacelist[i]);
2722                 switch ((int)edict->fields.server->solid)
2723                 {
2724                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
2725                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
2726                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
2727                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
2728                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
2729                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
2730                 }
2731                 color[3] *= r_showbboxes.value;
2732                 color[3] = bound(0, color[3], 1);
2733                 GL_DepthTest(!r_showdisabledepthtest.integer);
2734                 GL_CullFace(GL_BACK);
2735                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
2736         }
2737         SV_VM_End();
2738 }
2739
2740 static void R_DrawEntityBBoxes(void)
2741 {
2742         int i;
2743         prvm_edict_t *edict;
2744         vec3_t center;
2745         // this function draws bounding boxes of server entities
2746         if (!sv.active)
2747                 return;
2748         SV_VM_Begin();
2749         for (i = 0;i < prog->num_edicts;i++)
2750         {
2751                 edict = PRVM_EDICT_NUM(i);
2752                 if (edict->priv.server->free)
2753                         continue;
2754                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
2755                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
2756         }
2757         SV_VM_End();
2758 }
2759
2760 int nomodelelements[24] =
2761 {
2762         5, 2, 0,
2763         5, 1, 2,
2764         5, 0, 3,
2765         5, 3, 1,
2766         0, 2, 4,
2767         2, 1, 4,
2768         3, 0, 4,
2769         1, 3, 4
2770 };
2771
2772 float nomodelvertex3f[6*3] =
2773 {
2774         -16,   0,   0,
2775          16,   0,   0,
2776           0, -16,   0,
2777           0,  16,   0,
2778           0,   0, -16,
2779           0,   0,  16
2780 };
2781
2782 float nomodelcolor4f[6*4] =
2783 {
2784         0.0f, 0.0f, 0.5f, 1.0f,
2785         0.0f, 0.0f, 0.5f, 1.0f,
2786         0.0f, 0.5f, 0.0f, 1.0f,
2787         0.0f, 0.5f, 0.0f, 1.0f,
2788         0.5f, 0.0f, 0.0f, 1.0f,
2789         0.5f, 0.0f, 0.0f, 1.0f
2790 };
2791
2792 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2793 {
2794         int i;
2795         float f1, f2, *c;
2796         float color4f[6*4];
2797         // this is only called once per entity so numsurfaces is always 1, and
2798         // surfacelist is always {0}, so this code does not handle batches
2799         R_Mesh_Matrix(&ent->matrix);
2800
2801         if (ent->flags & EF_ADDITIVE)
2802         {
2803                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2804                 GL_DepthMask(false);
2805         }
2806         else if (ent->alpha < 1)
2807         {
2808                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2809                 GL_DepthMask(false);
2810         }
2811         else
2812         {
2813                 GL_BlendFunc(GL_ONE, GL_ZERO);
2814                 GL_DepthMask(true);
2815         }
2816         GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
2817         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2818         GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
2819         R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
2820         if (r_refdef.fogenabled)
2821         {
2822                 vec3_t org;
2823                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2824                 R_Mesh_ColorPointer(color4f, 0, 0);
2825                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2826                 f1 = FogPoint_World(org);
2827                 f2 = 1 - f1;
2828                 for (i = 0, c = color4f;i < 6;i++, c += 4)
2829                 {
2830                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2831                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2832                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2833                         c[3] *= ent->alpha;
2834                 }
2835         }
2836         else if (ent->alpha != 1)
2837         {
2838                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2839                 R_Mesh_ColorPointer(color4f, 0, 0);
2840                 for (i = 0, c = color4f;i < 6;i++, c += 4)
2841                         c[3] *= ent->alpha;
2842         }
2843         else
2844                 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
2845         R_Mesh_ResetTextureState();
2846         R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
2847 }
2848
2849 void R_DrawNoModel(entity_render_t *ent)
2850 {
2851         vec3_t org;
2852         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2853         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2854                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2855         //else
2856         //      R_DrawNoModelCallback(ent, 0);
2857 }
2858
2859 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2860 {
2861         vec3_t right1, right2, diff, normal;
2862
2863         VectorSubtract (org2, org1, normal);
2864
2865         // calculate 'right' vector for start
2866         VectorSubtract (r_view.origin, org1, diff);
2867         CrossProduct (normal, diff, right1);
2868         VectorNormalize (right1);
2869
2870         // calculate 'right' vector for end
2871         VectorSubtract (r_view.origin, org2, diff);
2872         CrossProduct (normal, diff, right2);
2873         VectorNormalize (right2);
2874
2875         vert[ 0] = org1[0] + width * right1[0];
2876         vert[ 1] = org1[1] + width * right1[1];
2877         vert[ 2] = org1[2] + width * right1[2];
2878         vert[ 3] = org1[0] - width * right1[0];
2879         vert[ 4] = org1[1] - width * right1[1];
2880         vert[ 5] = org1[2] - width * right1[2];
2881         vert[ 6] = org2[0] - width * right2[0];
2882         vert[ 7] = org2[1] - width * right2[1];
2883         vert[ 8] = org2[2] - width * right2[2];
2884         vert[ 9] = org2[0] + width * right2[0];
2885         vert[10] = org2[1] + width * right2[1];
2886         vert[11] = org2[2] + width * right2[2];
2887 }
2888
2889 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2890
2891 void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_t *fogtexture, qboolean depthdisable, qboolean depthshort, 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)
2892 {
2893         float fog = 1.0f;
2894         float vertex3f[12];
2895
2896         if (r_refdef.fogenabled)
2897                 fog = FogPoint_World(origin);
2898
2899         R_Mesh_Matrix(&identitymatrix);
2900         GL_BlendFunc(blendfunc1, blendfunc2);
2901         GL_DepthMask(false);
2902         GL_DepthRange(0, depthshort ? 0.0625 : 1);
2903         GL_DepthTest(!depthdisable);
2904
2905         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2906         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2907         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2908         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2909         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2910         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2911         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2912         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2913         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2914         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2915         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2916         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2917
2918         R_Mesh_VertexPointer(vertex3f, 0, 0);
2919         R_Mesh_ColorPointer(NULL, 0, 0);
2920         R_Mesh_ResetTextureState();
2921         R_Mesh_TexBind(0, R_GetTexture(texture));
2922         R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
2923         // FIXME: fixed function path can't properly handle r_view.colorscale > 1
2924         GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
2925         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2926
2927         if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2928         {
2929                 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2930                 GL_BlendFunc(blendfunc1, GL_ONE);
2931                 fog = 1 - fog;
2932                 GL_Color(r_refdef.fogcolor[0] * fog * r_view.colorscale, r_refdef.fogcolor[1] * fog * r_view.colorscale, r_refdef.fogcolor[2] * fog * r_view.colorscale, ca);
2933                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2934         }
2935 }
2936
2937 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
2938 {
2939         int i;
2940         float *vertex3f;
2941         float v[3];
2942         VectorSet(v, x, y, z);
2943         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2944                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2945                         break;
2946         if (i == mesh->numvertices)
2947         {
2948                 if (mesh->numvertices < mesh->maxvertices)
2949                 {
2950                         VectorCopy(v, vertex3f);
2951                         mesh->numvertices++;
2952                 }
2953                 return mesh->numvertices;
2954         }
2955         else
2956                 return i;
2957 }
2958
2959 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2960 {
2961         int i;
2962         int *e, element[3];
2963         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2964         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2965         e = mesh->element3i + mesh->numtriangles * 3;
2966         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2967         {
2968                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
2969                 if (mesh->numtriangles < mesh->maxtriangles)
2970                 {
2971                         *e++ = element[0];
2972                         *e++ = element[1];
2973                         *e++ = element[2];
2974                         mesh->numtriangles++;
2975                 }
2976                 element[1] = element[2];
2977         }
2978 }
2979
2980 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
2981 {
2982         int i;
2983         int *e, element[3];
2984         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2985         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2986         e = mesh->element3i + mesh->numtriangles * 3;
2987         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
2988         {
2989                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
2990                 if (mesh->numtriangles < mesh->maxtriangles)
2991                 {
2992                         *e++ = element[0];
2993                         *e++ = element[1];
2994                         *e++ = element[2];
2995                         mesh->numtriangles++;
2996                 }
2997                 element[1] = element[2];
2998         }
2999 }
3000
3001 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3002 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3003 {
3004         int planenum, planenum2;
3005         int w;
3006         int tempnumpoints;
3007         mplane_t *plane, *plane2;
3008         double maxdist;
3009         double temppoints[2][256*3];
3010         // figure out how large a bounding box we need to properly compute this brush
3011         maxdist = 0;
3012         for (w = 0;w < numplanes;w++)
3013                 maxdist = max(maxdist, planes[w].dist);
3014         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3015         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3016         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3017         {
3018                 w = 0;
3019                 tempnumpoints = 4;
3020                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3021                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3022                 {
3023                         if (planenum2 == planenum)
3024                                 continue;
3025                         PolygonD_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, R_MESH_PLANE_DIST_EPSILON, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
3026                         w = !w;
3027                 }
3028                 if (tempnumpoints < 3)
3029                         continue;
3030                 // generate elements forming a triangle fan for this polygon
3031                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3032         }
3033 }
3034
3035 static void R_DrawCollisionBrush(const colbrushf_t *brush)
3036 {
3037         int i;
3038         R_Mesh_VertexPointer(brush->points->v, 0, 0);
3039         i = (int)(((size_t)brush) / sizeof(colbrushf_t));
3040         GL_Color((i & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_view.colorscale, 0.2f);
3041         GL_LockArrays(0, brush->numpoints);
3042         R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements, 0, 0);
3043         GL_LockArrays(0, 0);
3044 }
3045
3046 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
3047 {
3048         int i;
3049         if (!surface->num_collisiontriangles)
3050                 return;
3051         R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
3052         i = (int)(((size_t)surface) / sizeof(msurface_t));
3053         GL_Color((i & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_view.colorscale, 0.2f);
3054         GL_LockArrays(0, surface->num_collisionvertices);
3055         R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
3056         GL_LockArrays(0, 0);
3057 }
3058
3059 static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, const matrix4x4_t *matrix, float r, float g, float b, float a)
3060 {
3061         texturelayer_t *layer;
3062         layer = t->currentlayers + t->currentnumlayers++;
3063         layer->type = type;
3064         layer->depthmask = depthmask;
3065         layer->blendfunc1 = blendfunc1;
3066         layer->blendfunc2 = blendfunc2;
3067         layer->texture = texture;
3068         layer->texmatrix = *matrix;
3069         layer->color[0] = r * r_view.colorscale;
3070         layer->color[1] = g * r_view.colorscale;
3071         layer->color[2] = b * r_view.colorscale;
3072         layer->color[3] = a;
3073 }
3074
3075 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3076 {
3077         model_t *model = ent->model;
3078
3079         // switch to an alternate material if this is a q1bsp animated material
3080         {
3081                 texture_t *texture = t;
3082                 int s = ent->skinnum;
3083                 if ((unsigned int)s >= (unsigned int)model->numskins)
3084                         s = 0;
3085                 if (model->skinscenes)
3086                 {
3087                         if (model->skinscenes[s].framecount > 1)
3088                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3089                         else
3090                                 s = model->skinscenes[s].firstframe;
3091                 }
3092                 if (s > 0)
3093                         t = t + s * model->num_surfaces;
3094                 if (t->animated)
3095                 {
3096                         // use an alternate animation if the entity's frame is not 0,
3097                         // and only if the texture has an alternate animation
3098                         if (ent->frame != 0 && t->anim_total[1])
3099                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3100                         else
3101                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3102                 }
3103                 texture->currentframe = t;
3104         }
3105
3106         // pick a new currentskinframe if the material is animated
3107         if (t->numskinframes >= 2)
3108                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3109         if (t->backgroundnumskinframes >= 2)
3110                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3111
3112         t->currentmaterialflags = t->basematerialflags;
3113         t->currentalpha = ent->alpha;
3114         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3115                 t->currentalpha *= r_wateralpha.value;
3116         if (!(ent->flags & RENDER_LIGHT))
3117                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3118         if (ent->effects & EF_ADDITIVE)
3119                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3120         else if (t->currentalpha < 1)
3121                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3122         if (ent->effects & EF_DOUBLESIDED)
3123                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3124         if (ent->effects & EF_NODEPTHTEST)
3125                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3126         if (ent->flags & RENDER_VIEWMODEL)
3127                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3128         if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3129                 t->currenttexmatrix = r_waterscrollmatrix;
3130         else
3131                 t->currenttexmatrix = identitymatrix;
3132         if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3133                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3134
3135         t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
3136         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3137         t->glosstexture = r_texture_white;
3138         t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
3139         t->backgroundglosstexture = r_texture_white;
3140         t->specularpower = r_shadow_glossexponent.value;
3141         // TODO: store reference values for these in the texture?
3142         t->specularscale = 0;
3143         if (r_shadow_gloss.integer > 0)
3144         {
3145                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
3146                 {
3147                         if (r_shadow_glossintensity.value > 0)
3148                         {
3149                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_black;
3150                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_black;
3151                                 t->specularscale = r_shadow_glossintensity.value;
3152                         }
3153                 }
3154                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
3155                         t->specularscale = r_shadow_gloss2intensity.value;
3156         }
3157
3158         t->currentnumlayers = 0;
3159         if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
3160         {
3161                 if (gl_lightmaps.integer)
3162                         R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
3163                 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
3164                 {
3165                         int blendfunc1, blendfunc2, depthmask;
3166                         if (t->currentmaterialflags & MATERIALFLAG_ADD)
3167                         {
3168                                 blendfunc1 = GL_SRC_ALPHA;
3169                                 blendfunc2 = GL_ONE;
3170                         }
3171                         else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
3172                         {
3173                                 blendfunc1 = GL_SRC_ALPHA;
3174                                 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
3175                         }
3176                         else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
3177                         {
3178                                 blendfunc1 = t->customblendfunc[0];
3179                                 blendfunc2 = t->customblendfunc[1];
3180                         }
3181                         else
3182                         {
3183                                 blendfunc1 = GL_ONE;
3184                                 blendfunc2 = GL_ZERO;
3185                         }
3186                         depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
3187                         if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
3188                         {
3189                                 rtexture_t *currentbasetexture;
3190                                 int layerflags = 0;
3191                                 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
3192                                         layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
3193                                 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3194                                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3195                                 {
3196                                         // fullbright is not affected by r_refdef.lightmapintensity
3197                                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
3198                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3199                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->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);
3200                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3201                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->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);
3202                                 }
3203                                 else
3204                                 {
3205                                         float colorscale;
3206                                         colorscale = 2;
3207                                         // q3bsp has no lightmap updates, so the lightstylevalue that
3208                                         // would normally be baked into the lightmap must be
3209                                         // applied to the color
3210                                         if (ent->model->type == mod_brushq3)
3211                                                 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
3212                                         colorscale *= r_refdef.lightmapintensity;
3213                                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha);
3214                                         if (r_ambient.value >= (1.0f/64.0f))
3215                                                 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);
3216                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3217                                         {
3218                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->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);
3219                                                 if (r_ambient.value >= (1.0f/64.0f))
3220                                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->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);
3221                                         }
3222                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3223                                         {
3224                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->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);
3225                                                 if (r_ambient.value >= (1.0f/64.0f))
3226                                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->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);
3227                                         }
3228                                 }
3229                                 if (t->currentskinframe->glow != NULL)
3230                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->currentalpha);
3231                                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
3232                                 {
3233                                         // if this is opaque use alpha blend which will darken the earlier
3234                                         // passes cheaply.
3235                                         //
3236                                         // if this is an alpha blended material, all the earlier passes
3237                                         // were darkened by fog already, so we only need to add the fog
3238                                         // color ontop through the fog mask texture
3239                                         //
3240                                         // if this is an additive blended material, all the earlier passes
3241                                         // were darkened by fog already, and we should not add fog color
3242                                         // (because the background was not darkened, there is no fog color
3243                                         // that was lost behind it).
3244                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &identitymatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha);
3245                                 }
3246                         }
3247                 }
3248         }
3249 }
3250
3251 void R_UpdateAllTextureInfo(entity_render_t *ent)
3252 {
3253         int i;
3254         if (ent->model)
3255                 for (i = 0;i < ent->model->num_textures;i++)
3256                         R_UpdateTextureInfo(ent, ent->model->data_textures + i);
3257 }
3258
3259 int rsurface_array_size = 0;
3260 float *rsurface_array_modelvertex3f = NULL;
3261 float *rsurface_array_modelsvector3f = NULL;
3262 float *rsurface_array_modeltvector3f = NULL;
3263 float *rsurface_array_modelnormal3f = NULL;
3264 float *rsurface_array_deformedvertex3f = NULL;
3265 float *rsurface_array_deformedsvector3f = NULL;
3266 float *rsurface_array_deformedtvector3f = NULL;
3267 float *rsurface_array_deformednormal3f = NULL;
3268 float *rsurface_array_color4f = NULL;
3269 float *rsurface_array_texcoord3f = NULL;
3270
3271 void R_Mesh_ResizeArrays(int newvertices)
3272 {
3273         float *base;
3274         if (rsurface_array_size >= newvertices)
3275                 return;
3276         if (rsurface_array_modelvertex3f)
3277                 Mem_Free(rsurface_array_modelvertex3f);
3278         rsurface_array_size = (newvertices + 1023) & ~1023;
3279         base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
3280         rsurface_array_modelvertex3f     = base + rsurface_array_size * 0;
3281         rsurface_array_modelsvector3f    = base + rsurface_array_size * 3;
3282         rsurface_array_modeltvector3f    = base + rsurface_array_size * 6;
3283         rsurface_array_modelnormal3f     = base + rsurface_array_size * 9;
3284         rsurface_array_deformedvertex3f  = base + rsurface_array_size * 12;
3285         rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
3286         rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
3287         rsurface_array_deformednormal3f  = base + rsurface_array_size * 21;
3288         rsurface_array_texcoord3f        = base + rsurface_array_size * 24;
3289         rsurface_array_color4f           = base + rsurface_array_size * 27;
3290 }
3291
3292 float *rsurface_modelvertex3f;
3293 int rsurface_modelvertex3f_bufferobject;
3294 size_t rsurface_modelvertex3f_bufferoffset;
3295 float *rsurface_modelsvector3f;
3296 int rsurface_modelsvector3f_bufferobject;
3297 size_t rsurface_modelsvector3f_bufferoffset;
3298 float *rsurface_modeltvector3f;
3299 int rsurface_modeltvector3f_bufferobject;
3300 size_t rsurface_modeltvector3f_bufferoffset;
3301 float *rsurface_modelnormal3f;
3302 int rsurface_modelnormal3f_bufferobject;
3303 size_t rsurface_modelnormal3f_bufferoffset;
3304 float *rsurface_vertex3f;
3305 int rsurface_vertex3f_bufferobject;
3306 size_t rsurface_vertex3f_bufferoffset;
3307 float *rsurface_svector3f;
3308 int rsurface_svector3f_bufferobject;
3309 size_t rsurface_svector3f_bufferoffset;
3310 float *rsurface_tvector3f;
3311 int rsurface_tvector3f_bufferobject;
3312 size_t rsurface_tvector3f_bufferoffset;
3313 float *rsurface_normal3f;
3314 int rsurface_normal3f_bufferobject;
3315 size_t rsurface_normal3f_bufferoffset;
3316 float *rsurface_lightmapcolor4f;
3317 int rsurface_lightmapcolor4f_bufferobject;
3318 size_t rsurface_lightmapcolor4f_bufferoffset;
3319 vec3_t rsurface_modelorg;
3320 qboolean rsurface_generatedvertex;
3321 const entity_render_t *rsurface_entity;
3322 const model_t *rsurface_model;
3323 texture_t *rsurface_texture;
3324 rtexture_t *rsurface_lightmaptexture;
3325 rtexture_t *rsurface_deluxemaptexture;
3326 rsurfmode_t rsurface_mode;
3327 int rsurface_lightmode; // 0 = lightmap or fullbright, 1 = color array from q3bsp, 2 = vertex shaded model
3328
3329 void RSurf_CleanUp(void)
3330 {
3331         CHECKGLERROR
3332         if (rsurface_mode == RSURFMODE_GLSL)
3333         {
3334                 qglUseProgramObjectARB(0);CHECKGLERROR
3335         }
3336         GL_AlphaTest(false);
3337         rsurface_mode = RSURFMODE_NONE;
3338         rsurface_lightmaptexture = NULL;
3339         rsurface_deluxemaptexture = NULL;
3340         rsurface_texture = NULL;
3341 }
3342
3343 void RSurf_ActiveWorldEntity(void)
3344 {
3345         RSurf_CleanUp();
3346         rsurface_entity = r_refdef.worldentity;
3347         rsurface_model = r_refdef.worldmodel;
3348         if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
3349                 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
3350         R_Mesh_Matrix(&identitymatrix);
3351         VectorCopy(r_view.origin, rsurface_modelorg);
3352         rsurface_modelvertex3f  = rsurface_model->surfmesh.data_vertex3f;
3353         rsurface_modelvertex3f_bufferobject = rsurface_model->surfmesh.vbo;
3354         rsurface_modelvertex3f_bufferoffset = rsurface_model->surfmesh.vbooffset_vertex3f;
3355         rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
3356         rsurface_modelsvector3f_bufferobject = rsurface_model->surfmesh.vbo;
3357         rsurface_modelsvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_svector3f;
3358         rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
3359         rsurface_modeltvector3f_bufferobject = rsurface_model->surfmesh.vbo;
3360         rsurface_modeltvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_tvector3f;
3361         rsurface_modelnormal3f  = rsurface_model->surfmesh.data_normal3f;
3362         rsurface_modelnormal3f_bufferobject = rsurface_model->surfmesh.vbo;
3363         rsurface_modelnormal3f_bufferoffset = rsurface_model->surfmesh.vbooffset_normal3f;
3364         rsurface_generatedvertex = false;
3365         rsurface_vertex3f  = rsurface_modelvertex3f;
3366         rsurface_vertex3f_bufferobject = rsurface_modelvertex3f_bufferobject;
3367         rsurface_vertex3f_bufferoffset = rsurface_modelvertex3f_bufferoffset;
3368         rsurface_svector3f = rsurface_modelsvector3f;
3369         rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject;
3370         rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset;
3371         rsurface_tvector3f = rsurface_modeltvector3f;
3372         rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject;
3373         rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset;
3374         rsurface_normal3f  = rsurface_modelnormal3f;
3375         rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject;
3376         rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset;
3377 }
3378
3379 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3380 {
3381         RSurf_CleanUp();
3382         rsurface_entity = ent;
3383         rsurface_model = ent->model;
3384         if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
3385                 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
3386         R_Mesh_Matrix(&ent->matrix);
3387         Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
3388         if (rsurface_model->surfmesh.isanimated && (rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0))
3389         {
3390                 if (wanttangents)
3391                 {
3392                         rsurface_modelvertex3f = rsurface_array_modelvertex3f;
3393                         rsurface_modelsvector3f = rsurface_array_modelsvector3f;
3394                         rsurface_modeltvector3f = rsurface_array_modeltvector3f;
3395                         rsurface_modelnormal3f = rsurface_array_modelnormal3f;
3396                         Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
3397                 }
3398                 else if (wantnormals)
3399                 {
3400                         rsurface_modelvertex3f = rsurface_array_modelvertex3f;
3401                         rsurface_modelsvector3f = NULL;
3402                         rsurface_modeltvector3f = NULL;
3403                         rsurface_modelnormal3f = rsurface_array_modelnormal3f;
3404                         Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
3405                 }
3406                 else
3407                 {
3408                         rsurface_modelvertex3f = rsurface_array_modelvertex3f;
3409                         rsurface_modelsvector3f = NULL;
3410                         rsurface_modeltvector3f = NULL;
3411                         rsurface_modelnormal3f = NULL;
3412                         Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
3413                 }
3414                 rsurface_modelvertex3f_bufferobject = 0;
3415                 rsurface_modelvertex3f_bufferoffset = 0;
3416                 rsurface_modelsvector3f_bufferobject = 0;
3417                 rsurface_modelsvector3f_bufferoffset = 0;
3418                 rsurface_modeltvector3f_bufferobject = 0;
3419                 rsurface_modeltvector3f_bufferoffset = 0;
3420                 rsurface_modelnormal3f_bufferobject = 0;
3421                 rsurface_modelnormal3f_bufferoffset = 0;
3422                 rsurface_generatedvertex = true;
3423         }
3424         else
3425         {
3426                 rsurface_modelvertex3f  = rsurface_model->surfmesh.data_vertex3f;
3427                 rsurface_modelvertex3f_bufferobject = rsurface_model->surfmesh.vbo;
3428                 rsurface_modelvertex3f_bufferoffset = rsurface_model->surfmesh.vbooffset_vertex3f;
3429                 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
3430                 rsurface_modelsvector3f_bufferobject = rsurface_model->surfmesh.vbo;
3431                 rsurface_modelsvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_svector3f;
3432                 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
3433                 rsurface_modeltvector3f_bufferobject = rsurface_model->surfmesh.vbo;
3434                 rsurface_modeltvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_tvector3f;
3435                 rsurface_modelnormal3f  = rsurface_model->surfmesh.data_normal3f;
3436                 rsurface_modelnormal3f_bufferobject = rsurface_model->surfmesh.vbo;
3437                 rsurface_modelnormal3f_bufferoffset = rsurface_model->surfmesh.vbooffset_normal3f;
3438                 rsurface_generatedvertex = false;
3439         }
3440         rsurface_vertex3f  = rsurface_modelvertex3f;
3441         rsurface_vertex3f_bufferobject = rsurface_modelvertex3f_bufferobject;
3442         rsurface_vertex3f_bufferoffset = rsurface_modelvertex3f_bufferoffset;
3443         rsurface_svector3f = rsurface_modelsvector3f;
3444         rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject;
3445         rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset;
3446         rsurface_tvector3f = rsurface_modeltvector3f;
3447         rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject;
3448         rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset;
3449         rsurface_normal3f  = rsurface_modelnormal3f;
3450         rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject;
3451         rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset;
3452 }
3453
3454 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
3455 {
3456         // if vertices are dynamic (animated models), generate them into the temporary rsurface_array_model* arrays and point rsurface_model* at them instead of the static data from the model itself
3457         if (rsurface_generatedvertex)
3458         {
3459                 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
3460                         generatetangents = true;
3461                 if (generatetangents)
3462                         generatenormals = true;
3463                 if (generatenormals && !rsurface_modelnormal3f)
3464                 {
3465                         rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
3466                         rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject = 0;
3467                         rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset = 0;
3468                         Mod_BuildNormals(0, rsurface_model->surfmesh.num_vertices, rsurface_model->surfmesh.num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_element3i, rsurface_array_modelnormal3f, r_smoothnormals_areaweighting.integer);
3469                 }
3470                 if (generatetangents && !rsurface_modelsvector3f)
3471                 {
3472                         rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
3473                         rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject = 0;
3474                         rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset = 0;
3475                         rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
3476                         rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject = 0;
3477                         rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset = 0;
3478                         Mod_BuildTextureVectorsFromNormals(0, rsurface_model->surfmesh.num_vertices, rsurface_model->surfmesh.num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_modelnormal3f, rsurface_model->surfmesh.data_element3i, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f, r_smoothnormals_areaweighting.integer);
3479                 }
3480         }
3481         // if vertices are deformed (sprite flares and things in maps, possibly water waves, bulges and other deformations), generate them into rsurface_deform* arrays from whatever the rsurface_model* array pointers point to (may be static model data or generated data for an animated model)
3482         if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
3483         {
3484                 int texturesurfaceindex;
3485                 float center[3], forward[3], right[3], up[3], v[4][3];
3486                 matrix4x4_t matrix1, imatrix1;
3487                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
3488                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
3489                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
3490                 // make deformed versions of only the model vertices used by the specified surfaces
3491                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3492                 {
3493                         int i, j;
3494                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3495                         // a single autosprite surface can contain multiple sprites...
3496                         for (j = 0;j < surface->num_vertices - 3;j += 4)
3497                         {
3498                                 VectorClear(center);
3499                                 for (i = 0;i < 4;i++)
3500                                         VectorAdd(center, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
3501                                 VectorScale(center, 0.25f, center);
3502                                 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
3503                                 {
3504                                         forward[0] = rsurface_modelorg[0] - center[0];
3505                                         forward[1] = rsurface_modelorg[1] - center[1];
3506                                         forward[2] = 0;
3507                                         VectorNormalize(forward);
3508                                         right[0] = forward[1];
3509                                         right[1] = -forward[0];
3510                                         right[2] = 0;
3511                                         VectorSet(up, 0, 0, 1);
3512                                 }
3513                                 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
3514                                 Matrix4x4_FromVectors(&matrix1, (rsurface_modelnormal3f + 3 * surface->num_firstvertex) + j*3, (rsurface_modelsvector3f + 3 * surface->num_firstvertex) + j*3, (rsurface_modeltvector3f + 3 * surface->num_firstvertex) + j*3, center);
3515                                 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
3516                                 for (i = 0;i < 4;i++)
3517                                         Matrix4x4_Transform(&imatrix1, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
3518                                 for (i = 0;i < 4;i++)
3519                                         VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
3520                         }
3521                         Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_deformednormal3f, r_smoothnormals_areaweighting.integer);
3522                         Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_array_deformednormal3f, rsurface_model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_deformedsvector3f, rsurface_array_deformedtvector3f, r_smoothnormals_areaweighting.integer);
3523                 }
3524                 rsurface_vertex3f = rsurface_array_deformedvertex3f;
3525                 rsurface_vertex3f_bufferobject = 0;
3526                 rsurface_vertex3f_bufferoffset = 0;
3527                 rsurface_svector3f = rsurface_array_deformedsvector3f;
3528                 rsurface_svector3f_bufferobject = 0;
3529                 rsurface_svector3f_bufferoffset = 0;
3530                 rsurface_tvector3f = rsurface_array_deformedtvector3f;
3531                 rsurface_tvector3f_bufferobject = 0;
3532                 rsurface_tvector3f_bufferoffset = 0;
3533                 rsurface_normal3f = rsurface_array_deformednormal3f;
3534                 rsurface_normal3f_bufferobject = 0;
3535                 rsurface_normal3f_bufferoffset = 0;
3536         }
3537         else
3538         {
3539                 rsurface_vertex3f  = rsurface_modelvertex3f;
3540                 rsurface_vertex3f_bufferobject = rsurface_modelvertex3f_bufferobject;
3541                 rsurface_vertex3f_bufferoffset = rsurface_modelvertex3f_bufferoffset;
3542                 rsurface_svector3f = rsurface_modelsvector3f;
3543                 rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject;
3544                 rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset;
3545                 rsurface_tvector3f = rsurface_modeltvector3f;
3546                 rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject;
3547                 rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset;
3548                 rsurface_normal3f  = rsurface_modelnormal3f;
3549                 rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject;
3550                 rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset;
3551         }
3552         R_Mesh_VertexPointer(rsurface_vertex3f, rsurface_vertex3f_bufferobject, rsurface_vertex3f_bufferoffset);
3553 }
3554
3555 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
3556 {
3557         int i, j;
3558         const msurface_t *surface = texturesurfacelist[0];
3559         const msurface_t *surface2;
3560         int firstvertex;
3561         int endvertex;
3562         int numvertices;
3563         int numtriangles;
3564         // TODO: lock all array ranges before render, rather than on each surface
3565         if (texturenumsurfaces == 1)
3566         {
3567                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3568                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle));
3569         }
3570         else if (r_batchmode.integer == 2)
3571         {
3572                 #define MAXBATCHTRIANGLES 4096
3573                 int batchtriangles = 0;
3574                 int batchelements[MAXBATCHTRIANGLES*3];
3575                 for (i = 0;i < texturenumsurfaces;i = j)
3576                 {
3577                         surface = texturesurfacelist[i];
3578                         j = i + 1;
3579                         if (surface->num_triangles > MAXBATCHTRIANGLES)
3580                         {
3581                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle));
3582                                 continue;
3583                         }
3584                         memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
3585                         batchtriangles = surface->num_triangles;
3586                         firstvertex = surface->num_firstvertex;
3587                         endvertex = surface->num_firstvertex + surface->num_vertices;
3588                         for (;j < texturenumsurfaces;j++)
3589                         {
3590                                 surface2 = texturesurfacelist[j];
3591                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
3592                                         break;
3593                                 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
3594                                 batchtriangles += surface2->num_triangles;
3595                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
3596                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
3597                         }
3598                         surface2 = texturesurfacelist[j-1];
3599                         numvertices = endvertex - firstvertex;
3600                         R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
3601                 }
3602         }
3603         else if (r_batchmode.integer == 1)
3604         {
3605                 for (i = 0;i < texturenumsurfaces;i = j)
3606                 {
3607                         surface = texturesurfacelist[i];
3608                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3609                                 if (texturesurfacelist[j] != surface2)
3610                                         break;
3611                         surface2 = texturesurfacelist[j-1];
3612                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3613                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3614                         GL_LockArrays(surface->num_firstvertex, numvertices);
3615                         R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle));
3616                 }
3617         }
3618         else
3619         {
3620                 for (i = 0;i < texturenumsurfaces;i++)
3621                 {
3622                         surface = texturesurfacelist[i];
3623                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3624                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle));
3625                 }
3626         }
3627 }
3628
3629 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3630 {
3631         int j;
3632         int texturesurfaceindex;
3633         if (r_showsurfaces.integer == 2)
3634         {
3635                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3636                 {
3637                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3638                         for (j = 0;j < surface->num_triangles;j++)
3639                         {
3640                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
3641                                 GL_Color(f, f, f, 1);
3642                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, 1, (rsurface_model->surfmesh.data_element3i + 3 * (j + surface->num_firsttriangle)), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * (j + surface->num_firsttriangle)));
3643                         }
3644                 }
3645         }
3646         else
3647         {
3648                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3649                 {
3650                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3651                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
3652                         GL_Color((k & 15) * (1.0f / 16.0f) * r_view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_view.colorscale, 1);
3653                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3654                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle));
3655                 }
3656         }
3657 }
3658
3659 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
3660 {
3661         int texturesurfaceindex;
3662         int i;
3663         float f;
3664         float *v, *c, *c2;
3665         if (rsurface_lightmapcolor4f)
3666         {
3667                 // generate color arrays for the surfaces in this list
3668                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3669                 {
3670                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3671                         for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
3672                         {
3673                                 f = FogPoint_Model(v);
3674                                 c2[0] = c[0] * f;
3675                                 c2[1] = c[1] * f;
3676                                 c2[2] = c[2] * f;
3677                                 c2[3] = c[3];
3678                         }
3679                 }
3680         }
3681         else
3682         {
3683                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3684                 {
3685                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3686                         for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
3687                         {
3688                                 f = FogPoint_Model(v);
3689                                 c2[0] = f;
3690                                 c2[1] = f;
3691                                 c2[2] = f;
3692                                 c2[3] = 1;
3693                         }
3694                 }
3695         }
3696         rsurface_lightmapcolor4f = rsurface_array_color4f;
3697         rsurface_lightmapcolor4f_bufferobject = 0;
3698         rsurface_lightmapcolor4f_bufferoffset = 0;
3699 }
3700
3701 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
3702 {
3703         int texturesurfaceindex;
3704         int i;
3705         float *c, *c2;
3706         if (!rsurface_lightmapcolor4f)
3707                 return;
3708         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3709         {
3710                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3711                 for (i = 0, c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
3712                 {
3713                         c2[0] = c[0] * r;
3714                         c2[1] = c[1] * g;
3715                         c2[2] = c[2] * b;
3716                         c2[3] = c[3] * a;
3717                 }
3718         }
3719         rsurface_lightmapcolor4f = rsurface_array_color4f;
3720         rsurface_lightmapcolor4f_bufferobject = 0;
3721         rsurface_lightmapcolor4f_bufferoffset = 0;
3722 }
3723
3724 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3725 {
3726         // TODO: optimize
3727         rsurface_lightmapcolor4f = NULL;
3728         rsurface_lightmapcolor4f_bufferobject = 0;
3729         rsurface_lightmapcolor4f_bufferoffset = 0;
3730         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3731         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3732         R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3733         GL_Color(r, g, b, a);
3734         R_Mesh_TexBind(0, R_GetTexture(rsurface_lightmaptexture));
3735         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3736 }
3737
3738 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3739 {
3740         // TODO: optimize applyfog && applycolor case
3741         // just apply fog if necessary, and tint the fog color array if necessary
3742         rsurface_lightmapcolor4f = NULL;
3743         rsurface_lightmapcolor4f_bufferobject = 0;
3744         rsurface_lightmapcolor4f_bufferoffset = 0;
3745         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3746         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3747         R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3748         GL_Color(r, g, b, a);
3749         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3750 }
3751
3752 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3753 {
3754         int texturesurfaceindex;
3755         int i;
3756         float *c;
3757         // TODO: optimize
3758         if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
3759         {
3760                 // generate color arrays for the surfaces in this list
3761                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3762                 {
3763                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3764                         for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
3765                         {
3766                                 if (surface->lightmapinfo->samples)
3767                                 {
3768                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
3769                                         float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
3770                                         VectorScale(lm, scale, c);
3771                                         if (surface->lightmapinfo->styles[1] != 255)
3772                                         {
3773                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
3774                                                 lm += size3;
3775                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
3776                                                 VectorMA(c, scale, lm, c);
3777                                                 if (surface->lightmapinfo->styles[2] != 255)
3778                                                 {
3779                                                         lm += size3;
3780                                                         scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
3781                                                         VectorMA(c, scale, lm, c);
3782                                                         if (surface->lightmapinfo->styles[3] != 255)
3783                                                         {
3784                                                                 lm += size3;
3785                                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
3786                                                                 VectorMA(c, scale, lm, c);
3787                                                         }
3788                                                 }
3789                                         }
3790                                 }
3791                                 else
3792                                         VectorClear(c);
3793                                 c[3] = 1;
3794                         }
3795                 }
3796                 rsurface_lightmapcolor4f = rsurface_array_color4f;
3797                 rsurface_lightmapcolor4f_bufferobject = 0;
3798                 rsurface_lightmapcolor4f_bufferoffset = 0;
3799         }
3800         else
3801         {
3802                 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
3803                 rsurface_lightmapcolor4f_bufferobject = rsurface_model->surfmesh.vbo;
3804                 rsurface_lightmapcolor4f_bufferoffset = rsurface_model->surfmesh.vbooffset_lightmapcolor4f;
3805         }
3806         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3807         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3808         R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3809         GL_Color(r, g, b, a);
3810         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3811 }
3812
3813 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3814 {
3815         int texturesurfaceindex;
3816         int i;
3817         float f;
3818         float *v, *c, *c2;
3819         vec3_t ambientcolor;
3820         vec3_t diffusecolor;
3821         vec3_t lightdir;
3822         // TODO: optimize
3823         // model lighting
3824         VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
3825         ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
3826         ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
3827         ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
3828         diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
3829         diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
3830         diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
3831         if (VectorLength2(diffusecolor) > 0)
3832         {
3833                 // generate color arrays for the surfaces in this list
3834                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3835                 {
3836                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3837                         int numverts = surface->num_vertices;
3838                         v = rsurface_vertex3f + 3 * surface->num_firstvertex;
3839                         c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
3840                         c = rsurface_array_color4f + 4 * surface->num_firstvertex;
3841                         // q3-style directional shading
3842                         for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
3843                         {
3844                                 if ((f = DotProduct(c2, lightdir)) > 0)
3845                                         VectorMA(ambientcolor, f, diffusecolor, c);
3846                                 else
3847                                         VectorCopy(ambientcolor, c);
3848                                 c[3] = a;
3849                         }
3850                 }
3851                 r = 1;
3852                 g = 1;
3853                 b = 1;
3854                 a = 1;
3855                 applycolor = false;
3856                 rsurface_lightmapcolor4f = rsurface_array_color4f;
3857                 rsurface_lightmapcolor4f_bufferobject = 0;
3858                 rsurface_lightmapcolor4f_bufferoffset = 0;
3859         }
3860         else
3861         {
3862                 r = ambientcolor[0];
3863                 g = ambientcolor[1];
3864                 b = ambientcolor[2];
3865                 rsurface_lightmapcolor4f = NULL;
3866                 rsurface_lightmapcolor4f_bufferobject = 0;
3867                 rsurface_lightmapcolor4f_bufferoffset = 0;
3868         }
3869         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3870         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3871         R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3872         GL_Color(r, g, b, a);
3873         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3874 }
3875
3876 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3877 {
3878         GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
3879         GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3880         GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3881         if (rsurface_mode != RSURFMODE_SHOWSURFACES)
3882         {
3883                 rsurface_mode = RSURFMODE_SHOWSURFACES;
3884                 GL_DepthMask(true);
3885                 GL_BlendFunc(GL_ONE, GL_ZERO);
3886                 R_Mesh_ColorPointer(NULL, 0, 0);
3887                 R_Mesh_ResetTextureState();
3888         }
3889         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3890         RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3891 }
3892
3893 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
3894 {
3895         // transparent sky would be ridiculous
3896         if ((rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3897                 return;
3898         if (rsurface_mode != RSURFMODE_SKY)
3899         {
3900                 if (rsurface_mode == RSURFMODE_GLSL)
3901                 {
3902                         qglUseProgramObjectARB(0);CHECKGLERROR
3903                 }
3904                 rsurface_mode = RSURFMODE_SKY;
3905         }
3906         if (skyrendernow)
3907         {
3908                 skyrendernow = false;
3909                 R_Sky();
3910                 // restore entity matrix
3911                 R_Mesh_Matrix(&rsurface_entity->matrix);
3912         }
3913         GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
3914         GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3915         GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3916         GL_DepthMask(true);
3917         // LordHavoc: HalfLife maps have freaky skypolys so don't use
3918         // skymasking on them, and Quake3 never did sky masking (unlike
3919         // software Quake and software Quake2), so disable the sky masking
3920         // in Quake3 maps as it causes problems with q3map2 sky tricks,
3921         // and skymasking also looks very bad when noclipping outside the
3922         // level, so don't use it then either.
3923         if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
3924         {
3925                 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
3926                 R_Mesh_ColorPointer(NULL, 0, 0);
3927                 R_Mesh_ResetTextureState();
3928                 if (skyrendermasked)
3929                 {
3930                         // depth-only (masking)
3931                         GL_ColorMask(0,0,0,0);
3932                         // just to make sure that braindead drivers don't draw
3933                         // anything despite that colormask...
3934                         GL_BlendFunc(GL_ZERO, GL_ONE);
3935                 }
3936                 else
3937                 {
3938                         // fog sky
3939                         GL_BlendFunc(GL_ONE, GL_ZERO);
3940                 }
3941                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3942                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3943                 if (skyrendermasked)
3944                         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
3945         }
3946 }
3947
3948 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
3949 {
3950         if (rsurface_mode != RSURFMODE_GLSL)
3951         {
3952                 rsurface_mode = RSURFMODE_GLSL;
3953                 R_Mesh_ResetTextureState();
3954         }
3955
3956         R_SetupSurfaceShader(vec3_origin, rsurface_lightmode == 2, 1, 1, rsurface_texture->specularscale);
3957         if (!r_glsl_permutation)
3958                 return;
3959
3960         if (rsurface_lightmode == 2)
3961                 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3962         else
3963                 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3964         R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_model->surfmesh.vbo, rsurface_model->surfmesh.vbooffset_texcoordtexture2f);
3965         R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f, rsurface_svector3f_bufferobject, rsurface_svector3f_bufferoffset);
3966         R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f, rsurface_tvector3f_bufferobject, rsurface_tvector3f_bufferoffset);
3967         R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f, rsurface_normal3f_bufferobject, rsurface_normal3f_bufferoffset);
3968         R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f, rsurface_model->surfmesh.vbo, rsurface_model->surfmesh.vbooffset_texcoordlightmap2f);
3969
3970         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3971         {
3972                 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3973                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3974                         R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3975                 R_Mesh_ColorPointer(NULL, 0, 0);
3976         }
3977         else if (rsurface_lightmaptexture)
3978         {
3979                 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
3980                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3981                         R_Mesh_TexBind(8, R_GetTexture(rsurface_deluxemaptexture));
3982                 R_Mesh_ColorPointer(NULL, 0, 0);
3983         }
3984         else
3985         {
3986                 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3987                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3988                         R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3989                 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f, rsurface_model->surfmesh.vbo, rsurface_model->surfmesh.vbooffset_lightmapcolor4f);
3990         }
3991
3992         if (rsurface_lightmaptexture && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
3993         {
3994                 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
3995                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3996                         R_Mesh_TexBind(8, R_GetTexture(rsurface_deluxemaptexture));
3997         }
3998         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3999         if (rsurface_texture->backgroundnumskinframes && !(rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4000         {
4001         }
4002 }
4003
4004 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
4005 {
4006         // OpenGL 1.3 path - anything not completely ancient
4007         int texturesurfaceindex;
4008         qboolean applycolor;
4009         qboolean applyfog;
4010         rmeshstate_t m;
4011         int layerindex;
4012         const texturelayer_t *layer;
4013         if (rsurface_mode != RSURFMODE_MULTIPASS)
4014                 rsurface_mode = RSURFMODE_MULTIPASS;
4015         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
4016         for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
4017         {
4018                 vec4_t layercolor;
4019                 int layertexrgbscale;
4020                 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4021                 {
4022                         if (layerindex == 0)
4023                                 GL_AlphaTest(true);
4024                         else
4025                         {
4026                                 GL_AlphaTest(false);
4027                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
4028                         }
4029                 }
4030                 GL_DepthMask(layer->depthmask);
4031                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
4032                 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
4033                 {
4034                         layertexrgbscale = 4;
4035                         VectorScale(layer->color, 0.25f, layercolor);
4036                 }
4037                 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
4038                 {
4039                         layertexrgbscale = 2;
4040                         VectorScale(layer->color, 0.5f, layercolor);
4041                 }
4042                 else
4043                 {
4044                         layertexrgbscale = 1;
4045                         VectorScale(layer->color, 1.0f, layercolor);
4046                 }
4047                 layercolor[3] = layer->color[3];
4048                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
4049                 R_Mesh_ColorPointer(NULL, 0, 0);
4050                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
4051                 switch (layer->type)
4052                 {
4053                 case TEXTURELAYERTYPE_LITTEXTURE:
4054                         memset(&m, 0, sizeof(m));
4055                         m.tex[0] = R_GetTexture(r_texture_white);
4056                         m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
4057                         m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
4058                         m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordlightmap2f;
4059                         m.tex[1] = R_GetTexture(layer->texture);
4060                         m.texmatrix[1] = layer->texmatrix;
4061                         m.texrgbscale[1] = layertexrgbscale;
4062                         m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
4063                         m.pointer_texcoord_bufferobject[1] = rsurface_model->surfmesh.vbo;
4064                         m.pointer_texcoord_bufferoffset[1] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
4065                         R_Mesh_TextureState(&m);
4066                         if (rsurface_lightmode == 2)
4067                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4068                         else if (rsurface_lightmaptexture)
4069                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4070                         else
4071                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4072                         break;
4073                 case TEXTURELAYERTYPE_TEXTURE:
4074                         memset(&m, 0, sizeof(m));
4075                         m.tex[0] = R_GetTexture(layer->texture);
4076                         m.texmatrix[0] = layer->texmatrix;
4077                         m.texrgbscale[0] = layertexrgbscale;
4078                         m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
4079                         m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
4080                         m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
4081                         R_Mesh_TextureState(&m);
4082                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4083                         break;
4084                 case TEXTURELAYERTYPE_FOG:
4085                         memset(&m, 0, sizeof(m));
4086                         m.texrgbscale[0] = layertexrgbscale;
4087                         if (layer->texture)
4088                         {
4089                                 m.tex[0] = R_GetTexture(layer->texture);
4090                                 m.texmatrix[0] = layer->texmatrix;
4091                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
4092                                 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
4093                                 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
4094                         }
4095                         R_Mesh_TextureState(&m);
4096                         // generate a color array for the fog pass
4097                         R_Mesh_ColorPointer(rsurface_array_color4f, 0, 0);
4098                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4099                         {
4100                                 int i;
4101                                 float f, *v, *c;
4102                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4103                                 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
4104                                 {
4105                                         f = 1 - FogPoint_Model(v);
4106                                         c[0] = layercolor[0];
4107                                         c[1] = layercolor[1];
4108                                         c[2] = layercolor[2];
4109                                         c[3] = f * layercolor[3];
4110                                 }
4111                         }
4112                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4113                         break;
4114                 default:
4115                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
4116                 }
4117                 GL_LockArrays(0, 0);
4118         }
4119         CHECKGLERROR
4120         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4121         {
4122                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4123                 GL_AlphaTest(false);
4124         }
4125 }
4126
4127 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
4128 {
4129         // OpenGL 1.1 - crusty old voodoo path
4130         int texturesurfaceindex;
4131         qboolean applyfog;
4132         rmeshstate_t m;
4133         int layerindex;
4134         const texturelayer_t *layer;
4135         if (rsurface_mode != RSURFMODE_MULTIPASS)
4136                 rsurface_mode = RSURFMODE_MULTIPASS;
4137         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
4138         for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
4139         {
4140                 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4141                 {
4142                         if (layerindex == 0)
4143                                 GL_AlphaTest(true);
4144                         else
4145                         {
4146                                 GL_AlphaTest(false);
4147                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
4148                         }
4149                 }
4150                 GL_DepthMask(layer->depthmask);
4151                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
4152                 R_Mesh_ColorPointer(NULL, 0, 0);
4153                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
4154                 switch (layer->type)
4155                 {
4156                 case TEXTURELAYERTYPE_LITTEXTURE:
4157                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
4158                         {
4159                                 // two-pass lit texture with 2x rgbscale
4160                                 // first the lightmap pass
4161                                 memset(&m, 0, sizeof(m));
4162                                 m.tex[0] = R_GetTexture(r_texture_white);
4163                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
4164                                 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
4165                                 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordlightmap2f;
4166                                 R_Mesh_TextureState(&m);
4167                                 if (rsurface_lightmode == 2)
4168                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4169                                 else if (rsurface_lightmaptexture)
4170                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4171                                 else
4172                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4173                                 GL_LockArrays(0, 0);
4174                                 // then apply the texture to it
4175                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4176                                 memset(&m, 0, sizeof(m));
4177                                 m.tex[0] = R_GetTexture(layer->texture);
4178                                 m.texmatrix[0] = layer->texmatrix;
4179                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
4180                                 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
4181                                 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
4182                                 R_Mesh_TextureState(&m);
4183                                 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
4184                         }
4185                         else
4186                         {
4187                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
4188                                 memset(&m, 0, sizeof(m));
4189                                 m.tex[0] = R_GetTexture(layer->texture);
4190                                 m.texmatrix[0] = layer->texmatrix;
4191                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
4192                                 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
4193                                 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
4194                                 R_Mesh_TextureState(&m);
4195                                 if (rsurface_lightmode == 2)
4196                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
4197                                 else
4198                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
4199                         }
4200                         break;
4201                 case TEXTURELAYERTYPE_TEXTURE:
4202                         // singletexture unlit texture with transparency support
4203                         memset(&m, 0, sizeof(m));
4204                         m.tex[0] = R_GetTexture(layer->texture);
4205                         m.texmatrix[0] = layer->texmatrix;
4206                         m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
4207                         m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
4208                         m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
4209                         R_Mesh_TextureState(&m);
4210                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
4211                         break;
4212                 case TEXTURELAYERTYPE_FOG:
4213                         // singletexture fogging
4214                         R_Mesh_ColorPointer(rsurface_array_color4f, 0, 0);
4215                         if (layer->texture)
4216                         {
4217                                 memset(&m, 0, sizeof(m));
4218                                 m.tex[0] = R_GetTexture(layer->texture);
4219                                 m.texmatrix[0] = layer->texmatrix;
4220                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
4221                                 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
4222                                 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
4223                                 R_Mesh_TextureState(&m);
4224                         }
4225                         else
4226                                 R_Mesh_ResetTextureState();
4227                         // generate a color array for the fog pass
4228                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4229                         {
4230                                 int i;
4231                                 float f, *v, *c;
4232                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4233                                 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
4234                                 {
4235                                         f = 1 - FogPoint_Model(v);
4236                                         c[0] = layer->color[0];
4237                                         c[1] = layer->color[1];
4238                                         c[2] = layer->color[2];
4239                                         c[3] = f * layer->color[3];
4240                                 }
4241                         }
4242                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4243                         break;
4244                 default:
4245                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
4246                 }
4247                 GL_LockArrays(0, 0);
4248         }
4249         CHECKGLERROR
4250         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4251         {
4252                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4253                 GL_AlphaTest(false);
4254         }
4255 }
4256
4257 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
4258 {
4259         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
4260                 return;
4261         r_shadow_rtlight = NULL;
4262         r_refdef.stats.entities_surfaces += texturenumsurfaces;
4263         CHECKGLERROR
4264         if (r_showsurfaces.integer)
4265                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
4266         else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
4267                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
4268         else if (rsurface_texture->currentnumlayers)
4269         {
4270                 GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4271                 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
4272                 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4273                 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
4274                 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
4275                 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
4276                 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4277                 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
4278                 rsurface_lightmode = ((rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
4279                 if (r_glsl.integer && gl_support_fragment_shader)
4280                         R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
4281                 else if (gl_combine.integer && r_textureunits.integer >= 2)
4282                         R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
4283                 else
4284                         R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
4285         }
4286         CHECKGLERROR
4287         GL_LockArrays(0, 0);
4288 }
4289
4290 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4291 {
4292         int i, j;
4293         int texturenumsurfaces, endsurface;
4294         texture_t *texture;
4295         msurface_t *surface;
4296         msurface_t *texturesurfacelist[1024];
4297
4298         // if the model is static it doesn't matter what value we give for
4299         // wantnormals and wanttangents, so this logic uses only rules applicable
4300         // to a model, knowing that they are meaningless otherwise
4301         if (ent == r_refdef.worldentity)
4302                 RSurf_ActiveWorldEntity();
4303         else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
4304                 RSurf_ActiveModelEntity(ent, false, false);
4305         else
4306                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
4307
4308         for (i = 0;i < numsurfaces;i = j)
4309         {
4310                 j = i + 1;
4311                 surface = rsurface_model->data_surfaces + surfacelist[i];
4312                 texture = surface->texture;
4313                 R_UpdateTextureInfo(ent, texture);
4314                 rsurface_texture = texture->currentframe;
4315                 rsurface_lightmaptexture = surface->lightmaptexture;
4316                 rsurface_deluxemaptexture = surface->deluxemaptexture;
4317                 // scan ahead until we find a different texture
4318                 endsurface = min(i + 1024, numsurfaces);
4319                 texturenumsurfaces = 0;
4320                 texturesurfacelist[texturenumsurfaces++] = surface;
4321                 for (;j < endsurface;j++)
4322                 {
4323                         surface = rsurface_model->data_surfaces + surfacelist[j];
4324                         if (texture != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
4325                                 break;
4326                         texturesurfacelist[texturenumsurfaces++] = surface;
4327                 }
4328                 // render the range of surfaces
4329                 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
4330         }
4331
4332         RSurf_CleanUp();
4333 }
4334
4335 void R_QueueSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask)
4336 {
4337         int i, j;
4338         vec3_t tempcenter, center;
4339         texture_t *texture;
4340         // break the surface list down into batches by texture and use of lightmapping
4341         for (i = 0;i < numsurfaces;i = j)
4342         {
4343                 j = i + 1;
4344                 // texture is the base texture pointer, rsurface_texture is the
4345                 // current frame/skin the texture is directing us to use (for example
4346                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
4347                 // use skin 1 instead)
4348                 texture = surfacelist[i]->texture;
4349                 rsurface_texture = texture->currentframe;
4350                 rsurface_lightmaptexture = surfacelist[i]->lightmaptexture;
4351                 rsurface_deluxemaptexture = surfacelist[i]->deluxemaptexture;
4352                 if (!(rsurface_texture->currentmaterialflags & flagsmask))
4353                 {
4354                         // if this texture is not the kind we want, skip ahead to the next one
4355                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
4356                                 ;
4357                         continue;
4358                 }
4359                 if (rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
4360                 {
4361                         // transparent surfaces get pushed off into the transparent queue
4362                         const msurface_t *surface = surfacelist[i];
4363                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
4364                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
4365                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
4366                         Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
4367                         R_MeshQueue_AddTransparent(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, rsurface_entity, surface - rsurface_model->data_surfaces, r_shadow_rtlight);
4368                 }
4369                 else
4370                 {
4371                         // simply scan ahead until we find a different texture or lightmap state
4372                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface_lightmaptexture == surfacelist[j]->lightmaptexture;j++)
4373                                 ;
4374                         // render the range of surfaces
4375                         R_DrawTextureSurfaceList(j - i, surfacelist + i);
4376                 }
4377         }
4378 }
4379
4380 float locboxvertex3f[6*4*3] =
4381 {
4382         1,0,1, 1,0,0, 1,1,0, 1,1,1,
4383         0,1,1, 0,1,0, 0,0,0, 0,0,1,
4384         1,1,1, 1,1,0, 0,1,0, 0,1,1,
4385         0,0,1, 0,0,0, 1,0,0, 1,0,1,
4386         0,0,1, 1,0,1, 1,1,1, 0,1,1,
4387         1,0,0, 0,0,0, 0,1,0, 1,1,0
4388 };
4389
4390 int locboxelement3i[6*2*3] =
4391 {
4392          0, 1, 2, 0, 2, 3,
4393          4, 5, 6, 4, 6, 7,
4394          8, 9,10, 8,10,11,
4395         12,13,14, 12,14,15,
4396         16,17,18, 16,18,19,
4397         20,21,22, 20,22,23
4398 };
4399
4400 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4401 {
4402         int i, j;
4403         cl_locnode_t *loc = (cl_locnode_t *)ent;
4404         vec3_t mins, size;
4405         float vertex3f[6*4*3];
4406         CHECKGLERROR
4407         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4408         GL_DepthMask(false);
4409         GL_DepthRange(0, 1);
4410         GL_DepthTest(true);
4411         GL_CullFace(GL_NONE);
4412         R_Mesh_Matrix(&identitymatrix);
4413
4414         R_Mesh_VertexPointer(vertex3f, 0, 0);
4415         R_Mesh_ColorPointer(NULL, 0, 0);
4416         R_Mesh_ResetTextureState();
4417
4418         i = surfacelist[0];
4419         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
4420                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
4421                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
4422                         surfacelist[0] < 0 ? 0.5f : 0.125f);
4423
4424         if (VectorCompare(loc->mins, loc->maxs))
4425         {
4426                 VectorSet(size, 2, 2, 2);
4427                 VectorMA(loc->mins, -0.5f, size, mins);
4428         }
4429         else
4430         {
4431                 VectorCopy(loc->mins, mins);
4432                 VectorSubtract(loc->maxs, loc->mins, size);
4433         }
4434
4435         for (i = 0;i < 6*4*3;)
4436                 for (j = 0;j < 3;j++, i++)
4437                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
4438
4439         R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
4440 }
4441
4442 void R_DrawLocs(void)
4443 {
4444         int index;
4445         cl_locnode_t *loc, *nearestloc;
4446         vec3_t center;
4447         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
4448         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
4449         {
4450                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
4451                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
4452         }
4453 }
4454
4455 void R_DrawCollisionBrushes(entity_render_t *ent)
4456 {
4457         int i;
4458         q3mbrush_t *brush;
4459         msurface_t *surface;
4460         model_t *model = ent->model;
4461         if (!model->brush.num_brushes)
4462                 return;
4463         CHECKGLERROR
4464         R_Mesh_ColorPointer(NULL, 0, 0);
4465         R_Mesh_ResetTextureState();
4466         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4467         GL_DepthMask(false);
4468         GL_DepthRange(0, 1);
4469         GL_DepthTest(!r_showdisabledepthtest.integer);
4470         qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
4471         for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
4472                 if (brush->colbrushf && brush->colbrushf->numtriangles)
4473                         R_DrawCollisionBrush(brush->colbrushf);
4474         for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
4475                 if (surface->num_collisiontriangles)
4476                         R_DrawCollisionSurface(ent, surface);
4477         qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
4478 }
4479
4480 void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
4481 {
4482         int i, j, k, l;
4483         const int *elements;
4484         msurface_t *surface;
4485         model_t *model = ent->model;
4486         vec3_t v;
4487         CHECKGLERROR
4488         GL_DepthRange(0, 1);
4489         GL_DepthTest(!r_showdisabledepthtest.integer);
4490         GL_DepthMask(true);
4491         GL_BlendFunc(GL_ONE, GL_ZERO);
4492         R_Mesh_ColorPointer(NULL, 0, 0);
4493         R_Mesh_ResetTextureState();
4494         for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
4495         {
4496                 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
4497                         continue;
4498                 rsurface_texture = surface->texture->currentframe;
4499                 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
4500                 {
4501                         RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
4502                         if (drawtris)
4503                         {
4504                                 if (!rsurface_texture->currentlayers->depthmask)
4505                                         GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
4506                                 else if (ent == r_refdef.worldentity)
4507                                         GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
4508                                 else
4509                                         GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
4510                                 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
4511                                 CHECKGLERROR
4512                                 qglBegin(GL_LINES);
4513                                 for (k = 0;k < surface->num_triangles;k++, elements += 3)
4514                                 {
4515 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface_vertex3f[elements[n]*3+0], rsurface_vertex3f[elements[n]*3+1], rsurface_vertex3f[elements[n]*3+2])
4516                                         GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
4517                                         GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
4518                                         GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
4519                                 }
4520                                 qglEnd();
4521                                 CHECKGLERROR
4522                         }
4523                         if (drawnormals)
4524                         {
4525                                 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
4526                                 qglBegin(GL_LINES);
4527                                 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4528                                 {
4529                                         VectorCopy(rsurface_vertex3f + l * 3, v);
4530                                         qglVertex3f(v[0], v[1], v[2]);
4531                                         VectorMA(v, 8, rsurface_svector3f + l * 3, v);
4532                                         qglVertex3f(v[0], v[1], v[2]);
4533                                 }
4534                                 qglEnd();
4535                                 CHECKGLERROR
4536                                 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
4537                                 qglBegin(GL_LINES);
4538                                 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4539                                 {
4540                                         VectorCopy(rsurface_vertex3f + l * 3, v);
4541                                         qglVertex3f(v[0], v[1], v[2]);
4542                                         VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
4543                                         qglVertex3f(v[0], v[1], v[2]);
4544                                 }
4545                                 qglEnd();
4546                                 CHECKGLERROR
4547                                 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
4548                                 qglBegin(GL_LINES);
4549                                 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4550                                 {
4551                                         VectorCopy(rsurface_vertex3f + l * 3, v);
4552                                         qglVertex3f(v[0], v[1], v[2]);
4553                                         VectorMA(v, 8, rsurface_normal3f + l * 3, v);
4554                                         qglVertex3f(v[0], v[1], v[2]);
4555                                 }
4556                                 qglEnd();
4557                                 CHECKGLERROR
4558                         }
4559                 }
4560         }
4561         rsurface_texture = NULL;
4562 }
4563
4564 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
4565 void R_DrawWorldSurfaces(qboolean skysurfaces)
4566 {
4567         int i, j, endj, f, flagsmask;
4568         int counttriangles = 0;
4569         msurface_t *surface, **surfacechain;
4570         texture_t *t;
4571         model_t *model = r_refdef.worldmodel;
4572         const int maxsurfacelist = 1024;
4573         int numsurfacelist = 0;
4574         msurface_t *surfacelist[1024];
4575         if (model == NULL)
4576                 return;
4577
4578         RSurf_ActiveWorldEntity();
4579
4580         // update light styles
4581         if (!skysurfaces && model->brushq1.light_styleupdatechains)
4582         {
4583                 for (i = 0;i < model->brushq1.light_styles;i++)
4584                 {
4585                         if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
4586                         {
4587                                 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
4588                                 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
4589                                         for (;(surface = *surfacechain);surfacechain++)
4590                                                 surface->cached_dlight = true;
4591                         }
4592                 }
4593         }
4594
4595         R_UpdateAllTextureInfo(r_refdef.worldentity);
4596         flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
4597         f = 0;
4598         t = NULL;
4599         rsurface_lightmaptexture = NULL;
4600         rsurface_deluxemaptexture = NULL;
4601         rsurface_texture = NULL;
4602         numsurfacelist = 0;
4603         j = model->firstmodelsurface;
4604         endj = j + model->nummodelsurfaces;
4605         while (j < endj)
4606         {
4607                 // quickly skip over non-visible surfaces
4608                 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
4609                         ;
4610                 // quickly iterate over visible surfaces
4611                 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
4612                 {
4613                         // process this surface
4614                         surface = model->data_surfaces + j;
4615                         // if this surface fits the criteria, add it to the list
4616                         if (surface->num_triangles)
4617                         {
4618                                 // if lightmap parameters changed, rebuild lightmap texture
4619                                 if (surface->cached_dlight)
4620                                         R_BuildLightMap(r_refdef.worldentity, surface);
4621                                 // add face to draw list
4622                                 surfacelist[numsurfacelist++] = surface;
4623                                 counttriangles += surface->num_triangles;
4624                                 if (numsurfacelist >= maxsurfacelist)
4625                                 {
4626                                         R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4627                                         numsurfacelist = 0;
4628                                 }
4629                         }
4630                 }
4631         }
4632         if (numsurfacelist)
4633                 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4634         r_refdef.stats.entities_triangles += counttriangles;
4635         RSurf_CleanUp();
4636
4637         if (r_showcollisionbrushes.integer && !skysurfaces)
4638                 R_DrawCollisionBrushes(r_refdef.worldentity);
4639
4640         if (r_showtris.integer || r_shownormals.integer)
4641                 R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
4642 }
4643
4644 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces)
4645 {
4646         int i, f, flagsmask;
4647         int counttriangles = 0;
4648         msurface_t *surface, *endsurface, **surfacechain;
4649         texture_t *t;
4650         model_t *model = ent->model;
4651         const int maxsurfacelist = 1024;
4652         int numsurfacelist = 0;
4653         msurface_t *surfacelist[1024];
4654         if (model == NULL)
4655                 return;
4656
4657         // if the model is static it doesn't matter what value we give for
4658         // wantnormals and wanttangents, so this logic uses only rules applicable
4659         // to a model, knowing that they are meaningless otherwise
4660         if (ent == r_refdef.worldentity)
4661                 RSurf_ActiveWorldEntity();
4662         else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
4663                 RSurf_ActiveModelEntity(ent, false, false);
4664         else
4665                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
4666
4667         // update light styles
4668         if (!skysurfaces && model->brushq1.light_styleupdatechains)
4669         {
4670                 for (i = 0;i < model->brushq1.light_styles;i++)
4671                 {
4672                         if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
4673                         {
4674                                 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
4675                                 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
4676                                         for (;(surface = *surfacechain);surfacechain++)
4677                                                 surface->cached_dlight = true;
4678                         }
4679                 }
4680         }
4681
4682         R_UpdateAllTextureInfo(ent);
4683         flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
4684         f = 0;
4685         t = NULL;
4686         rsurface_lightmaptexture = NULL;
4687         rsurface_deluxemaptexture = NULL;
4688         rsurface_texture = NULL;
4689         numsurfacelist = 0;
4690         surface = model->data_surfaces + model->firstmodelsurface;
4691         endsurface = surface + model->nummodelsurfaces;
4692         for (;surface < endsurface;surface++)
4693         {
4694                 // if this surface fits the criteria, add it to the list
4695                 if (surface->num_triangles)
4696                 {
4697                         // if lightmap parameters changed, rebuild lightmap texture
4698                         if (surface->cached_dlight)
4699                                 R_BuildLightMap(ent, surface);
4700                         // add face to draw list
4701                         surfacelist[numsurfacelist++] = surface;
4702                         counttriangles += surface->num_triangles;
4703                         if (numsurfacelist >= maxsurfacelist)
4704                         {
4705                                 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4706                                 numsurfacelist = 0;
4707                         }
4708                 }
4709         }
4710         if (numsurfacelist)
4711                 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4712         r_refdef.stats.entities_triangles += counttriangles;
4713         RSurf_CleanUp();
4714
4715         if (r_showcollisionbrushes.integer && !skysurfaces)
4716                 R_DrawCollisionBrushes(ent);
4717
4718         if (r_showtris.integer || r_shownormals.integer)
4719                 R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);
4720 }