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