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