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