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