]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
added r_showbboxes cvar and accompanying code to render server entity
[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_uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
885                 {
886                         // deluxemapping (light direction texture)
887                         if (rsurface_uselightmaptexture && 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 qboolean rsurface_uselightmaptexture;
2991 rsurfmode_t rsurface_mode;
2992 int rsurface_lightmode; // 0 = lightmap or fullbright, 1 = color array from q3bsp, 2 = vertex shaded model
2993
2994 void RSurf_CleanUp(void)
2995 {
2996         CHECKGLERROR
2997         if (rsurface_mode == RSURFMODE_GLSL)
2998         {
2999                 qglUseProgramObjectARB(0);CHECKGLERROR
3000         }
3001         GL_AlphaTest(false);
3002         rsurface_mode = RSURFMODE_NONE;
3003         rsurface_uselightmaptexture = false;
3004         rsurface_texture = NULL;
3005 }
3006
3007 void RSurf_ActiveWorldEntity(void)
3008 {
3009         RSurf_CleanUp();
3010         rsurface_entity = r_refdef.worldentity;
3011         rsurface_model = r_refdef.worldmodel;
3012         if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
3013                 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
3014         R_Mesh_Matrix(&identitymatrix);
3015         VectorCopy(r_view.origin, rsurface_modelorg);
3016         rsurface_modelvertex3f  = rsurface_model->surfmesh.data_vertex3f;
3017         rsurface_modelvertex3f_bufferobject = rsurface_model->surfmesh.vbo;
3018         rsurface_modelvertex3f_bufferoffset = rsurface_model->surfmesh.vbooffset_vertex3f;
3019         rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
3020         rsurface_modelsvector3f_bufferobject = rsurface_model->surfmesh.vbo;
3021         rsurface_modelsvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_svector3f;
3022         rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
3023         rsurface_modeltvector3f_bufferobject = rsurface_model->surfmesh.vbo;
3024         rsurface_modeltvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_tvector3f;
3025         rsurface_modelnormal3f  = rsurface_model->surfmesh.data_normal3f;
3026         rsurface_modelnormal3f_bufferobject = rsurface_model->surfmesh.vbo;
3027         rsurface_modelnormal3f_bufferoffset = rsurface_model->surfmesh.vbooffset_normal3f;
3028         rsurface_generatedvertex = false;
3029         rsurface_vertex3f  = rsurface_modelvertex3f;
3030         rsurface_vertex3f_bufferobject = rsurface_modelvertex3f_bufferobject;
3031         rsurface_vertex3f_bufferoffset = rsurface_modelvertex3f_bufferoffset;
3032         rsurface_svector3f = rsurface_modelsvector3f;
3033         rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject;
3034         rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset;
3035         rsurface_tvector3f = rsurface_modeltvector3f;
3036         rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject;
3037         rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset;
3038         rsurface_normal3f  = rsurface_modelnormal3f;
3039         rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject;
3040         rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset;
3041 }
3042
3043 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3044 {
3045         RSurf_CleanUp();
3046         rsurface_entity = ent;
3047         rsurface_model = ent->model;
3048         if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
3049                 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
3050         R_Mesh_Matrix(&ent->matrix);
3051         Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
3052         if (rsurface_model->surfmesh.isanimated && (rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0))
3053         {
3054                 if (wanttangents)
3055                 {
3056                         rsurface_modelvertex3f = rsurface_array_modelvertex3f;
3057                         rsurface_modelsvector3f = rsurface_array_modelsvector3f;
3058                         rsurface_modeltvector3f = rsurface_array_modeltvector3f;
3059                         rsurface_modelnormal3f = rsurface_array_modelnormal3f;
3060                         Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
3061                 }
3062                 else if (wantnormals)
3063                 {
3064                         rsurface_modelvertex3f = rsurface_array_modelvertex3f;
3065                         rsurface_modelsvector3f = NULL;
3066                         rsurface_modeltvector3f = NULL;
3067                         rsurface_modelnormal3f = rsurface_array_modelnormal3f;
3068                         Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
3069                 }
3070                 else
3071                 {
3072                         rsurface_modelvertex3f = rsurface_array_modelvertex3f;
3073                         rsurface_modelsvector3f = NULL;
3074                         rsurface_modeltvector3f = NULL;
3075                         rsurface_modelnormal3f = NULL;
3076                         Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
3077                 }
3078                 rsurface_modelvertex3f_bufferobject = 0;
3079                 rsurface_modelvertex3f_bufferoffset = 0;
3080                 rsurface_modelsvector3f_bufferobject = 0;
3081                 rsurface_modelsvector3f_bufferoffset = 0;
3082                 rsurface_modeltvector3f_bufferobject = 0;
3083                 rsurface_modeltvector3f_bufferoffset = 0;
3084                 rsurface_modelnormal3f_bufferobject = 0;
3085                 rsurface_modelnormal3f_bufferoffset = 0;
3086                 rsurface_generatedvertex = true;
3087         }
3088         else
3089         {
3090                 rsurface_modelvertex3f  = rsurface_model->surfmesh.data_vertex3f;
3091                 rsurface_modelvertex3f_bufferobject = rsurface_model->surfmesh.vbo;
3092                 rsurface_modelvertex3f_bufferoffset = rsurface_model->surfmesh.vbooffset_vertex3f;
3093                 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
3094                 rsurface_modelsvector3f_bufferobject = rsurface_model->surfmesh.vbo;
3095                 rsurface_modelsvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_svector3f;
3096                 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
3097                 rsurface_modeltvector3f_bufferobject = rsurface_model->surfmesh.vbo;
3098                 rsurface_modeltvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_tvector3f;
3099                 rsurface_modelnormal3f  = rsurface_model->surfmesh.data_normal3f;
3100                 rsurface_modelnormal3f_bufferobject = rsurface_model->surfmesh.vbo;
3101                 rsurface_modelnormal3f_bufferoffset = rsurface_model->surfmesh.vbooffset_normal3f;
3102                 rsurface_generatedvertex = false;
3103         }
3104         rsurface_vertex3f  = rsurface_modelvertex3f;
3105         rsurface_vertex3f_bufferobject = rsurface_modelvertex3f_bufferobject;
3106         rsurface_vertex3f_bufferoffset = rsurface_modelvertex3f_bufferoffset;
3107         rsurface_svector3f = rsurface_modelsvector3f;
3108         rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject;
3109         rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset;
3110         rsurface_tvector3f = rsurface_modeltvector3f;
3111         rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject;
3112         rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset;
3113         rsurface_normal3f  = rsurface_modelnormal3f;
3114         rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject;
3115         rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset;
3116 }
3117
3118 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
3119 {
3120         // 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
3121         if (rsurface_generatedvertex)
3122         {
3123                 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
3124                         generatetangents = true;
3125                 if (generatetangents)
3126                         generatenormals = true;
3127                 if (generatenormals && !rsurface_modelnormal3f)
3128                 {
3129                         rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
3130                         rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject = 0;
3131                         rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset = 0;
3132                         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);
3133                 }
3134                 if (generatetangents && !rsurface_modelsvector3f)
3135                 {
3136                         rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
3137                         rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject = 0;
3138                         rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset = 0;
3139                         rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
3140                         rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject = 0;
3141                         rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset = 0;
3142                         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);
3143                 }
3144         }
3145         // 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)
3146         if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
3147         {
3148                 int texturesurfaceindex;
3149                 float center[3], forward[3], right[3], up[3], v[4][3];
3150                 matrix4x4_t matrix1, imatrix1;
3151                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
3152                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
3153                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
3154                 // make deformed versions of only the model vertices used by the specified surfaces
3155                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3156                 {
3157                         int i, j;
3158                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3159                         // a single autosprite surface can contain multiple sprites...
3160                         for (j = 0;j < surface->num_vertices - 3;j += 4)
3161                         {
3162                                 VectorClear(center);
3163                                 for (i = 0;i < 4;i++)
3164                                         VectorAdd(center, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
3165                                 VectorScale(center, 0.25f, center);
3166                                 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
3167                                 {
3168                                         forward[0] = rsurface_modelorg[0] - center[0];
3169                                         forward[1] = rsurface_modelorg[1] - center[1];
3170                                         forward[2] = 0;
3171                                         VectorNormalize(forward);
3172                                         right[0] = forward[1];
3173                                         right[1] = -forward[0];
3174                                         right[2] = 0;
3175                                         VectorSet(up, 0, 0, 1);
3176                                 }
3177                                 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
3178                                 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);
3179                                 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
3180                                 for (i = 0;i < 4;i++)
3181                                         Matrix4x4_Transform(&imatrix1, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
3182                                 for (i = 0;i < 4;i++)
3183                                         VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
3184                         }
3185                         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);
3186                         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);
3187                 }
3188                 rsurface_vertex3f = rsurface_array_deformedvertex3f;
3189                 rsurface_vertex3f_bufferobject = 0;
3190                 rsurface_vertex3f_bufferoffset = 0;
3191                 rsurface_svector3f = rsurface_array_deformedsvector3f;
3192                 rsurface_svector3f_bufferobject = 0;
3193                 rsurface_svector3f_bufferoffset = 0;
3194                 rsurface_tvector3f = rsurface_array_deformedtvector3f;
3195                 rsurface_tvector3f_bufferobject = 0;
3196                 rsurface_tvector3f_bufferoffset = 0;
3197                 rsurface_normal3f = rsurface_array_deformednormal3f;
3198                 rsurface_normal3f_bufferobject = 0;
3199                 rsurface_normal3f_bufferoffset = 0;
3200         }
3201         else
3202         {
3203                 rsurface_vertex3f  = rsurface_modelvertex3f;
3204                 rsurface_vertex3f_bufferobject = rsurface_modelvertex3f_bufferobject;
3205                 rsurface_vertex3f_bufferoffset = rsurface_modelvertex3f_bufferoffset;
3206                 rsurface_svector3f = rsurface_modelsvector3f;
3207                 rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject;
3208                 rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset;
3209                 rsurface_tvector3f = rsurface_modeltvector3f;
3210                 rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject;
3211                 rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset;
3212                 rsurface_normal3f  = rsurface_modelnormal3f;
3213                 rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject;
3214                 rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset;
3215         }
3216         R_Mesh_VertexPointer(rsurface_vertex3f, rsurface_vertex3f_bufferobject, rsurface_vertex3f_bufferoffset);
3217 }
3218
3219 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
3220 {
3221         int i, j;
3222         const msurface_t *surface = texturesurfacelist[0];
3223         const msurface_t *surface2;
3224         int firstvertex;
3225         int endvertex;
3226         int numvertices;
3227         int numtriangles;
3228         // TODO: lock all array ranges before render, rather than on each surface
3229         if (texturenumsurfaces == 1)
3230         {
3231                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3232                 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));
3233         }
3234         else if (r_batchmode.integer == 2)
3235         {
3236                 #define MAXBATCHTRIANGLES 4096
3237                 int batchtriangles = 0;
3238                 int batchelements[MAXBATCHTRIANGLES*3];
3239                 for (i = 0;i < texturenumsurfaces;i = j)
3240                 {
3241                         surface = texturesurfacelist[i];
3242                         j = i + 1;
3243                         if (surface->num_triangles > MAXBATCHTRIANGLES)
3244                         {
3245                                 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));
3246                                 continue;
3247                         }
3248                         memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
3249                         batchtriangles = surface->num_triangles;
3250                         firstvertex = surface->num_firstvertex;
3251                         endvertex = surface->num_firstvertex + surface->num_vertices;
3252                         for (;j < texturenumsurfaces;j++)
3253                         {
3254                                 surface2 = texturesurfacelist[j];
3255                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
3256                                         break;
3257                                 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
3258                                 batchtriangles += surface2->num_triangles;
3259                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
3260                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
3261                         }
3262                         surface2 = texturesurfacelist[j-1];
3263                         numvertices = endvertex - firstvertex;
3264                         R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
3265                 }
3266         }
3267         else if (r_batchmode.integer == 1)
3268         {
3269                 for (i = 0;i < texturenumsurfaces;i = j)
3270                 {
3271                         surface = texturesurfacelist[i];
3272                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3273                                 if (texturesurfacelist[j] != surface2)
3274                                         break;
3275                         surface2 = texturesurfacelist[j-1];
3276                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3277                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3278                         GL_LockArrays(surface->num_firstvertex, numvertices);
3279                         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));
3280                 }
3281         }
3282         else
3283         {
3284                 for (i = 0;i < texturenumsurfaces;i++)
3285                 {
3286                         surface = texturesurfacelist[i];
3287                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3288                         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));
3289                 }
3290         }
3291 }
3292
3293 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
3294 {
3295         int i;
3296         int j;
3297         const msurface_t *surface = texturesurfacelist[0];
3298         const msurface_t *surface2;
3299         int firstvertex;
3300         int endvertex;
3301         int numvertices;
3302         int numtriangles;
3303         // TODO: lock all array ranges before render, rather than on each surface
3304         if (texturenumsurfaces == 1)
3305         {
3306                 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3307                 if (deluxemaptexunit >= 0)
3308                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3309                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3310                 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));
3311         }
3312         else if (r_batchmode.integer == 2)
3313         {
3314                 #define MAXBATCHTRIANGLES 4096
3315                 int batchtriangles = 0;
3316                 int batchelements[MAXBATCHTRIANGLES*3];
3317                 for (i = 0;i < texturenumsurfaces;i = j)
3318                 {
3319                         surface = texturesurfacelist[i];
3320                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3321                         if (deluxemaptexunit >= 0)
3322                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3323                         j = i + 1;
3324                         if (surface->num_triangles > MAXBATCHTRIANGLES)
3325                         {
3326                                 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));
3327                                 continue;
3328                         }
3329                         memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
3330                         batchtriangles = surface->num_triangles;
3331                         firstvertex = surface->num_firstvertex;
3332                         endvertex = surface->num_firstvertex + surface->num_vertices;
3333                         for (;j < texturenumsurfaces;j++)
3334                         {
3335                                 surface2 = texturesurfacelist[j];
3336                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
3337                                         break;
3338                                 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
3339                                 batchtriangles += surface2->num_triangles;
3340                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
3341                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
3342                         }
3343                         surface2 = texturesurfacelist[j-1];
3344                         numvertices = endvertex - firstvertex;
3345                         R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
3346                 }
3347         }
3348         else if (r_batchmode.integer == 1)
3349         {
3350 #if 0
3351                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface_texture->name);
3352                 for (i = 0;i < texturenumsurfaces;i = j)
3353                 {
3354                         surface = texturesurfacelist[i];
3355                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3356                                 if (texturesurfacelist[j] != surface2)
3357                                         break;
3358                         Con_Printf(" %i", j - i);
3359                 }
3360                 Con_Printf("\n");
3361                 Con_Printf("%s batch sizes honoring lightmap:", rsurface_texture->name);
3362 #endif
3363                 for (i = 0;i < texturenumsurfaces;i = j)
3364                 {
3365                         surface = texturesurfacelist[i];
3366                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3367                         if (deluxemaptexunit >= 0)
3368                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3369                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3370                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
3371                                         break;
3372 #if 0
3373                         Con_Printf(" %i", j - i);
3374 #endif
3375                         surface2 = texturesurfacelist[j-1];
3376                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3377                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3378                         GL_LockArrays(surface->num_firstvertex, numvertices);
3379                         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));
3380                 }
3381 #if 0
3382                 Con_Printf("\n");
3383 #endif
3384         }
3385         else
3386         {
3387                 for (i = 0;i < texturenumsurfaces;i++)
3388                 {
3389                         surface = texturesurfacelist[i];
3390                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3391                         if (deluxemaptexunit >= 0)
3392                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3393                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3394                         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));
3395                 }
3396         }
3397 }
3398
3399 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3400 {
3401         int j;
3402         int texturesurfaceindex;
3403         if (r_showsurfaces.integer == 2)
3404         {
3405                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3406                 {
3407                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3408                         for (j = 0;j < surface->num_triangles;j++)
3409                         {
3410                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
3411                                 GL_Color(f, f, f, 1);
3412                                 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)));
3413                         }
3414                 }
3415         }
3416         else
3417         {
3418                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3419                 {
3420                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3421                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
3422                         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);
3423                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3424                         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));
3425                 }
3426         }
3427 }
3428
3429 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
3430 {
3431         int texturesurfaceindex;
3432         int i;
3433         float f;
3434         float *v, *c, *c2;
3435         if (rsurface_lightmapcolor4f)
3436         {
3437                 // generate color arrays for the surfaces in this list
3438                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3439                 {
3440                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3441                         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)
3442                         {
3443                                 f = FogPoint_Model(v);
3444                                 c2[0] = c[0] * f;
3445                                 c2[1] = c[1] * f;
3446                                 c2[2] = c[2] * f;
3447                                 c2[3] = c[3];
3448                         }
3449                 }
3450         }
3451         else
3452         {
3453                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3454                 {
3455                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3456                         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)
3457                         {
3458                                 f = FogPoint_Model(v);
3459                                 c2[0] = f;
3460                                 c2[1] = f;
3461                                 c2[2] = f;
3462                                 c2[3] = 1;
3463                         }
3464                 }
3465         }
3466         rsurface_lightmapcolor4f = rsurface_array_color4f;
3467         rsurface_lightmapcolor4f_bufferobject = 0;
3468         rsurface_lightmapcolor4f_bufferoffset = 0;
3469 }
3470
3471 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
3472 {
3473         int texturesurfaceindex;
3474         int i;
3475         float *c, *c2;
3476         if (!rsurface_lightmapcolor4f)
3477                 return;
3478         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3479         {
3480                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3481                 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)
3482                 {
3483                         c2[0] = c[0] * r;
3484                         c2[1] = c[1] * g;
3485                         c2[2] = c[2] * b;
3486                         c2[3] = c[3] * a;
3487                 }
3488         }
3489         rsurface_lightmapcolor4f = rsurface_array_color4f;
3490         rsurface_lightmapcolor4f_bufferobject = 0;
3491         rsurface_lightmapcolor4f_bufferoffset = 0;
3492 }
3493
3494 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3495 {
3496         // TODO: optimize
3497         rsurface_lightmapcolor4f = NULL;
3498         rsurface_lightmapcolor4f_bufferobject = 0;
3499         rsurface_lightmapcolor4f_bufferoffset = 0;
3500         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3501         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3502         R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3503         GL_Color(r, g, b, a);
3504         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
3505 }
3506
3507 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3508 {
3509         // TODO: optimize applyfog && applycolor case
3510         // just apply fog if necessary, and tint the fog color array if necessary
3511         rsurface_lightmapcolor4f = NULL;
3512         rsurface_lightmapcolor4f_bufferobject = 0;
3513         rsurface_lightmapcolor4f_bufferoffset = 0;
3514         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3515         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3516         R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3517         GL_Color(r, g, b, a);
3518         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3519 }
3520
3521 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3522 {
3523         int texturesurfaceindex;
3524         int i;
3525         float *c;
3526         // TODO: optimize
3527         if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
3528         {
3529                 // generate color arrays for the surfaces in this list
3530                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3531                 {
3532                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3533                         for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
3534                         {
3535                                 if (surface->lightmapinfo->samples)
3536                                 {
3537                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
3538                                         float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
3539                                         VectorScale(lm, scale, c);
3540                                         if (surface->lightmapinfo->styles[1] != 255)
3541                                         {
3542                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
3543                                                 lm += size3;
3544                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
3545                                                 VectorMA(c, scale, lm, c);
3546                                                 if (surface->lightmapinfo->styles[2] != 255)
3547                                                 {
3548                                                         lm += size3;
3549                                                         scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
3550                                                         VectorMA(c, scale, lm, c);
3551                                                         if (surface->lightmapinfo->styles[3] != 255)
3552                                                         {
3553                                                                 lm += size3;
3554                                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
3555                                                                 VectorMA(c, scale, lm, c);
3556                                                         }
3557                                                 }
3558                                         }
3559                                 }
3560                                 else
3561                                         VectorClear(c);
3562                                 c[3] = 1;
3563                         }
3564                 }
3565                 rsurface_lightmapcolor4f = rsurface_array_color4f;
3566                 rsurface_lightmapcolor4f_bufferobject = 0;
3567                 rsurface_lightmapcolor4f_bufferoffset = 0;
3568         }
3569         else
3570         {
3571                 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
3572                 rsurface_lightmapcolor4f_bufferobject = rsurface_model->surfmesh.vbo;
3573                 rsurface_lightmapcolor4f_bufferoffset = rsurface_model->surfmesh.vbooffset_lightmapcolor4f;
3574         }
3575         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3576         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3577         R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3578         GL_Color(r, g, b, a);
3579         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3580 }
3581
3582 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3583 {
3584         int texturesurfaceindex;
3585         int i;
3586         float f;
3587         float *v, *c, *c2;
3588         vec3_t ambientcolor;
3589         vec3_t diffusecolor;
3590         vec3_t lightdir;
3591         // TODO: optimize
3592         // model lighting
3593         VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
3594         ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
3595         ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
3596         ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
3597         diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
3598         diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
3599         diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
3600         if (VectorLength2(diffusecolor) > 0)
3601         {
3602                 // generate color arrays for the surfaces in this list
3603                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3604                 {
3605                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3606                         int numverts = surface->num_vertices;
3607                         v = rsurface_vertex3f + 3 * surface->num_firstvertex;
3608                         c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
3609                         c = rsurface_array_color4f + 4 * surface->num_firstvertex;
3610                         // q3-style directional shading
3611                         for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
3612                         {
3613                                 if ((f = DotProduct(c2, lightdir)) > 0)
3614                                         VectorMA(ambientcolor, f, diffusecolor, c);
3615                                 else
3616                                         VectorCopy(ambientcolor, c);
3617                                 c[3] = a;
3618                         }
3619                 }
3620                 r = 1;
3621                 g = 1;
3622                 b = 1;
3623                 a = 1;
3624                 applycolor = false;
3625                 rsurface_lightmapcolor4f = rsurface_array_color4f;
3626                 rsurface_lightmapcolor4f_bufferobject = 0;
3627                 rsurface_lightmapcolor4f_bufferoffset = 0;
3628         }
3629         else
3630         {
3631                 r = ambientcolor[0];
3632                 g = ambientcolor[1];
3633                 b = ambientcolor[2];
3634                 rsurface_lightmapcolor4f = NULL;
3635                 rsurface_lightmapcolor4f_bufferobject = 0;
3636                 rsurface_lightmapcolor4f_bufferoffset = 0;
3637         }
3638         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3639         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3640         R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3641         GL_Color(r, g, b, a);
3642         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3643 }
3644
3645 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3646 {
3647         GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
3648         GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3649         GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3650         if (rsurface_mode != RSURFMODE_SHOWSURFACES)
3651         {
3652                 rsurface_mode = RSURFMODE_SHOWSURFACES;
3653                 GL_DepthMask(true);
3654                 GL_BlendFunc(GL_ONE, GL_ZERO);
3655                 R_Mesh_ColorPointer(NULL, 0, 0);
3656                 R_Mesh_ResetTextureState();
3657         }
3658         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3659         RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3660 }
3661
3662 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
3663 {
3664         // transparent sky would be ridiculous
3665         if ((rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3666                 return;
3667         if (rsurface_mode != RSURFMODE_SKY)
3668         {
3669                 if (rsurface_mode == RSURFMODE_GLSL)
3670                 {
3671                         qglUseProgramObjectARB(0);CHECKGLERROR
3672                 }
3673                 rsurface_mode = RSURFMODE_SKY;
3674         }
3675         if (skyrendernow)
3676         {
3677                 skyrendernow = false;
3678                 R_Sky();
3679                 // restore entity matrix
3680                 R_Mesh_Matrix(&rsurface_entity->matrix);
3681         }
3682         GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
3683         GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3684         GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3685         GL_DepthMask(true);
3686         // LordHavoc: HalfLife maps have freaky skypolys so don't use
3687         // skymasking on them, and Quake3 never did sky masking (unlike
3688         // software Quake and software Quake2), so disable the sky masking
3689         // in Quake3 maps as it causes problems with q3map2 sky tricks,
3690         // and skymasking also looks very bad when noclipping outside the
3691         // level, so don't use it then either.
3692         if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
3693         {
3694                 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
3695                 R_Mesh_ColorPointer(NULL, 0, 0);
3696                 R_Mesh_ResetTextureState();
3697                 if (skyrendermasked)
3698                 {
3699                         // depth-only (masking)
3700                         GL_ColorMask(0,0,0,0);
3701                         // just to make sure that braindead drivers don't draw
3702                         // anything despite that colormask...
3703                         GL_BlendFunc(GL_ZERO, GL_ONE);
3704                 }
3705                 else
3706                 {
3707                         // fog sky
3708                         GL_BlendFunc(GL_ONE, GL_ZERO);
3709                 }
3710                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3711                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3712                 if (skyrendermasked)
3713                         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
3714         }
3715 }
3716
3717 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
3718 {
3719         if (rsurface_mode != RSURFMODE_GLSL)
3720         {
3721                 rsurface_mode = RSURFMODE_GLSL;
3722                 R_Mesh_ResetTextureState();
3723         }
3724
3725         R_SetupSurfaceShader(vec3_origin, rsurface_lightmode == 2, 1, 1, rsurface_texture->specularscale);
3726         if (!r_glsl_permutation)
3727                 return;
3728
3729         if (rsurface_lightmode == 2)
3730                 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3731         else
3732                 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3733         R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_model->surfmesh.vbo, rsurface_model->surfmesh.vbooffset_texcoordtexture2f);
3734         R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f, rsurface_svector3f_bufferobject, rsurface_svector3f_bufferoffset);
3735         R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f, rsurface_tvector3f_bufferobject, rsurface_tvector3f_bufferoffset);
3736         R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f, rsurface_normal3f_bufferobject, rsurface_normal3f_bufferoffset);
3737         R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f, rsurface_model->surfmesh.vbo, rsurface_model->surfmesh.vbooffset_texcoordlightmap2f);
3738
3739         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3740         {
3741                 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3742                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3743                         R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3744                 R_Mesh_ColorPointer(NULL, 0, 0);
3745         }
3746         else if (rsurface_uselightmaptexture)
3747         {
3748                 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
3749                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3750                         R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
3751                 R_Mesh_ColorPointer(NULL, 0, 0);
3752         }
3753         else
3754         {
3755                 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3756                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3757                         R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3758                 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f, rsurface_model->surfmesh.vbo, rsurface_model->surfmesh.vbooffset_lightmapcolor4f);
3759         }
3760
3761         if (rsurface_uselightmaptexture && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
3762                 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
3763         else
3764                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3765         if (rsurface_texture->backgroundnumskinframes && !(rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3766         {
3767         }
3768 }
3769
3770 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
3771 {
3772         // OpenGL 1.3 path - anything not completely ancient
3773         int texturesurfaceindex;
3774         qboolean applycolor;
3775         qboolean applyfog;
3776         rmeshstate_t m;
3777         int layerindex;
3778         const texturelayer_t *layer;
3779         if (rsurface_mode != RSURFMODE_MULTIPASS)
3780                 rsurface_mode = RSURFMODE_MULTIPASS;
3781         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3782         for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3783         {
3784                 vec4_t layercolor;
3785                 int layertexrgbscale;
3786                 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3787                 {
3788                         if (layerindex == 0)
3789                                 GL_AlphaTest(true);
3790                         else
3791                         {
3792                                 GL_AlphaTest(false);
3793                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3794                         }
3795                 }
3796                 GL_DepthMask(layer->depthmask);
3797                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3798                 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
3799                 {
3800                         layertexrgbscale = 4;
3801                         VectorScale(layer->color, 0.25f, layercolor);
3802                 }
3803                 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
3804                 {
3805                         layertexrgbscale = 2;
3806                         VectorScale(layer->color, 0.5f, layercolor);
3807                 }
3808                 else
3809                 {
3810                         layertexrgbscale = 1;
3811                         VectorScale(layer->color, 1.0f, layercolor);
3812                 }
3813                 layercolor[3] = layer->color[3];
3814                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
3815                 R_Mesh_ColorPointer(NULL, 0, 0);
3816                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3817                 switch (layer->type)
3818                 {
3819                 case TEXTURELAYERTYPE_LITTEXTURE:
3820                         memset(&m, 0, sizeof(m));
3821                         m.tex[0] = R_GetTexture(r_texture_white);
3822                         m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3823                         m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3824                         m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordlightmap2f;
3825                         m.tex[1] = R_GetTexture(layer->texture);
3826                         m.texmatrix[1] = layer->texmatrix;
3827                         m.texrgbscale[1] = layertexrgbscale;
3828                         m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
3829                         m.pointer_texcoord_bufferobject[1] = rsurface_model->surfmesh.vbo;
3830                         m.pointer_texcoord_bufferoffset[1] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3831                         R_Mesh_TextureState(&m);
3832                         if (rsurface_lightmode == 2)
3833                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3834                         else if (rsurface_uselightmaptexture)
3835                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3836                         else
3837                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3838                         break;
3839                 case TEXTURELAYERTYPE_TEXTURE:
3840                         memset(&m, 0, sizeof(m));
3841                         m.tex[0] = R_GetTexture(layer->texture);
3842                         m.texmatrix[0] = layer->texmatrix;
3843                         m.texrgbscale[0] = layertexrgbscale;
3844                         m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3845                         m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3846                         m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3847                         R_Mesh_TextureState(&m);
3848                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3849                         break;
3850                 case TEXTURELAYERTYPE_FOG:
3851                         memset(&m, 0, sizeof(m));
3852                         m.texrgbscale[0] = layertexrgbscale;
3853                         if (layer->texture)
3854                         {
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                         }
3861                         R_Mesh_TextureState(&m);
3862                         // generate a color array for the fog pass
3863                         R_Mesh_ColorPointer(rsurface_array_color4f, 0, 0);
3864                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3865                         {
3866                                 int i;
3867                                 float f, *v, *c;
3868                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3869                                 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)
3870                                 {
3871                                         f = 1 - FogPoint_Model(v);
3872                                         c[0] = layercolor[0];
3873                                         c[1] = layercolor[1];
3874                                         c[2] = layercolor[2];
3875                                         c[3] = f * layercolor[3];
3876                                 }
3877                         }
3878                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3879                         break;
3880                 default:
3881                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3882                 }
3883                 GL_LockArrays(0, 0);
3884         }
3885         CHECKGLERROR
3886         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3887         {
3888                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3889                 GL_AlphaTest(false);
3890         }
3891 }
3892
3893 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3894 {
3895         // OpenGL 1.1 - crusty old voodoo path
3896         int texturesurfaceindex;
3897         qboolean applyfog;
3898         rmeshstate_t m;
3899         int layerindex;
3900         const texturelayer_t *layer;
3901         if (rsurface_mode != RSURFMODE_MULTIPASS)
3902                 rsurface_mode = RSURFMODE_MULTIPASS;
3903         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3904         for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3905         {
3906                 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3907                 {
3908                         if (layerindex == 0)
3909                                 GL_AlphaTest(true);
3910                         else
3911                         {
3912                                 GL_AlphaTest(false);
3913                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3914                         }
3915                 }
3916                 GL_DepthMask(layer->depthmask);
3917                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3918                 R_Mesh_ColorPointer(NULL, 0, 0);
3919                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3920                 switch (layer->type)
3921                 {
3922                 case TEXTURELAYERTYPE_LITTEXTURE:
3923                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3924                         {
3925                                 // two-pass lit texture with 2x rgbscale
3926                                 // first the lightmap pass
3927                                 memset(&m, 0, sizeof(m));
3928                                 m.tex[0] = R_GetTexture(r_texture_white);
3929                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3930                                 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3931                                 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordlightmap2f;
3932                                 R_Mesh_TextureState(&m);
3933                                 if (rsurface_lightmode == 2)
3934                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3935                                 else if (rsurface_uselightmaptexture)
3936                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3937                                 else
3938                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3939                                 GL_LockArrays(0, 0);
3940                                 // then apply the texture to it
3941                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3942                                 memset(&m, 0, sizeof(m));
3943                                 m.tex[0] = R_GetTexture(layer->texture);
3944                                 m.texmatrix[0] = layer->texmatrix;
3945                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3946                                 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3947                                 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3948                                 R_Mesh_TextureState(&m);
3949                                 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);
3950                         }
3951                         else
3952                         {
3953                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3954                                 memset(&m, 0, sizeof(m));
3955                                 m.tex[0] = R_GetTexture(layer->texture);
3956                                 m.texmatrix[0] = layer->texmatrix;
3957                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3958                                 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3959                                 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3960                                 R_Mesh_TextureState(&m);
3961                                 if (rsurface_lightmode == 2)
3962                                         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);
3963                                 else
3964                                         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);
3965                         }
3966                         break;
3967                 case TEXTURELAYERTYPE_TEXTURE:
3968                         // singletexture unlit texture with transparency support
3969                         memset(&m, 0, sizeof(m));
3970                         m.tex[0] = R_GetTexture(layer->texture);
3971                         m.texmatrix[0] = layer->texmatrix;
3972                         m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3973                         m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3974                         m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3975                         R_Mesh_TextureState(&m);
3976                         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);
3977                         break;
3978                 case TEXTURELAYERTYPE_FOG:
3979                         // singletexture fogging
3980                         R_Mesh_ColorPointer(rsurface_array_color4f, 0, 0);
3981                         if (layer->texture)
3982                         {
3983                                 memset(&m, 0, sizeof(m));
3984                                 m.tex[0] = R_GetTexture(layer->texture);
3985                                 m.texmatrix[0] = layer->texmatrix;
3986                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3987                                 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3988                                 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3989                                 R_Mesh_TextureState(&m);
3990                         }
3991                         else
3992                                 R_Mesh_ResetTextureState();
3993                         // generate a color array for the fog pass
3994                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3995                         {
3996                                 int i;
3997                                 float f, *v, *c;
3998                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3999                                 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)
4000                                 {
4001                                         f = 1 - FogPoint_Model(v);
4002                                         c[0] = layer->color[0];
4003                                         c[1] = layer->color[1];
4004                                         c[2] = layer->color[2];
4005                                         c[3] = f * layer->color[3];
4006                                 }
4007                         }
4008                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4009                         break;
4010                 default:
4011                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
4012                 }
4013                 GL_LockArrays(0, 0);
4014         }
4015         CHECKGLERROR
4016         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4017         {
4018                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4019                 GL_AlphaTest(false);
4020         }
4021 }
4022
4023 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
4024 {
4025         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
4026                 return;
4027         r_shadow_rtlight = NULL;
4028         r_refdef.stats.entities_surfaces += texturenumsurfaces;
4029         CHECKGLERROR
4030         if (r_showsurfaces.integer)
4031                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
4032         else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
4033                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
4034         else if (rsurface_texture->currentnumlayers)
4035         {
4036                 GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4037                 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
4038                 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4039                 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
4040                 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
4041                 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
4042                 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4043                 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
4044                 rsurface_lightmode = ((rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
4045                 if (r_glsl.integer && gl_support_fragment_shader)
4046                         R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
4047                 else if (gl_combine.integer && r_textureunits.integer >= 2)
4048                         R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
4049                 else
4050                         R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
4051         }
4052         CHECKGLERROR
4053         GL_LockArrays(0, 0);
4054 }
4055
4056 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4057 {
4058         int i, j;
4059         int texturenumsurfaces, endsurface;
4060         texture_t *texture;
4061         msurface_t *surface;
4062         msurface_t *texturesurfacelist[1024];
4063
4064         // if the model is static it doesn't matter what value we give for
4065         // wantnormals and wanttangents, so this logic uses only rules applicable
4066         // to a model, knowing that they are meaningless otherwise
4067         if (ent == r_refdef.worldentity)
4068                 RSurf_ActiveWorldEntity();
4069         else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
4070                 RSurf_ActiveModelEntity(ent, false, false);
4071         else
4072                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
4073
4074         for (i = 0;i < numsurfaces;i = j)
4075         {
4076                 j = i + 1;
4077                 surface = rsurface_model->data_surfaces + surfacelist[i];
4078                 texture = surface->texture;
4079                 R_UpdateTextureInfo(ent, texture);
4080                 rsurface_texture = texture->currentframe;
4081                 rsurface_uselightmaptexture = surface->lightmaptexture != NULL;
4082                 // scan ahead until we find a different texture
4083                 endsurface = min(i + 1024, numsurfaces);
4084                 texturenumsurfaces = 0;
4085                 texturesurfacelist[texturenumsurfaces++] = surface;
4086                 for (;j < endsurface;j++)
4087                 {
4088                         surface = rsurface_model->data_surfaces + surfacelist[j];
4089                         if (texture != surface->texture || rsurface_uselightmaptexture != (surface->lightmaptexture != NULL))
4090                                 break;
4091                         texturesurfacelist[texturenumsurfaces++] = surface;
4092                 }
4093                 // render the range of surfaces
4094                 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
4095         }
4096
4097         RSurf_CleanUp();
4098 }
4099
4100 void R_QueueSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask)
4101 {
4102         int i, j;
4103         vec3_t tempcenter, center;
4104         texture_t *texture;
4105         // break the surface list down into batches by texture and use of lightmapping
4106         for (i = 0;i < numsurfaces;i = j)
4107         {
4108                 j = i + 1;
4109                 // texture is the base texture pointer, rsurface_texture is the
4110                 // current frame/skin the texture is directing us to use (for example
4111                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
4112                 // use skin 1 instead)
4113                 texture = surfacelist[i]->texture;
4114                 rsurface_texture = texture->currentframe;
4115                 rsurface_uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
4116                 if (!(rsurface_texture->currentmaterialflags & flagsmask))
4117                 {
4118                         // if this texture is not the kind we want, skip ahead to the next one
4119                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
4120                                 ;
4121                         continue;
4122                 }
4123                 if (rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
4124                 {
4125                         // transparent surfaces get pushed off into the transparent queue
4126                         const msurface_t *surface = surfacelist[i];
4127                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
4128                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
4129                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
4130                         Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
4131                         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);
4132                 }
4133                 else
4134                 {
4135                         // simply scan ahead until we find a different texture or lightmap state
4136                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface_uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
4137                                 ;
4138                         // render the range of surfaces
4139                         R_DrawTextureSurfaceList(j - i, surfacelist + i);
4140                 }
4141         }
4142 }
4143
4144 float locboxvertex3f[6*4*3] =
4145 {
4146         1,0,1, 1,0,0, 1,1,0, 1,1,1,
4147         0,1,1, 0,1,0, 0,0,0, 0,0,1,
4148         1,1,1, 1,1,0, 0,1,0, 0,1,1,
4149         0,0,1, 0,0,0, 1,0,0, 1,0,1,
4150         0,0,1, 1,0,1, 1,1,1, 0,1,1,
4151         1,0,0, 0,0,0, 0,1,0, 1,1,0
4152 };
4153
4154 int locboxelement3i[6*2*3] =
4155 {
4156          0, 1, 2, 0, 2, 3,
4157          4, 5, 6, 4, 6, 7,
4158          8, 9,10, 8,10,11,
4159         12,13,14, 12,14,15,
4160         16,17,18, 16,18,19,
4161         20,21,22, 20,22,23
4162 };
4163
4164 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4165 {
4166         int i, j;
4167         cl_locnode_t *loc = (cl_locnode_t *)ent;
4168         vec3_t mins, size;
4169         float vertex3f[6*4*3];
4170         CHECKGLERROR
4171         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4172         GL_DepthMask(false);
4173         GL_DepthRange(0, 1);
4174         GL_DepthTest(true);
4175         GL_CullFace(GL_NONE);
4176         R_Mesh_Matrix(&identitymatrix);
4177
4178         R_Mesh_VertexPointer(vertex3f, 0, 0);
4179         R_Mesh_ColorPointer(NULL, 0, 0);
4180         R_Mesh_ResetTextureState();
4181
4182         i = surfacelist[0];
4183         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
4184                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
4185                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
4186                         surfacelist[0] < 0 ? 0.5f : 0.125f);
4187
4188         if (VectorCompare(loc->mins, loc->maxs))
4189         {
4190                 VectorSet(size, 2, 2, 2);
4191                 VectorMA(loc->mins, -0.5f, size, mins);
4192         }
4193         else
4194         {
4195                 VectorCopy(loc->mins, mins);
4196                 VectorSubtract(loc->maxs, loc->mins, size);
4197         }
4198
4199         for (i = 0;i < 6*4*3;)
4200                 for (j = 0;j < 3;j++, i++)
4201                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
4202
4203         R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
4204 }
4205
4206 void R_DrawLocs(void)
4207 {
4208         int index;
4209         cl_locnode_t *loc, *nearestloc;
4210         vec3_t center;
4211         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
4212         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
4213         {
4214                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
4215                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
4216         }
4217 }
4218
4219 void R_DrawCollisionBrushes(entity_render_t *ent)
4220 {
4221         int i;
4222         q3mbrush_t *brush;
4223         msurface_t *surface;
4224         model_t *model = ent->model;
4225         if (!model->brush.num_brushes)
4226                 return;
4227         CHECKGLERROR
4228         R_Mesh_ColorPointer(NULL, 0, 0);
4229         R_Mesh_ResetTextureState();
4230         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4231         GL_DepthMask(false);
4232         GL_DepthRange(0, 1);
4233         GL_DepthTest(!r_showdisabledepthtest.integer);
4234         qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
4235         for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
4236                 if (brush->colbrushf && brush->colbrushf->numtriangles)
4237                         R_DrawCollisionBrush(brush->colbrushf);
4238         for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
4239                 if (surface->num_collisiontriangles)
4240                         R_DrawCollisionSurface(ent, surface);
4241         qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
4242 }
4243
4244 void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
4245 {
4246         int i, j, k, l;
4247         const int *elements;
4248         msurface_t *surface;
4249         model_t *model = ent->model;
4250         vec3_t v;
4251         CHECKGLERROR
4252         GL_DepthRange(0, 1);
4253         GL_DepthTest(!r_showdisabledepthtest.integer);
4254         GL_DepthMask(true);
4255         GL_BlendFunc(GL_ONE, GL_ZERO);
4256         R_Mesh_ColorPointer(NULL, 0, 0);
4257         R_Mesh_ResetTextureState();
4258         for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
4259         {
4260                 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
4261                         continue;
4262                 rsurface_texture = surface->texture->currentframe;
4263                 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
4264                 {
4265                         RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
4266                         if (drawtris)
4267                         {
4268                                 if (!rsurface_texture->currentlayers->depthmask)
4269                                         GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
4270                                 else if (ent == r_refdef.worldentity)
4271                                         GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
4272                                 else
4273                                         GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
4274                                 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
4275                                 CHECKGLERROR
4276                                 qglBegin(GL_LINES);
4277                                 for (k = 0;k < surface->num_triangles;k++, elements += 3)
4278                                 {
4279                                         qglArrayElement(elements[0]);qglArrayElement(elements[1]);
4280                                         qglArrayElement(elements[1]);qglArrayElement(elements[2]);
4281                                         qglArrayElement(elements[2]);qglArrayElement(elements[0]);
4282                                 }
4283                                 qglEnd();
4284                                 CHECKGLERROR
4285                         }
4286                         if (drawnormals)
4287                         {
4288                                 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
4289                                 qglBegin(GL_LINES);
4290                                 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4291                                 {
4292                                         VectorCopy(rsurface_vertex3f + l * 3, v);
4293                                         qglVertex3f(v[0], v[1], v[2]);
4294                                         VectorMA(v, 8, rsurface_svector3f + l * 3, v);
4295                                         qglVertex3f(v[0], v[1], v[2]);
4296                                 }
4297                                 qglEnd();
4298                                 CHECKGLERROR
4299                                 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
4300                                 qglBegin(GL_LINES);
4301                                 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4302                                 {
4303                                         VectorCopy(rsurface_vertex3f + l * 3, v);
4304                                         qglVertex3f(v[0], v[1], v[2]);
4305                                         VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
4306                                         qglVertex3f(v[0], v[1], v[2]);
4307                                 }
4308                                 qglEnd();
4309                                 CHECKGLERROR
4310                                 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
4311                                 qglBegin(GL_LINES);
4312                                 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4313                                 {
4314                                         VectorCopy(rsurface_vertex3f + l * 3, v);
4315                                         qglVertex3f(v[0], v[1], v[2]);
4316                                         VectorMA(v, 8, rsurface_normal3f + l * 3, v);
4317                                         qglVertex3f(v[0], v[1], v[2]);
4318                                 }
4319                                 qglEnd();
4320                                 CHECKGLERROR
4321                         }
4322                 }
4323         }
4324         rsurface_texture = NULL;
4325 }
4326
4327 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
4328 void R_DrawWorldSurfaces(qboolean skysurfaces)
4329 {
4330         int i, j, endj, f, flagsmask;
4331         int counttriangles = 0;
4332         msurface_t *surface, **surfacechain;
4333         texture_t *t;
4334         model_t *model = r_refdef.worldmodel;
4335         const int maxsurfacelist = 1024;
4336         int numsurfacelist = 0;
4337         msurface_t *surfacelist[1024];
4338         if (model == NULL)
4339                 return;
4340
4341         RSurf_ActiveWorldEntity();
4342
4343         // update light styles
4344         if (!skysurfaces && model->brushq1.light_styleupdatechains)
4345         {
4346                 for (i = 0;i < model->brushq1.light_styles;i++)
4347                 {
4348                         if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
4349                         {
4350                                 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
4351                                 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
4352                                         for (;(surface = *surfacechain);surfacechain++)
4353                                                 surface->cached_dlight = true;
4354                         }
4355                 }
4356         }
4357
4358         R_UpdateAllTextureInfo(r_refdef.worldentity);
4359         flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
4360         f = 0;
4361         t = NULL;
4362         rsurface_uselightmaptexture = false;
4363         rsurface_texture = NULL;
4364         numsurfacelist = 0;
4365         j = model->firstmodelsurface;
4366         endj = j + model->nummodelsurfaces;
4367         while (j < endj)
4368         {
4369                 // quickly skip over non-visible surfaces
4370                 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
4371                         ;
4372                 // quickly iterate over visible surfaces
4373                 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
4374                 {
4375                         // process this surface
4376                         surface = model->data_surfaces + j;
4377                         // if this surface fits the criteria, add it to the list
4378                         if (surface->num_triangles)
4379                         {
4380                                 // if lightmap parameters changed, rebuild lightmap texture
4381                                 if (surface->cached_dlight)
4382                                         R_BuildLightMap(r_refdef.worldentity, surface);
4383                                 // add face to draw list
4384                                 surfacelist[numsurfacelist++] = surface;
4385                                 counttriangles += surface->num_triangles;
4386                                 if (numsurfacelist >= maxsurfacelist)
4387                                 {
4388                                         R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4389                                         numsurfacelist = 0;
4390                                 }
4391                         }
4392                 }
4393         }
4394         if (numsurfacelist)
4395                 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4396         r_refdef.stats.entities_triangles += counttriangles;
4397         RSurf_CleanUp();
4398
4399         if (r_showcollisionbrushes.integer && !skysurfaces)
4400                 R_DrawCollisionBrushes(r_refdef.worldentity);
4401
4402         if (r_showtris.integer || r_shownormals.integer)
4403                 R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
4404 }
4405
4406 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces)
4407 {
4408         int i, f, flagsmask;
4409         int counttriangles = 0;
4410         msurface_t *surface, *endsurface, **surfacechain;
4411         texture_t *t;
4412         model_t *model = ent->model;
4413         const int maxsurfacelist = 1024;
4414         int numsurfacelist = 0;
4415         msurface_t *surfacelist[1024];
4416         if (model == NULL)
4417                 return;
4418
4419         // if the model is static it doesn't matter what value we give for
4420         // wantnormals and wanttangents, so this logic uses only rules applicable
4421         // to a model, knowing that they are meaningless otherwise
4422         if (ent == r_refdef.worldentity)
4423                 RSurf_ActiveWorldEntity();
4424         else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
4425                 RSurf_ActiveModelEntity(ent, false, false);
4426         else
4427                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
4428
4429         // update light styles
4430         if (!skysurfaces && model->brushq1.light_styleupdatechains)
4431         {
4432                 for (i = 0;i < model->brushq1.light_styles;i++)
4433                 {
4434                         if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
4435                         {
4436                                 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
4437                                 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
4438                                         for (;(surface = *surfacechain);surfacechain++)
4439                                                 surface->cached_dlight = true;
4440                         }
4441                 }
4442         }
4443
4444         R_UpdateAllTextureInfo(ent);
4445         flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
4446         f = 0;
4447         t = NULL;
4448         rsurface_uselightmaptexture = false;
4449         rsurface_texture = NULL;
4450         numsurfacelist = 0;
4451         surface = model->data_surfaces + model->firstmodelsurface;
4452         endsurface = surface + model->nummodelsurfaces;
4453         for (;surface < endsurface;surface++)
4454         {
4455                 // if this surface fits the criteria, add it to the list
4456                 if (surface->num_triangles)
4457                 {
4458                         // if lightmap parameters changed, rebuild lightmap texture
4459                         if (surface->cached_dlight)
4460                                 R_BuildLightMap(ent, surface);
4461                         // add face to draw list
4462                         surfacelist[numsurfacelist++] = surface;
4463                         counttriangles += surface->num_triangles;
4464                         if (numsurfacelist >= maxsurfacelist)
4465                         {
4466                                 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4467                                 numsurfacelist = 0;
4468                         }
4469                 }
4470         }
4471         if (numsurfacelist)
4472                 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4473         r_refdef.stats.entities_triangles += counttriangles;
4474         RSurf_CleanUp();
4475
4476         if (r_showcollisionbrushes.integer && !skysurfaces)
4477                 R_DrawCollisionBrushes(ent);
4478
4479         if (r_showtris.integer || r_shownormals.integer)
4480                 R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);
4481 }