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