reorganized a lot of renderer variables into r_refdef, and split some things out...
[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
26 mempool_t *r_main_mempool;
27 rtexturepool_t *r_main_texturepool;
28
29 //
30 // screen size info
31 //
32 r_refdef_t r_refdef;
33 r_view_t r_view;
34 r_viewcache_t r_viewcache;
35
36 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
37 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "shows surfaces as different colors"};
38 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
39 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
40 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"};
41 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"};
42 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
43 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"};
44 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"};
45 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\n"};
46 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
47 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
48 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
49 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
50 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
51 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
52 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
53 cvar_t r_q1bsp_skymasking = {0, "r_qb1sp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
54
55 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
56 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
57 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
58 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
59 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
60 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
61 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
62
63 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)"};
64
65 cvar_t r_glsl = {0, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
66 cvar_t r_glsl_offsetmapping = {0, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
67 cvar_t r_glsl_offsetmapping_reliefmapping = {0, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
68 cvar_t r_glsl_offsetmapping_scale = {0, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
69 cvar_t r_glsl_deluxemapping = {0, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
70
71 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
72 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
73 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
74
75 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
76 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
77 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
78 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
79 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
80
81 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"};
82
83 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"};
84
85 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
86
87 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"}; // used for testing renderer code changes, otherwise does nothing
88 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
89
90 rtexture_t *r_bloom_texture_screen;
91 rtexture_t *r_bloom_texture_bloom;
92 rtexture_t *r_texture_blanknormalmap;
93 rtexture_t *r_texture_white;
94 rtexture_t *r_texture_black;
95 rtexture_t *r_texture_notexture;
96 rtexture_t *r_texture_whitecube;
97 rtexture_t *r_texture_normalizationcube;
98 rtexture_t *r_texture_fogattenuation;
99 //rtexture_t *r_texture_fogintensity;
100
101 // information about each possible shader permutation
102 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
103 // currently selected permutation
104 r_glsl_permutation_t *r_glsl_permutation;
105
106 // temporary variable used by a macro
107 int fogtableindex;
108
109 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
110 {
111         int i;
112         for (i = 0;i < verts;i++)
113         {
114                 out[0] = in[0] * r;
115                 out[1] = in[1] * g;
116                 out[2] = in[2] * b;
117                 out[3] = in[3];
118                 in += 4;
119                 out += 4;
120         }
121 }
122
123 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
124 {
125         int i;
126         for (i = 0;i < verts;i++)
127         {
128                 out[0] = r;
129                 out[1] = g;
130                 out[2] = b;
131                 out[3] = a;
132                 out += 4;
133         }
134 }
135
136 // FIXME: move this to client?
137 void FOG_clear(void)
138 {
139         if (gamemode == GAME_NEHAHRA)
140         {
141                 Cvar_Set("gl_fogenable", "0");
142                 Cvar_Set("gl_fogdensity", "0.2");
143                 Cvar_Set("gl_fogred", "0.3");
144                 Cvar_Set("gl_foggreen", "0.3");
145                 Cvar_Set("gl_fogblue", "0.3");
146         }
147         r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
148 }
149
150 // FIXME: move this to client?
151 void FOG_registercvars(void)
152 {
153         int x;
154         double r, alpha;
155
156         if (gamemode == GAME_NEHAHRA)
157         {
158                 Cvar_RegisterVariable (&gl_fogenable);
159                 Cvar_RegisterVariable (&gl_fogdensity);
160                 Cvar_RegisterVariable (&gl_fogred);
161                 Cvar_RegisterVariable (&gl_foggreen);
162                 Cvar_RegisterVariable (&gl_fogblue);
163                 Cvar_RegisterVariable (&gl_fogstart);
164                 Cvar_RegisterVariable (&gl_fogend);
165         }
166
167         r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
168         for (x = 0;x < FOGTABLEWIDTH;x++)
169         {
170                 alpha = exp(r / ((double)x*(double)x));
171                 if (x == FOGTABLEWIDTH - 1)
172                         alpha = 1;
173                 r_refdef.fogtable[x] = bound(0, alpha, 1);
174         }
175 }
176
177 static void R_BuildBlankTextures(void)
178 {
179         unsigned char data[4];
180         data[0] = 128; // normal X
181         data[1] = 128; // normal Y
182         data[2] = 255; // normal Z
183         data[3] = 128; // height
184         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
185         data[0] = 255;
186         data[1] = 255;
187         data[2] = 255;
188         data[3] = 255;
189         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
190         data[0] = 0;
191         data[1] = 0;
192         data[2] = 0;
193         data[3] = 255;
194         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
195 }
196
197 static void R_BuildNoTexture(void)
198 {
199         int x, y;
200         unsigned char pix[16][16][4];
201         // this makes a light grey/dark grey checkerboard texture
202         for (y = 0;y < 16;y++)
203         {
204                 for (x = 0;x < 16;x++)
205                 {
206                         if ((y < 8) ^ (x < 8))
207                         {
208                                 pix[y][x][0] = 128;
209                                 pix[y][x][1] = 128;
210                                 pix[y][x][2] = 128;
211                                 pix[y][x][3] = 255;
212                         }
213                         else
214                         {
215                                 pix[y][x][0] = 64;
216                                 pix[y][x][1] = 64;
217                                 pix[y][x][2] = 64;
218                                 pix[y][x][3] = 255;
219                         }
220                 }
221         }
222         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
223 }
224
225 static void R_BuildWhiteCube(void)
226 {
227         unsigned char data[6*1*1*4];
228         data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
229         data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
230         data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
231         data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
232         data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
233         data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
234         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
235 }
236
237 static void R_BuildNormalizationCube(void)
238 {
239         int x, y, side;
240         vec3_t v;
241         vec_t s, t, intensity;
242 #define NORMSIZE 64
243         unsigned char data[6][NORMSIZE][NORMSIZE][4];
244         for (side = 0;side < 6;side++)
245         {
246                 for (y = 0;y < NORMSIZE;y++)
247                 {
248                         for (x = 0;x < NORMSIZE;x++)
249                         {
250                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
251                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
252                                 switch(side)
253                                 {
254                                 default:
255                                 case 0:
256                                         v[0] = 1;
257                                         v[1] = -t;
258                                         v[2] = -s;
259                                         break;
260                                 case 1:
261                                         v[0] = -1;
262                                         v[1] = -t;
263                                         v[2] = s;
264                                         break;
265                                 case 2:
266                                         v[0] = s;
267                                         v[1] = 1;
268                                         v[2] = t;
269                                         break;
270                                 case 3:
271                                         v[0] = s;
272                                         v[1] = -1;
273                                         v[2] = -t;
274                                         break;
275                                 case 4:
276                                         v[0] = s;
277                                         v[1] = -t;
278                                         v[2] = 1;
279                                         break;
280                                 case 5:
281                                         v[0] = -s;
282                                         v[1] = -t;
283                                         v[2] = -1;
284                                         break;
285                                 }
286                                 intensity = 127.0f / sqrt(DotProduct(v, v));
287                                 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
288                                 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
289                                 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
290                                 data[side][y][x][3] = 255;
291                         }
292                 }
293         }
294         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
295 }
296
297 static void R_BuildFogTexture(void)
298 {
299         int x, b;
300         double r, alpha;
301 #define FOGWIDTH 64
302         unsigned char data1[FOGWIDTH][4];
303         //unsigned char data2[FOGWIDTH][4];
304         r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
305         for (x = 0;x < FOGWIDTH;x++)
306         {
307                 alpha = exp(r / ((double)x*(double)x));
308                 if (x == FOGWIDTH - 1)
309                         alpha = 1;
310                 b = (int)(256.0 * alpha);
311                 b = bound(0, b, 255);
312                 data1[x][0] = 255 - b;
313                 data1[x][1] = 255 - b;
314                 data1[x][2] = 255 - b;
315                 data1[x][3] = 255;
316                 //data2[x][0] = b;
317                 //data2[x][1] = b;
318                 //data2[x][2] = b;
319                 //data2[x][3] = 255;
320         }
321         r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
322         //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
323 }
324
325 static const char *builtinshaderstring =
326 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
327 "// written by Forest 'LordHavoc' Hale\n"
328 "\n"
329 "// common definitions between vertex shader and fragment shader:\n"
330 "\n"
331 "varying vec2 TexCoord;\n"
332 "varying vec2 TexCoordLightmap;\n"
333 "\n"
334 "varying vec3 CubeVector;\n"
335 "varying vec3 LightVector;\n"
336 "varying vec3 EyeVector;\n"
337 "#ifdef USEFOG\n"
338 "varying vec3 EyeVectorModelSpace;\n"
339 "#endif\n"
340 "\n"
341 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
342 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
343 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
344 "\n"
345 "\n"
346 "\n"
347 "\n"
348 "// vertex shader specific:\n"
349 "#ifdef VERTEX_SHADER\n"
350 "\n"
351 "uniform vec3 LightPosition;\n"
352 "uniform vec3 EyePosition;\n"
353 "uniform vec3 LightDir;\n"
354 "\n"
355 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
356 "\n"
357 "void main(void)\n"
358 "{\n"
359 "       gl_FrontColor = gl_Color;\n"
360 "       // copy the surface texcoord\n"
361 "       TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
362 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
363 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
364 "#endif\n"
365 "\n"
366 "#ifdef MODE_LIGHTSOURCE\n"
367 "       // transform vertex position into light attenuation/cubemap space\n"
368 "       // (-1 to +1 across the light box)\n"
369 "       CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
370 "\n"
371 "       // transform unnormalized light direction into tangent space\n"
372 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
373 "       //  normalize it per pixel)\n"
374 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
375 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
376 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
377 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
378 "#endif\n"
379 "\n"
380 "#ifdef MODE_LIGHTDIRECTION\n"
381 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
382 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
383 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
384 "#endif\n"
385 "\n"
386 "       // transform unnormalized eye direction into tangent space\n"
387 "#ifndef USEFOG\n"
388 "       vec3 EyeVectorModelSpace;\n"
389 "#endif\n"
390 "       EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
391 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
392 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
393 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
394 "\n"
395 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
396 "       VectorS = gl_MultiTexCoord1.xyz;\n"
397 "       VectorT = gl_MultiTexCoord2.xyz;\n"
398 "       VectorR = gl_MultiTexCoord3.xyz;\n"
399 "#endif\n"
400 "\n"
401 "       // transform vertex to camera space, using ftransform to match non-VS\n"
402 "       // rendering\n"
403 "       gl_Position = ftransform();\n"
404 "}\n"
405 "\n"
406 "#endif // VERTEX_SHADER\n"
407 "\n"
408 "\n"
409 "\n"
410 "\n"
411 "// fragment shader specific:\n"
412 "#ifdef FRAGMENT_SHADER\n"
413 "\n"
414 "uniform sampler2D Texture_Normal;\n"
415 "uniform sampler2D Texture_Color;\n"
416 "uniform sampler2D Texture_Gloss;\n"
417 "uniform samplerCube Texture_Cube;\n"
418 "uniform sampler2D Texture_FogMask;\n"
419 "uniform sampler2D Texture_Pants;\n"
420 "uniform sampler2D Texture_Shirt;\n"
421 "uniform sampler2D Texture_Lightmap;\n"
422 "uniform sampler2D Texture_Deluxemap;\n"
423 "uniform sampler2D Texture_Glow;\n"
424 "\n"
425 "uniform vec3 LightColor;\n"
426 "uniform vec3 AmbientColor;\n"
427 "uniform vec3 DiffuseColor;\n"
428 "uniform vec3 SpecularColor;\n"
429 "uniform vec3 Color_Pants;\n"
430 "uniform vec3 Color_Shirt;\n"
431 "uniform vec3 FogColor;\n"
432 "\n"
433 "uniform float OffsetMapping_Scale;\n"
434 "uniform float OffsetMapping_Bias;\n"
435 "uniform float FogRangeRecip;\n"
436 "\n"
437 "uniform float AmbientScale;\n"
438 "uniform float DiffuseScale;\n"
439 "uniform float SpecularScale;\n"
440 "uniform float SpecularPower;\n"
441 "\n"
442 "void main(void)\n"
443 "{\n"
444 "       // apply offsetmapping\n"
445 "#ifdef USEOFFSETMAPPING\n"
446 "       vec2 TexCoordOffset = TexCoord;\n"
447 "#define TexCoord TexCoordOffset\n"
448 "\n"
449 "       vec3 eyedir = vec3(normalize(EyeVector));\n"
450 "       float depthbias = 1.0 - eyedir.z; // should this be a -?\n"
451 "       depthbias = 1.0 - depthbias * depthbias;\n"
452 "\n"
453 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
454 "       // 14 sample relief mapping: linear search and then binary search\n"
455 "       vec3 OffsetVector = vec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
456 "       vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + OffsetVector;\n"
457 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
458 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
459 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
460 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
461 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
462 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
463 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
464 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
465 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
466 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
467 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
468 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
469 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
470 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
471 "       TexCoord = RT.xy;\n"
472 "#else\n"
473 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
474 "       vec2 OffsetVector = vec2((EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333));\n"
475 "       //TexCoord += OffsetVector * 3.0;\n"
476 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
477 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
478 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
479 "#endif\n"
480 "#endif\n"
481 "\n"
482 "       // combine the diffuse textures (base, pants, shirt)\n"
483 "       vec4 color = vec4(texture2D(Texture_Color, TexCoord));\n"
484 "#ifdef USECOLORMAPPING\n"
485 "       color.rgb += vec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + vec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
486 "#endif\n"
487 "\n"
488 "\n"
489 "\n"
490 "\n"
491 "#ifdef MODE_LIGHTSOURCE\n"
492 "       // light source\n"
493 "\n"
494 "       // get the surface normal and light normal\n"
495 "       vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
496 "       vec3 diffusenormal = vec3(normalize(LightVector));\n"
497 "\n"
498 "       // calculate directional shading\n"
499 "       color.rgb *= (AmbientScale + DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
500 "#ifdef USESPECULAR\n"
501 "       vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
502 "       color.rgb += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
503 "#endif\n"
504 "\n"
505 "#ifdef USECUBEFILTER\n"
506 "       // apply light cubemap filter\n"
507 "       //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
508 "       color.rgb *= vec3(textureCube(Texture_Cube, CubeVector));\n"
509 "#endif\n"
510 "\n"
511 "       // apply light color\n"
512 "       color.rgb *= LightColor;\n"
513 "\n"
514 "       // apply attenuation\n"
515 "       //\n"
516 "       // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
517 "       // center and sharp falloff at the edge, this is about the most efficient\n"
518 "       // we can get away with as far as providing illumination.\n"
519 "       //\n"
520 "       // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
521 "       // provide significant illumination, large = slow = pain.\n"
522 "       color.rgb *= max(1.0 - dot(CubeVector, CubeVector), 0.0);\n"
523 "\n"
524 "\n"
525 "\n"
526 "\n"
527 "#elif defined(MODE_LIGHTDIRECTION)\n"
528 "       // directional model lighting\n"
529 "\n"
530 "       // get the surface normal and light normal\n"
531 "       vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
532 "       vec3 diffusenormal = vec3(normalize(LightVector));\n"
533 "\n"
534 "       // calculate directional shading\n"
535 "       color.rgb *= AmbientColor + DiffuseColor * max(dot(surfacenormal, diffusenormal), 0.0);\n"
536 "#ifdef USESPECULAR\n"
537 "       vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
538 "       color.rgb += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
539 "#endif\n"
540 "\n"
541 "\n"
542 "\n"
543 "\n"
544 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE)\n"
545 "       // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
546 "\n"
547 "       // get the surface normal and light normal\n"
548 "       vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
549 "       vec3 diffusenormal_modelspace = vec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5;\n"
550 "       vec3 diffusenormal = normalize(vec3(dot(diffusenormal_modelspace, VectorS), dot(diffusenormal_modelspace, VectorT), dot(diffusenormal_modelspace, VectorR)));\n"
551 "\n"
552 "       // calculate directional shading\n"
553 "       vec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
554 "#ifdef USESPECULAR\n"
555 "       vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
556 "       tempcolor += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
557 "#endif\n"
558 "\n"
559 "       // apply lightmap color\n"
560 "       color.rgb = tempcolor * vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * vec3(AmbientScale);\n"
561 "\n"
562 "\n"
563 "\n"
564 "\n"
565 "#elif defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
566 "       // deluxemap lightmapping using light vectors in tangentspace\n"
567 "\n"
568 "       // get the surface normal and light normal\n"
569 "       vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
570 "       vec3 diffusenormal = normalize(vec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5);\n"
571 "\n"
572 "       // calculate directional shading\n"
573 "       vec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
574 "#ifdef USESPECULAR\n"
575 "       vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
576 "       tempcolor += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
577 "#endif\n"
578 "\n"
579 "       // apply lightmap color\n"
580 "       color.rgb = tempcolor * vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * vec3(AmbientScale);\n"
581 "\n"
582 "\n"
583 "\n"
584 "\n"
585 "#else // MODE none (lightmap)\n"
586 "       // apply lightmap color\n"
587 "       color.rgb *= vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + vec3(AmbientScale);\n"
588 "#endif // MODE\n"
589 "\n"
590 "       color *= gl_Color;\n"
591 "\n"
592 "#ifdef USEGLOW\n"
593 "       color.rgb += vec3(texture2D(Texture_Glow, TexCoord));\n"
594 "#endif\n"
595 "\n"
596 "#ifdef USEFOG\n"
597 "       // apply fog\n"
598 "       float fog = texture2D(Texture_FogMask, vec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0)).x;\n"
599 "       color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
600 "#endif\n"
601 "\n"
602 "       gl_FragColor = color;\n"
603 "}\n"
604 "\n"
605 "#endif // FRAGMENT_SHADER\n"
606 ;
607
608 void R_GLSL_CompilePermutation(int permutation)
609 {
610         r_glsl_permutation_t *p = r_glsl_permutations + permutation;
611         int vertstrings_count;
612         int fragstrings_count;
613         char *shaderstring;
614         const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
615         const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
616         char permutationname[256];
617         if (p->compiled)
618                 return;
619         p->compiled = true;
620         vertstrings_list[0] = "#define VERTEX_SHADER\n";
621         fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
622         vertstrings_count = 1;
623         fragstrings_count = 1;
624         permutationname[0] = 0;
625         if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
626         {
627                 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTSOURCE\n";
628                 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTSOURCE\n";
629                 strlcat(permutationname, " lightsource", sizeof(permutationname));
630         }
631         if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE)
632         {
633                 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
634                 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
635                 strlcat(permutationname, " lightdirectionmap_modelspace", sizeof(permutationname));
636         }
637         if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)
638         {
639                 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
640                 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
641                 strlcat(permutationname, " lightdirectionmap_tangentspace", sizeof(permutationname));
642         }
643         if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
644         {
645                 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
646                 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
647                 strlcat(permutationname, " lightdirection", sizeof(permutationname));
648         }
649         if (permutation & SHADERPERMUTATION_GLOW)
650         {
651                 vertstrings_list[vertstrings_count++] = "#define USEGLOW\n";
652                 fragstrings_list[fragstrings_count++] = "#define USEGLOW\n";
653                 strlcat(permutationname, " glow", sizeof(permutationname));
654         }
655         if (permutation & SHADERPERMUTATION_COLORMAPPING)
656         {
657                 vertstrings_list[vertstrings_count++] = "#define USECOLORMAPPING\n";
658                 fragstrings_list[fragstrings_count++] = "#define USECOLORMAPPING\n";
659                 strlcat(permutationname, " colormapping", sizeof(permutationname));
660         }
661         if (permutation & SHADERPERMUTATION_SPECULAR)
662         {
663                 vertstrings_list[vertstrings_count++] = "#define USESPECULAR\n";
664                 fragstrings_list[fragstrings_count++] = "#define USESPECULAR\n";
665                 strlcat(permutationname, " specular", sizeof(permutationname));
666         }
667         if (permutation & SHADERPERMUTATION_FOG)
668         {
669                 vertstrings_list[vertstrings_count++] = "#define USEFOG\n";
670                 fragstrings_list[fragstrings_count++] = "#define USEFOG\n";
671                 strlcat(permutationname, " fog", sizeof(permutationname));
672         }
673         if (permutation & SHADERPERMUTATION_CUBEFILTER)
674         {
675                 vertstrings_list[vertstrings_count++] = "#define USECUBEFILTER\n";
676                 fragstrings_list[fragstrings_count++] = "#define USECUBEFILTER\n";
677                 strlcat(permutationname, " cubefilter", sizeof(permutationname));
678         }
679         if (permutation & SHADERPERMUTATION_OFFSETMAPPING)
680         {
681                 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING\n";
682                 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING\n";
683                 strlcat(permutationname, " offsetmapping", sizeof(permutationname));
684         }
685         if (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING)
686         {
687                 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
688                 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
689                 strlcat(permutationname, " OFFSETMAPPING_RELIEFMAPPING", sizeof(permutationname));
690         }
691         shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
692         if (shaderstring)
693         {
694                 Con_DPrintf("GLSL shader text loaded from disk\n");
695                 vertstrings_list[vertstrings_count++] = shaderstring;
696                 fragstrings_list[fragstrings_count++] = shaderstring;
697         }
698         else
699         {
700                 vertstrings_list[vertstrings_count++] = builtinshaderstring;
701                 fragstrings_list[fragstrings_count++] = builtinshaderstring;
702         }
703         p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
704         if (p->program)
705         {
706                 CHECKGLERROR
707                 qglUseProgramObjectARB(p->program);CHECKGLERROR
708                 p->loc_Texture_Normal      = qglGetUniformLocationARB(p->program, "Texture_Normal");
709                 p->loc_Texture_Color       = qglGetUniformLocationARB(p->program, "Texture_Color");
710                 p->loc_Texture_Gloss       = qglGetUniformLocationARB(p->program, "Texture_Gloss");
711                 p->loc_Texture_Cube        = qglGetUniformLocationARB(p->program, "Texture_Cube");
712                 p->loc_Texture_FogMask     = qglGetUniformLocationARB(p->program, "Texture_FogMask");
713                 p->loc_Texture_Pants       = qglGetUniformLocationARB(p->program, "Texture_Pants");
714                 p->loc_Texture_Shirt       = qglGetUniformLocationARB(p->program, "Texture_Shirt");
715                 p->loc_Texture_Lightmap    = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
716                 p->loc_Texture_Deluxemap   = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
717                 p->loc_Texture_Glow        = qglGetUniformLocationARB(p->program, "Texture_Glow");
718                 p->loc_FogColor            = qglGetUniformLocationARB(p->program, "FogColor");
719                 p->loc_LightPosition       = qglGetUniformLocationARB(p->program, "LightPosition");
720                 p->loc_EyePosition         = qglGetUniformLocationARB(p->program, "EyePosition");
721                 p->loc_LightColor          = qglGetUniformLocationARB(p->program, "LightColor");
722                 p->loc_Color_Pants         = qglGetUniformLocationARB(p->program, "Color_Pants");
723                 p->loc_Color_Shirt         = qglGetUniformLocationARB(p->program, "Color_Shirt");
724                 p->loc_FogRangeRecip       = qglGetUniformLocationARB(p->program, "FogRangeRecip");
725                 p->loc_AmbientScale        = qglGetUniformLocationARB(p->program, "AmbientScale");
726                 p->loc_DiffuseScale        = qglGetUniformLocationARB(p->program, "DiffuseScale");
727                 p->loc_SpecularPower       = qglGetUniformLocationARB(p->program, "SpecularPower");
728                 p->loc_SpecularScale       = qglGetUniformLocationARB(p->program, "SpecularScale");
729                 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
730                 p->loc_AmbientColor        = qglGetUniformLocationARB(p->program, "AmbientColor");
731                 p->loc_DiffuseColor        = qglGetUniformLocationARB(p->program, "DiffuseColor");
732                 p->loc_SpecularColor       = qglGetUniformLocationARB(p->program, "SpecularColor");
733                 p->loc_LightDir            = qglGetUniformLocationARB(p->program, "LightDir");
734                 if (p->loc_Texture_Normal >= 0)    qglUniform1iARB(p->loc_Texture_Normal, 0);
735                 if (p->loc_Texture_Color >= 0)     qglUniform1iARB(p->loc_Texture_Color, 1);
736                 if (p->loc_Texture_Gloss >= 0)     qglUniform1iARB(p->loc_Texture_Gloss, 2);
737                 if (p->loc_Texture_Cube >= 0)      qglUniform1iARB(p->loc_Texture_Cube, 3);
738                 if (p->loc_Texture_FogMask >= 0)   qglUniform1iARB(p->loc_Texture_FogMask, 4);
739                 if (p->loc_Texture_Pants >= 0)     qglUniform1iARB(p->loc_Texture_Pants, 5);
740                 if (p->loc_Texture_Shirt >= 0)     qglUniform1iARB(p->loc_Texture_Shirt, 6);
741                 if (p->loc_Texture_Lightmap >= 0)  qglUniform1iARB(p->loc_Texture_Lightmap, 7);
742                 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
743                 if (p->loc_Texture_Glow >= 0)      qglUniform1iARB(p->loc_Texture_Glow, 9);
744                 CHECKGLERROR
745                 qglUseProgramObjectARB(0);CHECKGLERROR
746         }
747         else
748                 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
749         if (shaderstring)
750                 Mem_Free(shaderstring);
751 }
752
753 void R_GLSL_Restart_f(void)
754 {
755         int i;
756         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
757                 if (r_glsl_permutations[i].program)
758                         GL_Backend_FreeProgram(r_glsl_permutations[i].program);
759         memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
760 }
761
762 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting)
763 {
764         // select a permutation of the lighting shader appropriate to this
765         // combination of texture, entity, light source, and fogging, only use the
766         // minimum features necessary to avoid wasting rendering time in the
767         // fragment shader on features that are not being used
768         int permutation = 0;
769         float specularscale = rsurface_texture->specularscale;
770         r_glsl_permutation = NULL;
771         if (r_shadow_rtlight)
772         {
773                 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
774                 specularscale *= r_shadow_rtlight->specularscale;
775                 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
776                         permutation |= SHADERPERMUTATION_CUBEFILTER;
777         }
778         else
779         {
780                 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
781                 {
782                         if (modellighting)
783                                 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
784                         else
785                         {
786                                 if (r_glsl_deluxemapping.integer >= 1 && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && rsurface_lightmaptexture)
787                                 {
788                                         if (r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
789                                                 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
790                                         else
791                                                 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
792                                 }
793                                 else if (r_glsl_deluxemapping.integer >= 2) // fake mode
794                                         permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
795                         }
796                 }
797                 if (rsurface_texture->skin.glow)
798                         permutation |= SHADERPERMUTATION_GLOW;
799         }
800         if (specularscale > 0)
801                 permutation |= SHADERPERMUTATION_SPECULAR;
802         if (r_refdef.fogenabled)
803                 permutation |= SHADERPERMUTATION_FOG;
804         if (rsurface_texture->colormapping)
805                 permutation |= SHADERPERMUTATION_COLORMAPPING;
806         if (r_glsl_offsetmapping.integer)
807         {
808                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
809                 if (r_glsl_offsetmapping_reliefmapping.integer)
810                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
811         }
812         if (!r_glsl_permutations[permutation].program)
813         {
814                 if (!r_glsl_permutations[permutation].compiled)
815                         R_GLSL_CompilePermutation(permutation);
816                 if (!r_glsl_permutations[permutation].program)
817                 {
818                         // remove features until we find a valid permutation
819                         int i;
820                         for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
821                         {
822                                 // reduce i more quickly whenever it would not remove any bits
823                                 if (permutation < i)
824                                         continue;
825                                 permutation &= i;
826                                 if (!r_glsl_permutations[permutation].compiled)
827                                         R_GLSL_CompilePermutation(permutation);
828                                 if (r_glsl_permutations[permutation].program)
829                                         break;
830                                 if (!i)
831                                         return 0; // utterly failed
832                         }
833                 }
834         }
835         r_glsl_permutation = r_glsl_permutations + permutation;
836         CHECKGLERROR
837         qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
838         R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
839         if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
840         {
841                 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
842                 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, r_shadow_entitylightorigin[0], r_shadow_entitylightorigin[1], r_shadow_entitylightorigin[2]);
843                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
844                 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
845                 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
846                 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
847         }
848         else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
849         {
850                 if (r_glsl_permutation->loc_AmbientColor >= 0)
851                         qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0], rsurface_entity->modellight_ambient[1], rsurface_entity->modellight_ambient[2]);
852                 if (r_glsl_permutation->loc_DiffuseColor >= 0)
853                         qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0], rsurface_entity->modellight_diffuse[1], rsurface_entity->modellight_diffuse[2]);
854                 if (r_glsl_permutation->loc_SpecularColor >= 0)
855                         qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface_entity->modellight_diffuse[0] * rsurface_texture->specularscale, rsurface_entity->modellight_diffuse[1] * rsurface_texture->specularscale, rsurface_entity->modellight_diffuse[2] * rsurface_texture->specularscale);
856                 if (r_glsl_permutation->loc_LightDir >= 0)
857                         qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
858         }
859         else
860         {
861                 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
862                 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
863                 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
864         }
865         if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->skin.nmap));
866         if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
867         if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
868         //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
869         if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
870         if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->skin.pants));
871         if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->skin.shirt));
872         //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
873         //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
874         if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->skin.glow));
875         if (r_glsl_permutation->loc_FogColor >= 0)
876         {
877                 // additive passes are only darkened by fog, not tinted
878                 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
879                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
880                 else
881                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
882         }
883         if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
884         if (r_glsl_permutation->loc_Color_Pants >= 0)
885         {
886                 if (rsurface_texture->skin.pants)
887                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
888                 else
889                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
890         }
891         if (r_glsl_permutation->loc_Color_Shirt >= 0)
892         {
893                 if (rsurface_texture->skin.shirt)
894                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
895                 else
896                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
897         }
898         if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
899         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
900         if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
901         CHECKGLERROR
902         return permutation;
903 }
904
905 void R_SwitchSurfaceShader(int permutation)
906 {
907         if (r_glsl_permutation != r_glsl_permutations + permutation)
908         {
909                 r_glsl_permutation = r_glsl_permutations + permutation;
910                 CHECKGLERROR
911                 qglUseProgramObjectARB(r_glsl_permutation->program);
912                 CHECKGLERROR
913         }
914 }
915
916 void gl_main_start(void)
917 {
918         r_main_texturepool = R_AllocTexturePool();
919         r_bloom_texture_screen = NULL;
920         r_bloom_texture_bloom = NULL;
921         R_BuildBlankTextures();
922         R_BuildNoTexture();
923         if (gl_texturecubemap)
924         {
925                 R_BuildWhiteCube();
926                 R_BuildNormalizationCube();
927         }
928         R_BuildFogTexture();
929         memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
930 }
931
932 void gl_main_shutdown(void)
933 {
934         R_FreeTexturePool(&r_main_texturepool);
935         r_bloom_texture_screen = NULL;
936         r_bloom_texture_bloom = NULL;
937         r_texture_blanknormalmap = NULL;
938         r_texture_white = NULL;
939         r_texture_black = NULL;
940         r_texture_whitecube = NULL;
941         r_texture_normalizationcube = NULL;
942         R_GLSL_Restart_f();
943 }
944
945 extern void CL_ParseEntityLump(char *entitystring);
946 void gl_main_newmap(void)
947 {
948         // FIXME: move this code to client
949         int l;
950         char *entities, entname[MAX_QPATH];
951         if (cl.worldmodel)
952         {
953                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
954                 l = (int)strlen(entname) - 4;
955                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
956                 {
957                         strcpy(entname + l, ".ent");
958                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
959                         {
960                                 CL_ParseEntityLump(entities);
961                                 Mem_Free(entities);
962                                 return;
963                         }
964                 }
965                 if (cl.worldmodel->brush.entities)
966                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
967         }
968 }
969
970 void GL_Main_Init(void)
971 {
972         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
973
974         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
975         FOG_registercvars(); // FIXME: move this fog stuff to client?
976         Cvar_RegisterVariable(&r_nearclip);
977         Cvar_RegisterVariable(&r_showsurfaces);
978         Cvar_RegisterVariable(&r_showtris);
979         Cvar_RegisterVariable(&r_shownormals);
980         Cvar_RegisterVariable(&r_showlighting);
981         Cvar_RegisterVariable(&r_showshadowvolumes);
982         Cvar_RegisterVariable(&r_showcollisionbrushes);
983         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
984         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
985         Cvar_RegisterVariable(&r_showdisabledepthtest);
986         Cvar_RegisterVariable(&r_drawentities);
987         Cvar_RegisterVariable(&r_drawviewmodel);
988         Cvar_RegisterVariable(&r_speeds);
989         Cvar_RegisterVariable(&r_fullbrights);
990         Cvar_RegisterVariable(&r_wateralpha);
991         Cvar_RegisterVariable(&r_dynamic);
992         Cvar_RegisterVariable(&r_fullbright);
993         Cvar_RegisterVariable(&r_q1bsp_skymasking);
994         Cvar_RegisterVariable(&r_textureunits);
995         Cvar_RegisterVariable(&r_glsl);
996         Cvar_RegisterVariable(&r_glsl_offsetmapping);
997         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
998         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
999         Cvar_RegisterVariable(&r_glsl_deluxemapping);
1000         Cvar_RegisterVariable(&r_lerpsprites);
1001         Cvar_RegisterVariable(&r_lerpmodels);
1002         Cvar_RegisterVariable(&r_waterscroll);
1003         Cvar_RegisterVariable(&r_bloom);
1004         Cvar_RegisterVariable(&r_bloom_intensity);
1005         Cvar_RegisterVariable(&r_bloom_blur);
1006         Cvar_RegisterVariable(&r_bloom_resolution);
1007         Cvar_RegisterVariable(&r_bloom_power);
1008         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1009         Cvar_RegisterVariable(&developer_texturelogging);
1010         Cvar_RegisterVariable(&gl_lightmaps);
1011         Cvar_RegisterVariable(&r_test);
1012         Cvar_RegisterVariable(&r_batchmode);
1013         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1014                 Cvar_SetValue("r_fullbrights", 0);
1015         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1016 }
1017
1018 extern void R_Textures_Init(void);
1019 extern void GL_Draw_Init(void);
1020 extern void GL_Main_Init(void);
1021 extern void R_Shadow_Init(void);
1022 extern void R_Sky_Init(void);
1023 extern void GL_Surf_Init(void);
1024 extern void R_Crosshairs_Init(void);
1025 extern void R_Light_Init(void);
1026 extern void R_Particles_Init(void);
1027 extern void R_Explosion_Init(void);
1028 extern void gl_backend_init(void);
1029 extern void Sbar_Init(void);
1030 extern void R_LightningBeams_Init(void);
1031 extern void Mod_RenderInit(void);
1032
1033 void Render_Init(void)
1034 {
1035         gl_backend_init();
1036         R_Textures_Init();
1037         GL_Main_Init();
1038         GL_Draw_Init();
1039         R_Shadow_Init();
1040         R_Sky_Init();
1041         GL_Surf_Init();
1042         R_Crosshairs_Init();
1043         R_Light_Init();
1044         R_Particles_Init();
1045         R_Explosion_Init();
1046         Sbar_Init();
1047         R_LightningBeams_Init();
1048         Mod_RenderInit();
1049 }
1050
1051 /*
1052 ===============
1053 GL_Init
1054 ===============
1055 */
1056 extern char *ENGINE_EXTENSIONS;
1057 void GL_Init (void)
1058 {
1059         VID_CheckExtensions();
1060
1061         // LordHavoc: report supported extensions
1062         Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1063
1064         // clear to black (loading plaque will be seen over this)
1065         CHECKGLERROR
1066         qglClearColor(0,0,0,1);CHECKGLERROR
1067         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1068 }
1069
1070 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1071 {
1072         int i;
1073         mplane_t *p;
1074         for (i = 0;i < 4;i++)
1075         {
1076                 p = r_view.frustum + i;
1077                 switch(p->signbits)
1078                 {
1079                 default:
1080                 case 0:
1081                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1082                                 return true;
1083                         break;
1084                 case 1:
1085                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1086                                 return true;
1087                         break;
1088                 case 2:
1089                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1090                                 return true;
1091                         break;
1092                 case 3:
1093                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1094                                 return true;
1095                         break;
1096                 case 4:
1097                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1098                                 return true;
1099                         break;
1100                 case 5:
1101                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1102                                 return true;
1103                         break;
1104                 case 6:
1105                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1106                                 return true;
1107                         break;
1108                 case 7:
1109                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1110                                 return true;
1111                         break;
1112                 }
1113         }
1114         return false;
1115 }
1116
1117 //==================================================================================
1118
1119 static void R_UpdateEntityLighting(entity_render_t *ent)
1120 {
1121         vec3_t tempdiffusenormal;
1122         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));
1123         VectorClear(ent->modellight_diffuse);
1124         VectorClear(ent->modellight_lightdir);
1125         if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1126                 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1127         else // highly rare
1128                 VectorSet(ent->modellight_ambient, 1, 1, 1);
1129         Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1130         VectorNormalize(ent->modellight_lightdir);
1131         ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1132         ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1133         ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1134         ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1135         ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1136         ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1137 }
1138
1139 static void R_View_UpdateEntityVisible (void)
1140 {
1141         int i, renderimask;
1142         entity_render_t *ent;
1143
1144         if (!r_drawentities.integer)
1145                 return;
1146
1147         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1148         if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1149         {
1150                 // worldmodel can check visibility
1151                 for (i = 0;i < r_refdef.numentities;i++)
1152                 {
1153                         ent = r_refdef.entities[i];
1154                         r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_viewcache.world_leafvisible, ent->mins, ent->maxs));
1155                 }
1156         }
1157         else
1158         {
1159                 // no worldmodel or it can't check visibility
1160                 for (i = 0;i < r_refdef.numentities;i++)
1161                 {
1162                         ent = r_refdef.entities[i];
1163                         r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST);
1164                 }
1165         }
1166 }
1167
1168 // only used if skyrendermasked, and normally returns false
1169 int R_DrawBrushModelsSky (void)
1170 {
1171         int i, sky;
1172         entity_render_t *ent;
1173
1174         if (!r_drawentities.integer)
1175                 return false;
1176
1177         sky = false;
1178         for (i = 0;i < r_refdef.numentities;i++)
1179         {
1180                 if (!r_viewcache.entityvisible[i])
1181                         continue;
1182                 ent = r_refdef.entities[i];
1183                 if (!ent->model || !ent->model->DrawSky)
1184                         continue;
1185                 ent->model->DrawSky(ent);
1186                 sky = true;
1187         }
1188         return sky;
1189 }
1190
1191 void R_DrawNoModel(entity_render_t *ent);
1192 void R_DrawModels(void)
1193 {
1194         int i;
1195         entity_render_t *ent;
1196
1197         if (!r_drawentities.integer)
1198                 return;
1199
1200         for (i = 0;i < r_refdef.numentities;i++)
1201         {
1202                 if (!r_viewcache.entityvisible[i])
1203                         continue;
1204                 ent = r_refdef.entities[i];
1205                 r_refdef.stats.entities++;
1206                 if (ent->model && ent->model->Draw != NULL)
1207                         ent->model->Draw(ent);
1208                 else
1209                         R_DrawNoModel(ent);
1210         }
1211 }
1212
1213 static void R_View_SetFrustum(void)
1214 {
1215         // break apart the view matrix into vectors for various purposes
1216         Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1217         VectorNegate(r_view.left, r_view.right);
1218
1219 #if 0
1220         r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1221         r_view.frustum[0].normal[1] = 0 - 0;
1222         r_view.frustum[0].normal[2] = -1 - 0;
1223         r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1224         r_view.frustum[1].normal[1] = 0 + 0;
1225         r_view.frustum[1].normal[2] = -1 + 0;
1226         r_view.frustum[2].normal[0] = 0 - 0;
1227         r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1228         r_view.frustum[2].normal[2] = -1 - 0;
1229         r_view.frustum[3].normal[0] = 0 + 0;
1230         r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1231         r_view.frustum[3].normal[2] = -1 + 0;
1232 #endif
1233
1234 #if 0
1235         zNear = r_refdef.nearclip;
1236         nudge = 1.0 - 1.0 / (1<<23);
1237         r_view.frustum[4].normal[0] = 0 - 0;
1238         r_view.frustum[4].normal[1] = 0 - 0;
1239         r_view.frustum[4].normal[2] = -1 - -nudge;
1240         r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1241         r_view.frustum[5].normal[0] = 0 + 0;
1242         r_view.frustum[5].normal[1] = 0 + 0;
1243         r_view.frustum[5].normal[2] = -1 + -nudge;
1244         r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1245 #endif
1246
1247
1248
1249 #if 0
1250         r_view.frustum[0].normal[0] = m[3] - m[0];
1251         r_view.frustum[0].normal[1] = m[7] - m[4];
1252         r_view.frustum[0].normal[2] = m[11] - m[8];
1253         r_view.frustum[0].dist = m[15] - m[12];
1254
1255         r_view.frustum[1].normal[0] = m[3] + m[0];
1256         r_view.frustum[1].normal[1] = m[7] + m[4];
1257         r_view.frustum[1].normal[2] = m[11] + m[8];
1258         r_view.frustum[1].dist = m[15] + m[12];
1259
1260         r_view.frustum[2].normal[0] = m[3] - m[1];
1261         r_view.frustum[2].normal[1] = m[7] - m[5];
1262         r_view.frustum[2].normal[2] = m[11] - m[9];
1263         r_view.frustum[2].dist = m[15] - m[13];
1264
1265         r_view.frustum[3].normal[0] = m[3] + m[1];
1266         r_view.frustum[3].normal[1] = m[7] + m[5];
1267         r_view.frustum[3].normal[2] = m[11] + m[9];
1268         r_view.frustum[3].dist = m[15] + m[13];
1269
1270         r_view.frustum[4].normal[0] = m[3] - m[2];
1271         r_view.frustum[4].normal[1] = m[7] - m[6];
1272         r_view.frustum[4].normal[2] = m[11] - m[10];
1273         r_view.frustum[4].dist = m[15] - m[14];
1274
1275         r_view.frustum[5].normal[0] = m[3] + m[2];
1276         r_view.frustum[5].normal[1] = m[7] + m[6];
1277         r_view.frustum[5].normal[2] = m[11] + m[10];
1278         r_view.frustum[5].dist = m[15] + m[14];
1279 #endif
1280
1281
1282
1283         VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_x, r_view.left, r_view.frustum[0].normal);
1284         VectorMAM(1, r_view.forward, 1.0 /  r_view.frustum_x, r_view.left, r_view.frustum[1].normal);
1285         VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_y, r_view.up, r_view.frustum[2].normal);
1286         VectorMAM(1, r_view.forward, 1.0 /  r_view.frustum_y, r_view.up, r_view.frustum[3].normal);
1287         VectorCopy(r_view.forward, r_view.frustum[4].normal);
1288         VectorNormalize(r_view.frustum[0].normal);
1289         VectorNormalize(r_view.frustum[1].normal);
1290         VectorNormalize(r_view.frustum[2].normal);
1291         VectorNormalize(r_view.frustum[3].normal);
1292         r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1293         r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1294         r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1295         r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1296         r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1297         PlaneClassify(&r_view.frustum[0]);
1298         PlaneClassify(&r_view.frustum[1]);
1299         PlaneClassify(&r_view.frustum[2]);
1300         PlaneClassify(&r_view.frustum[3]);
1301         PlaneClassify(&r_view.frustum[4]);
1302
1303         // LordHavoc: note to all quake engine coders, Quake had a special case
1304         // for 90 degrees which assumed a square view (wrong), so I removed it,
1305         // Quake2 has it disabled as well.
1306
1307         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1308         //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1309         //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1310         //PlaneClassify(&frustum[0]);
1311
1312         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1313         //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1314         //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1315         //PlaneClassify(&frustum[1]);
1316
1317         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1318         //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1319         //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1320         //PlaneClassify(&frustum[2]);
1321
1322         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1323         //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1324         //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1325         //PlaneClassify(&frustum[3]);
1326
1327         // nearclip plane
1328         //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1329         //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1330         //PlaneClassify(&frustum[4]);
1331 }
1332
1333 void R_View_Update(void)
1334 {
1335         // GL is weird because it's bottom to top, r_view.y is top to bottom
1336         qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1337         GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1338         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1339         R_View_SetFrustum();
1340         R_View_WorldVisibility();
1341         R_View_UpdateEntityVisible();
1342 }
1343
1344 static void R_BlendView(void)
1345 {
1346         int screenwidth, screenheight;
1347         qboolean dobloom;
1348         qboolean doblend;
1349         float vertex3f[12];
1350         float texcoord2f[3][8];
1351
1352         // set the (poorly named) screenwidth and screenheight variables to
1353         // a power of 2 at least as large as the screen, these will define the
1354         // size of the texture to allocate
1355         for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1356         for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1357
1358         doblend = r_refdef.viewblend[3] >= 0.01f;
1359         dobloom = r_bloom.integer && screenwidth <= gl_max_texture_size && screenheight <= gl_max_texture_size && r_bloom_resolution.value >= 32 && r_bloom_power.integer >= 1 && r_bloom_power.integer < 100 && r_bloom_blur.value >= 0 && r_bloom_blur.value < 512;
1360
1361         if (!dobloom && !doblend)
1362                 return;
1363
1364         GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1365         GL_DepthMask(true);
1366         GL_DepthTest(false);
1367         R_Mesh_Matrix(&identitymatrix);
1368         // vertex coordinates for a quad that covers the screen exactly
1369         vertex3f[0] = 0;vertex3f[1] = 0;vertex3f[2] = 0;
1370         vertex3f[3] = 1;vertex3f[4] = 0;vertex3f[5] = 0;
1371         vertex3f[6] = 1;vertex3f[7] = 1;vertex3f[8] = 0;
1372         vertex3f[9] = 0;vertex3f[10] = 1;vertex3f[11] = 0;
1373         R_Mesh_VertexPointer(vertex3f);
1374         R_Mesh_ColorPointer(NULL);
1375         R_Mesh_ResetTextureState();
1376         if (dobloom)
1377         {
1378                 int bloomwidth, bloomheight, x, range;
1379                 float xoffset, yoffset, r;
1380                 r_refdef.stats.bloom++;
1381                 // allocate textures as needed
1382                 if (!r_bloom_texture_screen)
1383                         r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1384                 if (!r_bloom_texture_bloom)
1385                         r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1386                 // set bloomwidth and bloomheight to the bloom resolution that will be
1387                 // used (often less than the screen resolution for faster rendering)
1388                 bloomwidth = min(r_view.width, r_bloom_resolution.integer);
1389                 bloomheight = min(r_view.height, bloomwidth * r_view.height / r_view.width);
1390                 // set up a texcoord array for the full resolution screen image
1391                 // (we have to keep this around to copy back during final render)
1392                 texcoord2f[0][0] = 0;
1393                 texcoord2f[0][1] = (float)r_view.height / (float)screenheight;
1394                 texcoord2f[0][2] = (float)r_view.width / (float)screenwidth;
1395                 texcoord2f[0][3] = (float)r_view.height / (float)screenheight;
1396                 texcoord2f[0][4] = (float)r_view.width / (float)screenwidth;
1397                 texcoord2f[0][5] = 0;
1398                 texcoord2f[0][6] = 0;
1399                 texcoord2f[0][7] = 0;
1400                 // set up a texcoord array for the reduced resolution bloom image
1401                 // (which will be additive blended over the screen image)
1402                 texcoord2f[1][0] = 0;
1403                 texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1404                 texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1405                 texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1406                 texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1407                 texcoord2f[1][5] = 0;
1408                 texcoord2f[1][6] = 0;
1409                 texcoord2f[1][7] = 0;
1410                 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1411                 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1412                 // copy view into the full resolution screen image texture
1413                 GL_ActiveTexture(0);
1414                 CHECKGLERROR
1415                 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
1416                 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1417                 // now scale it down to the bloom size and raise to a power of itself
1418                 // to darken it (this leaves the really bright stuff bright, and
1419                 // everything else becomes very dark)
1420                 // TODO: optimize with multitexture or GLSL
1421                 CHECKGLERROR
1422                 qglViewport(r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1423                 GL_BlendFunc(GL_ONE, GL_ZERO);
1424                 GL_Color(1, 1, 1, 1);
1425                 R_Mesh_Draw(0, 4, 2, polygonelements);
1426                 r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1427                 // render multiple times with a multiply blendfunc to raise to a power
1428                 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1429                 for (x = 1;x < r_bloom_power.integer;x++)
1430                 {
1431                         R_Mesh_Draw(0, 4, 2, polygonelements);
1432                         r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1433                 }
1434                 // we now have a darkened bloom image in the framebuffer, copy it into
1435                 // the bloom image texture for more processing
1436                 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1437                 R_Mesh_TexCoordPointer(0, 2, texcoord2f[2]);
1438                 GL_ActiveTexture(0);
1439                 CHECKGLERROR
1440                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1441                 r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
1442                 // blend on at multiple vertical offsets to achieve a vertical blur
1443                 // TODO: do offset blends using GLSL
1444                 range = r_bloom_blur.integer * bloomwidth / 320;
1445                 GL_BlendFunc(GL_ONE, GL_ZERO);
1446                 for (x = -range;x <= range;x++)
1447                 {
1448                         xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1449                         yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1450                         // compute a texcoord array with the specified x and y offset
1451                         texcoord2f[2][0] = xoffset+0;
1452                         texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1453                         texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1454                         texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1455                         texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1456                         texcoord2f[2][5] = yoffset+0;
1457                         texcoord2f[2][6] = xoffset+0;
1458                         texcoord2f[2][7] = yoffset+0;
1459                         // this r value looks like a 'dot' particle, fading sharply to
1460                         // black at the edges
1461                         // (probably not realistic but looks good enough)
1462                         r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1463                         if (r < 0.01f)
1464                                 continue;
1465                         GL_Color(r, r, r, 1);
1466                         R_Mesh_Draw(0, 4, 2, polygonelements);
1467                         r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1468                         GL_BlendFunc(GL_ONE, GL_ONE);
1469                 }
1470                 // copy the vertically blurred bloom view to a texture
1471                 GL_ActiveTexture(0);
1472                 CHECKGLERROR
1473                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1474                 r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
1475                 // blend the vertically blurred image at multiple offsets horizontally
1476                 // to finish the blur effect
1477                 // TODO: do offset blends using GLSL
1478                 range = r_bloom_blur.integer * bloomwidth / 320;
1479                 GL_BlendFunc(GL_ONE, GL_ZERO);
1480                 for (x = -range;x <= range;x++)
1481                 {
1482                         xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1483                         yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1484                         // compute a texcoord array with the specified x and y offset
1485                         texcoord2f[2][0] = xoffset+0;
1486                         texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1487                         texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1488                         texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1489                         texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1490                         texcoord2f[2][5] = yoffset+0;
1491                         texcoord2f[2][6] = xoffset+0;
1492                         texcoord2f[2][7] = yoffset+0;
1493                         // this r value looks like a 'dot' particle, fading sharply to
1494                         // black at the edges
1495                         // (probably not realistic but looks good enough)
1496                         r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1497                         if (r < 0.01f)
1498                                 continue;
1499                         GL_Color(r, r, r, 1);
1500                         R_Mesh_Draw(0, 4, 2, polygonelements);
1501                         r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1502                         GL_BlendFunc(GL_ONE, GL_ONE);
1503                 }
1504                 // copy the blurred bloom view to a texture
1505                 GL_ActiveTexture(0);
1506                 CHECKGLERROR
1507                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1508                 r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
1509                 // go back to full view area
1510                 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1511                 // put the original screen image back in place and blend the bloom
1512                 // texture on it
1513                 GL_Color(1,1,1,1);
1514                 GL_BlendFunc(GL_ONE, GL_ZERO);
1515                 // do both in one pass if possible
1516                 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1517                 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1518                 if (r_textureunits.integer >= 2 && gl_combine.integer)
1519                 {
1520                         R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
1521                         R_Mesh_TexBind(1, R_GetTexture(r_bloom_texture_bloom));
1522                         R_Mesh_TexCoordPointer(1, 2, texcoord2f[1]);
1523                 }
1524                 else
1525                 {
1526                         R_Mesh_Draw(0, 4, 2, polygonelements);
1527                         r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1528                         // now blend on the bloom texture
1529                         GL_BlendFunc(GL_ONE, GL_ONE);
1530                         R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1531                         R_Mesh_TexCoordPointer(0, 2, texcoord2f[1]);
1532                 }
1533                 R_Mesh_Draw(0, 4, 2, polygonelements);
1534                 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1535         }
1536         if (doblend)
1537         {
1538                 // apply a color tint to the whole view
1539                 R_Mesh_ResetTextureState();
1540                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1541                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1542                 R_Mesh_Draw(0, 4, 2, polygonelements);
1543         }
1544 }
1545
1546 void R_RenderScene(void);
1547
1548 matrix4x4_t r_waterscrollmatrix;
1549
1550 void R_UpdateVariables(void)
1551 {
1552         int i;
1553
1554         R_Textures_Frame();
1555
1556         r_refdef.farclip = 4096;
1557         if (r_refdef.worldmodel)
1558                 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1559         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
1560
1561         r_refdef.polygonfactor = 0;
1562         r_refdef.polygonoffset = 0;
1563         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
1564         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
1565
1566         r_refdef.rtworld = r_shadow_realtime_world.integer;
1567         r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1568         r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1569         r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1570         r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1571         if (r_showsurfaces.integer)
1572         {
1573                 r_refdef.rtworld = false;
1574                 r_refdef.rtworldshadows = false;
1575                 r_refdef.rtdlight = false;
1576                 r_refdef.rtdlightshadows = false;
1577                 r_refdef.lightmapintensity = 0;
1578         }
1579
1580         if (gamemode == GAME_NEHAHRA)
1581         {
1582                 if (gl_fogenable.integer)
1583                 {
1584                         r_refdef.oldgl_fogenable = true;
1585                         r_refdef.fog_density = gl_fogdensity.value;
1586                         r_refdef.fog_red = gl_fogred.value;
1587                         r_refdef.fog_green = gl_foggreen.value;
1588                         r_refdef.fog_blue = gl_fogblue.value;
1589                 }
1590                 else if (r_refdef.oldgl_fogenable)
1591                 {
1592                         r_refdef.oldgl_fogenable = false;
1593                         r_refdef.fog_density = 0;
1594                         r_refdef.fog_red = 0;
1595                         r_refdef.fog_green = 0;
1596                         r_refdef.fog_blue = 0;
1597                 }
1598         }
1599         if (r_refdef.fog_density)
1600         {
1601                 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red  , 1.0f);
1602                 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
1603                 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
1604         }
1605         if (r_refdef.fog_density)
1606         {
1607                 r_refdef.fogenabled = true;
1608                 // this is the point where the fog reaches 0.9986 alpha, which we
1609                 // consider a good enough cutoff point for the texture
1610                 // (0.9986 * 256 == 255.6)
1611                 r_refdef.fogrange = 400 / r_refdef.fog_density;
1612                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
1613                 r_refdef.fogtabledistmultiplier = FOGTABLEWIDTH * r_refdef.fograngerecip;
1614                 // fog color was already set
1615         }
1616         else
1617                 r_refdef.fogenabled = false;
1618
1619         // update some cached entity properties...
1620         for (i = 0;i < r_refdef.numentities;i++)
1621         {
1622                 entity_render_t *ent = r_refdef.entities[i];
1623                 // some of the renderer still relies on origin...
1624                 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1625                 // some of the renderer still relies on scale...
1626                 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1627                 R_UpdateEntityLighting(ent);
1628         }
1629 }
1630
1631 /*
1632 ================
1633 R_RenderView
1634 ================
1635 */
1636 void R_RenderView(void)
1637 {
1638         if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1639                 return; //Host_Error ("R_RenderView: NULL worldmodel");
1640
1641         CHECKGLERROR
1642         GL_ScissorTest(true);
1643         GL_DepthMask(true);
1644         if (r_timereport_active)
1645                 R_TimeReport("setup");
1646
1647         R_View_Update();
1648         if (r_timereport_active)
1649                 R_TimeReport("visibility");
1650
1651         R_ClearScreen();
1652         if (r_timereport_active)
1653                 R_TimeReport("clear");
1654
1655         R_RenderScene();
1656
1657         R_BlendView();
1658         if (r_timereport_active)
1659                 R_TimeReport("blendview");
1660
1661         GL_Scissor(0, 0, vid.width, vid.height);
1662         GL_ScissorTest(false);
1663         CHECKGLERROR
1664 }
1665
1666 //[515]: csqc
1667 void CSQC_R_ClearScreen (void)
1668 {
1669         if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1670                 return; //Host_Error ("R_RenderView: NULL worldmodel");
1671
1672         CHECKGLERROR
1673         GL_ScissorTest(true);
1674         GL_DepthMask(true);
1675         if (r_timereport_active)
1676                 R_TimeReport("setup");
1677
1678         R_View_Update();
1679         if (r_timereport_active)
1680                 R_TimeReport("visibility");
1681
1682         R_ClearScreen();
1683         if (r_timereport_active)
1684                 R_TimeReport("clear");
1685         CHECKGLERROR
1686 }
1687
1688 //[515]: csqc
1689 void CSQC_R_RenderScene (void)
1690 {
1691         R_RenderScene();
1692
1693         R_BlendView();
1694         if (r_timereport_active)
1695                 R_TimeReport("blendview");
1696
1697         GL_Scissor(0, 0, vid.width, vid.height);
1698         GL_ScissorTest(false);
1699         CHECKGLERROR
1700 }
1701
1702 extern void R_DrawLightningBeams (void);
1703 extern void VM_AddPolygonsToMeshQueue (void);
1704 void R_RenderScene(void)
1705 {
1706         // don't let sound skip if going slow
1707         if (r_refdef.extraupdate)
1708                 S_ExtraUpdate ();
1709
1710         CHECKGLERROR
1711         if (gl_support_fragment_shader)
1712         {
1713                 qglUseProgramObjectARB(0);CHECKGLERROR
1714         }
1715         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1716         qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1717         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1718
1719         R_MeshQueue_BeginScene();
1720
1721         if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1722                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1723         else
1724                 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1725
1726         GL_SetupView_Orientation_FromEntity(&r_view.matrix);
1727
1728         R_Shadow_UpdateWorldLightSelection();
1729
1730         R_SkyStartFrame();
1731
1732         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);
1733
1734         if (cl.csqc_vidvars.drawworld)
1735         {
1736                 // don't let sound skip if going slow
1737                 if (r_refdef.extraupdate)
1738                         S_ExtraUpdate ();
1739
1740                 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1741                 {
1742                         r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1743                         if (r_timereport_active)
1744                                 R_TimeReport("worldsky");
1745                 }
1746
1747                 if (R_DrawBrushModelsSky() && r_timereport_active)
1748                         R_TimeReport("bmodelsky");
1749
1750                 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1751                 {
1752                         r_refdef.worldmodel->Draw(r_refdef.worldentity);
1753                         if (r_timereport_active)
1754                                 R_TimeReport("world");
1755                 }
1756         }
1757
1758         // don't let sound skip if going slow
1759         if (r_refdef.extraupdate)
1760                 S_ExtraUpdate ();
1761
1762         R_DrawModels();
1763         if (r_timereport_active)
1764                 R_TimeReport("models");
1765
1766         // don't let sound skip if going slow
1767         if (r_refdef.extraupdate)
1768                 S_ExtraUpdate ();
1769
1770         R_ShadowVolumeLighting(false);
1771         if (r_timereport_active)
1772                 R_TimeReport("rtlights");
1773
1774         // don't let sound skip if going slow
1775         if (r_refdef.extraupdate)
1776                 S_ExtraUpdate ();
1777
1778         if (cl.csqc_vidvars.drawworld)
1779         {
1780                 R_DrawLightningBeams();
1781                 if (r_timereport_active)
1782                         R_TimeReport("lightning");
1783
1784                 R_DrawParticles();
1785                 if (r_timereport_active)
1786                         R_TimeReport("particles");
1787
1788                 R_DrawExplosions();
1789                 if (r_timereport_active)
1790                         R_TimeReport("explosions");
1791         }
1792
1793         VM_AddPolygonsToMeshQueue();
1794
1795         R_MeshQueue_RenderTransparent();
1796         if (r_timereport_active)
1797                 R_TimeReport("drawtrans");
1798
1799         if (cl.csqc_vidvars.drawworld)
1800         {
1801                 R_DrawCoronas();
1802                 if (r_timereport_active)
1803                         R_TimeReport("coronas");
1804         }
1805         if(cl.csqc_vidvars.drawcrosshair)
1806         {
1807                 R_DrawWorldCrosshair();
1808                 if (r_timereport_active)
1809                         R_TimeReport("crosshair");
1810         }
1811
1812         // don't let sound skip if going slow
1813         if (r_refdef.extraupdate)
1814                 S_ExtraUpdate ();
1815
1816         CHECKGLERROR
1817         if (gl_support_fragment_shader)
1818         {
1819                 qglUseProgramObjectARB(0);CHECKGLERROR
1820         }
1821         qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1822         qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1823 }
1824
1825 /*
1826 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1827 {
1828         int i;
1829         float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1830         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1831         GL_DepthMask(false);
1832         GL_DepthTest(true);
1833         R_Mesh_Matrix(&identitymatrix);
1834
1835         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1836         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1837         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1838         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1839         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1840         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1841         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1842         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1843         R_FillColors(color, 8, cr, cg, cb, ca);
1844         if (r_refdef.fogenabled)
1845         {
1846                 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1847                 {
1848                         f2 = VERTEXFOGTABLE(VectorDistance(v, r_view.origin));
1849                         f1 = 1 - f2;
1850                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
1851                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
1852                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
1853                 }
1854         }
1855         R_Mesh_VertexPointer(vertex3f);
1856         R_Mesh_ColorPointer(color);
1857         R_Mesh_ResetTextureState();
1858         R_Mesh_Draw(8, 12);
1859 }
1860 */
1861
1862 int nomodelelements[24] =
1863 {
1864         5, 2, 0,
1865         5, 1, 2,
1866         5, 0, 3,
1867         5, 3, 1,
1868         0, 2, 4,
1869         2, 1, 4,
1870         3, 0, 4,
1871         1, 3, 4
1872 };
1873
1874 float nomodelvertex3f[6*3] =
1875 {
1876         -16,   0,   0,
1877          16,   0,   0,
1878           0, -16,   0,
1879           0,  16,   0,
1880           0,   0, -16,
1881           0,   0,  16
1882 };
1883
1884 float nomodelcolor4f[6*4] =
1885 {
1886         0.0f, 0.0f, 0.5f, 1.0f,
1887         0.0f, 0.0f, 0.5f, 1.0f,
1888         0.0f, 0.5f, 0.0f, 1.0f,
1889         0.0f, 0.5f, 0.0f, 1.0f,
1890         0.5f, 0.0f, 0.0f, 1.0f,
1891         0.5f, 0.0f, 0.0f, 1.0f
1892 };
1893
1894 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
1895 {
1896         int i;
1897         float f1, f2, *c;
1898         float color4f[6*4];
1899         // this is only called once per entity so numsurfaces is always 1, and
1900         // surfacelist is always {0}, so this code does not handle batches
1901         R_Mesh_Matrix(&ent->matrix);
1902
1903         if (ent->flags & EF_ADDITIVE)
1904         {
1905                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1906                 GL_DepthMask(false);
1907         }
1908         else if (ent->alpha < 1)
1909         {
1910                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1911                 GL_DepthMask(false);
1912         }
1913         else
1914         {
1915                 GL_BlendFunc(GL_ONE, GL_ZERO);
1916                 GL_DepthMask(true);
1917         }
1918         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1919         R_Mesh_VertexPointer(nomodelvertex3f);
1920         if (r_refdef.fogenabled)
1921         {
1922                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1923                 R_Mesh_ColorPointer(color4f);
1924                 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_view.origin));
1925                 f1 = 1 - f2;
1926                 for (i = 0, c = color4f;i < 6;i++, c += 4)
1927                 {
1928                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
1929                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
1930                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
1931                         c[3] *= ent->alpha;
1932                 }
1933         }
1934         else if (ent->alpha != 1)
1935         {
1936                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1937                 R_Mesh_ColorPointer(color4f);
1938                 for (i = 0, c = color4f;i < 6;i++, c += 4)
1939                         c[3] *= ent->alpha;
1940         }
1941         else
1942                 R_Mesh_ColorPointer(nomodelcolor4f);
1943         R_Mesh_ResetTextureState();
1944         R_Mesh_Draw(0, 6, 8, nomodelelements);
1945 }
1946
1947 void R_DrawNoModel(entity_render_t *ent)
1948 {
1949         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1950                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
1951         //else
1952         //      R_DrawNoModelCallback(ent, 0);
1953 }
1954
1955 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1956 {
1957         vec3_t right1, right2, diff, normal;
1958
1959         VectorSubtract (org2, org1, normal);
1960
1961         // calculate 'right' vector for start
1962         VectorSubtract (r_view.origin, org1, diff);
1963         CrossProduct (normal, diff, right1);
1964         VectorNormalize (right1);
1965
1966         // calculate 'right' vector for end
1967         VectorSubtract (r_view.origin, org2, diff);
1968         CrossProduct (normal, diff, right2);
1969         VectorNormalize (right2);
1970
1971         vert[ 0] = org1[0] + width * right1[0];
1972         vert[ 1] = org1[1] + width * right1[1];
1973         vert[ 2] = org1[2] + width * right1[2];
1974         vert[ 3] = org1[0] - width * right1[0];
1975         vert[ 4] = org1[1] - width * right1[1];
1976         vert[ 5] = org1[2] - width * right1[2];
1977         vert[ 6] = org2[0] - width * right2[0];
1978         vert[ 7] = org2[1] - width * right2[1];
1979         vert[ 8] = org2[2] - width * right2[2];
1980         vert[ 9] = org2[0] + width * right2[0];
1981         vert[10] = org2[1] + width * right2[1];
1982         vert[11] = org2[2] + width * right2[2];
1983 }
1984
1985 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1986
1987 void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_t *fogtexture, int depthdisable, 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)
1988 {
1989         float fog = 0.0f, ifog;
1990         float vertex3f[12];
1991
1992         if (r_refdef.fogenabled)
1993                 fog = VERTEXFOGTABLE(VectorDistance(origin, r_view.origin));
1994         ifog = 1 - fog;
1995
1996         R_Mesh_Matrix(&identitymatrix);
1997         GL_BlendFunc(blendfunc1, blendfunc2);
1998         GL_DepthMask(false);
1999         GL_DepthTest(!depthdisable);
2000
2001         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2002         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2003         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2004         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2005         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2006         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2007         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2008         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2009         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2010         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2011         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2012         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2013
2014         R_Mesh_VertexPointer(vertex3f);
2015         R_Mesh_ColorPointer(NULL);
2016         R_Mesh_ResetTextureState();
2017         R_Mesh_TexBind(0, R_GetTexture(texture));
2018         R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2019         GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2020         R_Mesh_Draw(0, 4, 2, polygonelements);
2021
2022         if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2023         {
2024                 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2025                 GL_BlendFunc(blendfunc1, GL_ONE);
2026                 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
2027                 R_Mesh_Draw(0, 4, 2, polygonelements);
2028         }
2029 }
2030
2031 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2032 {
2033         int i;
2034         float *vertex3f;
2035         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2036                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2037                         break;
2038         if (i == mesh->numvertices)
2039         {
2040                 if (mesh->numvertices < mesh->maxvertices)
2041                 {
2042                         VectorCopy(v, vertex3f);
2043                         mesh->numvertices++;
2044                 }
2045                 return mesh->numvertices;
2046         }
2047         else
2048                 return i;
2049 }
2050
2051 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2052 {
2053         int i;
2054         int *e, element[3];
2055         element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2056         element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2057         e = mesh->element3i + mesh->numtriangles * 3;
2058         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2059         {
2060                 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2061                 if (mesh->numtriangles < mesh->maxtriangles)
2062                 {
2063                         *e++ = element[0];
2064                         *e++ = element[1];
2065                         *e++ = element[2];
2066                         mesh->numtriangles++;
2067                 }
2068                 element[1] = element[2];
2069         }
2070 }
2071
2072 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2073 {
2074         int planenum, planenum2;
2075         int w;
2076         int tempnumpoints;
2077         mplane_t *plane, *plane2;
2078         float temppoints[2][256*3];
2079         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2080         {
2081                 w = 0;
2082                 tempnumpoints = 4;
2083                 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2084                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2085                 {
2086                         if (planenum2 == planenum)
2087                                 continue;
2088                         PolygonF_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, 1.0/32.0, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
2089                         w = !w;
2090                 }
2091                 if (tempnumpoints < 3)
2092                         continue;
2093                 // generate elements forming a triangle fan for this polygon
2094                 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2095         }
2096 }
2097
2098 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2099 {
2100         int i;
2101         R_Mesh_VertexPointer(brush->points->v);
2102         i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2103         GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2104         GL_LockArrays(0, brush->numpoints);
2105         R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2106         GL_LockArrays(0, 0);
2107 }
2108
2109 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2110 {
2111         int i;
2112         if (!surface->num_collisiontriangles)
2113                 return;
2114         R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2115         i = (int)(((size_t)surface) / sizeof(msurface_t));
2116         GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2117         GL_LockArrays(0, surface->num_collisionvertices);
2118         R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2119         GL_LockArrays(0, 0);
2120 }
2121
2122 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)
2123 {
2124         texturelayer_t *layer;
2125         layer = t->currentlayers + t->currentnumlayers++;
2126         layer->type = type;
2127         layer->depthmask = depthmask;
2128         layer->blendfunc1 = blendfunc1;
2129         layer->blendfunc2 = blendfunc2;
2130         layer->texture = texture;
2131         layer->texmatrix = *matrix;
2132         layer->color[0] = r;
2133         layer->color[1] = g;
2134         layer->color[2] = b;
2135         layer->color[3] = a;
2136 }
2137
2138 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2139 {
2140         // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2141         //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2142
2143         {
2144                 texture_t *texture = t;
2145                 model_t *model = ent->model;
2146                 int s = ent->skinnum;
2147                 if ((unsigned int)s >= (unsigned int)model->numskins)
2148                         s = 0;
2149                 if (model->skinscenes)
2150                 {
2151                         if (model->skinscenes[s].framecount > 1)
2152                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2153                         else
2154                                 s = model->skinscenes[s].firstframe;
2155                 }
2156                 if (s > 0)
2157                         t = t + s * model->num_surfaces;
2158                 if (t->animated)
2159                         t = t->anim_frames[ent->frame != 0][(t->anim_total[ent->frame != 0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[ent->frame != 0]) : 0];
2160                 texture->currentframe = t;
2161         }
2162
2163         t->currentmaterialflags = t->basematerialflags;
2164         t->currentalpha = ent->alpha;
2165         if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2166                 t->currentalpha *= r_wateralpha.value;
2167         if (!(ent->flags & RENDER_LIGHT))
2168                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2169         if (ent->effects & EF_ADDITIVE)
2170                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2171         else if (t->currentalpha < 1)
2172                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2173         if (ent->effects & EF_NODEPTHTEST)
2174                 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2175         if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2176                 t->currenttexmatrix = r_waterscrollmatrix;
2177         else
2178                 t->currenttexmatrix = identitymatrix;
2179
2180         t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2181         t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2182         t->glosstexture = r_texture_white;
2183         t->specularpower = 8;
2184         t->specularscale = 0;
2185         if (r_shadow_gloss.integer > 0)
2186         {
2187                 if (t->skin.gloss)
2188                 {
2189                         if (r_shadow_glossintensity.value > 0)
2190                         {
2191                                 t->glosstexture = t->skin.gloss;
2192                                 t->specularscale = r_shadow_glossintensity.value;
2193                         }
2194                 }
2195                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2196                         t->specularscale = r_shadow_gloss2intensity.value;
2197         }
2198
2199         t->currentnumlayers = 0;
2200         if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2201         {
2202                 if (gl_lightmaps.integer)
2203                         R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2204                 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2205                 {
2206                         int blendfunc1, blendfunc2, depthmask;
2207                         if (t->currentmaterialflags & MATERIALFLAG_ADD)
2208                         {
2209                                 blendfunc1 = GL_SRC_ALPHA;
2210                                 blendfunc2 = GL_ONE;
2211                         }
2212                         else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2213                         {
2214                                 blendfunc1 = GL_SRC_ALPHA;
2215                                 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2216                         }
2217                         else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2218                         {
2219                                 blendfunc1 = t->customblendfunc[0];
2220                                 blendfunc2 = t->customblendfunc[1];
2221                         }
2222                         else
2223                         {
2224                                 blendfunc1 = GL_ONE;
2225                                 blendfunc2 = GL_ZERO;
2226                         }
2227                         depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2228                         if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2229                         {
2230                                 rtexture_t *currentbasetexture;
2231                                 int layerflags = 0;
2232                                 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2233                                         layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2234                                 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2235                                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2236                                 {
2237                                         // fullbright is not affected by r_refdef.lightmapintensity
2238                                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2239                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2240                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.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);
2241                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2242                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.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);
2243                                 }
2244                                 else
2245                                 {
2246                                         float colorscale;
2247                                         colorscale = 2;
2248                                         // q3bsp has no lightmap updates, so the lightstylevalue that
2249                                         // would normally be baked into the lightmap must be
2250                                         // applied to the color
2251                                         if (ent->model->type == mod_brushq3)
2252                                                 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2253                                         colorscale *= r_refdef.lightmapintensity;
2254                                         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);
2255                                         if (r_ambient.value >= (1.0f/64.0f))
2256                                                 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);
2257                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2258                                         {
2259                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->skin.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);
2260                                                 if (r_ambient.value >= (1.0f/64.0f))
2261                                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.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);
2262                                         }
2263                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2264                                         {
2265                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->skin.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);
2266                                                 if (r_ambient.value >= (1.0f/64.0f))
2267                                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.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);
2268                                         }
2269                                 }
2270                                 if (t->skin.glow != NULL)
2271                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2272                                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2273                                 {
2274                                         // if this is opaque use alpha blend which will darken the earlier
2275                                         // passes cheaply.
2276                                         //
2277                                         // if this is an alpha blended material, all the earlier passes
2278                                         // were darkened by fog already, so we only need to add the fog
2279                                         // color ontop through the fog mask texture
2280                                         //
2281                                         // if this is an additive blended material, all the earlier passes
2282                                         // were darkened by fog already, and we should not add fog color
2283                                         // (because the background was not darkened, there is no fog color
2284                                         // that was lost behind it).
2285                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->skin.fog, &identitymatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha);
2286                                 }
2287                         }
2288                 }
2289         }
2290 }
2291
2292 void R_UpdateAllTextureInfo(entity_render_t *ent)
2293 {
2294         int i;
2295         if (ent->model)
2296                 for (i = 0;i < ent->model->num_textures;i++)
2297                         R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2298 }
2299
2300 int rsurface_array_size = 0;
2301 float *rsurface_array_modelvertex3f = NULL;
2302 float *rsurface_array_modelsvector3f = NULL;
2303 float *rsurface_array_modeltvector3f = NULL;
2304 float *rsurface_array_modelnormal3f = NULL;
2305 float *rsurface_array_deformedvertex3f = NULL;
2306 float *rsurface_array_deformedsvector3f = NULL;
2307 float *rsurface_array_deformedtvector3f = NULL;
2308 float *rsurface_array_deformednormal3f = NULL;
2309 float *rsurface_array_color4f = NULL;
2310 float *rsurface_array_texcoord3f = NULL;
2311
2312 void R_Mesh_ResizeArrays(int newvertices)
2313 {
2314         float *base;
2315         if (rsurface_array_size >= newvertices)
2316                 return;
2317         if (rsurface_array_modelvertex3f)
2318                 Mem_Free(rsurface_array_modelvertex3f);
2319         rsurface_array_size = (newvertices + 1023) & ~1023;
2320         base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2321         rsurface_array_modelvertex3f     = base + rsurface_array_size * 0;
2322         rsurface_array_modelsvector3f    = base + rsurface_array_size * 3;
2323         rsurface_array_modeltvector3f    = base + rsurface_array_size * 6;
2324         rsurface_array_modelnormal3f     = base + rsurface_array_size * 9;
2325         rsurface_array_deformedvertex3f  = base + rsurface_array_size * 12;
2326         rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2327         rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2328         rsurface_array_deformednormal3f  = base + rsurface_array_size * 21;
2329         rsurface_array_texcoord3f        = base + rsurface_array_size * 24;
2330         rsurface_array_color4f           = base + rsurface_array_size * 27;
2331 }
2332
2333 float *rsurface_modelvertex3f;
2334 float *rsurface_modelsvector3f;
2335 float *rsurface_modeltvector3f;
2336 float *rsurface_modelnormal3f;
2337 float *rsurface_vertex3f;
2338 float *rsurface_svector3f;
2339 float *rsurface_tvector3f;
2340 float *rsurface_normal3f;
2341 float *rsurface_lightmapcolor4f;
2342 vec3_t rsurface_modelorg;
2343 qboolean rsurface_generatedvertex;
2344 const entity_render_t *rsurface_entity;
2345 const model_t *rsurface_model;
2346 texture_t *rsurface_texture;
2347 rtexture_t *rsurface_lightmaptexture;
2348 rsurfmode_t rsurface_mode;
2349 texture_t *rsurface_glsl_texture;
2350 qboolean rsurface_glsl_uselightmap;
2351
2352 void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2353 {
2354         Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2355         rsurface_entity = ent;
2356         rsurface_model = ent->model;
2357         if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2358                 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2359         R_Mesh_Matrix(&ent->matrix);
2360         Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2361         if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && (rsurface_model->surfmesh.data_morphvertex3f || rsurface_model->surfmesh.data_vertexweightindex4i))
2362         {
2363                 if (wanttangents)
2364                 {
2365                         rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2366                         rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2367                         rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2368                         rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2369                         Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2370                 }
2371                 else if (wantnormals)
2372                 {
2373                         rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2374                         rsurface_modelsvector3f = NULL;
2375                         rsurface_modeltvector3f = NULL;
2376                         rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2377                         Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2378                 }
2379                 else
2380                 {
2381                         rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2382                         rsurface_modelsvector3f = NULL;
2383                         rsurface_modeltvector3f = NULL;
2384                         rsurface_modelnormal3f = NULL;
2385                         Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2386                 }
2387                 rsurface_generatedvertex = true;
2388         }
2389         else
2390         {
2391                 rsurface_modelvertex3f  = rsurface_model->surfmesh.data_vertex3f;
2392                 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2393                 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2394                 rsurface_modelnormal3f  = rsurface_model->surfmesh.data_normal3f;
2395                 rsurface_generatedvertex = false;
2396         }
2397         rsurface_vertex3f  = rsurface_modelvertex3f;
2398         rsurface_svector3f = rsurface_modelsvector3f;
2399         rsurface_tvector3f = rsurface_modeltvector3f;
2400         rsurface_normal3f  = rsurface_modelnormal3f;
2401         rsurface_mode = RSURFMODE_NONE;
2402         rsurface_lightmaptexture = NULL;
2403         rsurface_texture = NULL;
2404         rsurface_glsl_texture = NULL;
2405         rsurface_glsl_uselightmap = false;
2406 }
2407
2408 void RSurf_CleanUp(void)
2409 {
2410         CHECKGLERROR
2411         if (rsurface_mode == RSURFMODE_GLSL)
2412         {
2413                 qglUseProgramObjectARB(0);CHECKGLERROR
2414         }
2415         GL_AlphaTest(false);
2416         rsurface_mode = RSURFMODE_NONE;
2417         rsurface_lightmaptexture = NULL;
2418         rsurface_texture = NULL;
2419         rsurface_glsl_texture = NULL;
2420         rsurface_glsl_uselightmap = false;
2421 }
2422
2423 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2424 {
2425         if (rsurface_generatedvertex)
2426         {
2427                 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2428                         generatetangents = true;
2429                 if (generatetangents)
2430                         generatenormals = true;
2431                 if (generatenormals && !rsurface_modelnormal3f)
2432                 {
2433                         rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2434                         Mod_BuildNormals(0, rsurface_model->surfmesh.num_vertices, rsurface_model->surfmesh.num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_element3i, rsurface_array_modelnormal3f, r_smoothnormals_areaweighting.integer);
2435                 }
2436                 if (generatetangents && !rsurface_modelsvector3f)
2437                 {
2438                         rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2439                         rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2440                         Mod_BuildTextureVectorsFromNormals(0, rsurface_model->surfmesh.num_vertices, rsurface_model->surfmesh.num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_modelnormal3f, rsurface_model->surfmesh.data_element3i, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f, r_smoothnormals_areaweighting.integer);
2441                 }
2442         }
2443         if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2444         {
2445                 int texturesurfaceindex;
2446                 float center[3], forward[3], right[3], up[3], v[4][3];
2447                 matrix4x4_t matrix1, imatrix1;
2448                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
2449                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
2450                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
2451                 // make deformed versions of only the vertices used by the specified surfaces
2452                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2453                 {
2454                         int i, j;
2455                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2456                         // a single autosprite surface can contain multiple sprites...
2457                         for (j = 0;j < surface->num_vertices - 3;j += 4)
2458                         {
2459                                 VectorClear(center);
2460                                 for (i = 0;i < 4;i++)
2461                                         VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2462                                 VectorScale(center, 0.25f, center);
2463                                 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2464                                 {
2465                                         forward[0] = rsurface_modelorg[0] - center[0];
2466                                         forward[1] = rsurface_modelorg[1] - center[1];
2467                                         forward[2] = 0;
2468                                         VectorNormalize(forward);
2469                                         right[0] = forward[1];
2470                                         right[1] = -forward[0];
2471                                         right[2] = 0;
2472                                         VectorSet(up, 0, 0, 1);
2473                                 }
2474                                 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2475                                 Matrix4x4_FromVectors(&matrix1, (rsurface_normal3f + 3 * surface->num_firstvertex) + j*3, (rsurface_svector3f + 3 * surface->num_firstvertex) + j*3, (rsurface_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
2476                                 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2477                                 for (i = 0;i < 4;i++)
2478                                         Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2479                                 for (i = 0;i < 4;i++)
2480                                         VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_modelvertex3f + (surface->num_firstvertex+i+j) * 3);
2481                         }
2482                         Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_deformednormal3f, r_smoothnormals_areaweighting.integer);
2483                         Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_array_deformednormal3f, rsurface_model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_deformedsvector3f, rsurface_array_deformedtvector3f, r_smoothnormals_areaweighting.integer);
2484                 }
2485                 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2486                 rsurface_svector3f = rsurface_array_deformedsvector3f;
2487                 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2488                 rsurface_normal3f = rsurface_array_deformednormal3f;
2489         }
2490         R_Mesh_VertexPointer(rsurface_vertex3f);
2491 }
2492
2493 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
2494 {
2495         int texturesurfaceindex;
2496         const msurface_t *surface = texturesurfacelist[0];
2497         int firstvertex = surface->num_firstvertex;
2498         int endvertex = surface->num_firstvertex + surface->num_vertices;
2499         if (texturenumsurfaces == 1)
2500         {
2501                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2502                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2503         }
2504         else if (r_batchmode.integer == 2)
2505         {
2506                 #define MAXBATCHTRIANGLES 4096
2507                 int batchtriangles = 0;
2508                 int batchelements[MAXBATCHTRIANGLES*3];
2509                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2510                 {
2511                         surface = texturesurfacelist[texturesurfaceindex];
2512                         if (surface->num_triangles >= 256 || (batchtriangles == 0 && texturesurfaceindex + 1 >= texturenumsurfaces))
2513                         {
2514                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2515                                 continue;
2516                         }
2517                         if (batchtriangles + surface->num_triangles > MAXBATCHTRIANGLES)
2518                         {
2519                                 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2520                                 batchtriangles = 0;
2521                                 firstvertex = surface->num_firstvertex;
2522                                 endvertex = surface->num_firstvertex + surface->num_vertices;
2523                         }
2524                         else
2525                         {
2526                                 firstvertex = min(firstvertex, surface->num_firstvertex);
2527                                 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2528                         }
2529                         memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
2530                         batchtriangles += surface->num_triangles;
2531                 }
2532                 if (batchtriangles)
2533                         R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2534         }
2535         else if (r_batchmode.integer == 1)
2536         {
2537                 int firsttriangle = 0;
2538                 int endtriangle = -1;
2539                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2540                 {
2541                         surface = texturesurfacelist[texturesurfaceindex];
2542                         if (surface->num_firsttriangle != endtriangle)
2543                         {
2544                                 if (endtriangle > firsttriangle)
2545                                 {
2546                                         GL_LockArrays(firstvertex, endvertex - firstvertex);
2547                                         R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2548                                 }
2549                                 firstvertex = surface->num_firstvertex;
2550                                 endvertex = surface->num_firstvertex + surface->num_vertices;
2551                                 firsttriangle = surface->num_firsttriangle;
2552                         }
2553                         else
2554                         {
2555                                 firstvertex = min(firstvertex, surface->num_firstvertex);
2556                                 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2557                         }
2558                         endtriangle = surface->num_firsttriangle + surface->num_triangles;
2559                 }
2560                 if (endtriangle > firsttriangle)
2561                 {
2562                         GL_LockArrays(firstvertex, endvertex - firstvertex);
2563                         R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2564                 }
2565         }
2566         else
2567         {
2568                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2569                 {
2570                         surface = texturesurfacelist[texturesurfaceindex];
2571                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2572                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2573                 }
2574         }
2575 }
2576
2577 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2578 {
2579         int texturesurfaceindex;
2580         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2581         {
2582                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2583                 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2584                 GL_Color((k & 15) * (1.0f / 16.0f), ((k >> 4) & 15) * (1.0f / 16.0f), ((k >> 8) & 15) * (1.0f / 16.0f), 0.2f);
2585                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2586                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2587         }
2588 }
2589
2590 static void RSurf_DrawBatch_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2591 {
2592         int texturesurfaceindex;
2593         int i;
2594         float f;
2595         float *v, *c, *c2;
2596         // TODO: optimize
2597         if (lightmode >= 2)
2598         {
2599                 // model lighting
2600                 vec3_t ambientcolor;
2601                 vec3_t diffusecolor;
2602                 vec3_t lightdir;
2603                 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2604                 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2605                 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2606                 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2607                 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2608                 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2609                 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2610                 if (VectorLength2(diffusecolor) > 0)
2611                 {
2612                         // generate color arrays for the surfaces in this list
2613                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2614                         {
2615                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2616                                 int numverts = surface->num_vertices;
2617                                 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2618                                 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2619                                 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2620                                 // q3-style directional shading
2621                                 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2622                                 {
2623                                         if ((f = DotProduct(c2, lightdir)) > 0)
2624                                                 VectorMA(ambientcolor, f, diffusecolor, c);
2625                                         else
2626                                                 VectorCopy(ambientcolor, c);
2627                                         c[3] = a;
2628                                 }
2629                         }
2630                         r = 1;
2631                         g = 1;
2632                         b = 1;
2633                         a = 1;
2634                         applycolor = false;
2635                         rsurface_lightmapcolor4f = rsurface_array_color4f;
2636                 }
2637                 else
2638                 {
2639                         r = ambientcolor[0];
2640                         g = ambientcolor[1];
2641                         b = ambientcolor[2];
2642                         rsurface_lightmapcolor4f = NULL;
2643                 }
2644         }
2645         else if (lightmode >= 1 || !rsurface_lightmaptexture)
2646         {
2647                 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
2648                 {
2649                         // generate color arrays for the surfaces in this list
2650                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2651                         {
2652                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2653                                 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2654                                 {
2655                                         if (surface->lightmapinfo->samples)
2656                                         {
2657                                                 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2658                                                 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2659                                                 VectorScale(lm, scale, c);
2660                                                 if (surface->lightmapinfo->styles[1] != 255)
2661                                                 {
2662                                                         int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2663                                                         lm += size3;
2664                                                         scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2665                                                         VectorMA(c, scale, lm, c);
2666                                                         if (surface->lightmapinfo->styles[2] != 255)
2667                                                         {
2668                                                                 lm += size3;
2669                                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2670                                                                 VectorMA(c, scale, lm, c);
2671                                                                 if (surface->lightmapinfo->styles[3] != 255)
2672                                                                 {
2673                                                                         lm += size3;
2674                                                                         scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2675                                                                         VectorMA(c, scale, lm, c);
2676                                                                 }
2677                                                         }
2678                                                 }
2679                                         }
2680                                         else
2681                                                 VectorClear(c);
2682                                         c[3] = 1;
2683                                 }
2684                         }
2685                         rsurface_lightmapcolor4f = rsurface_array_color4f;
2686                 }
2687                 else
2688                         rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2689         }
2690         else
2691         {
2692                 // just lightmap it
2693                 rsurface_lightmapcolor4f = NULL;
2694         }
2695         if (applyfog)
2696         {
2697                 if (rsurface_lightmapcolor4f)
2698                 {
2699                         // generate color arrays for the surfaces in this list
2700                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2701                         {
2702                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2703                                 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)
2704                                 {
2705                                         f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2706                                         c2[0] = c[0] * f;
2707                                         c2[1] = c[1] * f;
2708                                         c2[2] = c[2] * f;
2709                                         c2[3] = c[3];
2710                                 }
2711                         }
2712                 }
2713                 else
2714                 {
2715                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2716                         {
2717                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2718                                 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)
2719                                 {
2720                                         f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2721                                         c2[0] = f;
2722                                         c2[1] = f;
2723                                         c2[2] = f;
2724                                         c2[3] = 1;
2725                                 }
2726                         }
2727                 }
2728                 rsurface_lightmapcolor4f = rsurface_array_color4f;
2729         }
2730         if (applycolor && rsurface_lightmapcolor4f)
2731         {
2732                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2733                 {
2734                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2735                         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)
2736                         {
2737                                 c2[0] = c[0] * r;
2738                                 c2[1] = c[1] * g;
2739                                 c2[2] = c[2] * b;
2740                                 c2[3] = c[3] * a;
2741                         }
2742                 }
2743                 rsurface_lightmapcolor4f = rsurface_array_color4f;
2744         }
2745         R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2746         GL_Color(r, g, b, a);
2747         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2748 }
2749
2750 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2751 {
2752         if (rsurface_mode != RSURFMODE_SHOWSURFACES)
2753         {
2754                 rsurface_mode = RSURFMODE_SHOWSURFACES;
2755                 GL_DepthMask(true);
2756                 GL_BlendFunc(GL_ONE, GL_ZERO);
2757                 R_Mesh_ColorPointer(NULL);
2758                 R_Mesh_ResetTextureState();
2759         }
2760         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2761         RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
2762 }
2763
2764 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
2765 {
2766         // transparent sky would be ridiculous
2767         if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2768                 return;
2769         if (rsurface_mode != RSURFMODE_SKY)
2770         {
2771                 if (rsurface_mode == RSURFMODE_GLSL)
2772                 {
2773                         qglUseProgramObjectARB(0);CHECKGLERROR
2774                 }
2775                 rsurface_mode = RSURFMODE_SKY;
2776         }
2777         if (skyrendernow)
2778         {
2779                 skyrendernow = false;
2780                 R_Sky();
2781                 // restore entity matrix
2782                 R_Mesh_Matrix(&rsurface_entity->matrix);
2783         }
2784         GL_DepthMask(true);
2785         // LordHavoc: HalfLife maps have freaky skypolys so don't use
2786         // skymasking on them, and Quake3 never did sky masking (unlike
2787         // software Quake and software Quake2), so disable the sky masking
2788         // in Quake3 maps as it causes problems with q3map2 sky tricks,
2789         // and skymasking also looks very bad when noclipping outside the
2790         // level, so don't use it then either.
2791         if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
2792         {
2793                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
2794                 R_Mesh_ColorPointer(NULL);
2795                 R_Mesh_ResetTextureState();
2796                 if (skyrendermasked)
2797                 {
2798                         // depth-only (masking)
2799                         GL_ColorMask(0,0,0,0);
2800                         // just to make sure that braindead drivers don't draw
2801                         // anything despite that colormask...
2802                         GL_BlendFunc(GL_ZERO, GL_ONE);
2803                 }
2804                 else
2805                 {
2806                         // fog sky
2807                         GL_BlendFunc(GL_ONE, GL_ZERO);
2808                 }
2809                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2810                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2811                 if (skyrendermasked)
2812                         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2813         }
2814 }
2815
2816 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
2817 {
2818         int lightmode;
2819         // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
2820         lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
2821         if (rsurface_mode != RSURFMODE_GLSL)
2822         {
2823                 rsurface_mode = RSURFMODE_GLSL;
2824                 rsurface_glsl_texture = NULL;
2825                 rsurface_glsl_uselightmap = false;
2826                 R_Mesh_ResetTextureState();
2827         }
2828         if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != (rsurface_lightmaptexture != NULL))
2829         {
2830                 rsurface_glsl_texture = rsurface_texture;
2831                 rsurface_glsl_uselightmap = rsurface_lightmaptexture != NULL;
2832                 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
2833                 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
2834                 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
2835                 R_SetupSurfaceShader(vec3_origin, lightmode == 2);
2836                 //permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, false);
2837                 //if (r_glsl_deluxemapping.integer)
2838                 //      permutation_deluxemapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, true);
2839                 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
2840                 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
2841                 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2842         }
2843         if (!r_glsl_permutation)
2844                 return;
2845         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
2846         R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2847         R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2848         R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2849         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2850         {
2851                 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2852                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2853                         R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2854                 R_Mesh_ColorPointer(NULL);
2855         }
2856         else if (rsurface_lightmaptexture)
2857         {
2858                 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
2859                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2860                         R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
2861                 R_Mesh_ColorPointer(NULL);
2862         }
2863         else
2864         {
2865                 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2866                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2867                         R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2868                 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
2869         }
2870         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2871 }
2872
2873 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
2874 {
2875         // OpenGL 1.3 path - anything not completely ancient
2876         int texturesurfaceindex;
2877         int lightmode;
2878         qboolean applycolor;
2879         qboolean applyfog;
2880         rmeshstate_t m;
2881         int layerindex;
2882         const texturelayer_t *layer;
2883         CHECKGLERROR
2884         // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
2885         lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
2886         if (rsurface_mode != RSURFMODE_MULTIPASS)
2887                 rsurface_mode = RSURFMODE_MULTIPASS;
2888         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
2889         for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
2890         {
2891                 vec4_t layercolor;
2892                 int layertexrgbscale;
2893                 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2894                 {
2895                         if (layerindex == 0)
2896                                 GL_AlphaTest(true);
2897                         else
2898                         {
2899                                 GL_AlphaTest(false);
2900                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
2901                         }
2902                 }
2903                 GL_DepthMask(layer->depthmask);
2904                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2905                 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2906                 {
2907                         layertexrgbscale = 4;
2908                         VectorScale(layer->color, 0.25f, layercolor);
2909                 }
2910                 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2911                 {
2912                         layertexrgbscale = 2;
2913                         VectorScale(layer->color, 0.5f, layercolor);
2914                 }
2915                 else
2916                 {
2917                         layertexrgbscale = 1;
2918                         VectorScale(layer->color, 1.0f, layercolor);
2919                 }
2920                 layercolor[3] = layer->color[3];
2921                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2922                 R_Mesh_ColorPointer(NULL);
2923                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2924                 switch (layer->type)
2925                 {
2926                 case TEXTURELAYERTYPE_LITTEXTURE:
2927                         memset(&m, 0, sizeof(m));
2928                         if (lightmode >= 1 || !rsurface_lightmaptexture)
2929                                 m.tex[0] = R_GetTexture(r_texture_white);
2930                         else
2931                                 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
2932                         m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
2933                         m.tex[1] = R_GetTexture(layer->texture);
2934                         m.texmatrix[1] = layer->texmatrix;
2935                         m.texrgbscale[1] = layertexrgbscale;
2936                         m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
2937                         R_Mesh_TextureState(&m);
2938                         RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode, applycolor, applyfog);
2939                         break;
2940                 case TEXTURELAYERTYPE_TEXTURE:
2941                         memset(&m, 0, sizeof(m));
2942                         m.tex[0] = R_GetTexture(layer->texture);
2943                         m.texmatrix[0] = layer->texmatrix;
2944                         m.texrgbscale[0] = layertexrgbscale;
2945                         m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
2946                         R_Mesh_TextureState(&m);
2947                         RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2948                         break;
2949                 case TEXTURELAYERTYPE_FOG:
2950                         memset(&m, 0, sizeof(m));
2951                         m.texrgbscale[0] = layertexrgbscale;
2952                         if (layer->texture)
2953                         {
2954                                 m.tex[0] = R_GetTexture(layer->texture);
2955                                 m.texmatrix[0] = layer->texmatrix;
2956                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
2957                         }
2958                         R_Mesh_TextureState(&m);
2959                         // generate a color array for the fog pass
2960                         R_Mesh_ColorPointer(rsurface_array_color4f);
2961                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2962                         {
2963                                 int i;
2964                                 float f, *v, *c;
2965                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2966                                 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)
2967                                 {
2968                                         f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2969                                         c[0] = layercolor[0];
2970                                         c[1] = layercolor[1];
2971                                         c[2] = layercolor[2];
2972                                         c[3] = f * layercolor[3];
2973                                 }
2974                         }
2975                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2976                         break;
2977                 default:
2978                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2979                 }
2980                 GL_LockArrays(0, 0);
2981         }
2982         CHECKGLERROR
2983         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2984         {
2985                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2986                 GL_AlphaTest(false);
2987         }
2988 }
2989
2990 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
2991 {
2992         // OpenGL 1.1 - crusty old voodoo path
2993         int texturesurfaceindex;
2994         int lightmode;
2995         qboolean applyfog;
2996         rmeshstate_t m;
2997         int layerindex;
2998         const texturelayer_t *layer;
2999         CHECKGLERROR
3000         // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3001         lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3002         if (rsurface_mode != RSURFMODE_MULTIPASS)
3003                 rsurface_mode = RSURFMODE_MULTIPASS;
3004         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3005         for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3006         {
3007                 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3008                 {
3009                         if (layerindex == 0)
3010                                 GL_AlphaTest(true);
3011                         else
3012                         {
3013                                 GL_AlphaTest(false);
3014                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3015                         }
3016                 }
3017                 GL_DepthMask(layer->depthmask);
3018                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3019                 R_Mesh_ColorPointer(NULL);
3020                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3021                 switch (layer->type)
3022                 {
3023                 case TEXTURELAYERTYPE_LITTEXTURE:
3024                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3025                         {
3026                                 // two-pass lit texture with 2x rgbscale
3027                                 // first the lightmap pass
3028                                 memset(&m, 0, sizeof(m));
3029                                 if (lightmode >= 1 || !rsurface_lightmaptexture)
3030                                         m.tex[0] = R_GetTexture(r_texture_white);
3031                                 else
3032                                         m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3033                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3034                                 R_Mesh_TextureState(&m);
3035                                 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, lightmode, false, false);
3036                                 GL_LockArrays(0, 0);
3037                                 // then apply the texture to it
3038                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3039                                 memset(&m, 0, sizeof(m));
3040                                 m.tex[0] = R_GetTexture(layer->texture);
3041                                 m.texmatrix[0] = layer->texmatrix;
3042                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3043                                 R_Mesh_TextureState(&m);
3044                                 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], 0, layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
3045                         }
3046                         else
3047                         {
3048                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3049                                 memset(&m, 0, sizeof(m));
3050                                 m.tex[0] = R_GetTexture(layer->texture);
3051                                 m.texmatrix[0] = layer->texmatrix;
3052                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3053                                 R_Mesh_TextureState(&m);
3054                                 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], lightmode == 2 ? 2 : 1, layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
3055                         }
3056                         break;
3057                 case TEXTURELAYERTYPE_TEXTURE:
3058                         // singletexture unlit texture with transparency support
3059                         memset(&m, 0, sizeof(m));
3060                         m.tex[0] = R_GetTexture(layer->texture);
3061                         m.texmatrix[0] = layer->texmatrix;
3062                         m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3063                         R_Mesh_TextureState(&m);
3064                         RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], 0, layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
3065                         break;
3066                 case TEXTURELAYERTYPE_FOG:
3067                         // singletexture fogging
3068                         R_Mesh_ColorPointer(rsurface_array_color4f);
3069                         if (layer->texture)
3070                         {
3071                                 memset(&m, 0, sizeof(m));
3072                                 m.tex[0] = R_GetTexture(layer->texture);
3073                                 m.texmatrix[0] = layer->texmatrix;
3074                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3075                                 R_Mesh_TextureState(&m);
3076                         }
3077                         else
3078                                 R_Mesh_ResetTextureState();
3079                         // generate a color array for the fog pass
3080                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)