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