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