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