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