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