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