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