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