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