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