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