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