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