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