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