implemented Shadow Volume BSP based culling of lit surfaces, this is slightly better...
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "r_shadow.h"
24 #include "polygon.h"
25
26 mempool_t *r_main_mempool;
27 rtexturepool_t *r_main_texturepool;
28
29 //
30 // screen size info
31 //
32 r_refdef_t r_refdef;
33 r_view_t r_view;
34 r_viewcache_t r_viewcache;
35
36 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
37 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "shows surfaces as different colors"};
38 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
39 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
40 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
41 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
42 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
43 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
44 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
45 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
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", "1", "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", "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_lightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
920                 {
921                         // deluxemapping (light direction texture)
922                         if (rsurface_lightmaptexture && 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("\nengine extensions: %s\n", vm_sv_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;
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_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_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
2624         t->currentmaterialflags = t->basematerialflags;
2625         t->currentalpha = ent->alpha;
2626         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
2627                 t->currentalpha *= r_wateralpha.value;
2628         if (!(ent->flags & RENDER_LIGHT))
2629                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2630         if (ent->effects & EF_ADDITIVE)
2631                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
2632         else if (t->currentalpha < 1)
2633                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
2634         if (ent->flags & RENDER_NOCULLFACE)
2635                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW;
2636         if (ent->effects & EF_NODEPTHTEST)
2637                 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_NOSHADOW;
2638         if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2639                 t->currenttexmatrix = r_waterscrollmatrix;
2640         else
2641                 t->currenttexmatrix = identitymatrix;
2642
2643         t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2644         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2645         t->glosstexture = r_texture_white;
2646         t->specularpower = r_shadow_glossexponent.value;
2647         t->specularscale = 0;
2648         if (r_shadow_gloss.integer > 0)
2649         {
2650                 if (t->currentskinframe->gloss)
2651                 {
2652                         if (r_shadow_glossintensity.value > 0)
2653                         {
2654                                 t->glosstexture = t->currentskinframe->gloss;
2655                                 t->specularscale = r_shadow_glossintensity.value;
2656                         }
2657                 }
2658                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2659                         t->specularscale = r_shadow_gloss2intensity.value;
2660         }
2661
2662         t->currentnumlayers = 0;
2663         if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2664         {
2665                 if (gl_lightmaps.integer)
2666                         R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2667                 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2668                 {
2669                         int blendfunc1, blendfunc2, depthmask;
2670                         if (t->currentmaterialflags & MATERIALFLAG_ADD)
2671                         {
2672                                 blendfunc1 = GL_SRC_ALPHA;
2673                                 blendfunc2 = GL_ONE;
2674                         }
2675                         else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2676                         {
2677                                 blendfunc1 = GL_SRC_ALPHA;
2678                                 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2679                         }
2680                         else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2681                         {
2682                                 blendfunc1 = t->customblendfunc[0];
2683                                 blendfunc2 = t->customblendfunc[1];
2684                         }
2685                         else
2686                         {
2687                                 blendfunc1 = GL_ONE;
2688                                 blendfunc2 = GL_ZERO;
2689                         }
2690                         depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2691                         if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2692                         {
2693                                 rtexture_t *currentbasetexture;
2694                                 int layerflags = 0;
2695                                 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2696                                         layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2697                                 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2698                                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2699                                 {
2700                                         // fullbright is not affected by r_refdef.lightmapintensity
2701                                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2702                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2703                                                 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);
2704                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2705                                                 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);
2706                                 }
2707                                 else
2708                                 {
2709                                         float colorscale;
2710                                         colorscale = 2;
2711                                         // q3bsp has no lightmap updates, so the lightstylevalue that
2712                                         // would normally be baked into the lightmap must be
2713                                         // applied to the color
2714                                         if (ent->model->type == mod_brushq3)
2715                                                 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2716                                         colorscale *= r_refdef.lightmapintensity;
2717                                         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);
2718                                         if (r_ambient.value >= (1.0f/64.0f))
2719                                                 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);
2720                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2721                                         {
2722                                                 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);
2723                                                 if (r_ambient.value >= (1.0f/64.0f))
2724                                                         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);
2725                                         }
2726                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2727                                         {
2728                                                 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);
2729                                                 if (r_ambient.value >= (1.0f/64.0f))
2730                                                         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);
2731                                         }
2732                                 }
2733                                 if (t->currentskinframe->glow != NULL)
2734                                         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);
2735                                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2736                                 {
2737                                         // if this is opaque use alpha blend which will darken the earlier
2738                                         // passes cheaply.
2739                                         //
2740                                         // if this is an alpha blended material, all the earlier passes
2741                                         // were darkened by fog already, so we only need to add the fog
2742                                         // color ontop through the fog mask texture
2743                                         //
2744                                         // if this is an additive blended material, all the earlier passes
2745                                         // were darkened by fog already, and we should not add fog color
2746                                         // (because the background was not darkened, there is no fog color
2747                                         // that was lost behind it).
2748                                         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);
2749                                 }
2750                         }
2751                 }
2752         }
2753 }
2754
2755 void R_UpdateAllTextureInfo(entity_render_t *ent)
2756 {
2757         int i;
2758         if (ent->model)
2759                 for (i = 0;i < ent->model->num_textures;i++)
2760                         R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2761 }
2762
2763 int rsurface_array_size = 0;
2764 float *rsurface_array_modelvertex3f = NULL;
2765 float *rsurface_array_modelsvector3f = NULL;
2766 float *rsurface_array_modeltvector3f = NULL;
2767 float *rsurface_array_modelnormal3f = NULL;
2768 float *rsurface_array_deformedvertex3f = NULL;
2769 float *rsurface_array_deformedsvector3f = NULL;
2770 float *rsurface_array_deformedtvector3f = NULL;
2771 float *rsurface_array_deformednormal3f = NULL;
2772 float *rsurface_array_color4f = NULL;
2773 float *rsurface_array_texcoord3f = NULL;
2774
2775 void R_Mesh_ResizeArrays(int newvertices)
2776 {
2777         float *base;
2778         if (rsurface_array_size >= newvertices)
2779                 return;
2780         if (rsurface_array_modelvertex3f)
2781                 Mem_Free(rsurface_array_modelvertex3f);
2782         rsurface_array_size = (newvertices + 1023) & ~1023;
2783         base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2784         rsurface_array_modelvertex3f     = base + rsurface_array_size * 0;
2785         rsurface_array_modelsvector3f    = base + rsurface_array_size * 3;
2786         rsurface_array_modeltvector3f    = base + rsurface_array_size * 6;
2787         rsurface_array_modelnormal3f     = base + rsurface_array_size * 9;
2788         rsurface_array_deformedvertex3f  = base + rsurface_array_size * 12;
2789         rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2790         rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2791         rsurface_array_deformednormal3f  = base + rsurface_array_size * 21;
2792         rsurface_array_texcoord3f        = base + rsurface_array_size * 24;
2793         rsurface_array_color4f           = base + rsurface_array_size * 27;
2794 }
2795
2796 float *rsurface_modelvertex3f;
2797 float *rsurface_modelsvector3f;
2798 float *rsurface_modeltvector3f;
2799 float *rsurface_modelnormal3f;
2800 float *rsurface_vertex3f;
2801 float *rsurface_svector3f;
2802 float *rsurface_tvector3f;
2803 float *rsurface_normal3f;
2804 float *rsurface_lightmapcolor4f;
2805 vec3_t rsurface_modelorg;
2806 qboolean rsurface_generatedvertex;
2807 const entity_render_t *rsurface_entity;
2808 const model_t *rsurface_model;
2809 texture_t *rsurface_texture;
2810 rtexture_t *rsurface_lightmaptexture;
2811 rsurfmode_t rsurface_mode;
2812 texture_t *rsurface_glsl_texture;
2813 qboolean rsurface_glsl_uselightmap;
2814
2815 void RSurf_CleanUp(void)
2816 {
2817         CHECKGLERROR
2818         if (rsurface_mode == RSURFMODE_GLSL)
2819         {
2820                 qglUseProgramObjectARB(0);CHECKGLERROR
2821         }
2822         GL_AlphaTest(false);
2823         rsurface_mode = RSURFMODE_NONE;
2824         rsurface_lightmaptexture = NULL;
2825         rsurface_texture = NULL;
2826         rsurface_glsl_texture = NULL;
2827         rsurface_glsl_uselightmap = false;
2828 }
2829
2830 void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2831 {
2832         RSurf_CleanUp();
2833         Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2834         rsurface_entity = ent;
2835         rsurface_model = ent->model;
2836         if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2837                 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2838         R_Mesh_Matrix(&ent->matrix);
2839         Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2840         if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && rsurface_model->surfmesh.isanimated)
2841         {
2842                 if (wanttangents)
2843                 {
2844                         rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2845                         rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2846                         rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2847                         rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2848                         Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2849                 }
2850                 else if (wantnormals)
2851                 {
2852                         rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2853                         rsurface_modelsvector3f = NULL;
2854                         rsurface_modeltvector3f = NULL;
2855                         rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2856                         Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2857                 }
2858                 else
2859                 {
2860                         rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2861                         rsurface_modelsvector3f = NULL;
2862                         rsurface_modeltvector3f = NULL;
2863                         rsurface_modelnormal3f = NULL;
2864                         Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2865                 }
2866                 rsurface_generatedvertex = true;
2867         }
2868         else
2869         {
2870                 rsurface_modelvertex3f  = rsurface_model->surfmesh.data_vertex3f;
2871                 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2872                 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2873                 rsurface_modelnormal3f  = rsurface_model->surfmesh.data_normal3f;
2874                 rsurface_generatedvertex = false;
2875         }
2876         rsurface_vertex3f  = rsurface_modelvertex3f;
2877         rsurface_svector3f = rsurface_modelsvector3f;
2878         rsurface_tvector3f = rsurface_modeltvector3f;
2879         rsurface_normal3f  = rsurface_modelnormal3f;
2880 }
2881
2882 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2883 {
2884         // 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
2885         if (rsurface_generatedvertex)
2886         {
2887                 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2888                         generatetangents = true;
2889                 if (generatetangents)
2890                         generatenormals = true;
2891                 if (generatenormals && !rsurface_modelnormal3f)
2892                 {
2893                         rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2894                         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);
2895                 }
2896                 if (generatetangents && !rsurface_modelsvector3f)
2897                 {
2898                         rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2899                         rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2900                         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);
2901                 }
2902         }
2903         // 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)
2904         if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2905         {
2906                 int texturesurfaceindex;
2907                 float center[3], forward[3], right[3], up[3], v[4][3];
2908                 matrix4x4_t matrix1, imatrix1;
2909                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
2910                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
2911                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
2912                 // make deformed versions of only the model vertices used by the specified surfaces
2913                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2914                 {
2915                         int i, j;
2916                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2917                         // a single autosprite surface can contain multiple sprites...
2918                         for (j = 0;j < surface->num_vertices - 3;j += 4)
2919                         {
2920                                 VectorClear(center);
2921                                 for (i = 0;i < 4;i++)
2922                                         VectorAdd(center, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2923                                 VectorScale(center, 0.25f, center);
2924                                 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2925                                 {
2926                                         forward[0] = rsurface_modelorg[0] - center[0];
2927                                         forward[1] = rsurface_modelorg[1] - center[1];
2928                                         forward[2] = 0;
2929                                         VectorNormalize(forward);
2930                                         right[0] = forward[1];
2931                                         right[1] = -forward[0];
2932                                         right[2] = 0;
2933                                         VectorSet(up, 0, 0, 1);
2934                                 }
2935                                 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2936                                 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);
2937                                 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2938                                 for (i = 0;i < 4;i++)
2939                                         Matrix4x4_Transform(&imatrix1, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2940                                 for (i = 0;i < 4;i++)
2941                                         VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
2942                         }
2943                         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);
2944                         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);
2945                 }
2946                 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2947                 rsurface_svector3f = rsurface_array_deformedsvector3f;
2948                 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2949                 rsurface_normal3f = rsurface_array_deformednormal3f;
2950         }
2951         else
2952         {
2953                 rsurface_vertex3f = rsurface_modelvertex3f;
2954                 rsurface_svector3f = rsurface_modelsvector3f;
2955                 rsurface_tvector3f = rsurface_modeltvector3f;
2956                 rsurface_normal3f = rsurface_modelnormal3f;
2957         }
2958         R_Mesh_VertexPointer(rsurface_vertex3f);
2959 }
2960
2961 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
2962 {
2963         int texturesurfaceindex;
2964         const msurface_t *surface = texturesurfacelist[0];
2965         int firstvertex = surface->num_firstvertex;
2966         int endvertex = surface->num_firstvertex + surface->num_vertices;
2967         if (texturenumsurfaces == 1)
2968         {
2969                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2970                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2971         }
2972         else if (r_batchmode.integer == 2)
2973         {
2974                 #define MAXBATCHTRIANGLES 4096
2975                 int batchtriangles = 0;
2976                 int batchelements[MAXBATCHTRIANGLES*3];
2977                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2978                 {
2979                         surface = texturesurfacelist[texturesurfaceindex];
2980                         if (surface->num_triangles >= 256 || (batchtriangles == 0 && texturesurfaceindex + 1 >= texturenumsurfaces))
2981                         {
2982                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2983                                 continue;
2984                         }
2985                         if (batchtriangles + surface->num_triangles > MAXBATCHTRIANGLES)
2986                         {
2987                                 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2988                                 batchtriangles = 0;
2989                                 firstvertex = surface->num_firstvertex;
2990                                 endvertex = surface->num_firstvertex + surface->num_vertices;
2991                         }
2992                         else
2993                         {
2994                                 firstvertex = min(firstvertex, surface->num_firstvertex);
2995                                 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2996                         }
2997                         memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
2998                         batchtriangles += surface->num_triangles;
2999                 }
3000                 if (batchtriangles)
3001                         R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
3002         }
3003         else if (r_batchmode.integer == 1)
3004         {
3005                 int firsttriangle = 0;
3006                 int endtriangle = -1;
3007                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3008                 {
3009                         surface = texturesurfacelist[texturesurfaceindex];
3010                         if (surface->num_firsttriangle != endtriangle)
3011                         {
3012                                 if (endtriangle > firsttriangle)
3013                                 {
3014                                         GL_LockArrays(firstvertex, endvertex - firstvertex);
3015                                         R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
3016                                 }
3017                                 firstvertex = surface->num_firstvertex;
3018                                 endvertex = surface->num_firstvertex + surface->num_vertices;
3019                                 firsttriangle = surface->num_firsttriangle;
3020                         }
3021                         else
3022                         {
3023                                 firstvertex = min(firstvertex, surface->num_firstvertex);
3024                                 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
3025                         }
3026                         endtriangle = surface->num_firsttriangle + surface->num_triangles;
3027                 }
3028                 if (endtriangle > firsttriangle)
3029                 {
3030                         GL_LockArrays(firstvertex, endvertex - firstvertex);
3031                         R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
3032                 }
3033         }
3034         else
3035         {
3036                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3037                 {
3038                         surface = texturesurfacelist[texturesurfaceindex];
3039                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3040                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3041                 }
3042         }
3043 }
3044
3045 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3046 {
3047         int texturesurfaceindex;
3048         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3049         {
3050                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3051                 int k = (int)(((size_t)surface) / sizeof(msurface_t));
3052                 GL_Color((k & 15) * (1.0f / 16.0f) * r_view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_view.colorscale, 0.2f);
3053                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3054                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3055         }
3056 }
3057
3058 static void RSurf_DrawBatch_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
3059 {
3060         int texturesurfaceindex;
3061         int i;
3062         float f;
3063         float *v, *c, *c2;
3064         // TODO: optimize
3065         if (lightmode >= 2)
3066         {
3067                 // model lighting
3068                 vec3_t ambientcolor;
3069                 vec3_t diffusecolor;
3070                 vec3_t lightdir;
3071                 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
3072                 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
3073                 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
3074                 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
3075                 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
3076                 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
3077                 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
3078                 if (VectorLength2(diffusecolor) > 0)
3079                 {
3080                         // generate color arrays for the surfaces in this list
3081                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3082                         {
3083                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3084                                 int numverts = surface->num_vertices;
3085                                 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
3086                                 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
3087                                 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
3088                                 // q3-style directional shading
3089                                 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
3090                                 {
3091                                         if ((f = DotProduct(c2, lightdir)) > 0)
3092                                                 VectorMA(ambientcolor, f, diffusecolor, c);
3093                                         else
3094                                                 VectorCopy(ambientcolor, c);
3095                                         c[3] = a;
3096                                 }
3097                         }
3098                         r = 1;
3099                         g = 1;
3100                         b = 1;
3101                         a = 1;
3102                         applycolor = false;
3103                         rsurface_lightmapcolor4f = rsurface_array_color4f;
3104                 }
3105                 else
3106                 {
3107                         r = ambientcolor[0];
3108                         g = ambientcolor[1];
3109                         b = ambientcolor[2];
3110                         rsurface_lightmapcolor4f = NULL;
3111                 }
3112         }
3113         else if (lightmode >= 1 || !rsurface_lightmaptexture)
3114         {
3115                 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
3116                 {
3117                         // generate color arrays for the surfaces in this list
3118                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3119                         {
3120                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3121                                 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
3122                                 {
3123                                         if (surface->lightmapinfo->samples)
3124                                         {
3125                                                 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
3126                                                 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
3127                                                 VectorScale(lm, scale, c);
3128                                                 if (surface->lightmapinfo->styles[1] != 255)
3129                                                 {
3130                                                         int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
3131                                                         lm += size3;
3132                                                         scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
3133                                                         VectorMA(c, scale, lm, c);
3134                                                         if (surface->lightmapinfo->styles[2] != 255)
3135                                                         {
3136                                                                 lm += size3;
3137                                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
3138                                                                 VectorMA(c, scale, lm, c);
3139                                                                 if (surface->lightmapinfo->styles[3] != 255)
3140                                                                 {
3141                                                                         lm += size3;
3142                                                                         scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
3143                                                                         VectorMA(c, scale, lm, c);
3144                                                                 }
3145                                                         }
3146                                                 }
3147                                         }
3148                                         else
3149                                                 VectorClear(c);
3150                                         c[3] = 1;
3151                                 }
3152                         }
3153                         rsurface_lightmapcolor4f = rsurface_array_color4f;
3154                 }
3155                 else
3156                         rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
3157         }
3158         else
3159         {
3160                 // just lightmap it
3161                 rsurface_lightmapcolor4f = NULL;
3162         }
3163         if (applyfog)
3164         {