]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
modified surface renderer batching to batch all lightmapped surfaces with the same...
[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 "\n"
626 "\n"
627 "\n"
628 "\n"
629 "#elif defined(MODE_LIGHTDIRECTION)\n"
630 "       // directional model lighting\n"
631 "\n"
632 "       // get the surface normal and light normal\n"
633 "       myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
634 "       myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
635 "\n"
636 "       // calculate directional shading\n"
637 "       color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
638 "#ifdef USESPECULAR\n"
639 "       myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
640 "       color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
641 "#endif\n"
642 "\n"
643 "\n"
644 "\n"
645 "\n"
646 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
647 "       // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
648 "\n"
649 "       // get the surface normal and light normal\n"
650 "       myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
651 "\n"
652 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
653 "       myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
654 "       myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
655 "#else\n"
656 "       myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
657 "#endif\n"
658 "       // calculate directional shading\n"
659 "       myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
660 "#ifdef USESPECULAR\n"
661 "       myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
662 "       tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
663 "#endif\n"
664 "\n"
665 "       // apply lightmap color\n"
666 "       color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * AmbientScale;\n"
667 "\n"
668 "\n"
669 "#else // MODE none (lightmap)\n"
670 "       // apply lightmap color\n"
671 "       color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
672 "#endif // MODE\n"
673 "\n"
674 "       color *= myhvec4(gl_Color);\n"
675 "\n"
676 "#ifdef USEGLOW\n"
677 "       color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
678 "#endif\n"
679 "\n"
680 "#ifdef USEFOG\n"
681 "       // apply fog\n"
682 "       myhalf fog = myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0)).x);\n"
683 "       color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
684 "#endif\n"
685 "\n"
686 "       color.rgb *= SceneBrightness;\n"
687 "\n"
688 "       gl_FragColor = vec4(color);\n"
689 "}\n"
690 "\n"
691 "#endif // FRAGMENT_SHADER\n"
692 ;
693
694 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
695 const char *permutationinfo[][2] =
696 {
697         {"#define MODE_LIGHTSOURCE\n", " lightsource"},
698         {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
699         {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
700         {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
701         {"#define USEGLOW\n", " glow"},
702         {"#define USEFOG\n", " fog"},
703         {"#define USECOLORMAPPING\n", " colormapping"},
704         {"#define USESPECULAR\n", " specular"},
705         {"#define USECUBEFILTER\n", " cubefilter"},
706         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
707         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
708         {NULL, NULL}
709 };
710
711 void R_GLSL_CompilePermutation(const char *filename, int permutation)
712 {
713         int i;
714         qboolean shaderfound;
715         r_glsl_permutation_t *p = r_glsl_permutations + (permutation & SHADERPERMUTATION_COUNTMASK);
716         int vertstrings_count;
717         int geomstrings_count;
718         int fragstrings_count;
719         char *shaderstring;
720         const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
721         const char *geomstrings_list[SHADERPERMUTATION_COUNT+1];
722         const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
723         char permutationname[256];
724         if (p->compiled)
725                 return;
726         p->compiled = true;
727         p->program = 0;
728         vertstrings_list[0] = "#define VERTEX_SHADER\n";
729         geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
730         fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
731         vertstrings_count = 1;
732         geomstrings_count = 1;
733         fragstrings_count = 1;
734         permutationname[0] = 0;
735         for (i = 0;permutationinfo[i][0];i++)
736         {
737                 if (permutation & (1<<i))
738                 {
739                         vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
740                         geomstrings_list[geomstrings_count++] = permutationinfo[i][0];
741                         fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
742                         strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
743                 }
744                 else
745                 {
746                         // keep line numbers correct
747                         vertstrings_list[vertstrings_count++] = "\n";
748                         geomstrings_list[geomstrings_count++] = "\n";
749                         fragstrings_list[fragstrings_count++] = "\n";
750                 }
751         }
752         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
753         shaderfound = false;
754         if (shaderstring)
755         {
756                 Con_DPrintf("GLSL shader text for \"%s\" loaded from disk\n", filename);
757                 vertstrings_list[vertstrings_count++] = shaderstring;
758                 geomstrings_list[geomstrings_count++] = shaderstring;
759                 fragstrings_list[fragstrings_count++] = shaderstring;
760                 shaderfound = true;
761         }
762         else if (!strcmp(filename, "glsl/default.glsl"))
763         {
764                 Con_DPrintf("GLSL shader text for \"%s\" loaded from engine\n", filename);
765                 vertstrings_list[vertstrings_count++] = builtinshaderstring;
766                 geomstrings_list[geomstrings_count++] = builtinshaderstring;
767                 fragstrings_list[fragstrings_count++] = builtinshaderstring;
768                 shaderfound = true;
769         }
770         // clear any lists that are not needed by this shader
771         if (!(permutation & SHADERPERMUTATION_USES_VERTEXSHADER))
772                 vertstrings_count = 0;
773         if (!(permutation & SHADERPERMUTATION_USES_GEOMETRYSHADER))
774                 geomstrings_count = 0;
775         if (!(permutation & SHADERPERMUTATION_USES_FRAGMENTSHADER))
776                 fragstrings_count = 0;
777         // compile the shader program
778         if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
779                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
780         if (p->program)
781         {
782                 CHECKGLERROR
783                 qglUseProgramObjectARB(p->program);CHECKGLERROR
784                 // look up all the uniform variable names we care about, so we don't
785                 // have to look them up every time we set them
786                 p->loc_Texture_Normal      = qglGetUniformLocationARB(p->program, "Texture_Normal");
787                 p->loc_Texture_Color       = qglGetUniformLocationARB(p->program, "Texture_Color");
788                 p->loc_Texture_Gloss       = qglGetUniformLocationARB(p->program, "Texture_Gloss");
789                 p->loc_Texture_Cube        = qglGetUniformLocationARB(p->program, "Texture_Cube");
790                 p->loc_Texture_FogMask     = qglGetUniformLocationARB(p->program, "Texture_FogMask");
791                 p->loc_Texture_Pants       = qglGetUniformLocationARB(p->program, "Texture_Pants");
792                 p->loc_Texture_Shirt       = qglGetUniformLocationARB(p->program, "Texture_Shirt");
793                 p->loc_Texture_Lightmap    = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
794                 p->loc_Texture_Deluxemap   = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
795                 p->loc_Texture_Glow        = qglGetUniformLocationARB(p->program, "Texture_Glow");
796                 p->loc_FogColor            = qglGetUniformLocationARB(p->program, "FogColor");
797                 p->loc_LightPosition       = qglGetUniformLocationARB(p->program, "LightPosition");
798                 p->loc_EyePosition         = qglGetUniformLocationARB(p->program, "EyePosition");
799                 p->loc_LightColor          = qglGetUniformLocationARB(p->program, "LightColor");
800                 p->loc_Color_Pants         = qglGetUniformLocationARB(p->program, "Color_Pants");
801                 p->loc_Color_Shirt         = qglGetUniformLocationARB(p->program, "Color_Shirt");
802                 p->loc_FogRangeRecip       = qglGetUniformLocationARB(p->program, "FogRangeRecip");
803                 p->loc_AmbientScale        = qglGetUniformLocationARB(p->program, "AmbientScale");
804                 p->loc_DiffuseScale        = qglGetUniformLocationARB(p->program, "DiffuseScale");
805                 p->loc_SpecularPower       = qglGetUniformLocationARB(p->program, "SpecularPower");
806                 p->loc_SpecularScale       = qglGetUniformLocationARB(p->program, "SpecularScale");
807                 p->loc_GlowScale           = qglGetUniformLocationARB(p->program, "GlowScale");
808                 p->loc_SceneBrightness     = qglGetUniformLocationARB(p->program, "SceneBrightness");
809                 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
810                 p->loc_AmbientColor        = qglGetUniformLocationARB(p->program, "AmbientColor");
811                 p->loc_DiffuseColor        = qglGetUniformLocationARB(p->program, "DiffuseColor");
812                 p->loc_SpecularColor       = qglGetUniformLocationARB(p->program, "SpecularColor");
813                 p->loc_LightDir            = qglGetUniformLocationARB(p->program, "LightDir");
814                 // initialize the samplers to refer to the texture units we use
815                 if (p->loc_Texture_Normal >= 0)    qglUniform1iARB(p->loc_Texture_Normal, 0);
816                 if (p->loc_Texture_Color >= 0)     qglUniform1iARB(p->loc_Texture_Color, 1);
817                 if (p->loc_Texture_Gloss >= 0)     qglUniform1iARB(p->loc_Texture_Gloss, 2);
818                 if (p->loc_Texture_Cube >= 0)      qglUniform1iARB(p->loc_Texture_Cube, 3);
819                 if (p->loc_Texture_FogMask >= 0)   qglUniform1iARB(p->loc_Texture_FogMask, 4);
820                 if (p->loc_Texture_Pants >= 0)     qglUniform1iARB(p->loc_Texture_Pants, 5);
821                 if (p->loc_Texture_Shirt >= 0)     qglUniform1iARB(p->loc_Texture_Shirt, 6);
822                 if (p->loc_Texture_Lightmap >= 0)  qglUniform1iARB(p->loc_Texture_Lightmap, 7);
823                 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
824                 if (p->loc_Texture_Glow >= 0)      qglUniform1iARB(p->loc_Texture_Glow, 9);
825                 CHECKGLERROR
826                 qglUseProgramObjectARB(0);CHECKGLERROR
827         }
828         else
829                 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
830         if (shaderstring)
831                 Mem_Free(shaderstring);
832 }
833
834 void R_GLSL_Restart_f(void)
835 {
836         int i;
837         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
838                 if (r_glsl_permutations[i].program)
839                         GL_Backend_FreeProgram(r_glsl_permutations[i].program);
840         memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
841 }
842
843 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting)
844 {
845         // select a permutation of the lighting shader appropriate to this
846         // combination of texture, entity, light source, and fogging, only use the
847         // minimum features necessary to avoid wasting rendering time in the
848         // fragment shader on features that are not being used
849         const char *shaderfilename = NULL;
850         int permutation = 0;
851         float specularscale = rsurface_texture->specularscale;
852         r_glsl_permutation = NULL;
853         // TODO: implement geometry-shader based shadow volumes someday
854         if (r_shadow_rtlight)
855         {
856                 // light source
857                 shaderfilename = "glsl/default.glsl";
858                 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
859                 specularscale *= r_shadow_rtlight->specularscale;
860                 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
861                         permutation |= SHADERPERMUTATION_CUBEFILTER;
862                 if (specularscale > 0)
863                         permutation |= SHADERPERMUTATION_SPECULAR;
864                 if (r_refdef.fogenabled)
865                         permutation |= SHADERPERMUTATION_FOG;
866                 if (rsurface_texture->colormapping)
867                         permutation |= SHADERPERMUTATION_COLORMAPPING;
868                 if (r_glsl_offsetmapping.integer)
869                 {
870                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
871                         if (r_glsl_offsetmapping_reliefmapping.integer)
872                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
873                 }
874         }
875         else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
876         {
877                 // bright unshaded geometry
878                 shaderfilename = "glsl/default.glsl";
879                 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
880                 if (rsurface_texture->currentskinframe->glow)
881                         permutation |= SHADERPERMUTATION_GLOW;
882                 if (r_refdef.fogenabled)
883                         permutation |= SHADERPERMUTATION_FOG;
884                 if (rsurface_texture->colormapping)
885                         permutation |= SHADERPERMUTATION_COLORMAPPING;
886                 if (r_glsl_offsetmapping.integer)
887                 {
888                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
889                         if (r_glsl_offsetmapping_reliefmapping.integer)
890                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
891                 }
892         }
893         else if (modellighting)
894         {
895                 // directional model lighting
896                 shaderfilename = "glsl/default.glsl";
897                 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
898                 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
899                 if (rsurface_texture->currentskinframe->glow)
900                         permutation |= SHADERPERMUTATION_GLOW;
901                 if (specularscale > 0)
902                         permutation |= SHADERPERMUTATION_SPECULAR;
903                 if (r_refdef.fogenabled)
904                         permutation |= SHADERPERMUTATION_FOG;
905                 if (rsurface_texture->colormapping)
906                         permutation |= SHADERPERMUTATION_COLORMAPPING;
907                 if (r_glsl_offsetmapping.integer)
908                 {
909                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
910                         if (r_glsl_offsetmapping_reliefmapping.integer)
911                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
912                 }
913         }
914         else
915         {
916                 // lightmapped wall
917                 shaderfilename = "glsl/default.glsl";
918                 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
919                 if (r_glsl_deluxemapping.integer >= 1 && rsurface_uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
920                 {
921                         // deluxemapping (light direction texture)
922                         if (rsurface_uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
923                                 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
924                         else
925                                 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
926                         if (specularscale > 0)
927                                 permutation |= SHADERPERMUTATION_SPECULAR;
928                 }
929                 else if (r_glsl_deluxemapping.integer >= 2)
930                 {
931                         // fake deluxemapping (uniform light direction in tangentspace)
932                         permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
933                         if (specularscale > 0)
934                                 permutation |= SHADERPERMUTATION_SPECULAR;
935                 }
936                 else
937                 {
938                         // ordinary lightmapping
939                         permutation |= 0;
940                 }
941                 if (rsurface_texture->currentskinframe->glow)
942                         permutation |= SHADERPERMUTATION_GLOW;
943                 if (r_refdef.fogenabled)
944                         permutation |= SHADERPERMUTATION_FOG;
945                 if (rsurface_texture->colormapping)
946                         permutation |= SHADERPERMUTATION_COLORMAPPING;
947                 if (r_glsl_offsetmapping.integer)
948                 {
949                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
950                         if (r_glsl_offsetmapping_reliefmapping.integer)
951                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
952                 }
953         }
954         if (!r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].program)
955         {
956                 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].compiled)
957                         R_GLSL_CompilePermutation(shaderfilename, permutation);
958                 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].program)
959                 {
960                         // remove features until we find a valid permutation
961                         int i;
962                         for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
963                         {
964                                 // reduce i more quickly whenever it would not remove any bits
965                                 if (permutation < i)
966                                         continue;
967                                 permutation &= i;
968                                 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].compiled)
969                                         R_GLSL_CompilePermutation(shaderfilename, permutation);
970                                 if (r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].program)
971                                         break;
972                                 if (!i)
973                                         return 0; // utterly failed
974                         }
975                 }
976         }
977         r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_COUNTMASK);
978         CHECKGLERROR
979         qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
980         R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
981         if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
982         {
983                 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
984                 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]);
985                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
986                 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
987                 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
988                 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
989         }
990         else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
991         {
992                 if (r_glsl_permutation->loc_AmbientColor >= 0)
993                         qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0], rsurface_entity->modellight_ambient[1], rsurface_entity->modellight_ambient[2]);
994                 if (r_glsl_permutation->loc_DiffuseColor >= 0)
995                         qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0], rsurface_entity->modellight_diffuse[1], rsurface_entity->modellight_diffuse[2]);
996                 if (r_glsl_permutation->loc_SpecularColor >= 0)
997                         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);
998                 if (r_glsl_permutation->loc_LightDir >= 0)
999                         qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
1000         }
1001         else
1002         {
1003                 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1004                 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1005                 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1006         }
1007         if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->currentskinframe->nmap));
1008         if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
1009         if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
1010         //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
1011         if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1012         if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->currentskinframe->pants));
1013         if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->currentskinframe->shirt));
1014         //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
1015         //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
1016         if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->currentskinframe->glow));
1017         if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1018         if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1019         if (r_glsl_permutation->loc_FogColor >= 0)
1020         {
1021                 // additive passes are only darkened by fog, not tinted
1022                 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
1023                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1024                 else
1025                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1026         }
1027         if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
1028         if (r_glsl_permutation->loc_Color_Pants >= 0)
1029         {
1030                 if (rsurface_texture->currentskinframe->pants)
1031                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
1032                 else
1033                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1034         }
1035         if (r_glsl_permutation->loc_Color_Shirt >= 0)
1036         {
1037                 if (rsurface_texture->currentskinframe->shirt)
1038                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
1039                 else
1040                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1041         }
1042         if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1043         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
1044         if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1045         CHECKGLERROR
1046         return permutation;
1047 }
1048
1049 void R_SwitchSurfaceShader(int permutation)
1050 {
1051         if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_COUNTMASK))
1052         {
1053                 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_COUNTMASK);
1054                 CHECKGLERROR
1055                 qglUseProgramObjectARB(r_glsl_permutation->program);
1056                 CHECKGLERROR
1057         }
1058 }
1059
1060 void gl_main_start(void)
1061 {
1062         r_main_texturepool = R_AllocTexturePool();
1063         R_BuildBlankTextures();
1064         R_BuildNoTexture();
1065         if (gl_texturecubemap)
1066         {
1067                 R_BuildWhiteCube();
1068                 R_BuildNormalizationCube();
1069         }
1070         R_BuildFogTexture();
1071         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1072         memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1073         memset(&r_svbsp, 0, sizeof (r_svbsp));
1074 }
1075
1076 void gl_main_shutdown(void)
1077 {
1078         if (r_svbsp.nodes)
1079                 Mem_Free(r_svbsp.nodes);
1080         memset(&r_svbsp, 0, sizeof (r_svbsp));
1081         R_FreeTexturePool(&r_main_texturepool);
1082         r_texture_blanknormalmap = NULL;
1083         r_texture_white = NULL;
1084         r_texture_black = NULL;
1085         r_texture_whitecube = NULL;
1086         r_texture_normalizationcube = NULL;
1087         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1088         R_GLSL_Restart_f();
1089 }
1090
1091 extern void CL_ParseEntityLump(char *entitystring);
1092 void gl_main_newmap(void)
1093 {
1094         // FIXME: move this code to client
1095         int l;
1096         char *entities, entname[MAX_QPATH];
1097         if (cl.worldmodel)
1098         {
1099                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1100                 l = (int)strlen(entname) - 4;
1101                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1102                 {
1103                         memcpy(entname + l, ".ent", 5);
1104                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1105                         {
1106                                 CL_ParseEntityLump(entities);
1107                                 Mem_Free(entities);
1108                                 return;
1109                         }
1110                 }
1111                 if (cl.worldmodel->brush.entities)
1112                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
1113         }
1114 }
1115
1116 void GL_Main_Init(void)
1117 {
1118         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1119
1120         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
1121         FOG_registercvars(); // FIXME: move this fog stuff to client?
1122         Cvar_RegisterVariable(&r_nearclip);
1123         Cvar_RegisterVariable(&r_showsurfaces);
1124         Cvar_RegisterVariable(&r_showtris);
1125         Cvar_RegisterVariable(&r_shownormals);
1126         Cvar_RegisterVariable(&r_showlighting);
1127         Cvar_RegisterVariable(&r_showshadowvolumes);
1128         Cvar_RegisterVariable(&r_showcollisionbrushes);
1129         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1130         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1131         Cvar_RegisterVariable(&r_showdisabledepthtest);
1132         Cvar_RegisterVariable(&r_drawportals);
1133         Cvar_RegisterVariable(&r_drawentities);
1134         Cvar_RegisterVariable(&r_drawviewmodel);
1135         Cvar_RegisterVariable(&r_speeds);
1136         Cvar_RegisterVariable(&r_fullbrights);
1137         Cvar_RegisterVariable(&r_wateralpha);
1138         Cvar_RegisterVariable(&r_dynamic);
1139         Cvar_RegisterVariable(&r_fullbright);
1140         Cvar_RegisterVariable(&r_shadows);
1141         Cvar_RegisterVariable(&r_shadows_throwdistance);
1142         Cvar_RegisterVariable(&r_q1bsp_skymasking);
1143         Cvar_RegisterVariable(&r_textureunits);
1144         Cvar_RegisterVariable(&r_glsl);
1145         Cvar_RegisterVariable(&r_glsl_offsetmapping);
1146         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1147         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1148         Cvar_RegisterVariable(&r_glsl_deluxemapping);
1149         Cvar_RegisterVariable(&r_lerpsprites);
1150         Cvar_RegisterVariable(&r_lerpmodels);
1151         Cvar_RegisterVariable(&r_waterscroll);
1152         Cvar_RegisterVariable(&r_bloom);
1153         Cvar_RegisterVariable(&r_bloom_colorscale);
1154         Cvar_RegisterVariable(&r_bloom_brighten);
1155         Cvar_RegisterVariable(&r_bloom_blur);
1156         Cvar_RegisterVariable(&r_bloom_resolution);
1157         Cvar_RegisterVariable(&r_bloom_colorexponent);
1158         Cvar_RegisterVariable(&r_bloom_colorsubtract);
1159         Cvar_RegisterVariable(&r_hdr);
1160         Cvar_RegisterVariable(&r_hdr_scenebrightness);
1161         Cvar_RegisterVariable(&r_hdr_glowintensity);
1162         Cvar_RegisterVariable(&r_hdr_range);
1163         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1164         Cvar_RegisterVariable(&developer_texturelogging);
1165         Cvar_RegisterVariable(&gl_lightmaps);
1166         Cvar_RegisterVariable(&r_test);
1167         Cvar_RegisterVariable(&r_batchmode);
1168         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1169                 Cvar_SetValue("r_fullbrights", 0);
1170         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1171 }
1172
1173 extern void R_Textures_Init(void);
1174 extern void GL_Draw_Init(void);
1175 extern void GL_Main_Init(void);
1176 extern void R_Shadow_Init(void);
1177 extern void R_Sky_Init(void);
1178 extern void GL_Surf_Init(void);
1179 extern void R_Light_Init(void);
1180 extern void R_Particles_Init(void);
1181 extern void R_Explosion_Init(void);
1182 extern void gl_backend_init(void);
1183 extern void Sbar_Init(void);
1184 extern void R_LightningBeams_Init(void);
1185 extern void Mod_RenderInit(void);
1186
1187 void Render_Init(void)
1188 {
1189         gl_backend_init();
1190         R_Textures_Init();
1191         GL_Main_Init();
1192         GL_Draw_Init();
1193         R_Shadow_Init();
1194         R_Sky_Init();
1195         GL_Surf_Init();
1196         Sbar_Init();
1197         R_Light_Init();
1198         R_Particles_Init();
1199         R_Explosion_Init();
1200         R_LightningBeams_Init();
1201         Mod_RenderInit();
1202 }
1203
1204 /*
1205 ===============
1206 GL_Init
1207 ===============
1208 */
1209 extern char *ENGINE_EXTENSIONS;
1210 void GL_Init (void)
1211 {
1212         VID_CheckExtensions();
1213
1214         // LordHavoc: report supported extensions
1215         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1216
1217         // clear to black (loading plaque will be seen over this)
1218         CHECKGLERROR
1219         qglClearColor(0,0,0,1);CHECKGLERROR
1220         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1221 }
1222
1223 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1224 {
1225         int i;
1226         mplane_t *p;
1227         for (i = 0;i < 4;i++)
1228         {
1229                 p = r_view.frustum + i;
1230                 switch(p->signbits)
1231                 {
1232                 default:
1233                 case 0:
1234                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1235                                 return true;
1236                         break;
1237                 case 1:
1238                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1239                                 return true;
1240                         break;
1241                 case 2:
1242                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1243                                 return true;
1244                         break;
1245                 case 3:
1246                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1247                                 return true;
1248                         break;
1249                 case 4:
1250                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1251                                 return true;
1252                         break;
1253                 case 5:
1254                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1255                                 return true;
1256                         break;
1257                 case 6:
1258                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1259                                 return true;
1260                         break;
1261                 case 7:
1262                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1263                                 return true;
1264                         break;
1265                 }
1266         }
1267         return false;
1268 }
1269
1270 //==================================================================================
1271
1272 static void R_UpdateEntityLighting(entity_render_t *ent)
1273 {
1274         vec3_t tempdiffusenormal;
1275
1276         // fetch the lighting from the worldmodel data
1277         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));
1278         VectorClear(ent->modellight_diffuse);
1279         VectorClear(tempdiffusenormal);
1280         if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1281         {
1282                 vec3_t org;
1283                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1284                 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1285         }
1286         else // highly rare
1287                 VectorSet(ent->modellight_ambient, 1, 1, 1);
1288
1289         // move the light direction into modelspace coordinates for lighting code
1290         Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1291         VectorNormalize(ent->modellight_lightdir);
1292
1293         // scale ambient and directional light contributions according to rendering variables
1294         ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1295         ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1296         ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1297         ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1298         ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1299         ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1300 }
1301
1302 static void R_View_UpdateEntityVisible (void)
1303 {
1304         int i, renderimask;
1305         entity_render_t *ent;
1306
1307         if (!r_drawentities.integer)
1308                 return;
1309
1310         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1311         if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1312         {
1313                 // worldmodel can check visibility
1314                 for (i = 0;i < r_refdef.numentities;i++)
1315                 {
1316                         ent = r_refdef.entities[i];
1317                         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));
1318                 }
1319         }
1320         else
1321         {
1322                 // no worldmodel or it can't check visibility
1323                 for (i = 0;i < r_refdef.numentities;i++)
1324                 {
1325                         ent = r_refdef.entities[i];
1326                         r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1327                 }
1328         }
1329
1330         // update entity lighting (even on hidden entities for r_shadows)
1331         for (i = 0;i < r_refdef.numentities;i++)
1332                 R_UpdateEntityLighting(r_refdef.entities[i]);
1333 }
1334
1335 // only used if skyrendermasked, and normally returns false
1336 int R_DrawBrushModelsSky (void)
1337 {
1338         int i, sky;
1339         entity_render_t *ent;
1340
1341         if (!r_drawentities.integer)
1342                 return false;
1343
1344         sky = false;
1345         for (i = 0;i < r_refdef.numentities;i++)
1346         {
1347                 if (!r_viewcache.entityvisible[i])
1348                         continue;
1349                 ent = r_refdef.entities[i];
1350                 if (!ent->model || !ent->model->DrawSky)
1351                         continue;
1352                 ent->model->DrawSky(ent);
1353                 sky = true;
1354         }
1355         return sky;
1356 }
1357
1358 void R_DrawNoModel(entity_render_t *ent);
1359 void R_DrawModels(void)
1360 {
1361         int i;
1362         entity_render_t *ent;
1363
1364         if (!r_drawentities.integer)
1365                 return;
1366
1367         for (i = 0;i < r_refdef.numentities;i++)
1368         {
1369                 if (!r_viewcache.entityvisible[i])
1370                         continue;
1371                 ent = r_refdef.entities[i];
1372                 r_refdef.stats.entities++;
1373                 if (ent->model && ent->model->Draw != NULL)
1374                         ent->model->Draw(ent);
1375                 else
1376                         R_DrawNoModel(ent);
1377         }
1378 }
1379
1380 static void R_View_SetFrustum(void)
1381 {
1382         // break apart the view matrix into vectors for various purposes
1383         Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1384         VectorNegate(r_view.left, r_view.right);
1385
1386 #if 0
1387         r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1388         r_view.frustum[0].normal[1] = 0 - 0;
1389         r_view.frustum[0].normal[2] = -1 - 0;
1390         r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1391         r_view.frustum[1].normal[1] = 0 + 0;
1392         r_view.frustum[1].normal[2] = -1 + 0;
1393         r_view.frustum[2].normal[0] = 0 - 0;
1394         r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1395         r_view.frustum[2].normal[2] = -1 - 0;
1396         r_view.frustum[3].normal[0] = 0 + 0;
1397         r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1398         r_view.frustum[3].normal[2] = -1 + 0;
1399 #endif
1400
1401 #if 0
1402         zNear = r_refdef.nearclip;
1403         nudge = 1.0 - 1.0 / (1<<23);
1404         r_view.frustum[4].normal[0] = 0 - 0;
1405         r_view.frustum[4].normal[1] = 0 - 0;
1406         r_view.frustum[4].normal[2] = -1 - -nudge;
1407         r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1408         r_view.frustum[5].normal[0] = 0 + 0;
1409         r_view.frustum[5].normal[1] = 0 + 0;
1410         r_view.frustum[5].normal[2] = -1 + -nudge;
1411         r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1412 #endif
1413
1414
1415
1416 #if 0
1417         r_view.frustum[0].normal[0] = m[3] - m[0];
1418         r_view.frustum[0].normal[1] = m[7] - m[4];
1419         r_view.frustum[0].normal[2] = m[11] - m[8];
1420         r_view.frustum[0].dist = m[15] - m[12];
1421
1422         r_view.frustum[1].normal[0] = m[3] + m[0];
1423         r_view.frustum[1].normal[1] = m[7] + m[4];
1424         r_view.frustum[1].normal[2] = m[11] + m[8];
1425         r_view.frustum[1].dist = m[15] + m[12];
1426
1427         r_view.frustum[2].normal[0] = m[3] - m[1];
1428         r_view.frustum[2].normal[1] = m[7] - m[5];
1429         r_view.frustum[2].normal[2] = m[11] - m[9];
1430         r_view.frustum[2].dist = m[15] - m[13];
1431
1432         r_view.frustum[3].normal[0] = m[3] + m[1];
1433         r_view.frustum[3].normal[1] = m[7] + m[5];
1434         r_view.frustum[3].normal[2] = m[11] + m[9];
1435         r_view.frustum[3].dist = m[15] + m[13];
1436
1437         r_view.frustum[4].normal[0] = m[3] - m[2];
1438         r_view.frustum[4].normal[1] = m[7] - m[6];
1439         r_view.frustum[4].normal[2] = m[11] - m[10];
1440         r_view.frustum[4].dist = m[15] - m[14];
1441
1442         r_view.frustum[5].normal[0] = m[3] + m[2];
1443         r_view.frustum[5].normal[1] = m[7] + m[6];
1444         r_view.frustum[5].normal[2] = m[11] + m[10];
1445         r_view.frustum[5].dist = m[15] + m[14];
1446 #endif
1447
1448
1449
1450         VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_x, r_view.left, r_view.frustum[0].normal);
1451         VectorMAM(1, r_view.forward, 1.0 /  r_view.frustum_x, r_view.left, r_view.frustum[1].normal);
1452         VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_y, r_view.up, r_view.frustum[2].normal);
1453         VectorMAM(1, r_view.forward, 1.0 /  r_view.frustum_y, r_view.up, r_view.frustum[3].normal);
1454         VectorCopy(r_view.forward, r_view.frustum[4].normal);
1455         VectorNormalize(r_view.frustum[0].normal);
1456         VectorNormalize(r_view.frustum[1].normal);
1457         VectorNormalize(r_view.frustum[2].normal);
1458         VectorNormalize(r_view.frustum[3].normal);
1459         r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1460         r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1461         r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1462         r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1463         r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1464         PlaneClassify(&r_view.frustum[0]);
1465         PlaneClassify(&r_view.frustum[1]);
1466         PlaneClassify(&r_view.frustum[2]);
1467         PlaneClassify(&r_view.frustum[3]);
1468         PlaneClassify(&r_view.frustum[4]);
1469
1470         // LordHavoc: note to all quake engine coders, Quake had a special case
1471         // for 90 degrees which assumed a square view (wrong), so I removed it,
1472         // Quake2 has it disabled as well.
1473
1474         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1475         //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1476         //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1477         //PlaneClassify(&frustum[0]);
1478
1479         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1480         //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1481         //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1482         //PlaneClassify(&frustum[1]);
1483
1484         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1485         //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1486         //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1487         //PlaneClassify(&frustum[2]);
1488
1489         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1490         //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1491         //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1492         //PlaneClassify(&frustum[3]);
1493
1494         // nearclip plane
1495         //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1496         //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1497         //PlaneClassify(&frustum[4]);
1498 }
1499
1500 void R_View_Update(void)
1501 {
1502         R_View_SetFrustum();
1503         R_View_WorldVisibility();
1504         R_View_UpdateEntityVisible();
1505 }
1506
1507 void R_SetupView(const matrix4x4_t *matrix)
1508 {
1509         if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1510                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1511         else
1512                 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1513
1514         GL_SetupView_Orientation_FromEntity(matrix);
1515 }
1516
1517 void R_ResetViewRendering2D(void)
1518 {
1519         if (gl_support_fragment_shader)
1520         {
1521                 qglUseProgramObjectARB(0);CHECKGLERROR
1522         }
1523
1524         DrawQ_Finish();
1525
1526         // GL is weird because it's bottom to top, r_view.y is top to bottom
1527         qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1528         GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1529         GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1530         GL_Color(1, 1, 1, 1);
1531         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1532         GL_BlendFunc(GL_ONE, GL_ZERO);
1533         GL_AlphaTest(false);
1534         GL_ScissorTest(false);
1535         GL_DepthMask(false);
1536         GL_DepthTest(false);
1537         R_Mesh_Matrix(&identitymatrix);
1538         R_Mesh_ResetTextureState();
1539         qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1540         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1541         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1542         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1543         qglStencilMask(~0);CHECKGLERROR
1544         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1545         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1546         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1547 }
1548
1549 void R_ResetViewRendering3D(void)
1550 {
1551         if (gl_support_fragment_shader)
1552         {
1553                 qglUseProgramObjectARB(0);CHECKGLERROR
1554         }
1555
1556         DrawQ_Finish();
1557
1558         // GL is weird because it's bottom to top, r_view.y is top to bottom
1559         qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1560         R_SetupView(&r_view.matrix);
1561         GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1562         GL_Color(1, 1, 1, 1);
1563         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1564         GL_BlendFunc(GL_ONE, GL_ZERO);
1565         GL_AlphaTest(false);
1566         GL_ScissorTest(true);
1567         GL_DepthMask(true);
1568         GL_DepthTest(true);
1569         R_Mesh_Matrix(&identitymatrix);
1570         R_Mesh_ResetTextureState();
1571         qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1572         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1573         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1574         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1575         qglStencilMask(~0);CHECKGLERROR
1576         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1577         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1578         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1579 }
1580
1581 /*
1582         R_Bloom_SetupShader(
1583 "// bloom shader\n"
1584 "// written by Forest 'LordHavoc' Hale\n"
1585 "\n"
1586 "// common definitions between vertex shader and fragment shader:\n"
1587 "\n"
1588 "#ifdef __GLSL_CG_DATA_TYPES\n"
1589 "#define myhalf half\n"
1590 "#define myhvec2 hvec2\n"
1591 "#define myhvec3 hvec3\n"
1592 "#define myhvec4 hvec4\n"
1593 "#else\n"
1594 "#define myhalf float\n"
1595 "#define myhvec2 vec2\n"
1596 "#define myhvec3 vec3\n"
1597 "#define myhvec4 vec4\n"
1598 "#endif\n"
1599 "\n"
1600 "varying vec2 ScreenTexCoord;\n"
1601 "varying vec2 BloomTexCoord;\n"
1602 "\n"
1603 "\n"
1604 "\n"
1605 "\n"
1606 "// vertex shader specific:\n"
1607 "#ifdef VERTEX_SHADER\n"
1608 "\n"
1609 "void main(void)\n"
1610 "{\n"
1611 "       ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
1612 "       BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
1613 "       // transform vertex to camera space, using ftransform to match non-VS\n"
1614 "       // rendering\n"
1615 "       gl_Position = ftransform();\n"
1616 "}\n"
1617 "\n"
1618 "#endif // VERTEX_SHADER\n"
1619 "\n"
1620 "\n"
1621 "\n"
1622 "\n"
1623 "// fragment shader specific:\n"
1624 "#ifdef FRAGMENT_SHADER\n"
1625 "\n"
1626 "void main(void)\n"
1627 "{\n"
1628 "       int x, y;
1629 "       myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
1630 "       for (x = -BLUR_X;x <= BLUR_X;x++)
1631 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
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
1636 "       gl_FragColor = vec4(color);\n"
1637 "}\n"
1638 "\n"
1639 "#endif // FRAGMENT_SHADER\n"
1640 */
1641
1642 void R_RenderScene(void);
1643
1644 void R_Bloom_StartFrame(void)
1645 {
1646         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
1647
1648         // set bloomwidth and bloomheight to the bloom resolution that will be
1649         // used (often less than the screen resolution for faster rendering)
1650         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
1651         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
1652         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
1653
1654         // calculate desired texture sizes
1655         if (gl_support_arb_texture_non_power_of_two)
1656         {
1657                 screentexturewidth = r_view.width;
1658                 screentextureheight = r_view.height;
1659                 bloomtexturewidth = r_bloomstate.bloomwidth;
1660                 bloomtextureheight = r_bloomstate.bloomheight;
1661         }
1662         else
1663         {
1664                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
1665                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
1666                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
1667                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
1668         }
1669
1670         if (r_hdr.integer)
1671         {
1672                 screentexturewidth = screentextureheight = 0;
1673         }
1674         else if (r_bloom.integer)
1675         {
1676         }
1677         else
1678         {
1679                 screentexturewidth = screentextureheight = 0;
1680                 bloomtexturewidth = bloomtextureheight = 0;
1681         }
1682
1683         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)
1684         {
1685                 // can't use bloom if the parameters are too weird
1686                 // can't use bloom if the card does not support the texture size
1687                 if (r_bloomstate.texture_screen)
1688                         R_FreeTexture(r_bloomstate.texture_screen);
1689                 if (r_bloomstate.texture_bloom)
1690                         R_FreeTexture(r_bloomstate.texture_bloom);
1691                 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1692                 return;
1693         }
1694
1695         r_bloomstate.enabled = true;
1696         r_bloomstate.hdr = r_hdr.integer != 0;
1697
1698         // allocate textures as needed
1699         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
1700         {
1701                 if (r_bloomstate.texture_screen)
1702                         R_FreeTexture(r_bloomstate.texture_screen);
1703                 r_bloomstate.texture_screen = NULL;
1704                 r_bloomstate.screentexturewidth = screentexturewidth;
1705                 r_bloomstate.screentextureheight = screentextureheight;
1706                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
1707                         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);
1708         }
1709         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
1710         {
1711                 if (r_bloomstate.texture_bloom)
1712                         R_FreeTexture(r_bloomstate.texture_bloom);
1713                 r_bloomstate.texture_bloom = NULL;
1714                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
1715                 r_bloomstate.bloomtextureheight = bloomtextureheight;
1716                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
1717                         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);
1718         }
1719
1720         // set up a texcoord array for the full resolution screen image
1721         // (we have to keep this around to copy back during final render)
1722         r_bloomstate.screentexcoord2f[0] = 0;
1723         r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1724         r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1725         r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1726         r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1727         r_bloomstate.screentexcoord2f[5] = 0;
1728         r_bloomstate.screentexcoord2f[6] = 0;
1729         r_bloomstate.screentexcoord2f[7] = 0;
1730
1731         // set up a texcoord array for the reduced resolution bloom image
1732         // (which will be additive blended over the screen image)
1733         r_bloomstate.bloomtexcoord2f[0] = 0;
1734         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1735         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1736         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1737         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1738         r_bloomstate.bloomtexcoord2f[5] = 0;
1739         r_bloomstate.bloomtexcoord2f[6] = 0;
1740         r_bloomstate.bloomtexcoord2f[7] = 0;
1741 }
1742
1743 void R_Bloom_CopyScreenTexture(float colorscale)
1744 {
1745         r_refdef.stats.bloom++;
1746
1747         R_ResetViewRendering2D();
1748         R_Mesh_VertexPointer(r_screenvertex3f);
1749         R_Mesh_ColorPointer(NULL);
1750         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f);
1751         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
1752
1753         // copy view into the screen texture
1754         GL_ActiveTexture(0);
1755         CHECKGLERROR
1756         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
1757         r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1758
1759         // now scale it down to the bloom texture size
1760         CHECKGLERROR
1761         qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1762         GL_BlendFunc(GL_ONE, GL_ZERO);
1763         GL_Color(colorscale, colorscale, colorscale, 1);
1764         // TODO: optimize with multitexture or GLSL
1765         R_Mesh_Draw(0, 4, 2, polygonelements);
1766         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1767
1768         // we now have a bloom image in the framebuffer
1769         // copy it into the bloom image texture for later processing
1770         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1771         GL_ActiveTexture(0);
1772         CHECKGLERROR
1773         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
1774         r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1775 }
1776
1777 void R_Bloom_CopyHDRTexture(void)
1778 {
1779         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1780         GL_ActiveTexture(0);
1781         CHECKGLERROR
1782         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
1783         r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1784 }
1785
1786 void R_Bloom_MakeTexture(void)
1787 {
1788         int x, range, dir;
1789         float xoffset, yoffset, r, brighten;
1790
1791         r_refdef.stats.bloom++;
1792
1793         R_ResetViewRendering2D();
1794         R_Mesh_VertexPointer(r_screenvertex3f);
1795         R_Mesh_ColorPointer(NULL);
1796
1797         // we have a bloom image in the framebuffer
1798         CHECKGLERROR
1799         qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1800
1801         for (x = 1;x < r_bloom_colorexponent.value;)
1802         {
1803                 x *= 2;
1804                 r = bound(0, r_bloom_colorexponent.value / x, 1);
1805                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1806                 GL_Color(r, r, r, 1);
1807                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1808                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1809                 R_Mesh_Draw(0, 4, 2, polygonelements);
1810                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1811
1812                 // copy the vertically blurred bloom view to a texture
1813                 GL_ActiveTexture(0);
1814                 CHECKGLERROR
1815                 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
1816                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1817         }
1818
1819         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
1820         brighten = r_bloom_brighten.value;
1821         if (r_hdr.integer)
1822                 brighten *= r_hdr_range.value;
1823         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1824         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f);
1825
1826         for (dir = 0;dir < 2;dir++)
1827         {
1828                 // blend on at multiple vertical offsets to achieve a vertical blur
1829                 // TODO: do offset blends using GLSL
1830                 GL_BlendFunc(GL_ONE, GL_ZERO);
1831                 for (x = -range;x <= range;x++)
1832                 {
1833                         if (!dir){xoffset = 0;yoffset = x;}
1834                         else {xoffset = x;yoffset = 0;}
1835                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
1836                         yoffset /= (float)r_bloomstate.bloomtextureheight;
1837                         // compute a texcoord array with the specified x and y offset
1838                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
1839                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1840                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1841                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1842                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1843                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
1844                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
1845                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
1846                         // this r value looks like a 'dot' particle, fading sharply to
1847                         // black at the edges
1848                         // (probably not realistic but looks good enough)
1849                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
1850                         //r = (dir ? 1.0f : brighten)/(range*2+1);
1851                         r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
1852                         GL_Color(r, r, r, 1);
1853                         R_Mesh_Draw(0, 4, 2, polygonelements);
1854                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1855                         GL_BlendFunc(GL_ONE, GL_ONE);
1856                 }
1857
1858                 // copy the vertically blurred bloom view to a texture
1859                 GL_ActiveTexture(0);
1860                 CHECKGLERROR
1861                 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
1862                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1863         }
1864
1865         // apply subtract last
1866         // (just like it would be in a GLSL shader)
1867         if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
1868         {
1869                 GL_BlendFunc(GL_ONE, GL_ZERO);
1870                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1871                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1872                 GL_Color(1, 1, 1, 1);
1873                 R_Mesh_Draw(0, 4, 2, polygonelements);
1874                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1875
1876                 GL_BlendFunc(GL_ONE, GL_ONE);
1877                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
1878                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1879                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1880                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
1881                 R_Mesh_Draw(0, 4, 2, polygonelements);
1882                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1883                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
1884
1885                 // copy the darkened bloom view to a texture
1886                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1887                 GL_ActiveTexture(0);
1888                 CHECKGLERROR
1889                 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
1890                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1891         }
1892 }
1893
1894 void R_HDR_RenderBloomTexture(void)
1895 {
1896         int oldwidth, oldheight;
1897
1898         oldwidth = r_view.width;
1899         oldheight = r_view.height;
1900         r_view.width = r_bloomstate.bloomwidth;
1901         r_view.height = r_bloomstate.bloomheight;
1902
1903         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
1904         // TODO: add exposure compensation features
1905         // TODO: add fp16 framebuffer support
1906
1907         r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
1908         if (r_hdr.integer)
1909                 r_view.colorscale /= r_hdr_range.value;
1910         R_RenderScene();
1911
1912         R_ResetViewRendering2D();
1913
1914         R_Bloom_CopyHDRTexture();
1915         R_Bloom_MakeTexture();
1916
1917         R_ResetViewRendering3D();
1918
1919         R_ClearScreen();
1920         if (r_timereport_active)
1921                 R_TimeReport("clear");
1922
1923
1924         // restore the view settings
1925         r_view.width = oldwidth;
1926         r_view.height = oldheight;
1927 }
1928
1929 static void R_BlendView(void)
1930 {
1931         if (r_bloomstate.enabled && r_bloomstate.hdr)
1932         {
1933                 // render high dynamic range bloom effect
1934                 // the bloom texture was made earlier this render, so we just need to
1935                 // blend it onto the screen...
1936                 R_ResetViewRendering2D();
1937                 R_Mesh_VertexPointer(r_screenvertex3f);
1938                 R_Mesh_ColorPointer(NULL);
1939                 GL_Color(1, 1, 1, 1);
1940                 GL_BlendFunc(GL_ONE, GL_ONE);
1941                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1942                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1943                 R_Mesh_Draw(0, 4, 2, polygonelements);
1944                 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1945         }
1946         else if (r_bloomstate.enabled)
1947         {
1948                 // render simple bloom effect
1949                 // copy the screen and shrink it and darken it for the bloom process
1950                 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
1951                 // make the bloom texture
1952                 R_Bloom_MakeTexture();
1953                 // put the original screen image back in place and blend the bloom
1954                 // texture on it
1955                 R_ResetViewRendering2D();
1956                 R_Mesh_VertexPointer(r_screenvertex3f);
1957                 R_Mesh_ColorPointer(NULL);
1958                 GL_Color(1, 1, 1, 1);
1959                 GL_BlendFunc(GL_ONE, GL_ZERO);
1960                 // do both in one pass if possible
1961                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1962                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1963                 if (r_textureunits.integer >= 2 && gl_combine.integer)
1964                 {
1965                         R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
1966                         R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
1967                         R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f);
1968                 }
1969                 else
1970                 {
1971                         R_Mesh_Draw(0, 4, 2, polygonelements);
1972                         r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1973                         // now blend on the bloom texture
1974                         GL_BlendFunc(GL_ONE, GL_ONE);
1975                         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
1976                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f);
1977                 }
1978                 R_Mesh_Draw(0, 4, 2, polygonelements);
1979                 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1980         }
1981         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
1982         {
1983                 // apply a color tint to the whole view
1984                 R_ResetViewRendering2D();
1985                 R_Mesh_VertexPointer(r_screenvertex3f);
1986                 R_Mesh_ColorPointer(NULL);
1987                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1988                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1989                 R_Mesh_Draw(0, 4, 2, polygonelements);
1990         }
1991 }
1992
1993 void R_RenderScene(void);
1994
1995 matrix4x4_t r_waterscrollmatrix;
1996
1997 void R_UpdateVariables(void)
1998 {
1999         R_Textures_Frame();
2000
2001         r_refdef.farclip = 4096;
2002         if (r_refdef.worldmodel)
2003                 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
2004         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
2005
2006         r_refdef.polygonfactor = 0;
2007         r_refdef.polygonoffset = 0;
2008         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
2009         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
2010
2011         r_refdef.rtworld = r_shadow_realtime_world.integer;
2012         r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
2013         r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
2014         r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
2015         r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
2016         if (r_showsurfaces.integer)
2017         {
2018                 r_refdef.rtworld = false;
2019                 r_refdef.rtworldshadows = false;
2020                 r_refdef.rtdlight = false;
2021                 r_refdef.rtdlightshadows = false;
2022                 r_refdef.lightmapintensity = 0;
2023         }
2024
2025         if (gamemode == GAME_NEHAHRA)
2026         {
2027                 if (gl_fogenable.integer)
2028                 {
2029                         r_refdef.oldgl_fogenable = true;
2030                         r_refdef.fog_density = gl_fogdensity.value;
2031                         r_refdef.fog_red = gl_fogred.value;
2032                         r_refdef.fog_green = gl_foggreen.value;
2033                         r_refdef.fog_blue = gl_fogblue.value;
2034                 }
2035                 else if (r_refdef.oldgl_fogenable)
2036                 {
2037                         r_refdef.oldgl_fogenable = false;
2038                         r_refdef.fog_density = 0;
2039                         r_refdef.fog_red = 0;
2040                         r_refdef.fog_green = 0;
2041                         r_refdef.fog_blue = 0;
2042                 }
2043         }
2044         if (r_refdef.fog_density)
2045         {
2046                 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red  , 1.0f);
2047                 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
2048                 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
2049         }
2050         if (r_refdef.fog_density)
2051         {
2052                 r_refdef.fogenabled = true;
2053                 // this is the point where the fog reaches 0.9986 alpha, which we
2054                 // consider a good enough cutoff point for the texture
2055                 // (0.9986 * 256 == 255.6)
2056                 r_refdef.fogrange = 400 / r_refdef.fog_density;
2057                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
2058                 r_refdef.fogtabledistmultiplier = FOGTABLEWIDTH * r_refdef.fograngerecip;
2059                 // fog color was already set
2060         }
2061         else
2062                 r_refdef.fogenabled = false;
2063 }
2064
2065 /*
2066 ================
2067 R_RenderView
2068 ================
2069 */
2070 void R_RenderView(void)
2071 {
2072         if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
2073                 return; //Host_Error ("R_RenderView: NULL worldmodel");
2074
2075         R_Shadow_UpdateWorldLightSelection();
2076
2077         CHECKGLERROR
2078         if (r_timereport_active)
2079                 R_TimeReport("setup");
2080
2081         R_View_Update();
2082         if (r_timereport_active)
2083                 R_TimeReport("visibility");
2084
2085         R_ResetViewRendering3D();
2086
2087         R_ClearScreen();
2088         if (r_timereport_active)
2089                 R_TimeReport("clear");
2090
2091         R_Bloom_StartFrame();
2092
2093         // this produces a bloom texture to be used in R_BlendView() later
2094         if (r_hdr.integer)
2095                 R_HDR_RenderBloomTexture();
2096
2097         r_view.colorscale = r_hdr_scenebrightness.value;
2098         R_RenderScene();
2099
2100         R_BlendView();
2101         if (r_timereport_active)
2102                 R_TimeReport("blendview");
2103
2104         GL_Scissor(0, 0, vid.width, vid.height);
2105         GL_ScissorTest(false);
2106         CHECKGLERROR
2107 }
2108
2109 extern void R_DrawLightningBeams (void);
2110 extern void VM_CL_AddPolygonsToMeshQueue (void);
2111 extern void R_DrawPortals (void);
2112 void R_RenderScene(void)
2113 {
2114         // don't let sound skip if going slow
2115         if (r_refdef.extraupdate)
2116                 S_ExtraUpdate ();
2117
2118         R_ResetViewRendering3D();
2119
2120         R_MeshQueue_BeginScene();
2121
2122         R_SkyStartFrame();
2123
2124         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);
2125
2126         if (cl.csqc_vidvars.drawworld)
2127         {
2128                 // don't let sound skip if going slow
2129                 if (r_refdef.extraupdate)
2130                         S_ExtraUpdate ();
2131
2132                 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2133                 {
2134                         r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2135                         if (r_timereport_active)
2136                                 R_TimeReport("worldsky");
2137                 }
2138
2139                 if (R_DrawBrushModelsSky() && r_timereport_active)
2140                         R_TimeReport("bmodelsky");
2141
2142                 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2143                 {
2144                         r_refdef.worldmodel->Draw(r_refdef.worldentity);
2145                         if (r_timereport_active)
2146                                 R_TimeReport("world");
2147                 }
2148         }
2149
2150         // don't let sound skip if going slow
2151         if (r_refdef.extraupdate)
2152                 S_ExtraUpdate ();
2153
2154         R_DrawModels();
2155         if (r_timereport_active)
2156                 R_TimeReport("models");
2157
2158         // don't let sound skip if going slow
2159         if (r_refdef.extraupdate)
2160                 S_ExtraUpdate ();
2161
2162         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2163         {
2164                 R_DrawModelShadows();
2165
2166                 R_ResetViewRendering3D();
2167
2168                 // don't let sound skip if going slow
2169                 if (r_refdef.extraupdate)
2170                         S_ExtraUpdate ();
2171         }
2172
2173         R_ShadowVolumeLighting(false);
2174         if (r_timereport_active)
2175                 R_TimeReport("rtlights");
2176
2177         // don't let sound skip if going slow
2178         if (r_refdef.extraupdate)
2179                 S_ExtraUpdate ();
2180
2181         if (cl.csqc_vidvars.drawworld)
2182         {
2183                 R_DrawLightningBeams();
2184                 if (r_timereport_active)
2185                         R_TimeReport("lightning");
2186
2187                 R_DrawParticles();
2188                 if (r_timereport_active)
2189                         R_TimeReport("particles");
2190
2191                 R_DrawExplosions();
2192                 if (r_timereport_active)
2193                         R_TimeReport("explosions");
2194         }
2195
2196         if (gl_support_fragment_shader)
2197         {
2198                 qglUseProgramObjectARB(0);CHECKGLERROR
2199         }
2200         VM_CL_AddPolygonsToMeshQueue();
2201
2202         if (r_drawportals.integer)
2203         {
2204                 R_DrawPortals();
2205                 if (r_timereport_active)
2206                         R_TimeReport("portals");
2207         }
2208
2209         if (gl_support_fragment_shader)
2210         {
2211                 qglUseProgramObjectARB(0);CHECKGLERROR
2212         }
2213         R_MeshQueue_RenderTransparent();
2214         if (r_timereport_active)
2215                 R_TimeReport("drawtrans");
2216
2217         if (gl_support_fragment_shader)
2218         {
2219                 qglUseProgramObjectARB(0);CHECKGLERROR
2220         }
2221
2222         if (cl.csqc_vidvars.drawworld)
2223         {
2224                 R_DrawCoronas();
2225                 if (r_timereport_active)
2226                         R_TimeReport("coronas");
2227         }
2228
2229         // don't let sound skip if going slow
2230         if (r_refdef.extraupdate)
2231                 S_ExtraUpdate ();
2232
2233         R_ResetViewRendering2D();
2234 }
2235
2236 /*
2237 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2238 {
2239         int i;
2240         float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2241         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2242         GL_DepthMask(false);
2243         GL_DepthTest(true);
2244         R_Mesh_Matrix(&identitymatrix);
2245
2246         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2247         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2248         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2249         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2250         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2251         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2252         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2253         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2254         R_FillColors(color, 8, cr, cg, cb, ca);
2255         if (r_refdef.fogenabled)
2256         {
2257                 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2258                 {
2259                         f2 = VERTEXFOGTABLE(VectorDistance(v, r_view.origin));
2260                         f1 = 1 - f2;
2261                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2262                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2263                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2264                 }
2265         }
2266         R_Mesh_VertexPointer(vertex3f);
2267         R_Mesh_ColorPointer(color);
2268         R_Mesh_ResetTextureState();
2269         R_Mesh_Draw(8, 12);
2270 }
2271 */
2272
2273 int nomodelelements[24] =
2274 {
2275         5, 2, 0,
2276         5, 1, 2,
2277         5, 0, 3,
2278         5, 3, 1,
2279         0, 2, 4,
2280         2, 1, 4,
2281         3, 0, 4,
2282         1, 3, 4
2283 };
2284
2285 float nomodelvertex3f[6*3] =
2286 {
2287         -16,   0,   0,
2288          16,   0,   0,
2289           0, -16,   0,
2290           0,  16,   0,
2291           0,   0, -16,
2292           0,   0,  16
2293 };
2294
2295 float nomodelcolor4f[6*4] =
2296 {
2297         0.0f, 0.0f, 0.5f, 1.0f,
2298         0.0f, 0.0f, 0.5f, 1.0f,
2299         0.0f, 0.5f, 0.0f, 1.0f,
2300         0.0f, 0.5f, 0.0f, 1.0f,
2301         0.5f, 0.0f, 0.0f, 1.0f,
2302         0.5f, 0.0f, 0.0f, 1.0f
2303 };
2304
2305 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2306 {
2307         int i;
2308         float f1, f2, *c;
2309         float color4f[6*4];
2310         // this is only called once per entity so numsurfaces is always 1, and
2311         // surfacelist is always {0}, so this code does not handle batches
2312         R_Mesh_Matrix(&ent->matrix);
2313
2314         if (ent->flags & EF_ADDITIVE)
2315         {
2316                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2317                 GL_DepthMask(false);
2318         }
2319         else if (ent->alpha < 1)
2320         {
2321                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2322                 GL_DepthMask(false);
2323         }
2324         else
2325         {
2326                 GL_BlendFunc(GL_ONE, GL_ZERO);
2327                 GL_DepthMask(true);
2328         }
2329         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2330         GL_CullFace((ent->flags & RENDER_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
2331         R_Mesh_VertexPointer(nomodelvertex3f);
2332         if (r_refdef.fogenabled)
2333         {
2334                 vec3_t org;
2335                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2336                 R_Mesh_ColorPointer(color4f);
2337                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2338                 f2 = VERTEXFOGTABLE(VectorDistance(org, r_view.origin));
2339                 f1 = 1 - f2;
2340                 for (i = 0, c = color4f;i < 6;i++, c += 4)
2341                 {
2342                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2343                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2344                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2345                         c[3] *= ent->alpha;
2346                 }
2347         }
2348         else if (ent->alpha != 1)
2349         {
2350                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2351                 R_Mesh_ColorPointer(color4f);
2352                 for (i = 0, c = color4f;i < 6;i++, c += 4)
2353                         c[3] *= ent->alpha;
2354         }
2355         else
2356                 R_Mesh_ColorPointer(nomodelcolor4f);
2357         R_Mesh_ResetTextureState();
2358         R_Mesh_Draw(0, 6, 8, nomodelelements);
2359 }
2360
2361 void R_DrawNoModel(entity_render_t *ent)
2362 {
2363         vec3_t org;
2364         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2365         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2366                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2367         //else
2368         //      R_DrawNoModelCallback(ent, 0);
2369 }
2370
2371 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2372 {
2373         vec3_t right1, right2, diff, normal;
2374
2375         VectorSubtract (org2, org1, normal);
2376
2377         // calculate 'right' vector for start
2378         VectorSubtract (r_view.origin, org1, diff);
2379         CrossProduct (normal, diff, right1);
2380         VectorNormalize (right1);
2381
2382         // calculate 'right' vector for end
2383         VectorSubtract (r_view.origin, org2, diff);
2384         CrossProduct (normal, diff, right2);
2385         VectorNormalize (right2);
2386
2387         vert[ 0] = org1[0] + width * right1[0];
2388         vert[ 1] = org1[1] + width * right1[1];
2389         vert[ 2] = org1[2] + width * right1[2];
2390         vert[ 3] = org1[0] - width * right1[0];
2391         vert[ 4] = org1[1] - width * right1[1];
2392         vert[ 5] = org1[2] - width * right1[2];
2393         vert[ 6] = org2[0] - width * right2[0];
2394         vert[ 7] = org2[1] - width * right2[1];
2395         vert[ 8] = org2[2] - width * right2[2];
2396         vert[ 9] = org2[0] + width * right2[0];
2397         vert[10] = org2[1] + width * right2[1];
2398         vert[11] = org2[2] + width * right2[2];
2399 }
2400
2401 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2402
2403 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)
2404 {
2405         float fog = 0.0f, ifog;
2406         float vertex3f[12];
2407
2408         if (r_refdef.fogenabled)
2409                 fog = VERTEXFOGTABLE(VectorDistance(origin, r_view.origin));
2410         ifog = 1 - fog;
2411
2412         R_Mesh_Matrix(&identitymatrix);
2413         GL_BlendFunc(blendfunc1, blendfunc2);
2414         GL_DepthMask(false);
2415         GL_DepthTest(!depthdisable);
2416
2417         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2418         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2419         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2420         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2421         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2422         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2423         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2424         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2425         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2426         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2427         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2428         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2429
2430         R_Mesh_VertexPointer(vertex3f);
2431         R_Mesh_ColorPointer(NULL);
2432         R_Mesh_ResetTextureState();
2433         R_Mesh_TexBind(0, R_GetTexture(texture));
2434         R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2435         // FIXME: fixed function path can't properly handle r_view.colorscale > 1
2436         GL_Color(cr * ifog * r_view.colorscale, cg * ifog * r_view.colorscale, cb * ifog * r_view.colorscale, ca);
2437         R_Mesh_Draw(0, 4, 2, polygonelements);
2438
2439         if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2440         {
2441                 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2442                 GL_BlendFunc(blendfunc1, GL_ONE);
2443                 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);
2444                 R_Mesh_Draw(0, 4, 2, polygonelements);
2445         }
2446 }
2447
2448 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
2449 {
2450         int i;
2451         float *vertex3f;
2452         float v[3];
2453         VectorSet(v, x, y, z);
2454         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2455                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2456                         break;
2457         if (i == mesh->numvertices)
2458         {
2459                 if (mesh->numvertices < mesh->maxvertices)
2460                 {
2461                         VectorCopy(v, vertex3f);
2462                         mesh->numvertices++;
2463                 }
2464                 return mesh->numvertices;
2465         }
2466         else
2467                 return i;
2468 }
2469
2470 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2471 {
2472         int i;
2473         int *e, element[3];
2474         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2475         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2476         e = mesh->element3i + mesh->numtriangles * 3;
2477         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2478         {
2479                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
2480                 if (mesh->numtriangles < mesh->maxtriangles)
2481                 {
2482                         *e++ = element[0];
2483                         *e++ = element[1];
2484                         *e++ = element[2];
2485                         mesh->numtriangles++;
2486                 }
2487                 element[1] = element[2];
2488         }
2489 }
2490
2491 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
2492 {
2493         int i;
2494         int *e, element[3];
2495         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2496         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2497         e = mesh->element3i + mesh->numtriangles * 3;
2498         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
2499         {
2500                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
2501                 if (mesh->numtriangles < mesh->maxtriangles)
2502                 {
2503                         *e++ = element[0];
2504                         *e++ = element[1];
2505                         *e++ = element[2];
2506                         mesh->numtriangles++;
2507                 }
2508                 element[1] = element[2];
2509         }
2510 }
2511
2512 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
2513 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2514 {
2515         int planenum, planenum2;
2516         int w;
2517         int tempnumpoints;
2518         mplane_t *plane, *plane2;
2519         double maxdist;
2520         double temppoints[2][256*3];
2521         // figure out how large a bounding box we need to properly compute this brush
2522         maxdist = 0;
2523         for (w = 0;w < numplanes;w++)
2524                 maxdist = max(maxdist, planes[w].dist);
2525         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
2526         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
2527         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2528         {
2529                 w = 0;
2530                 tempnumpoints = 4;
2531                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
2532                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2533                 {
2534                         if (planenum2 == planenum)
2535                                 continue;
2536                         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);
2537                         w = !w;
2538                 }
2539                 if (tempnumpoints < 3)
2540                         continue;
2541                 // generate elements forming a triangle fan for this polygon
2542                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
2543         }
2544 }
2545
2546 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2547 {
2548         int i;
2549         R_Mesh_VertexPointer(brush->points->v);
2550         i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2551         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);
2552         GL_LockArrays(0, brush->numpoints);
2553         R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2554         GL_LockArrays(0, 0);
2555 }
2556
2557 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2558 {
2559         int i;
2560         if (!surface->num_collisiontriangles)
2561                 return;
2562         R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2563         i = (int)(((size_t)surface) / sizeof(msurface_t));
2564         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);
2565         GL_LockArrays(0, surface->num_collisionvertices);
2566         R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2567         GL_LockArrays(0, 0);
2568 }
2569
2570 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)
2571 {
2572         texturelayer_t *layer;
2573         layer = t->currentlayers + t->currentnumlayers++;
2574         layer->type = type;
2575         layer->depthmask = depthmask;
2576         layer->blendfunc1 = blendfunc1;
2577         layer->blendfunc2 = blendfunc2;
2578         layer->texture = texture;
2579         layer->texmatrix = *matrix;
2580         layer->color[0] = r * r_view.colorscale;
2581         layer->color[1] = g * r_view.colorscale;
2582         layer->color[2] = b * r_view.colorscale;
2583         layer->color[3] = a;
2584 }
2585
2586 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2587 {
2588         model_t *model = ent->model;
2589
2590         // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2591         //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2592
2593         // switch to an alternate material if this is a q1bsp animated material
2594         {
2595                 texture_t *texture = t;
2596                 int s = ent->skinnum;
2597                 if ((unsigned int)s >= (unsigned int)model->numskins)
2598                         s = 0;
2599                 if (model->skinscenes)
2600                 {
2601                         if (model->skinscenes[s].framecount > 1)
2602                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2603                         else
2604                                 s = model->skinscenes[s].firstframe;
2605                 }
2606                 if (s > 0)
2607                         t = t + s * model->num_surfaces;
2608                 if (t->animated)
2609                 {
2610                         // use an alternate animation if the entity's frame is not 0,
2611                         // and only if the texture has an alternate animation
2612                         if (ent->frame != 0 && t->anim_total[1])
2613                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
2614                         else
2615                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
2616                 }
2617                 texture->currentframe = t;
2618         }
2619
2620         // pick a new currentskinframe if the material is animated
2621         if (t->numskinframes >= 2)
2622                 t->currentskinframe = t->skinframes + ((int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes);
2623         if (t->backgroundnumskinframes >= 2)
2624                 t->backgroundcurrentskinframe = t->backgroundskinframes + ((int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes);
2625
2626         t->currentmaterialflags = t->basematerialflags;
2627         t->currentalpha = ent->alpha;
2628         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
2629                 t->currentalpha *= r_wateralpha.value;
2630         if (!(ent->flags & RENDER_LIGHT))
2631                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2632         if (ent->effects & EF_ADDITIVE)
2633                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
2634         else if (t->currentalpha < 1)
2635                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
2636         if (ent->flags & RENDER_NOCULLFACE)
2637                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW;
2638         if (ent->effects & EF_NODEPTHTEST)
2639                 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_NOSHADOW;
2640         if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2641                 t->currenttexmatrix = r_waterscrollmatrix;
2642         else
2643                 t->currenttexmatrix = identitymatrix;
2644         if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2645                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
2646
2647         t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2648         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2649         t->glosstexture = r_texture_white;
2650         t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
2651         t->backgroundglosstexture = r_texture_white;
2652         t->specularpower = r_shadow_glossexponent.value;
2653         t->specularscale = 0;
2654         if (r_shadow_gloss.integer > 0)
2655         {
2656                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
2657                 {
2658                         if (r_shadow_glossintensity.value > 0)
2659                         {
2660                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_black;
2661                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_black;
2662                                 t->specularscale = r_shadow_glossintensity.value;
2663                         }
2664                 }
2665                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2666                         t->specularscale = r_shadow_gloss2intensity.value;
2667         }
2668
2669         t->currentnumlayers = 0;
2670         if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2671         {
2672                 if (gl_lightmaps.integer)
2673                         R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2674                 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2675                 {
2676                         int blendfunc1, blendfunc2, depthmask;
2677                         if (t->currentmaterialflags & MATERIALFLAG_ADD)
2678                         {
2679                                 blendfunc1 = GL_SRC_ALPHA;
2680                                 blendfunc2 = GL_ONE;
2681                         }
2682                         else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2683                         {
2684                                 blendfunc1 = GL_SRC_ALPHA;
2685                                 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2686                         }
2687                         else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2688                         {
2689                                 blendfunc1 = t->customblendfunc[0];
2690                                 blendfunc2 = t->customblendfunc[1];
2691                         }
2692                         else
2693                         {
2694                                 blendfunc1 = GL_ONE;
2695                                 blendfunc2 = GL_ZERO;
2696                         }
2697                         depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2698                         if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2699                         {
2700                                 rtexture_t *currentbasetexture;
2701                                 int layerflags = 0;
2702                                 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2703                                         layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2704                                 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2705                                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2706                                 {
2707                                         // fullbright is not affected by r_refdef.lightmapintensity
2708                                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2709                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2710                                                 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);
2711                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2712                                                 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);
2713                                 }
2714                                 else
2715                                 {
2716                                         float colorscale;
2717                                         colorscale = 2;
2718                                         // q3bsp has no lightmap updates, so the lightstylevalue that
2719                                         // would normally be baked into the lightmap must be
2720                                         // applied to the color
2721                                         if (ent->model->type == mod_brushq3)
2722                                                 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2723                                         colorscale *= r_refdef.lightmapintensity;
2724                                         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);
2725                                         if (r_ambient.value >= (1.0f/64.0f))
2726                                                 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);
2727                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2728                                         {
2729                                                 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);
2730                                                 if (r_ambient.value >= (1.0f/64.0f))
2731                                                         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);
2732                                         }
2733                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2734                                         {
2735                                                 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);
2736                                                 if (r_ambient.value >= (1.0f/64.0f))
2737                                                         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);
2738                                         }
2739                                 }
2740                                 if (t->currentskinframe->glow != NULL)
2741                                         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);
2742                                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2743                                 {
2744                                         // if this is opaque use alpha blend which will darken the earlier
2745                                         // passes cheaply.
2746                                         //
2747                                         // if this is an alpha blended material, all the earlier passes
2748                                         // were darkened by fog already, so we only need to add the fog
2749                                         // color ontop through the fog mask texture
2750                                         //
2751                                         // if this is an additive blended material, all the earlier passes
2752                                         // were darkened by fog already, and we should not add fog color
2753                                         // (because the background was not darkened, there is no fog color
2754                                         // that was lost behind it).
2755                                         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);
2756                                 }
2757                         }
2758                 }
2759         }
2760 }
2761
2762 void R_UpdateAllTextureInfo(entity_render_t *ent)
2763 {
2764         int i;
2765         if (ent->model)
2766                 for (i = 0;i < ent->model->num_textures;i++)
2767                         R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2768 }
2769
2770 int rsurface_array_size = 0;
2771 float *rsurface_array_modelvertex3f = NULL;
2772 float *rsurface_array_modelsvector3f = NULL;
2773 float *rsurface_array_modeltvector3f = NULL;
2774 float *rsurface_array_modelnormal3f = NULL;
2775 float *rsurface_array_deformedvertex3f = NULL;
2776 float *rsurface_array_deformedsvector3f = NULL;
2777 float *rsurface_array_deformedtvector3f = NULL;
2778 float *rsurface_array_deformednormal3f = NULL;
2779 float *rsurface_array_color4f = NULL;
2780 float *rsurface_array_texcoord3f = NULL;
2781
2782 void R_Mesh_ResizeArrays(int newvertices)
2783 {
2784         float *base;
2785         if (rsurface_array_size >= newvertices)
2786                 return;
2787         if (rsurface_array_modelvertex3f)
2788                 Mem_Free(rsurface_array_modelvertex3f);
2789         rsurface_array_size = (newvertices + 1023) & ~1023;
2790         base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2791         rsurface_array_modelvertex3f     = base + rsurface_array_size * 0;
2792         rsurface_array_modelsvector3f    = base + rsurface_array_size * 3;
2793         rsurface_array_modeltvector3f    = base + rsurface_array_size * 6;
2794         rsurface_array_modelnormal3f     = base + rsurface_array_size * 9;
2795         rsurface_array_deformedvertex3f  = base + rsurface_array_size * 12;
2796         rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2797         rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2798         rsurface_array_deformednormal3f  = base + rsurface_array_size * 21;
2799         rsurface_array_texcoord3f        = base + rsurface_array_size * 24;
2800         rsurface_array_color4f           = base + rsurface_array_size * 27;
2801 }
2802
2803 float *rsurface_modelvertex3f;
2804 float *rsurface_modelsvector3f;
2805 float *rsurface_modeltvector3f;
2806 float *rsurface_modelnormal3f;
2807 float *rsurface_vertex3f;
2808 float *rsurface_svector3f;
2809 float *rsurface_tvector3f;
2810 float *rsurface_normal3f;
2811 float *rsurface_lightmapcolor4f;
2812 vec3_t rsurface_modelorg;
2813 qboolean rsurface_generatedvertex;
2814 const entity_render_t *rsurface_entity;
2815 const model_t *rsurface_model;
2816 texture_t *rsurface_texture;
2817 qboolean rsurface_uselightmaptexture;
2818 rsurfmode_t rsurface_mode;
2819 texture_t *rsurface_glsl_texture;
2820 qboolean rsurface_glsl_uselightmap;
2821
2822 void RSurf_CleanUp(void)
2823 {
2824         CHECKGLERROR
2825         if (rsurface_mode == RSURFMODE_GLSL)
2826         {
2827                 qglUseProgramObjectARB(0);CHECKGLERROR
2828         }
2829         GL_AlphaTest(false);
2830         rsurface_mode = RSURFMODE_NONE;
2831         rsurface_uselightmaptexture = false;
2832         rsurface_texture = NULL;
2833         rsurface_glsl_texture = NULL;
2834         rsurface_glsl_uselightmap = false;
2835 }
2836
2837 void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2838 {
2839         RSurf_CleanUp();
2840         Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2841         rsurface_entity = ent;
2842         rsurface_model = ent->model;
2843         if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2844                 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2845         R_Mesh_Matrix(&ent->matrix);
2846         Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2847         if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && rsurface_model->surfmesh.isanimated)
2848         {
2849                 if (wanttangents)
2850                 {
2851                         rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2852                         rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2853                         rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2854                         rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2855                         Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2856                 }
2857                 else if (wantnormals)
2858                 {
2859                         rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2860                         rsurface_modelsvector3f = NULL;
2861                         rsurface_modeltvector3f = NULL;
2862                         rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2863                         Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2864                 }
2865                 else
2866                 {
2867                         rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2868                         rsurface_modelsvector3f = NULL;
2869                         rsurface_modeltvector3f = NULL;
2870                         rsurface_modelnormal3f = NULL;
2871                         Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2872                 }
2873                 rsurface_generatedvertex = true;
2874         }
2875         else
2876         {
2877                 rsurface_modelvertex3f  = rsurface_model->surfmesh.data_vertex3f;
2878                 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2879                 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2880                 rsurface_modelnormal3f  = rsurface_model->surfmesh.data_normal3f;
2881                 rsurface_generatedvertex = false;
2882         }
2883         rsurface_vertex3f  = rsurface_modelvertex3f;
2884         rsurface_svector3f = rsurface_modelsvector3f;
2885         rsurface_tvector3f = rsurface_modeltvector3f;
2886         rsurface_normal3f  = rsurface_modelnormal3f;
2887 }
2888
2889 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2890 {
2891         // 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
2892         if (rsurface_generatedvertex)
2893         {
2894                 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2895                         generatetangents = true;
2896                 if (generatetangents)
2897                         generatenormals = true;
2898                 if (generatenormals && !rsurface_modelnormal3f)
2899                 {
2900                         rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2901                         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);
2902                 }
2903                 if (generatetangents && !rsurface_modelsvector3f)
2904                 {
2905                         rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2906                         rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2907                         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);
2908                 }
2909         }
2910         // 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)
2911         if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2912         {
2913                 int texturesurfaceindex;
2914                 float center[3], forward[3], right[3], up[3], v[4][3];
2915                 matrix4x4_t matrix1, imatrix1;
2916                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
2917                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
2918                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
2919                 // make deformed versions of only the model vertices used by the specified surfaces
2920                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2921                 {
2922                         int i, j;
2923                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2924                         // a single autosprite surface can contain multiple sprites...
2925                         for (j = 0;j < surface->num_vertices - 3;j += 4)
2926                         {
2927                                 VectorClear(center);
2928                                 for (i = 0;i < 4;i++)
2929                                         VectorAdd(center, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2930                                 VectorScale(center, 0.25f, center);
2931                                 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2932                                 {
2933                                         forward[0] = rsurface_modelorg[0] - center[0];
2934                                         forward[1] = rsurface_modelorg[1] - center[1];
2935                                         forward[2] = 0;
2936                                         VectorNormalize(forward);
2937                                         right[0] = forward[1];
2938                                         right[1] = -forward[0];
2939                                         right[2] = 0;
2940                                         VectorSet(up, 0, 0, 1);
2941                                 }
2942                                 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2943                                 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);
2944                                 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2945                                 for (i = 0;i < 4;i++)
2946                                         Matrix4x4_Transform(&imatrix1, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2947                                 for (i = 0;i < 4;i++)
2948                                         VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
2949                         }
2950                         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);
2951                         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);
2952                 }
2953                 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2954                 rsurface_svector3f = rsurface_array_deformedsvector3f;
2955                 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2956                 rsurface_normal3f = rsurface_array_deformednormal3f;
2957         }
2958         else
2959         {
2960                 rsurface_vertex3f = rsurface_modelvertex3f;
2961                 rsurface_svector3f = rsurface_modelsvector3f;
2962                 rsurface_tvector3f = rsurface_modeltvector3f;
2963                 rsurface_normal3f = rsurface_modelnormal3f;
2964         }
2965         R_Mesh_VertexPointer(rsurface_vertex3f);
2966 }
2967
2968 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
2969 {
2970         int i, j;
2971         const msurface_t *surface = texturesurfacelist[0];
2972         const msurface_t *surface2;
2973         int firstvertex;
2974         int endvertex;
2975         int numvertices;
2976         int numtriangles;
2977         // TODO: lock all array ranges before render, rather than on each surface
2978         if (texturenumsurfaces == 1)
2979         {
2980                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2981                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2982         }
2983         else if (r_batchmode.integer == 2)
2984         {
2985                 #define MAXBATCHTRIANGLES 4096
2986                 int batchtriangles = 0;
2987                 int batchelements[MAXBATCHTRIANGLES*3];
2988                 for (i = 0;i < texturenumsurfaces;i = j)
2989                 {
2990                         surface = texturesurfacelist[i];
2991                         j = i + 1;
2992                         if (surface->num_triangles > MAXBATCHTRIANGLES)
2993                         {
2994                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2995                                 continue;
2996                         }
2997                         memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
2998                         batchtriangles = surface->num_triangles;
2999                         firstvertex = surface->num_firstvertex;
3000                         endvertex = surface->num_firstvertex + surface->num_vertices;
3001                         for (;j < texturenumsurfaces;j++)
3002                         {
3003                                 surface2 = texturesurfacelist[j];
3004                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
3005                                         break;
3006                                 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
3007                                 batchtriangles += surface2->num_triangles;
3008                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
3009                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
3010                         }
3011                         surface2 = texturesurfacelist[j-1];
3012                         numvertices = endvertex - firstvertex;
3013                         R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements);
3014                 }
3015         }
3016         else if (r_batchmode.integer == 1)
3017         {
3018                 for (i = 0;i < texturenumsurfaces;i = j)
3019                 {
3020                         surface = texturesurfacelist[i];
3021                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3022                                 if (texturesurfacelist[j] != surface2)
3023                                         break;
3024                         surface2 = texturesurfacelist[j-1];
3025                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3026                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3027                         GL_LockArrays(surface->num_firstvertex, numvertices);
3028                         R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3029                 }
3030         }
3031         else
3032         {
3033                 for (i = 0;i < texturenumsurfaces;i++)
3034                 {
3035                         surface = texturesurfacelist[i];
3036                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3037                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3038                 }
3039         }
3040 }
3041
3042 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
3043 {
3044         int i;
3045         int j;
3046         const msurface_t *surface = texturesurfacelist[0];
3047         const msurface_t *surface2;
3048         int firstvertex;
3049         int endvertex;
3050         int numvertices;
3051         int numtriangles;
3052         // TODO: lock all array ranges before render, rather than on each surface
3053         if (texturenumsurfaces == 1)
3054         {
3055                 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3056                 if (deluxemaptexunit >= 0)
3057                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3058                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3059                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3060         }
3061         else if (r_batchmode.integer == 2)
3062         {
3063                 #define MAXBATCHTRIANGLES 4096
3064                 int batchtriangles = 0;
3065                 int batchelements[MAXBATCHTRIANGLES*3];
3066                 for (i = 0;i < texturenumsurfaces;i = j)
3067                 {
3068                         surface = texturesurfacelist[i];
3069                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3070                         if (deluxemaptexunit >= 0)
3071                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3072                         j = i + 1;
3073                         if (surface->num_triangles > MAXBATCHTRIANGLES)
3074                         {
3075                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3076                                 continue;
3077                         }
3078                         memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
3079                         batchtriangles = surface->num_triangles;
3080                         firstvertex = surface->num_firstvertex;
3081                         endvertex = surface->num_firstvertex + surface->num_vertices;
3082                         for (;j < texturenumsurfaces;j++)
3083                         {
3084                                 surface2 = texturesurfacelist[j];
3085                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
3086                                         break;
3087                                 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
3088                                 batchtriangles += surface2->num_triangles;
3089                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
3090                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
3091                         }
3092                         surface2 = texturesurfacelist[j-1];
3093                         numvertices = endvertex - firstvertex;
3094                         R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements);
3095                 }
3096         }
3097         else if (r_batchmode.integer == 1)
3098         {
3099                 for (i = 0;i < texturenumsurfaces;i = j)
3100                 {
3101                         surface = texturesurfacelist[i];
3102                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3103                         if (deluxemaptexunit >= 0)
3104                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3105                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3106                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
3107                                         break;
3108                         surface2 = texturesurfacelist[j-1];
3109                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3110                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3111                         GL_LockArrays(surface->num_firstvertex, numvertices);
3112                         R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3113                 }
3114         }
3115         else
3116         {
3117                 for (i = 0;i < texturenumsurfaces;i++)
3118                 {
3119                         surface = texturesurfacelist[i];
3120                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3121                         if (deluxemaptexunit >= 0)
3122                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3123                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3124                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3125                 }
3126         }
3127 }
3128
3129 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3130 {
3131         int j;
3132         int texturesurfaceindex;
3133         if (r_showsurfaces.integer == 2)
3134         {
3135                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3136                 {
3137                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3138                         for (j = 0;j < surface->num_triangles;j++)
3139                         {
3140                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
3141                                 GL_Color(f, f, f, 1);
3142                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, 1, (rsurface_model->surfmesh.data_element3i + 3 * (j + surface->num_firsttriangle)));
3143                         }
3144                 }
3145         }
3146         else
3147         {
3148                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3149                 {
3150                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3151                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
3152                         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);
3153                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3154                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3155                 }
3156         }
3157 }
3158
3159 static void RSurf_DrawBatch_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
3160 {
3161         int texturesurfaceindex;
3162         int i;
3163         float f;
3164         float *v, *c, *c2;
3165         // TODO: optimize
3166         if (lightmode >= 2)
3167         {
3168                 // model lighting
3169                 vec3_t ambientcolor;
3170                 vec3_t diffusecolor;
3171                 vec3_t lightdir;
3172                 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
3173                 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
3174                 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
3175                 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
3176                 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
3177                 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
3178                 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
3179                 if (VectorLength2(diffusecolor) > 0)
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                                 int numverts = surface->num_vertices;
3186                                 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
3187                                 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
3188                                 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
3189                                 // q3-style directional shading
3190                                 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
3191                                 {
3192                                         if ((f = DotProduct(c2, lightdir)) > 0)
3193                                                 VectorMA(ambientcolor, f, diffusecolor, c);
3194                                         else
3195                                                 VectorCopy(ambientcolor, c);
3196                                         c[3] = a;
3197                                 }
3198                         }
3199                         r = 1;
3200                         g = 1;
3201                         b = 1;
3202                         a = 1;
3203                         applycolor = false;
3204                         rsurface_lightmapcolor4f = rsurface_array_color4f;
3205                 }
3206                 else
3207                 {
3208                         r = ambientcolor[0];
3209                         g = ambientcolor[1];
3210                         b = ambientcolor[2];
3211                         rsurface_lightmapcolor4f = NULL;
3212                 }
3213         }
3214         else if (lightmode >= 1 || !rsurface_uselightmaptexture)
3215         {
3216                 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
3217                 {
3218                         // generate color arrays for the surfaces in this list
3219                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3220                         {
3221                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3222                                 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
3223                                 {
3224                                         if (surface->lightmapinfo->samples)
3225                                         {
3226                                                 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
3227                                                 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
3228                                                 VectorScale(lm, scale, c);
3229                                                 if (surface->lightmapinfo->styles[1] != 255)
3230                                                 {
3231                                                         int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
3232                                                         lm += size3;
3233                                                         scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
3234                                                         VectorMA(c, scale, lm, c);
3235                                                         if (surface->lightmapinfo->styles[2] != 255)
3236                                                         {
3237                                                                 lm += size3;
3238                                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
3239                                                                 VectorMA(c, scale, lm, c);
3240                                                                 if (surface->lightmapinfo->styles[3] != 255)
3241                                                                 {
3242                                                                         lm += size3;
3243                                                                         scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
3244                                                                         VectorMA(c, scale, lm, c);
3245                                                                 }
3246                                                         }
3247                                                 }
3248                                         }
3249                                         else
3250                                                 VectorClear(c);
3251                                         c[3] = 1;
3252                                 }
3253                         }
3254                         rsurface_lightmapcolor4f = rsurface_array_color4f;
3255                 }
3256                 else
3257                         rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
3258         }
3259         else
3260         {
3261                 // just lightmap it
3262                 rsurface_lightmapcolor4f = NULL;
3263         }
3264         if (applyfog)
3265         {
3266                 if (rsurface_lightmapcolor4f)
3267                 {
3268                         // generate color arrays for the surfaces in this list
3269                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3270                         {
3271                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3272                                 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)
3273                                 {
3274                                         f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3275                                         c2[0] = c[0] * f;
3276                                         c2[1] = c[1] * f;
3277                                         c2[2] = c[2] * f;
3278                                         c2[3] = c[3];
3279                                 }
3280                         }
3281                 }
3282                 else
3283                 {
3284                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3285                         {
3286                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3287                                 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)
3288                                 {
3289                                         f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3290                                         c2[0] = f;
3291                                         c2[1] = f;
3292                                         c2[2] = f;
3293                                         c2[3] = 1;
3294                                 }
3295                         }
3296                 }
3297                 rsurface_lightmapcolor4f = rsurface_array_color4f;
3298         }
3299         if (applycolor && rsurface_lightmapcolor4f)
3300         {
3301                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3302                 {
3303                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3304                         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)
3305                         {
3306                                 c2[0] = c[0] * r;
3307                                 c2[1] = c[1] * g;
3308                                 c2[2] = c[2] * b;
3309                                 c2[3] = c[3] * a;
3310                         }
3311                 }
3312                 rsurface_lightmapcolor4f = rsurface_array_color4f;
3313         }
3314         R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3315         GL_Color(r, g, b, a);
3316         if (rsurface_uselightmaptexture && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
3317                 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
3318         else
3319                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3320 }
3321
3322 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3323 {
3324         GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3325         GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3326         if (rsurface_mode != RSURFMODE_SHOWSURFACES)
3327         {
3328                 rsurface_mode = RSURFMODE_SHOWSURFACES;
3329                 GL_DepthMask(true);
3330                 GL_BlendFunc(GL_ONE, GL_ZERO);
3331                 R_Mesh_ColorPointer(NULL);
3332                 R_Mesh_ResetTextureState();
3333         }
3334         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3335         RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3336 }
3337
3338 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
3339 {
3340         // transparent sky would be ridiculous
3341         if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
3342                 return;
3343         if (rsurface_mode != RSURFMODE_SKY)
3344         {
3345                 if (rsurface_mode == RSURFMODE_GLSL)
3346                 {
3347                         qglUseProgramObjectARB(0);CHECKGLERROR
3348                 }
3349                 rsurface_mode = RSURFMODE_SKY;
3350         }
3351         if (skyrendernow)
3352         {
3353                 skyrendernow = false;
3354                 R_Sky();
3355                 // restore entity matrix
3356                 R_Mesh_Matrix(&rsurface_entity->matrix);
3357         }
3358         GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3359         GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3360         GL_DepthMask(true);
3361         // LordHavoc: HalfLife maps have freaky skypolys so don't use
3362         // skymasking on them, and Quake3 never did sky masking (unlike
3363         // software Quake and software Quake2), so disable the sky masking
3364         // in Quake3 maps as it causes problems with q3map2 sky tricks,
3365         // and skymasking also looks very bad when noclipping outside the
3366         // level, so don't use it then either.
3367         if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
3368         {
3369                 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
3370                 R_Mesh_ColorPointer(NULL);
3371                 R_Mesh_ResetTextureState();
3372                 if (skyrendermasked)
3373                 {
3374                         // depth-only (masking)
3375                         GL_ColorMask(0,0,0,0);
3376                         // just to make sure that braindead drivers don't draw
3377                         // anything despite that colormask...
3378                         GL_BlendFunc(GL_ZERO, GL_ONE);
3379                 }
3380                 else
3381                 {
3382                         // fog sky
3383                         GL_BlendFunc(GL_ONE, GL_ZERO);
3384                 }
3385                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3386                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3387                 if (skyrendermasked)
3388                         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
3389         }
3390 }
3391
3392 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
3393 {
3394         if (rsurface_mode != RSURFMODE_GLSL)
3395         {
3396                 rsurface_mode = RSURFMODE_GLSL;
3397                 rsurface_glsl_texture = NULL;
3398                 rsurface_glsl_uselightmap = false;
3399                 R_Mesh_ResetTextureState();
3400         }
3401         if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != rsurface_uselightmaptexture)
3402         {
3403                 int lightmode;
3404                 rsurface_glsl_texture = rsurface_texture;
3405                 rsurface_glsl_uselightmap = rsurface_uselightmaptexture;
3406                 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3407                 GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3408                 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
3409                 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
3410                 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
3411                 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3412                 lightmode = ((rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3413                 R_SetupSurfaceShader(vec3_origin, lightmode == 2);
3414                 //permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, false);
3415                 //if (r_glsl_deluxemapping.integer)
3416                 //      permutation_deluxemapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, true);
3417                 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
3418                 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
3419                 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
3420                 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
3421                 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
3422                 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
3423                 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
3424                 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3425                 {
3426                         R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3427                         if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3428                                 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3429                         R_Mesh_ColorPointer(NULL);
3430                 }
3431                 else if (rsurface_uselightmaptexture)
3432                 {
3433                         R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
3434                         if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3435                                 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
3436                         R_Mesh_ColorPointer(NULL);
3437                 }
3438                 else
3439                 {
3440                         R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3441                         if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3442                                 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3443                         R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
3444                 }
3445         }
3446         else
3447                 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
3448         if (!r_glsl_permutation)
3449                 return;
3450         if (rsurface_uselightmaptexture && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
3451                 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
3452         else
3453                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3454         if (rsurface_texture->backgroundnumskinframes && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
3455         {
3456         }
3457 }
3458
3459 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
3460 {
3461         // OpenGL 1.3 path - anything not completely ancient
3462         int texturesurfaceindex;
3463         int lightmode;
3464         qboolean applycolor;
3465         qboolean applyfog;
3466         rmeshstate_t m;
3467         int layerindex;
3468         const texturelayer_t *layer;
3469         CHECKGLERROR
3470         GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3471         GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3472         // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3473         lightmode = ((rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3474         if (rsurface_mode != RSURFMODE_MULTIPASS)
3475                 rsurface_mode = RSURFMODE_MULTIPASS;
3476         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3477         for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3478         {
3479                 vec4_t layercolor;
3480                 int layertexrgbscale;
3481                 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3482                 {
3483                         if (layerindex == 0)
3484                                 GL_AlphaTest(true);
3485                         else
3486                         {
3487                                 GL_AlphaTest(false);
3488                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3489                         }
3490                 }
3491                 GL_DepthMask(layer->depthmask);
3492                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3493                 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
3494                 {
3495                         layertexrgbscale = 4;
3496                         VectorScale(layer->color, 0.25f, layercolor);
3497                 }
3498                 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
3499                 {
3500                         layertexrgbscale = 2;
3501                         VectorScale(layer->color, 0.5f, layercolor);
3502                 }
3503                 else
3504                 {
3505                         layertexrgbscale = 1;
3506                         VectorScale(layer->color, 1.0f, layercolor);
3507                 }
3508                 layercolor[3] = layer->color[3];
3509                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
3510                 R_Mesh_ColorPointer(NULL);
3511                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3512                 switch (layer->type)
3513                 {
3514                 case TEXTURELAYERTYPE_LITTEXTURE:
3515                         memset(&m, 0, sizeof(m));
3516                         m.tex[0] = R_GetTexture(r_texture_white);
3517                         m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3518                         m.tex[1] = R_GetTexture(layer->texture);
3519                         m.texmatrix[1] = layer->texmatrix;
3520                         m.texrgbscale[1] = layertexrgbscale;
3521                         m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
3522                         R_Mesh_TextureState(&m);
3523                         RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode, applycolor, applyfog);
3524                         break;
3525                 case TEXTURELAYERTYPE_TEXTURE:
3526                         memset(&m, 0, sizeof(m));
3527                         m.tex[0] = R_GetTexture(layer->texture);
3528                         m.texmatrix[0] = layer->texmatrix;
3529                         m.texrgbscale[0] = layertexrgbscale;
3530                         m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3531                         R_Mesh_TextureState(&m);
3532                         RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3533                         break;
3534                 case TEXTURELAYERTYPE_FOG:
3535                         memset(&m, 0, sizeof(m));
3536                         m.texrgbscale[0] = layertexrgbscale;
3537                         if (layer->texture)
3538                         {
3539                                 m.tex[0] = R_GetTexture(layer->texture);
3540                                 m.texmatrix[0] = layer->texmatrix;
3541                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3542                         }
3543                         R_Mesh_TextureState(&m);
3544                         // generate a color array for the fog pass
3545                         R_Mesh_ColorPointer(rsurface_array_color4f);
3546                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3547                         {
3548                                 int i;
3549                                 float f, *v, *c;
3550                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3551                                 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)
3552                                 {
3553                                         f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3554                                         c[0] = layercolor[0];
3555                                         c[1] = layercolor[1];
3556                                         c[2] = layercolor[2];
3557                                         c[3] = f * layercolor[3];
3558                                 }
3559                         }
3560                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3561                         break;
3562                 default:
3563                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3564                 }
3565                 GL_LockArrays(0, 0);
3566         }
3567         CHECKGLERROR
3568         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3569         {
3570                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3571                 GL_AlphaTest(false);
3572         }
3573 }
3574
3575 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3576 {
3577         // OpenGL 1.1 - crusty old voodoo path
3578         int texturesurfaceindex;
3579         int lightmode;
3580         qboolean applyfog;
3581         rmeshstate_t m;
3582         int layerindex;
3583         const texturelayer_t *layer;
3584         CHECKGLERROR
3585         GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3586         GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3587         // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3588         lightmode = ((rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3589         if (rsurface_mode != RSURFMODE_MULTIPASS)
3590                 rsurface_mode = RSURFMODE_MULTIPASS;
3591         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3592         for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3593         {
3594                 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3595                 {
3596                         if (layerindex == 0)
3597                                 GL_AlphaTest(true);
3598                         else
3599                         {
3600                                 GL_AlphaTest(false);
3601                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3602                         }
3603                 }
3604                 GL_DepthMask(layer->depthmask);
3605                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3606                 R_Mesh_ColorPointer(NULL);
3607                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3608                 switch (layer->type)
3609                 {
3610                 case TEXTURELAYERTYPE_LITTEXTURE:
3611                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3612                         {
3613                                 // two-pass lit texture with 2x rgbscale
3614                                 // first the lightmap pass
3615                                 memset(&m, 0, sizeof(m));
3616                                 m.tex[0] = R_GetTexture(r_texture_white);
3617                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3618                                 R_Mesh_TextureState(&m);
3619                                 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, lightmode, false, false);
3620                                 GL_LockArrays(0, 0);
3621                                 // then apply the texture to it
3622                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3623                                 memset(&m, 0, sizeof(m));
3624                                 m.tex[0] = R_GetTexture(layer->texture);
3625                                 m.texmatrix[0] = layer->texmatrix;
3626                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3627                                 R_Mesh_TextureState(&m);
3628                                 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], 0, layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
3629                         }
3630                         else
3631                         {
3632                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3633                                 memset(&m, 0, sizeof(m));
3634                                 m.tex[0] = R_GetTexture(layer->texture);
3635                                 m.texmatrix[0] = layer->texmatrix;
3636                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3637                                 R_Mesh_TextureState(&m);
3638                                 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], lightmode == 2 ? 2 : 1, layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
3639                         }
3640                         break;
3641                 case TEXTURELAYERTYPE_TEXTURE:
3642                         // singletexture unlit texture with transparency support
3643                         memset(&m, 0, sizeof(m));
3644                         m.tex[0] = R_GetTexture(layer->texture);
3645                         m.texmatrix[0] = layer->texmatrix;
3646                         m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3647                         R_Mesh_TextureState(&m);
3648                         RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], 0, layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
3649                         break;
3650                 case TEXTURELAYERTYPE_FOG:
3651                         // singletexture fogging
3652                         R_Mesh_ColorPointer(rsurface_array_color4f);
3653                         if (layer->texture)
3654                         {
3655                                 memset(&m, 0, sizeof(m));
3656                                 m.tex[0] = R_GetTexture(layer->texture);
3657                                 m.texmatrix[0] = layer->texmatrix;
3658                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3659                                 R_Mesh_TextureState(&m);
3660                         }
3661                         else
3662                                 R_Mesh_ResetTextureState();
3663                         // generate a color array for the fog pass
3664                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3665                         {
3666                                 int i;
3667                                 float f, *v, *c;
3668                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3669                                 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)
3670                                 {
3671                                         f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3672                                         c[0] = layer->color[0];
3673                                         c[1] = layer->color[1];
3674                                         c[2] = layer->color[2];
3675                                         c[3] = f * layer->color[3];
3676                                 }
3677                         }
3678                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3679                         break;
3680                 default:
3681                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3682                 }
3683                 GL_LockArrays(0, 0);
3684         }
3685         CHECKGLERROR
3686         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3687         {
3688                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3689                 GL_AlphaTest(false);
3690         }
3691 }
3692
3693 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3694 {
3695         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3696                 return;
3697         r_shadow_rtlight = NULL;
3698         r_refdef.stats.entities_surfaces += texturenumsurfaces;
3699         CHECKGLERROR
3700         if (r_showsurfaces.integer)
3701                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3702         else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3703                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3704         else if (rsurface_texture->currentnumlayers)
3705         {
3706                 if (r_glsl.integer && gl_support_fragment_shader)
3707                         R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3708                 else if (gl_combine.integer && r_textureunits.integer >= 2)
3709                         R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3710                 else
3711                         R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3712         }
3713         CHECKGLERROR
3714         GL_LockArrays(0, 0);
3715 }
3716
3717 #define BATCHSIZE 256
3718 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3719 {
3720         int surfacelistindex;
3721         int batchcount;
3722         texture_t *t;
3723         msurface_t *texturesurfacelist[BATCHSIZE];
3724         // if the model is static it doesn't matter what value we give for
3725         // wantnormals and wanttangents, so this logic uses only rules applicable
3726         // to a model, knowing that they are meaningless otherwise
3727         if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3728                 RSurf_ActiveEntity(ent, false, false);
3729         else
3730                 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3731         batchcount = 0;
3732         t = NULL;
3733         rsurface_uselightmaptexture = false;
3734         for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3735         {
3736                 msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
3737
3738                 if (t != surface->texture || rsurface_uselightmaptexture != (surface->lightmaptexture != NULL))
3739                 {
3740                         if (batchcount > 0)
3741                                 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)) // transparent sky is too difficult
3742                                         R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3743                         batchcount = 0;
3744                         t = surface->texture;
3745                         rsurface_uselightmaptexture = (surface->lightmaptexture != NULL);
3746                         R_UpdateTextureInfo(ent, t);
3747                         rsurface_texture = t->currentframe;
3748                 }
3749
3750                 texturesurfacelist[batchcount++] = surface;
3751         }
3752         if (batchcount > 0)
3753                 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)) // transparent sky is too difficult
3754                         R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3755         RSurf_CleanUp();
3756 }
3757
3758 void R_QueueTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3759 {
3760         int texturesurfaceindex;
3761         vec3_t tempcenter, center;
3762         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3763         {
3764                 // drawing sky transparently would be too difficult
3765                 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY))
3766                 {
3767                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3768                         {
3769                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3770                                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3771                                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3772                                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3773                                 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3774                                 R_MeshQueue_AddTransparent(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, rsurface_entity, surface - rsurface_model->data_surfaces, r_shadow_rtlight);
3775                         }
3776                 }
3777         }
3778         else
3779                 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3780 }
3781
3782 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3783 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3784 {
3785         int i, j, k, l, endj, f, flagsmask;
3786         int counttriangles = 0;
3787         msurface_t *surface, *endsurface, **surfacechain;
3788         texture_t *t;
3789         q3mbrush_t *brush;
3790         model_t *model = ent->model;
3791         const int *elements;
3792         const int maxsurfacelist = 1024;
3793         int numsurfacelist = 0;
3794         msurface_t *surfacelist[1024];
3795         vec3_t v;
3796         if (model == NULL)
3797                 return;
3798
3799         // if the model is static it doesn't matter what value we give for
3800         // wantnormals and wanttangents, so this logic uses only rules applicable
3801         // to a model, knowing that they are meaningless otherwise
3802         if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3803                 RSurf_ActiveEntity(ent, false, false);
3804         else
3805                 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3806
3807         // update light styles
3808         if (!skysurfaces && model->brushq1.light_styleupdatechains)
3809         {
3810                 for (i = 0;i < model->brushq1.light_styles;i++)
3811                 {
3812                         if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3813                         {
3814                                 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3815                                 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3816                                         for (;(surface = *surfacechain);surfacechain++)
3817                                                 surface->cached_dlight = true;
3818                         }
3819                 }
3820         }
3821
3822         R_UpdateAllTextureInfo(ent);
3823         flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3824         f = 0;
3825         t = NULL;
3826         rsurface_uselightmaptexture = false;
3827         rsurface_texture = NULL;
3828         numsurfacelist = 0;
3829         if (ent == r_refdef.worldentity)
3830         {
3831                 j = model->firstmodelsurface;
3832                 endj = j + model->nummodelsurfaces;
3833                 while (j < endj)
3834                 {
3835                         // quickly skip over non-visible surfaces
3836                         for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
3837                                 ;
3838                         // quickly iterate over visible surfaces
3839                         for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
3840                         {
3841                                 // process this surface
3842                                 surface = model->data_surfaces + j;
3843                                 // if texture or lightmap has changed, start a new batch
3844                                 if (t != surface->texture || rsurface_uselightmaptexture != (surface->lightmaptexture != NULL))
3845                                 {
3846                                         if (numsurfacelist)
3847                                         {
3848                                                 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3849                                                 numsurfacelist = 0;
3850                                         }
3851                                         t = surface->texture;
3852                                         rsurface_uselightmaptexture = surface->lightmaptexture != NULL;
3853                                         rsurface_texture = t->currentframe;
3854                                         f = rsurface_texture->currentmaterialflags & flagsmask;
3855                                 }
3856                                 // if this surface fits the criteria, add it to the list
3857                                 if (f && surface->num_triangles)
3858                                 {
3859                                         // if lightmap parameters changed, rebuild lightmap texture
3860                                         if (surface->cached_dlight)
3861                                                 R_BuildLightMap(ent, surface);
3862                                         // add face to draw list
3863                                         surfacelist[numsurfacelist++] = surface;
3864                                         counttriangles += surface->num_triangles;
3865                                         if (numsurfacelist >= maxsurfacelist)
3866                                         {
3867                                                 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3868                                                 numsurfacelist = 0;
3869                                         }
3870                                 }
3871                         }
3872                 }
3873         }
3874         else
3875         {
3876                 surface = model->data_surfaces + model->firstmodelsurface;
3877                 endsurface = surface + model->nummodelsurfaces;
3878                 for (;surface < endsurface;surface++)
3879                 {
3880                         // if texture or lightmap has changed, start a new batch
3881                         if (t != surface->texture || rsurface_uselightmaptexture != (surface->lightmaptexture != NULL))
3882                         {
3883                                 if (numsurfacelist)
3884                                 {
3885                                         R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3886                                         numsurfacelist = 0;
3887                                 }
3888                                 t = surface->texture;
3889                                 rsurface_uselightmaptexture = (surface->lightmaptexture != NULL);
3890                                 rsurface_texture = t->currentframe;
3891                                 f = rsurface_texture->currentmaterialflags & flagsmask;
3892                         }
3893                         // if this surface fits the criteria, add it to the list
3894                         if (f && surface->num_triangles)
3895                         {
3896                                 // if lightmap parameters changed, rebuild lightmap texture
3897                                 if (surface->cached_dlight)
3898                                         R_BuildLightMap(ent, surface);
3899                                 // add face to draw list
3900                                 surfacelist[numsurfacelist++] = surface;
3901                                 counttriangles += surface->num_triangles;
3902                                 if (numsurfacelist >= maxsurfacelist)
3903                                 {
3904                                         R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3905                                         numsurfacelist = 0;
3906                                 }
3907                         }
3908                 }
3909         }
3910         if (numsurfacelist)
3911                 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3912         r_refdef.stats.entities_triangles += counttriangles;
3913         RSurf_CleanUp();
3914
3915         if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3916         {
3917                 CHECKGLERROR
3918                 R_Mesh_Matrix(&ent->matrix);
3919                 R_Mesh_ColorPointer(NULL);
3920                 R_Mesh_ResetTextureState();
3921                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3922                 GL_DepthMask(false);
3923                 GL_DepthTest(!r_showdisabledepthtest.integer);
3924                 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3925                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3926                         if (brush->colbrushf && brush->colbrushf->numtriangles)
3927                                 R_DrawCollisionBrush(brush->colbrushf);
3928                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3929                         if (surface->num_collisiontriangles)
3930                                 R_DrawCollisionSurface(ent, surface);
3931                 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
3932         }
3933
3934         if (r_showtris.integer || r_shownormals.integer)
3935         {
3936                 CHECKGLERROR
3937                 GL_DepthTest(!r_showdisabledepthtest.integer);
3938                 GL_DepthMask(true);
3939                 GL_BlendFunc(GL_ONE, GL_ZERO);
3940                 R_Mesh_ColorPointer(NULL);
3941                 R_Mesh_ResetTextureState();
3942                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3943                 {
3944                         if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
3945                                 continue;
3946                         rsurface_texture = surface->texture->currentframe;
3947                         if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3948                         {
3949                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3950                                 if (r_showtris.integer)
3951                                 {
3952                                         if (!rsurface_texture->currentlayers->depthmask)
3953                                                 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
3954                                         else if (ent == r_refdef.worldentity)
3955                                                 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
3956                                         else
3957                                                 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
3958                                         elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3959                                         CHECKGLERROR
3960                                         qglBegin(GL_LINES);
3961                                         for (k = 0;k < surface->num_triangles;k++, elements += 3)
3962                                         {
3963                                                 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3964                                                 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3965                                                 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3966                                         }
3967                                         qglEnd();
3968                                         CHECKGLERROR
3969                                 }
3970                                 if (r_shownormals.integer)
3971                                 {
3972                                         GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
3973                                         qglBegin(GL_LINES);
3974                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3975                                         {
3976                                                 VectorCopy(rsurface_vertex3f + l * 3, v);
3977                                                 qglVertex3f(v[0], v[1], v[2]);
3978                                                 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3979                                                 qglVertex3f(v[0], v[1], v[2]);
3980                                         }
3981                                         qglEnd();
3982                                         CHECKGLERROR
3983                                         GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
3984                                         qglBegin(GL_LINES);
3985                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3986                                         {
3987                                                 VectorCopy(rsurface_vertex3f + l * 3, v);
3988                                                 qglVertex3f(v[0], v[1], v[2]);
3989                                                 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3990                                                 qglVertex3f(v[0], v[1], v[2]);
3991                                         }
3992                                         qglEnd();
3993                                         CHECKGLERROR
3994                                         GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
3995                                         qglBegin(GL_LINES);
3996                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3997                                         {
3998                                                 VectorCopy(rsurface_vertex3f + l * 3, v);
3999                                                 qglVertex3f(v[0], v[1], v[2]);
4000                                                 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
4001                                                 qglVertex3f(v[0], v[1], v[2]);
4002                                         }
4003                                         qglEnd();
4004                                         CHECKGLERROR
4005                                 }
4006                         }
4007                 }
4008                 rsurface_texture = NULL;
4009         }
4010 }