compute sorted surface list at load of each model - this tripled
[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 "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
30
31 static int r_frame = 0; // used only by R_GetCurrentTexture
32
33 //
34 // screen size info
35 //
36 r_refdef_t r_refdef;
37
38 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "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"};
39 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
40 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
41 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
42 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)"};
43 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
44 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
45 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"};
46 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"};
47 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
48 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"};
49 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"};
50 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"};
51 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
52 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
53 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
54 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
55 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
56 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
57 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
58 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
59 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
60 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
61 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
62 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
63 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows DOWN, otherwise use the model lighting"};
64 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
65 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
66 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"};
67 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"};
68 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
69 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
70
71 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
72 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
73 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
74 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
75 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
76 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
77 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
78 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
79
80 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)"};
81
82 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
83 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)"};
84 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)"};
85 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
86 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
87 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
88 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
89 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
90 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
91 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
92 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
93 cvar_t r_glsl_usegeneric = {CVAR_SAVE, "r_glsl_usegeneric", "1", "use shaders for rendering simple geometry (rather than conventional fixed-function rendering for this purpose)"};
94
95 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
96 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
97 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
98 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
99 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
100
101 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
102 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
103 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
104 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
105
106 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
107 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
108 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
109 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
110 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
111 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
112 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
113
114 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
115 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
116 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
117 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)"};
118
119 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"};
120
121 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"};
122
123 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
124
125 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
126 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
127 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
128 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
129 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
130 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
131
132 extern cvar_t v_glslgamma;
133
134 extern qboolean v_flipped_state;
135
136 static struct r_bloomstate_s
137 {
138         qboolean enabled;
139         qboolean hdr;
140
141         int bloomwidth, bloomheight;
142
143         int screentexturewidth, screentextureheight;
144         rtexture_t *texture_screen;
145
146         int bloomtexturewidth, bloomtextureheight;
147         rtexture_t *texture_bloom;
148
149         // arrays for rendering the screen passes
150         float screentexcoord2f[8];
151         float bloomtexcoord2f[8];
152         float offsettexcoord2f[8];
153 }
154 r_bloomstate;
155
156 r_waterstate_t r_waterstate;
157
158 // shadow volume bsp struct with automatically growing nodes buffer
159 svbsp_t r_svbsp;
160
161 rtexture_t *r_texture_blanknormalmap;
162 rtexture_t *r_texture_white;
163 rtexture_t *r_texture_grey128;
164 rtexture_t *r_texture_black;
165 rtexture_t *r_texture_notexture;
166 rtexture_t *r_texture_whitecube;
167 rtexture_t *r_texture_normalizationcube;
168 rtexture_t *r_texture_fogattenuation;
169 rtexture_t *r_texture_gammaramps;
170 unsigned int r_texture_gammaramps_serial;
171 //rtexture_t *r_texture_fogintensity;
172
173 unsigned int r_queries[R_MAX_OCCLUSION_QUERIES];
174 unsigned int r_numqueries;
175 unsigned int r_maxqueries;
176
177 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
178 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
179
180 // vertex coordinates for a quad that covers the screen exactly
181 const static float r_screenvertex3f[12] =
182 {
183         0, 0, 0,
184         1, 0, 0,
185         1, 1, 0,
186         0, 1, 0
187 };
188
189 extern void R_DrawModelShadows(void);
190
191 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
192 {
193         int i;
194         for (i = 0;i < verts;i++)
195         {
196                 out[0] = in[0] * r;
197                 out[1] = in[1] * g;
198                 out[2] = in[2] * b;
199                 out[3] = in[3];
200                 in += 4;
201                 out += 4;
202         }
203 }
204
205 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
206 {
207         int i;
208         for (i = 0;i < verts;i++)
209         {
210                 out[0] = r;
211                 out[1] = g;
212                 out[2] = b;
213                 out[3] = a;
214                 out += 4;
215         }
216 }
217
218 // FIXME: move this to client?
219 void FOG_clear(void)
220 {
221         if (gamemode == GAME_NEHAHRA)
222         {
223                 Cvar_Set("gl_fogenable", "0");
224                 Cvar_Set("gl_fogdensity", "0.2");
225                 Cvar_Set("gl_fogred", "0.3");
226                 Cvar_Set("gl_foggreen", "0.3");
227                 Cvar_Set("gl_fogblue", "0.3");
228         }
229         r_refdef.fog_density = 0;
230         r_refdef.fog_red = 0;
231         r_refdef.fog_green = 0;
232         r_refdef.fog_blue = 0;
233         r_refdef.fog_alpha = 1;
234         r_refdef.fog_start = 0;
235         r_refdef.fog_end = 0;
236 }
237
238 float FogForDistance(vec_t dist)
239 {
240         unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
241         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
242 }
243
244 float FogPoint_World(const vec3_t p)
245 {
246         return FogForDistance(VectorDistance((p), r_refdef.view.origin));
247 }
248
249 float FogPoint_Model(const vec3_t p)
250 {
251         return FogForDistance(VectorDistance((p), rsurface.modelorg) * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
252 }
253
254 static void R_BuildBlankTextures(void)
255 {
256         unsigned char data[4];
257         data[2] = 128; // normal X
258         data[1] = 128; // normal Y
259         data[0] = 255; // normal Z
260         data[3] = 128; // height
261         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
262         data[0] = 255;
263         data[1] = 255;
264         data[2] = 255;
265         data[3] = 255;
266         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
267         data[0] = 128;
268         data[1] = 128;
269         data[2] = 128;
270         data[3] = 255;
271         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
272         data[0] = 0;
273         data[1] = 0;
274         data[2] = 0;
275         data[3] = 255;
276         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
277 }
278
279 static void R_BuildNoTexture(void)
280 {
281         int x, y;
282         unsigned char pix[16][16][4];
283         // this makes a light grey/dark grey checkerboard texture
284         for (y = 0;y < 16;y++)
285         {
286                 for (x = 0;x < 16;x++)
287                 {
288                         if ((y < 8) ^ (x < 8))
289                         {
290                                 pix[y][x][0] = 128;
291                                 pix[y][x][1] = 128;
292                                 pix[y][x][2] = 128;
293                                 pix[y][x][3] = 255;
294                         }
295                         else
296                         {
297                                 pix[y][x][0] = 64;
298                                 pix[y][x][1] = 64;
299                                 pix[y][x][2] = 64;
300                                 pix[y][x][3] = 255;
301                         }
302                 }
303         }
304         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
305 }
306
307 static void R_BuildWhiteCube(void)
308 {
309         unsigned char data[6*1*1*4];
310         memset(data, 255, sizeof(data));
311         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
312 }
313
314 static void R_BuildNormalizationCube(void)
315 {
316         int x, y, side;
317         vec3_t v;
318         vec_t s, t, intensity;
319 #define NORMSIZE 64
320         unsigned char data[6][NORMSIZE][NORMSIZE][4];
321         for (side = 0;side < 6;side++)
322         {
323                 for (y = 0;y < NORMSIZE;y++)
324                 {
325                         for (x = 0;x < NORMSIZE;x++)
326                         {
327                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
328                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
329                                 switch(side)
330                                 {
331                                 default:
332                                 case 0:
333                                         v[0] = 1;
334                                         v[1] = -t;
335                                         v[2] = -s;
336                                         break;
337                                 case 1:
338                                         v[0] = -1;
339                                         v[1] = -t;
340                                         v[2] = s;
341                                         break;
342                                 case 2:
343                                         v[0] = s;
344                                         v[1] = 1;
345                                         v[2] = t;
346                                         break;
347                                 case 3:
348                                         v[0] = s;
349                                         v[1] = -1;
350                                         v[2] = -t;
351                                         break;
352                                 case 4:
353                                         v[0] = s;
354                                         v[1] = -t;
355                                         v[2] = 1;
356                                         break;
357                                 case 5:
358                                         v[0] = -s;
359                                         v[1] = -t;
360                                         v[2] = -1;
361                                         break;
362                                 }
363                                 intensity = 127.0f / sqrt(DotProduct(v, v));
364                                 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
365                                 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
366                                 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
367                                 data[side][y][x][3] = 255;
368                         }
369                 }
370         }
371         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
372 }
373
374 static void R_BuildFogTexture(void)
375 {
376         int x, b;
377 #define FOGWIDTH 256
378         unsigned char data1[FOGWIDTH][4];
379         //unsigned char data2[FOGWIDTH][4];
380         double d, r, alpha;
381
382         r_refdef.fogmasktable_start = r_refdef.fog_start;
383         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
384         r_refdef.fogmasktable_range = r_refdef.fogrange;
385         r_refdef.fogmasktable_density = r_refdef.fog_density;
386
387         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
388         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
389         {
390                 d = (x * r - r_refdef.fogmasktable_start);
391                 if(developer.integer >= 100)
392                         Con_Printf("%f ", d);
393                 d = max(0, d);
394                 if (r_fog_exp2.integer)
395                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
396                 else
397                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
398                 if(developer.integer >= 100)
399                         Con_Printf(" : %f ", alpha);
400                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
401                 if(developer.integer >= 100)
402                         Con_Printf(" = %f\n", alpha);
403                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
404         }
405
406         for (x = 0;x < FOGWIDTH;x++)
407         {
408                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
409                 data1[x][0] = b;
410                 data1[x][1] = b;
411                 data1[x][2] = b;
412                 data1[x][3] = 255;
413                 //data2[x][0] = 255 - b;
414                 //data2[x][1] = 255 - b;
415                 //data2[x][2] = 255 - b;
416                 //data2[x][3] = 255;
417         }
418         if (r_texture_fogattenuation)
419         {
420                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
421                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
422         }
423         else
424         {
425                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
426                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
427         }
428 }
429
430 static const char *builtinshaderstring =
431 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
432 "// written by Forest 'LordHavoc' Hale\n"
433 "\n"
434 "// common definitions between vertex shader and fragment shader:\n"
435 "\n"
436 "//#ifdef __GLSL_CG_DATA_TYPES\n"
437 "//# define myhalf half\n"
438 "//# define myhalf2 half2\n"
439 "//# define myhalf3 half3\n"
440 "//# define myhalf4 half4\n"
441 "//#else\n"
442 "# define myhalf float\n"
443 "# define myhalf2 vec2\n"
444 "# define myhalf3 vec3\n"
445 "# define myhalf4 vec4\n"
446 "//#endif\n"
447 "\n"
448 "#ifdef MODE_DEPTH_OR_SHADOW\n"
449 "\n"
450 "# ifdef VERTEX_SHADER\n"
451 "void main(void)\n"
452 "{\n"
453 "       gl_Position = ftransform();\n"
454 "}\n"
455 "# endif\n"
456 "\n"
457 "#else\n"
458 "\n"
459 "#ifdef MODE_POSTPROCESS\n"
460 "# ifdef VERTEX_SHADER\n"
461 "void main(void)\n"
462 "{\n"
463 "       gl_FrontColor = gl_Color;\n"
464 "       gl_Position = ftransform();\n"
465 "       gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
466 "#ifdef USEGLOW\n"
467 "       gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
468 "#endif\n"
469 "}\n"
470 "# endif\n"
471 "# ifdef FRAGMENT_SHADER\n"
472 "\n"
473 "uniform sampler2D Texture_First;\n"
474 "#ifdef USEGLOW\n"
475 "uniform sampler2D Texture_Second;\n"
476 "#endif\n"
477 "#ifdef USEGAMMARAMPS\n"
478 "uniform sampler2D Texture_GammaRamps;\n"
479 "#endif\n"
480 "#ifdef USEVERTEXTEXTUREBLEND\n"
481 "uniform vec4 TintColor;\n"
482 "#endif\n"
483 "#ifdef USECOLORMOD\n"
484 "uniform vec3 Gamma;\n"
485 "#endif\n"
486 "//uncomment these if you want to use them:\n"
487 "uniform vec4 UserVec1;\n"
488 "// uniform vec4 UserVec2;\n"
489 "// uniform vec4 UserVec3;\n"
490 "// uniform vec4 UserVec4;\n"
491 "// uniform float ClientTime;\n"
492 "uniform vec2 PixelSize;\n"
493 "void main(void)\n"
494 "{\n"
495 "       gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
496 "#ifdef USEGLOW\n"
497 "       gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
498 "#endif\n"
499 "#ifdef USEVERTEXTEXTUREBLEND\n"
500 "       gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
501 "#endif\n"
502 "\n"
503 "#ifdef USEPOSTPROCESSING\n"
504 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
505 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
506 "       gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
507 "       gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
508 "       gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
509 "       gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
510 "       gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
511 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
512 "#endif\n"
513 "\n"
514 "#ifdef USEGAMMARAMPS\n"
515 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
516 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
517 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
518 "#endif\n"
519 "}\n"
520 "# endif\n"
521 "\n"
522 "\n"
523 "#else\n"
524 "#ifdef MODE_GENERIC\n"
525 "# ifdef VERTEX_SHADER\n"
526 "void main(void)\n"
527 "{\n"
528 "       gl_FrontColor = gl_Color;\n"
529 "#  ifdef USEDIFFUSE\n"
530 "       gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
531 "#  endif\n"
532 "#  ifdef USESPECULAR\n"
533 "       gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
534 "#  endif\n"
535 "       gl_Position = ftransform();\n"
536 "}\n"
537 "# endif\n"
538 "# ifdef FRAGMENT_SHADER\n"
539 "\n"
540 "#  ifdef USEDIFFUSE\n"
541 "uniform sampler2D Texture_First;\n"
542 "#  endif\n"
543 "#  ifdef USESPECULAR\n"
544 "uniform sampler2D Texture_Second;\n"
545 "#  endif\n"
546 "\n"
547 "void main(void)\n"
548 "{\n"
549 "       gl_FragColor = gl_Color;\n"
550 "#  ifdef USEDIFFUSE\n"
551 "       gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
552 "#  endif\n"
553 "\n"
554 "#  ifdef USESPECULAR\n"
555 "       vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
556 "#  endif\n"
557 "#  ifdef USECOLORMAPPING\n"
558 "       gl_FragColor *= tex2;\n"
559 "#  endif\n"
560 "#  ifdef USEGLOW\n"
561 "       gl_FragColor += tex2;\n"
562 "#  endif\n"
563 "#  ifdef USEVERTEXTEXTUREBLEND\n"
564 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
565 "#  endif\n"
566 "}\n"
567 "# endif\n"
568 "\n"
569 "#else // !MODE_GENERIC\n"
570 "\n"
571 "varying vec2 TexCoord;\n"
572 "varying vec2 TexCoordLightmap;\n"
573 "\n"
574 "#ifdef MODE_LIGHTSOURCE\n"
575 "varying vec3 CubeVector;\n"
576 "#endif\n"
577 "\n"
578 "#ifdef MODE_LIGHTSOURCE\n"
579 "varying vec3 LightVector;\n"
580 "#endif\n"
581 "#ifdef MODE_LIGHTDIRECTION\n"
582 "varying vec3 LightVector;\n"
583 "#endif\n"
584 "\n"
585 "varying vec3 EyeVector;\n"
586 "#ifdef USEFOG\n"
587 "varying vec3 EyeVectorModelSpace;\n"
588 "#endif\n"
589 "\n"
590 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
591 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
592 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
593 "\n"
594 "#ifdef MODE_WATER\n"
595 "varying vec4 ModelViewProjectionPosition;\n"
596 "#endif\n"
597 "#ifdef MODE_REFRACTION\n"
598 "varying vec4 ModelViewProjectionPosition;\n"
599 "#endif\n"
600 "#ifdef USEREFLECTION\n"
601 "varying vec4 ModelViewProjectionPosition;\n"
602 "#endif\n"
603 "\n"
604 "\n"
605 "\n"
606 "\n"
607 "\n"
608 "// vertex shader specific:\n"
609 "#ifdef VERTEX_SHADER\n"
610 "\n"
611 "uniform vec3 LightPosition;\n"
612 "uniform vec3 EyePosition;\n"
613 "uniform vec3 LightDir;\n"
614 "\n"
615 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
616 "\n"
617 "void main(void)\n"
618 "{\n"
619 "       gl_FrontColor = gl_Color;\n"
620 "       // copy the surface texcoord\n"
621 "       TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
622 "#ifndef MODE_LIGHTSOURCE\n"
623 "# ifndef MODE_LIGHTDIRECTION\n"
624 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
625 "# endif\n"
626 "#endif\n"
627 "\n"
628 "#ifdef MODE_LIGHTSOURCE\n"
629 "       // transform vertex position into light attenuation/cubemap space\n"
630 "       // (-1 to +1 across the light box)\n"
631 "       CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
632 "\n"
633 "       // transform unnormalized light direction into tangent space\n"
634 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
635 "       //  normalize it per pixel)\n"
636 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
637 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
638 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
639 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
640 "#endif\n"
641 "\n"
642 "#ifdef MODE_LIGHTDIRECTION\n"
643 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
644 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
645 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
646 "#endif\n"
647 "\n"
648 "       // transform unnormalized eye direction into tangent space\n"
649 "#ifndef USEFOG\n"
650 "       vec3 EyeVectorModelSpace;\n"
651 "#endif\n"
652 "       EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
653 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
654 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
655 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
656 "\n"
657 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
658 "       VectorS = gl_MultiTexCoord1.xyz;\n"
659 "       VectorT = gl_MultiTexCoord2.xyz;\n"
660 "       VectorR = gl_MultiTexCoord3.xyz;\n"
661 "#endif\n"
662 "\n"
663 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
664 "//     ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
665 "//     //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
666 "//     //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
667 "//#endif\n"
668 "\n"
669 "// transform vertex to camera space, using ftransform to match non-VS\n"
670 "       // rendering\n"
671 "       gl_Position = ftransform();\n"
672 "\n"
673 "#ifdef MODE_WATER\n"
674 "       ModelViewProjectionPosition = gl_Position;\n"
675 "#endif\n"
676 "#ifdef MODE_REFRACTION\n"
677 "       ModelViewProjectionPosition = gl_Position;\n"
678 "#endif\n"
679 "#ifdef USEREFLECTION\n"
680 "       ModelViewProjectionPosition = gl_Position;\n"
681 "#endif\n"
682 "}\n"
683 "\n"
684 "#endif // VERTEX_SHADER\n"
685 "\n"
686 "\n"
687 "\n"
688 "\n"
689 "// fragment shader specific:\n"
690 "#ifdef FRAGMENT_SHADER\n"
691 "\n"
692 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
693 "uniform sampler2D Texture_Normal;\n"
694 "uniform sampler2D Texture_Color;\n"
695 "uniform sampler2D Texture_Gloss;\n"
696 "uniform sampler2D Texture_Glow;\n"
697 "uniform sampler2D Texture_SecondaryNormal;\n"
698 "uniform sampler2D Texture_SecondaryColor;\n"
699 "uniform sampler2D Texture_SecondaryGloss;\n"
700 "uniform sampler2D Texture_SecondaryGlow;\n"
701 "uniform sampler2D Texture_Pants;\n"
702 "uniform sampler2D Texture_Shirt;\n"
703 "uniform sampler2D Texture_FogMask;\n"
704 "uniform sampler2D Texture_Lightmap;\n"
705 "uniform sampler2D Texture_Deluxemap;\n"
706 "uniform sampler2D Texture_Refraction;\n"
707 "uniform sampler2D Texture_Reflection;\n"
708 "uniform sampler2D Texture_Attenuation;\n"
709 "uniform samplerCube Texture_Cube;\n"
710 "\n"
711 "uniform myhalf3 LightColor;\n"
712 "uniform myhalf3 AmbientColor;\n"
713 "uniform myhalf3 DiffuseColor;\n"
714 "uniform myhalf3 SpecularColor;\n"
715 "uniform myhalf3 Color_Pants;\n"
716 "uniform myhalf3 Color_Shirt;\n"
717 "uniform myhalf3 FogColor;\n"
718 "\n"
719 "uniform myhalf4 TintColor;\n"
720 "\n"
721 "\n"
722 "//#ifdef MODE_WATER\n"
723 "uniform vec4 DistortScaleRefractReflect;\n"
724 "uniform vec4 ScreenScaleRefractReflect;\n"
725 "uniform vec4 ScreenCenterRefractReflect;\n"
726 "uniform myhalf4 RefractColor;\n"
727 "uniform myhalf4 ReflectColor;\n"
728 "uniform myhalf ReflectFactor;\n"
729 "uniform myhalf ReflectOffset;\n"
730 "//#else\n"
731 "//# ifdef MODE_REFRACTION\n"
732 "//uniform vec4 DistortScaleRefractReflect;\n"
733 "//uniform vec4 ScreenScaleRefractReflect;\n"
734 "//uniform vec4 ScreenCenterRefractReflect;\n"
735 "//uniform myhalf4 RefractColor;\n"
736 "//#  ifdef USEREFLECTION\n"
737 "//uniform myhalf4 ReflectColor;\n"
738 "//#  endif\n"
739 "//# else\n"
740 "//#  ifdef USEREFLECTION\n"
741 "//uniform vec4 DistortScaleRefractReflect;\n"
742 "//uniform vec4 ScreenScaleRefractReflect;\n"
743 "//uniform vec4 ScreenCenterRefractReflect;\n"
744 "//uniform myhalf4 ReflectColor;\n"
745 "//#  endif\n"
746 "//# endif\n"
747 "//#endif\n"
748 "\n"
749 "uniform myhalf GlowScale;\n"
750 "uniform myhalf SceneBrightness;\n"
751 "#ifdef USECONTRASTBOOST\n"
752 "uniform myhalf ContrastBoostCoeff;\n"
753 "#endif\n"
754 "\n"
755 "uniform float OffsetMapping_Scale;\n"
756 "uniform float OffsetMapping_Bias;\n"
757 "uniform float FogRangeRecip;\n"
758 "\n"
759 "uniform myhalf AmbientScale;\n"
760 "uniform myhalf DiffuseScale;\n"
761 "uniform myhalf SpecularScale;\n"
762 "uniform myhalf SpecularPower;\n"
763 "\n"
764 "#ifdef USEOFFSETMAPPING\n"
765 "vec2 OffsetMapping(vec2 TexCoord)\n"
766 "{\n"
767 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
768 "       // 14 sample relief mapping: linear search and then binary search\n"
769 "       // this basically steps forward a small amount repeatedly until it finds\n"
770 "       // itself inside solid, then jitters forward and back using decreasing\n"
771 "       // amounts to find the impact\n"
772 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
773 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
774 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
775 "       vec3 RT = vec3(TexCoord, 1);\n"
776 "       OffsetVector *= 0.1;\n"
777 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
778 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
779 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
780 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
781 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
782 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
783 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
784 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
785 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
786 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
787 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
788 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
789 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
790 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
791 "       return RT.xy;\n"
792 "#else\n"
793 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
794 "       // this basically moves forward the full distance, and then backs up based\n"
795 "       // on height of samples\n"
796 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
797 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
798 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
799 "       TexCoord += OffsetVector;\n"
800 "       OffsetVector *= 0.333;\n"
801 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
802 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
803 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
804 "       return TexCoord;\n"
805 "#endif\n"
806 "}\n"
807 "#endif // USEOFFSETMAPPING\n"
808 "\n"
809 "#ifdef MODE_WATER\n"
810 "\n"
811 "// water pass\n"
812 "void main(void)\n"
813 "{\n"
814 "#ifdef USEOFFSETMAPPING\n"
815 "       // apply offsetmapping\n"
816 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
817 "#define TexCoord TexCoordOffset\n"
818 "#endif\n"
819 "\n"
820 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
821 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
822 "       vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
823 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
824 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
825 "}\n"
826 "\n"
827 "#else // !MODE_WATER\n"
828 "#ifdef MODE_REFRACTION\n"
829 "\n"
830 "// refraction pass\n"
831 "void main(void)\n"
832 "{\n"
833 "#ifdef USEOFFSETMAPPING\n"
834 "       // apply offsetmapping\n"
835 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
836 "#define TexCoord TexCoordOffset\n"
837 "#endif\n"
838 "\n"
839 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
840 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
841 "       vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
842 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
843 "}\n"
844 "\n"
845 "#else // !MODE_REFRACTION\n"
846 "void main(void)\n"
847 "{\n"
848 "#ifdef USEOFFSETMAPPING\n"
849 "       // apply offsetmapping\n"
850 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
851 "#define TexCoord TexCoordOffset\n"
852 "#endif\n"
853 "\n"
854 "       // combine the diffuse textures (base, pants, shirt)\n"
855 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
856 "#ifdef USECOLORMAPPING\n"
857 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
858 "#endif\n"
859 "#ifdef USEVERTEXTEXTUREBLEND\n"
860 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
861 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
862 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
863 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord)), color.rgb, terrainblend);\n"
864 "       color.a = 1.0;\n"
865 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
866 "#endif\n"
867 "\n"
868 "#ifdef USEDIFFUSE\n"
869 "       // get the surface normal and the gloss color\n"
870 "# ifdef USEVERTEXTEXTUREBLEND\n"
871 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
872 "#  ifdef USESPECULAR\n"
873 "       myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
874 "#  endif\n"
875 "# else\n"
876 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
877 "#  ifdef USESPECULAR\n"
878 "       myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
879 "#  endif\n"
880 "# endif\n"
881 "#endif\n"
882 "\n"
883 "\n"
884 "\n"
885 "#ifdef MODE_LIGHTSOURCE\n"
886 "       // light source\n"
887 "\n"
888 "       // calculate surface normal, light normal, and specular normal\n"
889 "       // compute color intensity for the two textures (colormap and glossmap)\n"
890 "       // scale by light color and attenuation as efficiently as possible\n"
891 "       // (do as much scalar math as possible rather than vector math)\n"
892 "# ifdef USEDIFFUSE\n"
893 "       // get the light normal\n"
894 "       myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
895 "# endif\n"
896 "# ifdef USESPECULAR\n"
897 "#  ifndef USEEXACTSPECULARMATH\n"
898 "       myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
899 "\n"
900 "#  endif\n"
901 "       // calculate directional shading\n"
902 "#  ifdef USEEXACTSPECULARMATH\n"
903 "       color.rgb = 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(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower)) * glosscolor);\n"
904 "#  else\n"
905 "       color.rgb = 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)) * glosscolor);\n"
906 "#  endif\n"
907 "# else\n"
908 "#  ifdef USEDIFFUSE\n"
909 "       // calculate directional shading\n"
910 "       color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
911 "#  else\n"
912 "       // calculate directionless shading\n"
913 "       color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
914 "#  endif\n"
915 "# endif\n"
916 "\n"
917 "# ifdef USECUBEFILTER\n"
918 "       // apply light cubemap filter\n"
919 "       //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
920 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
921 "# endif\n"
922 "#endif // MODE_LIGHTSOURCE\n"
923 "\n"
924 "\n"
925 "\n"
926 "\n"
927 "#ifdef MODE_LIGHTDIRECTION\n"
928 "       // directional model lighting\n"
929 "# ifdef USEDIFFUSE\n"
930 "       // get the light normal\n"
931 "       myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
932 "# endif\n"
933 "# ifdef USESPECULAR\n"
934 "       // calculate directional shading\n"
935 "       color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
936 "#  ifdef USEEXACTSPECULARMATH\n"
937 "       color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
938 "#  else\n"
939 "       myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
940 "       color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
941 "#  endif\n"
942 "# else\n"
943 "#  ifdef USEDIFFUSE\n"
944 "\n"
945 "       // calculate directional shading\n"
946 "       color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
947 "#  else\n"
948 "       color.rgb *= AmbientColor;\n"
949 "#  endif\n"
950 "# endif\n"
951 "#endif // MODE_LIGHTDIRECTION\n"
952 "\n"
953 "\n"
954 "\n"
955 "\n"
956 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
957 "       // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
958 "\n"
959 "       // get the light normal\n"
960 "       myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
961 "       myhalf3 diffusenormal;\n"
962 "       diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
963 "       diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
964 "       diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
965 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
966 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
967 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
968 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
969 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
970 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
971 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
972 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
973 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
974 "       myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
975 "               // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
976 "# ifdef USESPECULAR\n"
977 "#  ifdef USEEXACTSPECULARMATH\n"
978 "       tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
979 "#  else\n"
980 "       myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
981 "       tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
982 "#  endif\n"
983 "# endif\n"
984 "\n"
985 "       // apply lightmap color\n"
986 "       color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
987 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
988 "\n"
989 "\n"
990 "\n"
991 "\n"
992 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
993 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
994 "\n"
995 "       // get the light normal\n"
996 "       myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
997 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
998 "       myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
999 "# ifdef USESPECULAR\n"
1000 "#  ifdef USEEXACTSPECULARMATH\n"
1001 "       tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1002 "#  else\n"
1003 "       myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1004 "       tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1005 "#  endif\n"
1006 "# endif\n"
1007 "\n"
1008 "       // apply lightmap color\n"
1009 "       color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1010 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1011 "\n"
1012 "\n"
1013 "\n"
1014 "\n"
1015 "#ifdef MODE_LIGHTMAP\n"
1016 "       // apply lightmap color\n"
1017 "       color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1018 "#endif // MODE_LIGHTMAP\n"
1019 "\n"
1020 "\n"
1021 "\n"
1022 "\n"
1023 "#ifdef MODE_VERTEXCOLOR\n"
1024 "       // apply lightmap color\n"
1025 "       color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1026 "#endif // MODE_VERTEXCOLOR\n"
1027 "\n"
1028 "\n"
1029 "\n"
1030 "\n"
1031 "#ifdef MODE_FLATCOLOR\n"
1032 "#endif // MODE_FLATCOLOR\n"
1033 "\n"
1034 "\n"
1035 "\n"
1036 "\n"
1037 "\n"
1038 "\n"
1039 "\n"
1040 "       color *= TintColor;\n"
1041 "\n"
1042 "#ifdef USEGLOW\n"
1043 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
1044 "#endif\n"
1045 "\n"
1046 "#ifdef USECONTRASTBOOST\n"
1047 "       color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n"
1048 "#endif\n"
1049 "\n"
1050 "       color.rgb *= SceneBrightness;\n"
1051 "\n"
1052 "       // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1053 "#ifdef USEFOG\n"
1054 "       color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1055 "#endif\n"
1056 "\n"
1057 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1058 "#ifdef USEREFLECTION\n"
1059 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1060 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1061 "       vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1062 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
1063 "#endif\n"
1064 "\n"
1065 "       gl_FragColor = vec4(color);\n"
1066 "}\n"
1067 "#endif // !MODE_REFRACTION\n"
1068 "#endif // !MODE_WATER\n"
1069 "\n"
1070 "#endif // FRAGMENT_SHADER\n"
1071 "\n"
1072 "#endif // !MODE_GENERIC\n"
1073 "#endif // !MODE_POSTPROCESS\n"
1074 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1075 ;
1076
1077 typedef struct shaderpermutationinfo_s
1078 {
1079         const char *pretext;
1080         const char *name;
1081 }
1082 shaderpermutationinfo_t;
1083
1084 typedef struct shadermodeinfo_s
1085 {
1086         const char *vertexfilename;
1087         const char *geometryfilename;
1088         const char *fragmentfilename;
1089         const char *pretext;
1090         const char *name;
1091 }
1092 shadermodeinfo_t;
1093
1094 typedef enum shaderpermutation_e
1095 {
1096         SHADERPERMUTATION_DIFFUSE = 1<<0, // (lightsource) whether to use directional shading
1097         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, // indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1098         SHADERPERMUTATION_COLORMAPPING = 1<<2, // indicates this is a colormapped skin
1099         SHADERPERMUTATION_CONTRASTBOOST = 1<<3, // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
1100         SHADERPERMUTATION_FOG = 1<<4, // tint the color by fog color or black if using additive blend mode
1101         SHADERPERMUTATION_CUBEFILTER = 1<<5, // (lightsource) use cubemap light filter
1102         SHADERPERMUTATION_GLOW = 1<<6, // (lightmap) blend in an additive glow texture
1103         SHADERPERMUTATION_SPECULAR = 1<<7, // (lightsource or deluxemapping) render specular effects
1104         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<8, // (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1105         SHADERPERMUTATION_REFLECTION = 1<<9, // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1106         SHADERPERMUTATION_OFFSETMAPPING = 1<<10, // adjust texcoords to roughly simulate a displacement mapped surface
1107         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<11, // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1108         SHADERPERMUTATION_GAMMARAMPS = 1<<12, // gamma (postprocessing only)
1109         SHADERPERMUTATION_POSTPROCESSING = 1<<13, // user defined postprocessing
1110         SHADERPERMUTATION_LIMIT = 1<<14, // size of permutations array
1111         SHADERPERMUTATION_COUNT = 14 // size of shaderpermutationinfo array
1112 }
1113 shaderpermutation_t;
1114
1115 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1116 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1117 {
1118         {"#define USEDIFFUSE\n", " diffuse"},
1119         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1120         {"#define USECOLORMAPPING\n", " colormapping"},
1121         {"#define USECONTRASTBOOST\n", " contrastboost"},
1122         {"#define USEFOG\n", " fog"},
1123         {"#define USECUBEFILTER\n", " cubefilter"},
1124         {"#define USEGLOW\n", " glow"},
1125         {"#define USESPECULAR\n", " specular"},
1126         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1127         {"#define USEREFLECTION\n", " reflection"},
1128         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1129         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1130         {"#define USEGAMMARAMPS\n", " gammaramps"},
1131         {"#define USEPOSTPROCESSING\n", " postprocessing"},
1132 };
1133
1134 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
1135 typedef enum shadermode_e
1136 {
1137         SHADERMODE_GENERIC, // (particles/HUD/etc) vertex color, optionally multiplied by one texture
1138         SHADERMODE_POSTPROCESS, // postprocessing shader (r_glsl_postprocess)
1139         SHADERMODE_DEPTH_OR_SHADOW, // (depthfirst/shadows) vertex shader only
1140         SHADERMODE_FLATCOLOR, // (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1141         SHADERMODE_VERTEXCOLOR, // (lightmap) modulate texture by vertex colors (q3bsp)
1142         SHADERMODE_LIGHTMAP, // (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1143         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1144         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1145         SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1146         SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
1147         SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
1148         SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
1149         SHADERMODE_COUNT
1150 }
1151 shadermode_t;
1152
1153 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1154 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1155 {
1156         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1157         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1158         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1159         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1160         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1161         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1162         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1163         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1164         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1165         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1166         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1167         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1168 };
1169
1170 typedef struct r_glsl_permutation_s
1171 {
1172         // indicates if we have tried compiling this permutation already
1173         qboolean compiled;
1174         // 0 if compilation failed
1175         int program;
1176         // locations of detected uniforms in program object, or -1 if not found
1177         int loc_Texture_First;
1178         int loc_Texture_Second;
1179         int loc_Texture_GammaRamps;
1180         int loc_Texture_Normal;
1181         int loc_Texture_Color;
1182         int loc_Texture_Gloss;
1183         int loc_Texture_Glow;
1184         int loc_Texture_SecondaryNormal;
1185         int loc_Texture_SecondaryColor;
1186         int loc_Texture_SecondaryGloss;
1187         int loc_Texture_SecondaryGlow;
1188         int loc_Texture_Pants;
1189         int loc_Texture_Shirt;
1190         int loc_Texture_FogMask;
1191         int loc_Texture_Lightmap;
1192         int loc_Texture_Deluxemap;
1193         int loc_Texture_Attenuation;
1194         int loc_Texture_Cube;
1195         int loc_Texture_Refraction;
1196         int loc_Texture_Reflection;
1197         int loc_FogColor;
1198         int loc_LightPosition;
1199         int loc_EyePosition;
1200         int loc_Color_Pants;
1201         int loc_Color_Shirt;
1202         int loc_FogRangeRecip;
1203         int loc_AmbientScale;
1204         int loc_DiffuseScale;
1205         int loc_SpecularScale;
1206         int loc_SpecularPower;
1207         int loc_GlowScale;
1208         int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1209         int loc_OffsetMapping_Scale;
1210         int loc_TintColor;
1211         int loc_AmbientColor;
1212         int loc_DiffuseColor;
1213         int loc_SpecularColor;
1214         int loc_LightDir;
1215         int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
1216         int loc_GammaCoeff; // 1 / gamma
1217         int loc_DistortScaleRefractReflect;
1218         int loc_ScreenScaleRefractReflect;
1219         int loc_ScreenCenterRefractReflect;
1220         int loc_RefractColor;
1221         int loc_ReflectColor;
1222         int loc_ReflectFactor;
1223         int loc_ReflectOffset;
1224         int loc_UserVec1;
1225         int loc_UserVec2;
1226         int loc_UserVec3;
1227         int loc_UserVec4;
1228         int loc_ClientTime;
1229         int loc_PixelSize;
1230 }
1231 r_glsl_permutation_t;
1232
1233 // information about each possible shader permutation
1234 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1235 // currently selected permutation
1236 r_glsl_permutation_t *r_glsl_permutation;
1237
1238 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1239 {
1240         char *shaderstring;
1241         if (!filename || !filename[0])
1242                 return NULL;
1243         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1244         if (shaderstring)
1245         {
1246                 if (printfromdisknotice)
1247                         Con_DPrint("from disk... ");
1248                 return shaderstring;
1249         }
1250         else if (!strcmp(filename, "glsl/default.glsl"))
1251         {
1252                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1253                 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1254         }
1255         return shaderstring;
1256 }
1257
1258 static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutation)
1259 {
1260         int i;
1261         shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1262         r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1263         int vertstrings_count = 0;
1264         int geomstrings_count = 0;
1265         int fragstrings_count = 0;
1266         char *vertexstring, *geometrystring, *fragmentstring;
1267         const char *vertstrings_list[32+3];
1268         const char *geomstrings_list[32+3];
1269         const char *fragstrings_list[32+3];
1270         char permutationname[256];
1271
1272         if (p->compiled)
1273                 return;
1274         p->compiled = true;
1275         p->program = 0;
1276
1277         permutationname[0] = 0;
1278         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1279         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1280         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1281
1282         strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1283
1284         // the first pretext is which type of shader to compile as
1285         // (later these will all be bound together as a program object)
1286         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1287         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1288         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1289
1290         // the second pretext is the mode (for example a light source)
1291         vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1292         geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1293         fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1294         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1295
1296         // now add all the permutation pretexts
1297         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1298         {
1299                 if (permutation & (1<<i))
1300                 {
1301                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1302                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1303                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1304                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1305                 }
1306                 else
1307                 {
1308                         // keep line numbers correct
1309                         vertstrings_list[vertstrings_count++] = "\n";
1310                         geomstrings_list[geomstrings_count++] = "\n";
1311                         fragstrings_list[fragstrings_count++] = "\n";
1312                 }
1313         }
1314
1315         // now append the shader text itself
1316         vertstrings_list[vertstrings_count++] = vertexstring;
1317         geomstrings_list[geomstrings_count++] = geometrystring;
1318         fragstrings_list[fragstrings_count++] = fragmentstring;
1319
1320         // if any sources were NULL, clear the respective list
1321         if (!vertexstring)
1322                 vertstrings_count = 0;
1323         if (!geometrystring)
1324                 geomstrings_count = 0;
1325         if (!fragmentstring)
1326                 fragstrings_count = 0;
1327
1328         // compile the shader program
1329         if (vertstrings_count + geomstrings_count + fragstrings_count)
1330                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1331         if (p->program)
1332         {
1333                 CHECKGLERROR
1334                 qglUseProgramObjectARB(p->program);CHECKGLERROR
1335                 // look up all the uniform variable names we care about, so we don't
1336                 // have to look them up every time we set them
1337                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
1338                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
1339                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1340                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
1341                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
1342                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1343                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
1344                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1345                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1346                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1347                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1348                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1349                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
1350                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1351                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1352                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1353                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1354                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1355                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1356                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
1357                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
1358                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
1359                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
1360                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
1361                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
1362                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1363                 p->loc_AmbientScale               = qglGetUniformLocationARB(p->program, "AmbientScale");
1364                 p->loc_DiffuseScale               = qglGetUniformLocationARB(p->program, "DiffuseScale");
1365                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
1366                 p->loc_SpecularScale              = qglGetUniformLocationARB(p->program, "SpecularScale");
1367                 p->loc_GlowScale                  = qglGetUniformLocationARB(p->program, "GlowScale");
1368                 p->loc_SceneBrightness            = qglGetUniformLocationARB(p->program, "SceneBrightness");
1369                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1370                 p->loc_TintColor                  = qglGetUniformLocationARB(p->program, "TintColor");
1371                 p->loc_AmbientColor               = qglGetUniformLocationARB(p->program, "AmbientColor");
1372                 p->loc_DiffuseColor               = qglGetUniformLocationARB(p->program, "DiffuseColor");
1373                 p->loc_SpecularColor              = qglGetUniformLocationARB(p->program, "SpecularColor");
1374                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
1375                 p->loc_ContrastBoostCoeff         = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1376                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1377                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1378                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1379                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
1380                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
1381                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
1382                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
1383                 p->loc_GammaCoeff                 = qglGetUniformLocationARB(p->program, "GammaCoeff");
1384                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
1385                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
1386                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
1387                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
1388                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
1389                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
1390                 // initialize the samplers to refer to the texture units we use
1391                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
1392                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
1393                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
1394                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
1395                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
1396                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
1397                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
1398                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1399                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1400                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1401                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
1402                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
1403                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
1404                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
1405                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
1406                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
1407                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
1408                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
1409                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
1410                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
1411                 CHECKGLERROR
1412                 if (developer.integer)
1413                         Con_Printf("GLSL shader %s compiled.\n", permutationname);
1414         }
1415         else
1416                 Con_Printf("GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1417
1418         // free the strings
1419         if (vertexstring)
1420                 Mem_Free(vertexstring);
1421         if (geometrystring)
1422                 Mem_Free(geometrystring);
1423         if (fragmentstring)
1424                 Mem_Free(fragmentstring);
1425 }
1426
1427 void R_GLSL_Restart_f(void)
1428 {
1429         unsigned int mode;
1430         unsigned int permutation;
1431         for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1432                 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1433                         if (r_glsl_permutations[mode][permutation].program)
1434                                 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1435         memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1436 }
1437
1438 void R_GLSL_DumpShader_f(void)
1439 {
1440         int i;
1441
1442         qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1443         if(!file)
1444         {
1445                 Con_Printf("failed to write to glsl/default.glsl\n");
1446                 return;
1447         }
1448
1449         FS_Print(file, "// The engine may define the following macros:\n");
1450         FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1451         for (i = 0;i < SHADERMODE_COUNT;i++)
1452                 FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
1453         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1454                 FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
1455         FS_Print(file, "\n");
1456         FS_Print(file, builtinshaderstring);
1457         FS_Close(file);
1458
1459         Con_Printf("glsl/default.glsl written\n");
1460 }
1461
1462 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1463 {
1464         r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1465         if (r_glsl_permutation != perm)
1466         {
1467                 r_glsl_permutation = perm;
1468                 if (!r_glsl_permutation->program)
1469                 {
1470                         if (!r_glsl_permutation->compiled)
1471                                 R_GLSL_CompilePermutation(mode, permutation);
1472                         if (!r_glsl_permutation->program)
1473                         {
1474                                 // remove features until we find a valid permutation
1475                                 int i;
1476                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1477                                 {
1478                                         // reduce i more quickly whenever it would not remove any bits
1479                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1480                                         if (!(permutation & j))
1481                                                 continue;
1482                                         permutation -= j;
1483                                         r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1484                                         if (!r_glsl_permutation->compiled)
1485                                                 R_GLSL_CompilePermutation(mode, permutation);
1486                                         if (r_glsl_permutation->program)
1487                                                 break;
1488                                 }
1489                                 if (i >= SHADERPERMUTATION_COUNT)
1490                                 {
1491                                         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");
1492                                         Cvar_SetValueQuick(&r_glsl, 0);
1493                                         R_GLSL_Restart_f(); // unload shaders
1494                                         return; // no bit left to clear
1495                                 }
1496                         }
1497                 }
1498                 CHECKGLERROR
1499                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1500         }
1501 }
1502
1503 void R_SetupGenericShader(qboolean usetexture)
1504 {
1505         if (gl_support_fragment_shader)
1506         {
1507                 if (r_glsl.integer && r_glsl_usegeneric.integer)
1508                         R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1509                 else if (r_glsl_permutation)
1510                 {
1511                         r_glsl_permutation = NULL;
1512                         qglUseProgramObjectARB(0);CHECKGLERROR
1513                 }
1514         }
1515 }
1516
1517 void R_SetupGenericTwoTextureShader(int texturemode)
1518 {
1519         if (gl_support_fragment_shader)
1520         {
1521                 if (r_glsl.integer && r_glsl_usegeneric.integer)
1522                         R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1523                 else if (r_glsl_permutation)
1524                 {
1525                         r_glsl_permutation = NULL;
1526                         qglUseProgramObjectARB(0);CHECKGLERROR
1527                 }
1528         }
1529         if (!r_glsl_permutation)
1530         {
1531                 if (texturemode == GL_DECAL && gl_combine.integer)
1532                         texturemode = GL_INTERPOLATE_ARB;
1533                 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1534         }
1535 }
1536
1537 void R_SetupDepthOrShadowShader(void)
1538 {
1539         if (gl_support_fragment_shader)
1540         {
1541                 if (r_glsl.integer && r_glsl_usegeneric.integer)
1542                         R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1543                 else if (r_glsl_permutation)
1544                 {
1545                         r_glsl_permutation = NULL;
1546                         qglUseProgramObjectARB(0);CHECKGLERROR
1547                 }
1548         }
1549 }
1550
1551 extern rtexture_t *r_shadow_attenuationgradienttexture;
1552 extern rtexture_t *r_shadow_attenuation2dtexture;
1553 extern rtexture_t *r_shadow_attenuation3dtexture;
1554 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1555 {
1556         // select a permutation of the lighting shader appropriate to this
1557         // combination of texture, entity, light source, and fogging, only use the
1558         // minimum features necessary to avoid wasting rendering time in the
1559         // fragment shader on features that are not being used
1560         unsigned int permutation = 0;
1561         unsigned int mode = 0;
1562         // TODO: implement geometry-shader based shadow volumes someday
1563         if (r_glsl_offsetmapping.integer)
1564         {
1565                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1566                 if (r_glsl_offsetmapping_reliefmapping.integer)
1567                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1568         }
1569         if (rsurfacepass == RSURFPASS_BACKGROUND)
1570         {
1571                 // distorted background
1572                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1573                         mode = SHADERMODE_WATER;
1574                 else
1575                         mode = SHADERMODE_REFRACTION;
1576         }
1577         else if (rsurfacepass == RSURFPASS_RTLIGHT)
1578         {
1579                 // light source
1580                 mode = SHADERMODE_LIGHTSOURCE;
1581                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1582                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1583                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1584                         permutation |= SHADERPERMUTATION_CUBEFILTER;
1585                 if (diffusescale > 0)
1586                         permutation |= SHADERPERMUTATION_DIFFUSE;
1587                 if (specularscale > 0)
1588                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1589                 if (r_refdef.fogenabled)
1590                         permutation |= SHADERPERMUTATION_FOG;
1591                 if (rsurface.texture->colormapping)
1592                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1593                 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1594                         permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1595         }
1596         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1597         {
1598                 // unshaded geometry (fullbright or ambient model lighting)
1599                 mode = SHADERMODE_FLATCOLOR;
1600                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1601                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1602                 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1603                         permutation |= SHADERPERMUTATION_GLOW;
1604                 if (r_refdef.fogenabled)
1605                         permutation |= SHADERPERMUTATION_FOG;
1606                 if (rsurface.texture->colormapping)
1607                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1608                 if (r_glsl_offsetmapping.integer)
1609                 {
1610                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1611                         if (r_glsl_offsetmapping_reliefmapping.integer)
1612                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1613                 }
1614                 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1615                         permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1616                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1617                         permutation |= SHADERPERMUTATION_REFLECTION;
1618         }
1619         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1620         {
1621                 // directional model lighting
1622                 mode = SHADERMODE_LIGHTDIRECTION;
1623                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1624                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1625                 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1626                         permutation |= SHADERPERMUTATION_GLOW;
1627                 permutation |= SHADERPERMUTATION_DIFFUSE;
1628                 if (specularscale > 0)
1629                         permutation |= SHADERPERMUTATION_SPECULAR;
1630                 if (r_refdef.fogenabled)
1631                         permutation |= SHADERPERMUTATION_FOG;
1632                 if (rsurface.texture->colormapping)
1633                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1634                 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1635                         permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1636                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1637                         permutation |= SHADERPERMUTATION_REFLECTION;
1638         }
1639         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1640         {
1641                 // ambient model lighting
1642                 mode = SHADERMODE_LIGHTDIRECTION;
1643                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1644                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1645                 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1646                         permutation |= SHADERPERMUTATION_GLOW;
1647                 if (r_refdef.fogenabled)
1648                         permutation |= SHADERPERMUTATION_FOG;
1649                 if (rsurface.texture->colormapping)
1650                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1651                 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1652                         permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1653                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1654                         permutation |= SHADERPERMUTATION_REFLECTION;
1655         }
1656         else
1657         {
1658                 // lightmapped wall
1659                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1660                 {
1661                         // deluxemapping (light direction texture)
1662                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1663                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1664                         else
1665                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1666                         permutation |= SHADERPERMUTATION_DIFFUSE;
1667                         if (specularscale > 0)
1668                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1669                 }
1670                 else if (r_glsl_deluxemapping.integer >= 2)
1671                 {
1672                         // fake deluxemapping (uniform light direction in tangentspace)
1673                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1674                         permutation |= SHADERPERMUTATION_DIFFUSE;
1675                         if (specularscale > 0)
1676                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1677                 }
1678                 else if (rsurface.uselightmaptexture)
1679                 {
1680                         // ordinary lightmapping (q1bsp, q3bsp)
1681                         mode = SHADERMODE_LIGHTMAP;
1682                 }
1683                 else
1684                 {
1685                         // ordinary vertex coloring (q3bsp)
1686                         mode = SHADERMODE_VERTEXCOLOR;
1687                 }
1688                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1689                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1690                 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1691                         permutation |= SHADERPERMUTATION_GLOW;
1692                 if (r_refdef.fogenabled)
1693                         permutation |= SHADERPERMUTATION_FOG;
1694                 if (rsurface.texture->colormapping)
1695                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1696                 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1697                         permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1698                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1699                         permutation |= SHADERPERMUTATION_REFLECTION;
1700         }
1701         if(permutation & SHADERPERMUTATION_SPECULAR)
1702                 if(r_shadow_glossexact.integer)
1703                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
1704         R_SetupShader_SetPermutation(mode, permutation);
1705         if (mode == SHADERMODE_LIGHTSOURCE)
1706         {
1707                 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1708                 if (permutation & SHADERPERMUTATION_DIFFUSE)
1709                 {
1710                         if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
1711                         if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1712                         if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1713                         if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1714                 }
1715                 else
1716                 {
1717                         // ambient only is simpler
1718                         if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale, rsurface.texture->lightmapcolor[3]);
1719                         if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1720                         if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1721                         if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1722                 }
1723                 // additive passes are only darkened by fog, not tinted
1724                 if (r_glsl_permutation->loc_FogColor >= 0)
1725                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1726         }
1727         else
1728         {
1729                 if (mode == SHADERMODE_LIGHTDIRECTION)
1730                 {
1731                         if (r_glsl_permutation->loc_AmbientColor  >= 0) qglUniform3fARB(r_glsl_permutation->loc_AmbientColor , rsurface.modellight_ambient[0] * ambientscale  * 0.5f, rsurface.modellight_ambient[1] * ambientscale  * 0.5f, rsurface.modellight_ambient[2] * ambientscale  * 0.5f);
1732                         if (r_glsl_permutation->loc_DiffuseColor  >= 0) qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor , rsurface.modellight_diffuse[0] * diffusescale  * 0.5f, rsurface.modellight_diffuse[1] * diffusescale  * 0.5f, rsurface.modellight_diffuse[2] * diffusescale  * 0.5f);
1733                         if (r_glsl_permutation->loc_SpecularColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale * 0.5f, rsurface.modellight_diffuse[1] * specularscale * 0.5f, rsurface.modellight_diffuse[2] * specularscale * 0.5f);
1734                         if (r_glsl_permutation->loc_LightDir      >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1735                 }
1736                 else
1737                 {
1738                         if (r_glsl_permutation->loc_AmbientScale  >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
1739                         if (r_glsl_permutation->loc_DiffuseScale  >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1740                         if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1741                 }
1742                 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2], rsurface.texture->lightmapcolor[3]);
1743                 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1744                 // additive passes are only darkened by fog, not tinted
1745                 if (r_glsl_permutation->loc_FogColor >= 0)
1746                 {
1747                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
1748                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1749                         else
1750                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1751                 }
1752                 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
1753                 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
1754                 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
1755                 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1756                 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1757                 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1758                 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1759         }
1760         if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1761         {
1762                 // The formula used is actually:
1763                 //   color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1764                 //   color.rgb *= SceneBrightness;
1765                 // simplified:
1766                 //   color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1767                 // and do [[calculations]] here in the engine
1768                 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1769                 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
1770         }
1771         else
1772                 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
1773         if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1774         if (r_glsl_permutation->loc_Color_Pants >= 0)
1775         {
1776                 if (rsurface.texture->currentskinframe->pants)
1777                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1778                 else
1779                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1780         }
1781         if (r_glsl_permutation->loc_Color_Shirt >= 0)
1782         {
1783                 if (rsurface.texture->currentskinframe->shirt)
1784                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1785                 else
1786                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1787         }
1788         if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
1789         if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
1790         {
1791                 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
1792         }
1793         else
1794         {
1795                 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1796         }
1797         if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1798         CHECKGLERROR
1799 }
1800
1801 #define SKINFRAME_HASH 1024
1802
1803 typedef struct
1804 {
1805         int loadsequence; // incremented each level change
1806         memexpandablearray_t array;
1807         skinframe_t *hash[SKINFRAME_HASH];
1808 }
1809 r_skinframe_t;
1810 r_skinframe_t r_skinframe;
1811
1812 void R_SkinFrame_PrepareForPurge(void)
1813 {
1814         r_skinframe.loadsequence++;
1815         // wrap it without hitting zero
1816         if (r_skinframe.loadsequence >= 200)
1817                 r_skinframe.loadsequence = 1;
1818 }
1819
1820 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1821 {
1822         if (!skinframe)
1823                 return;
1824         // mark the skinframe as used for the purging code
1825         skinframe->loadsequence = r_skinframe.loadsequence;
1826 }
1827
1828 void R_SkinFrame_Purge(void)
1829 {
1830         int i;
1831         skinframe_t *s;
1832         for (i = 0;i < SKINFRAME_HASH;i++)
1833         {
1834                 for (s = r_skinframe.hash[i];s;s = s->next)
1835                 {
1836                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1837                         {
1838                                 if (s->merged == s->base)
1839                                         s->merged = NULL;
1840                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1841                                 R_PurgeTexture(s->stain );s->stain  = NULL;
1842                                 R_PurgeTexture(s->merged);s->merged = NULL;
1843                                 R_PurgeTexture(s->base  );s->base   = NULL;
1844                                 R_PurgeTexture(s->pants );s->pants  = NULL;
1845                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
1846                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
1847                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
1848                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
1849                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
1850                                 s->loadsequence = 0;
1851                         }
1852                 }
1853         }
1854 }
1855
1856 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1857         skinframe_t *item;
1858         char basename[MAX_QPATH];
1859
1860         Image_StripImageExtension(name, basename, sizeof(basename));
1861
1862         if( last == NULL ) {
1863                 int hashindex;
1864                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1865                 item = r_skinframe.hash[hashindex];
1866         } else {
1867                 item = last->next;
1868         }
1869
1870         // linearly search through the hash bucket
1871         for( ; item ; item = item->next ) {
1872                 if( !strcmp( item->basename, basename ) ) {
1873                         return item;
1874                 }
1875         }
1876         return NULL;
1877 }
1878
1879 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1880 {
1881         skinframe_t *item;
1882         int hashindex;
1883         char basename[MAX_QPATH];
1884
1885         Image_StripImageExtension(name, basename, sizeof(basename));
1886
1887         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1888         for (item = r_skinframe.hash[hashindex];item;item = item->next)
1889                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1890                         break;
1891
1892         if (!item) {
1893                 rtexture_t *dyntexture;
1894                 // check whether its a dynamic texture
1895                 dyntexture = CL_GetDynTexture( basename );
1896                 if (!add && !dyntexture)
1897                         return NULL;
1898                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1899                 memset(item, 0, sizeof(*item));
1900                 strlcpy(item->basename, basename, sizeof(item->basename));
1901                 item->base = dyntexture; // either NULL or dyntexture handle
1902                 item->textureflags = textureflags;
1903                 item->comparewidth = comparewidth;
1904                 item->compareheight = compareheight;
1905                 item->comparecrc = comparecrc;
1906                 item->next = r_skinframe.hash[hashindex];
1907                 r_skinframe.hash[hashindex] = item;
1908         }
1909         else if( item->base == NULL )
1910         {
1911                 rtexture_t *dyntexture;
1912                 // check whether its a dynamic texture
1913                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
1914                 dyntexture = CL_GetDynTexture( basename );
1915                 item->base = dyntexture; // either NULL or dyntexture handle
1916         }
1917
1918         R_SkinFrame_MarkUsed(item);
1919         return item;
1920 }
1921
1922 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
1923         { \
1924                 unsigned long long avgcolor[5], wsum; \
1925                 int pix, comp, w; \
1926                 avgcolor[0] = 0; \
1927                 avgcolor[1] = 0; \
1928                 avgcolor[2] = 0; \
1929                 avgcolor[3] = 0; \
1930                 avgcolor[4] = 0; \
1931                 wsum = 0; \
1932                 for(pix = 0; pix < cnt; ++pix) \
1933                 { \
1934                         w = 0; \
1935                         for(comp = 0; comp < 3; ++comp) \
1936                                 w += getpixel; \
1937                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
1938                         { \
1939                                 ++wsum; \
1940                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
1941                                 w = getpixel; \
1942                                 for(comp = 0; comp < 3; ++comp) \
1943                                         avgcolor[comp] += getpixel * w; \
1944                                 avgcolor[3] += w; \
1945                         } \
1946                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
1947                         avgcolor[4] += getpixel; \
1948                 } \
1949                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
1950                         avgcolor[3] = 1; \
1951                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
1952                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
1953                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
1954                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
1955         }
1956
1957 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
1958 {
1959         // FIXME: it should be possible to disable loading various layers using
1960         // cvars, to prevent wasted loading time and memory usage if the user does
1961         // not want them
1962         qboolean loadnormalmap = true;
1963         qboolean loadgloss = true;
1964         qboolean loadpantsandshirt = true;
1965         qboolean loadglow = true;
1966         int j;
1967         unsigned char *pixels;
1968         unsigned char *bumppixels;
1969         unsigned char *basepixels = NULL;
1970         int basepixels_width;
1971         int basepixels_height;
1972         skinframe_t *skinframe;
1973
1974         *has_alpha = false;
1975
1976         if (cls.state == ca_dedicated)
1977                 return NULL;
1978
1979         // return an existing skinframe if already loaded
1980         // if loading of the first image fails, don't make a new skinframe as it
1981         // would cause all future lookups of this to be missing
1982         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1983         if (skinframe && skinframe->base)
1984                 return skinframe;
1985
1986         basepixels = loadimagepixelsbgra(name, complain, true);
1987         if (basepixels == NULL)
1988                 return NULL;
1989
1990         if (developer_loading.integer)
1991                 Con_Printf("loading skin \"%s\"\n", name);
1992
1993         // we've got some pixels to store, so really allocate this new texture now
1994         if (!skinframe)
1995                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1996         skinframe->stain = NULL;
1997         skinframe->merged = NULL;
1998         skinframe->base = r_texture_notexture;
1999         skinframe->pants = NULL;
2000         skinframe->shirt = NULL;
2001         skinframe->nmap = r_texture_blanknormalmap;
2002         skinframe->gloss = NULL;
2003         skinframe->glow = NULL;
2004         skinframe->fog = NULL;
2005
2006         basepixels_width = image_width;
2007         basepixels_height = image_height;
2008         skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2009
2010         if (textureflags & TEXF_ALPHA)
2011         {
2012                 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2013                         if (basepixels[j] < 255)
2014                                 break;
2015                 if (j < basepixels_width * basepixels_height * 4)
2016                 {
2017                         // has transparent pixels
2018                         *has_alpha = true;
2019                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2020                         for (j = 0;j < image_width * image_height * 4;j += 4)
2021                         {
2022                                 pixels[j+0] = 255;
2023                                 pixels[j+1] = 255;
2024                                 pixels[j+2] = 255;
2025                                 pixels[j+3] = basepixels[j+3];
2026                         }
2027                         skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2028                         Mem_Free(pixels);
2029                 }
2030         }
2031
2032         R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2033         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2034
2035         // _norm is the name used by tenebrae and has been adopted as standard
2036         if (loadnormalmap)
2037         {
2038                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2039                 {
2040                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2041                         Mem_Free(pixels);
2042                         pixels = NULL;
2043                 }
2044                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2045                 {
2046                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2047                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2048                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2049                         Mem_Free(pixels);
2050                         Mem_Free(bumppixels);
2051                 }
2052                 else if (r_shadow_bumpscale_basetexture.value > 0)
2053                 {
2054                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2055                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2056                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2057                         Mem_Free(pixels);
2058                 }
2059         }
2060         // _luma is supported for tenebrae compatibility
2061         // (I think it's a very stupid name, but oh well)
2062         // _glow is the preferred name
2063         if (loadglow          && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) != NULL || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2064         if (loadgloss         && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2065         if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2066         if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2067
2068         if (basepixels)
2069                 Mem_Free(basepixels);
2070
2071         return skinframe;
2072 }
2073
2074 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2075 {
2076         qboolean has_alpha;
2077         return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha);
2078 }
2079
2080 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)
2081 {
2082         int i;
2083         if (!force)
2084         {
2085                 for (i = 0;i < width*height;i++)
2086                         if (((unsigned char *)&palette[in[i]])[3] > 0)
2087                                 break;
2088                 if (i == width*height)
2089                         return NULL;
2090         }
2091         return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2092 }
2093
2094 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2095 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2096 {
2097         int i;
2098         unsigned char *temp1, *temp2;
2099         skinframe_t *skinframe;
2100
2101         if (cls.state == ca_dedicated)
2102                 return NULL;
2103
2104         // if already loaded just return it, otherwise make a new skinframe
2105         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2106         if (skinframe && skinframe->base)
2107                 return skinframe;
2108
2109         skinframe->stain = NULL;
2110         skinframe->merged = NULL;
2111         skinframe->base = r_texture_notexture;
2112         skinframe->pants = NULL;
2113         skinframe->shirt = NULL;
2114         skinframe->nmap = r_texture_blanknormalmap;
2115         skinframe->gloss = NULL;
2116         skinframe->glow = NULL;
2117         skinframe->fog = NULL;
2118
2119         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2120         if (!skindata)
2121                 return NULL;
2122
2123         if (developer_loading.integer)
2124                 Con_Printf("loading 32bit skin \"%s\"\n", name);
2125
2126         if (r_shadow_bumpscale_basetexture.value > 0)
2127         {
2128                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2129                 temp2 = temp1 + width * height * 4;
2130                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2131                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2132                 Mem_Free(temp1);
2133         }
2134         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2135         if (textureflags & TEXF_ALPHA)
2136         {
2137                 for (i = 3;i < width * height * 4;i += 4)
2138                         if (skindata[i] < 255)
2139                                 break;
2140                 if (i < width * height * 4)
2141                 {
2142                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2143                         memcpy(fogpixels, skindata, width * height * 4);
2144                         for (i = 0;i < width * height * 4;i += 4)
2145                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2146                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2147                         Mem_Free(fogpixels);
2148                 }
2149         }
2150
2151         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2152         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2153
2154         return skinframe;
2155 }
2156
2157 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2158 {
2159         int i;
2160         unsigned char *temp1, *temp2;
2161         unsigned int *palette;
2162         skinframe_t *skinframe;
2163
2164         if (cls.state == ca_dedicated)
2165                 return NULL;
2166
2167         // if already loaded just return it, otherwise make a new skinframe
2168         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2169         if (skinframe && skinframe->base)
2170                 return skinframe;
2171
2172         palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2173
2174         skinframe->stain = NULL;
2175         skinframe->merged = NULL;
2176         skinframe->base = r_texture_notexture;
2177         skinframe->pants = NULL;
2178         skinframe->shirt = NULL;
2179         skinframe->nmap = r_texture_blanknormalmap;
2180         skinframe->gloss = NULL;
2181         skinframe->glow = NULL;
2182         skinframe->fog = NULL;
2183
2184         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2185         if (!skindata)
2186                 return NULL;
2187
2188         if (developer_loading.integer)
2189                 Con_Printf("loading quake skin \"%s\"\n", name);
2190
2191         if (r_shadow_bumpscale_basetexture.value > 0)
2192         {
2193                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2194                 temp2 = temp1 + width * height * 4;
2195                 // use either a custom palette or the quake palette
2196                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2197                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2198                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2199                 Mem_Free(temp1);
2200         }
2201         // use either a custom palette, or the quake palette
2202         skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2203         if (loadglowtexture)
2204                 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2205         if (loadpantsandshirt)
2206         {
2207                 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2208                 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2209         }
2210         if (skinframe->pants || skinframe->shirt)
2211                 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename), loadglowtexture ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap, skinframe->textureflags, false); // no special colors
2212         if (textureflags & TEXF_ALPHA)
2213         {
2214                 for (i = 0;i < width * height;i++)
2215                         if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2216                                 break;
2217                 if (i < width * height)
2218                         skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2219         }
2220
2221         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2222         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2223
2224         return skinframe;
2225 }
2226
2227 skinframe_t *R_SkinFrame_LoadMissing(void)
2228 {
2229         skinframe_t *skinframe;
2230
2231         if (cls.state == ca_dedicated)
2232                 return NULL;
2233
2234         skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2235         skinframe->stain = NULL;
2236         skinframe->merged = NULL;
2237         skinframe->base = r_texture_notexture;
2238         skinframe->pants = NULL;
2239         skinframe->shirt = NULL;
2240         skinframe->nmap = r_texture_blanknormalmap;
2241         skinframe->gloss = NULL;
2242         skinframe->glow = NULL;
2243         skinframe->fog = NULL;
2244
2245         skinframe->avgcolor[0] = rand() / RAND_MAX;
2246         skinframe->avgcolor[1] = rand() / RAND_MAX;
2247         skinframe->avgcolor[2] = rand() / RAND_MAX;
2248         skinframe->avgcolor[3] = 1;
2249
2250         return skinframe;
2251 }
2252
2253 void gl_main_start(void)
2254 {
2255         r_numqueries = 0;
2256         r_maxqueries = 0;
2257         memset(r_queries, 0, sizeof(r_queries));
2258
2259         memset(r_qwskincache, 0, sizeof(r_qwskincache));
2260         memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2261
2262         // set up r_skinframe loading system for textures
2263         memset(&r_skinframe, 0, sizeof(r_skinframe));
2264         r_skinframe.loadsequence = 1;
2265         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2266
2267         r_main_texturepool = R_AllocTexturePool();
2268         R_BuildBlankTextures();
2269         R_BuildNoTexture();
2270         if (gl_texturecubemap)
2271         {
2272                 R_BuildWhiteCube();
2273                 R_BuildNormalizationCube();
2274         }
2275         r_texture_fogattenuation = NULL;
2276         r_texture_gammaramps = NULL;
2277         //r_texture_fogintensity = NULL;
2278         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2279         memset(&r_waterstate, 0, sizeof(r_waterstate));
2280         memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2281         memset(&r_svbsp, 0, sizeof (r_svbsp));
2282
2283         r_refdef.fogmasktable_density = 0;
2284 }
2285
2286 void gl_main_shutdown(void)
2287 {
2288         if (r_maxqueries)
2289                 qglDeleteQueriesARB(r_maxqueries, r_queries);
2290
2291         r_numqueries = 0;
2292         r_maxqueries = 0;
2293         memset(r_queries, 0, sizeof(r_queries));
2294
2295         memset(r_qwskincache, 0, sizeof(r_qwskincache));
2296         memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2297
2298         // clear out the r_skinframe state
2299         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2300         memset(&r_skinframe, 0, sizeof(r_skinframe));
2301
2302         if (r_svbsp.nodes)
2303                 Mem_Free(r_svbsp.nodes);
2304         memset(&r_svbsp, 0, sizeof (r_svbsp));
2305         R_FreeTexturePool(&r_main_texturepool);
2306         r_texture_blanknormalmap = NULL;
2307         r_texture_white = NULL;
2308         r_texture_grey128 = NULL;
2309         r_texture_black = NULL;
2310         r_texture_whitecube = NULL;
2311         r_texture_normalizationcube = NULL;
2312         r_texture_fogattenuation = NULL;
2313         r_texture_gammaramps = NULL;
2314         //r_texture_fogintensity = NULL;
2315         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2316         memset(&r_waterstate, 0, sizeof(r_waterstate));
2317         R_GLSL_Restart_f();
2318 }
2319
2320 extern void CL_ParseEntityLump(char *entitystring);
2321 void gl_main_newmap(void)
2322 {
2323         // FIXME: move this code to client
2324         int l;
2325         char *entities, entname[MAX_QPATH];
2326         if (cl.worldmodel)
2327         {
2328                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2329                 l = (int)strlen(entname) - 4;
2330                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2331                 {
2332                         memcpy(entname + l, ".ent", 5);
2333                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2334                         {
2335                                 CL_ParseEntityLump(entities);
2336                                 Mem_Free(entities);
2337                                 return;
2338                         }
2339                 }
2340                 if (cl.worldmodel->brush.entities)
2341                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
2342         }
2343 }
2344
2345 void GL_Main_Init(void)
2346 {
2347         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2348
2349         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2350         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2351         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2352         if (gamemode == GAME_NEHAHRA)
2353         {
2354                 Cvar_RegisterVariable (&gl_fogenable);
2355                 Cvar_RegisterVariable (&gl_fogdensity);
2356                 Cvar_RegisterVariable (&gl_fogred);
2357                 Cvar_RegisterVariable (&gl_foggreen);
2358                 Cvar_RegisterVariable (&gl_fogblue);
2359                 Cvar_RegisterVariable (&gl_fogstart);
2360                 Cvar_RegisterVariable (&gl_fogend);
2361                 Cvar_RegisterVariable (&gl_skyclip);
2362         }
2363         Cvar_RegisterVariable(&r_depthfirst);
2364         Cvar_RegisterVariable(&r_useinfinitefarclip);
2365         Cvar_RegisterVariable(&r_nearclip);
2366         Cvar_RegisterVariable(&r_showbboxes);
2367         Cvar_RegisterVariable(&r_showsurfaces);
2368         Cvar_RegisterVariable(&r_showtris);
2369         Cvar_RegisterVariable(&r_shownormals);
2370         Cvar_RegisterVariable(&r_showlighting);
2371         Cvar_RegisterVariable(&r_showshadowvolumes);
2372         Cvar_RegisterVariable(&r_showcollisionbrushes);
2373         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2374         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2375         Cvar_RegisterVariable(&r_showdisabledepthtest);
2376         Cvar_RegisterVariable(&r_drawportals);
2377         Cvar_RegisterVariable(&r_drawentities);
2378         Cvar_RegisterVariable(&r_cullentities_trace);
2379         Cvar_RegisterVariable(&r_cullentities_trace_samples);
2380         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2381         Cvar_RegisterVariable(&r_cullentities_trace_delay);
2382         Cvar_RegisterVariable(&r_drawviewmodel);
2383         Cvar_RegisterVariable(&r_speeds);
2384         Cvar_RegisterVariable(&r_fullbrights);
2385         Cvar_RegisterVariable(&r_wateralpha);
2386         Cvar_RegisterVariable(&r_dynamic);
2387         Cvar_RegisterVariable(&r_fullbright);
2388         Cvar_RegisterVariable(&r_shadows);
2389         Cvar_RegisterVariable(&r_shadows_throwdistance);
2390         Cvar_RegisterVariable(&r_q1bsp_skymasking);
2391         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2392         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2393         Cvar_RegisterVariable(&r_fog_exp2);
2394         Cvar_RegisterVariable(&r_drawfog);
2395         Cvar_RegisterVariable(&r_textureunits);
2396         Cvar_RegisterVariable(&r_glsl);
2397         Cvar_RegisterVariable(&r_glsl_contrastboost);
2398         Cvar_RegisterVariable(&r_glsl_deluxemapping);
2399         Cvar_RegisterVariable(&r_glsl_offsetmapping);
2400         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2401         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2402         Cvar_RegisterVariable(&r_glsl_postprocess);
2403         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2404         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2405         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2406         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2407         Cvar_RegisterVariable(&r_glsl_usegeneric);
2408         Cvar_RegisterVariable(&r_water);
2409         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2410         Cvar_RegisterVariable(&r_water_clippingplanebias);
2411         Cvar_RegisterVariable(&r_water_refractdistort);
2412         Cvar_RegisterVariable(&r_water_reflectdistort);
2413         Cvar_RegisterVariable(&r_lerpsprites);
2414         Cvar_RegisterVariable(&r_lerpmodels);
2415         Cvar_RegisterVariable(&r_lerplightstyles);
2416         Cvar_RegisterVariable(&r_waterscroll);
2417         Cvar_RegisterVariable(&r_bloom);
2418         Cvar_RegisterVariable(&r_bloom_colorscale);
2419         Cvar_RegisterVariable(&r_bloom_brighten);
2420         Cvar_RegisterVariable(&r_bloom_blur);
2421         Cvar_RegisterVariable(&r_bloom_resolution);
2422         Cvar_RegisterVariable(&r_bloom_colorexponent);
2423         Cvar_RegisterVariable(&r_bloom_colorsubtract);
2424         Cvar_RegisterVariable(&r_hdr);
2425         Cvar_RegisterVariable(&r_hdr_scenebrightness);
2426         Cvar_RegisterVariable(&r_hdr_glowintensity);
2427         Cvar_RegisterVariable(&r_hdr_range);
2428         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2429         Cvar_RegisterVariable(&developer_texturelogging);
2430         Cvar_RegisterVariable(&gl_lightmaps);
2431         Cvar_RegisterVariable(&r_test);
2432         Cvar_RegisterVariable(&r_batchmode);
2433         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2434                 Cvar_SetValue("r_fullbrights", 0);
2435         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2436
2437         Cvar_RegisterVariable(&r_track_sprites);
2438         Cvar_RegisterVariable(&r_track_sprites_flags);
2439         Cvar_RegisterVariable(&r_track_sprites_scalew);
2440         Cvar_RegisterVariable(&r_track_sprites_scaleh);
2441 }
2442
2443 extern void R_Textures_Init(void);
2444 extern void GL_Draw_Init(void);
2445 extern void GL_Main_Init(void);
2446 extern void R_Shadow_Init(void);
2447 extern void R_Sky_Init(void);
2448 extern void GL_Surf_Init(void);
2449 extern void R_Particles_Init(void);
2450 extern void R_Explosion_Init(void);
2451 extern void gl_backend_init(void);
2452 extern void Sbar_Init(void);
2453 extern void R_LightningBeams_Init(void);
2454 extern void Mod_RenderInit(void);
2455
2456 void Render_Init(void)
2457 {
2458         gl_backend_init();
2459         R_Textures_Init();
2460         GL_Main_Init();
2461         GL_Draw_Init();
2462         R_Shadow_Init();
2463         R_Sky_Init();
2464         GL_Surf_Init();
2465         Sbar_Init();
2466         R_Particles_Init();
2467         R_Explosion_Init();
2468         R_LightningBeams_Init();
2469         Mod_RenderInit();
2470 }
2471
2472 /*
2473 ===============
2474 GL_Init
2475 ===============
2476 */
2477 extern char *ENGINE_EXTENSIONS;
2478 void GL_Init (void)
2479 {
2480         gl_renderer = (const char *)qglGetString(GL_RENDERER);
2481         gl_vendor = (const char *)qglGetString(GL_VENDOR);
2482         gl_version = (const char *)qglGetString(GL_VERSION);
2483         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2484
2485         if (!gl_extensions)
2486                 gl_extensions = "";
2487         if (!gl_platformextensions)
2488                 gl_platformextensions = "";
2489
2490         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2491         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2492         Con_Printf("GL_VERSION: %s\n", gl_version);
2493         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
2494         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2495
2496         VID_CheckExtensions();
2497
2498         // LordHavoc: report supported extensions
2499         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2500
2501         // clear to black (loading plaque will be seen over this)
2502         CHECKGLERROR
2503         qglClearColor(0,0,0,1);CHECKGLERROR
2504         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2505 }
2506
2507 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2508 {
2509         int i;
2510         mplane_t *p;
2511         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2512         {
2513                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2514                 if (i == 4)
2515                         continue;
2516                 p = r_refdef.view.frustum + i;
2517                 switch(p->signbits)
2518                 {
2519                 default:
2520                 case 0:
2521                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2522                                 return true;
2523                         break;
2524                 case 1:
2525                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2526                                 return true;
2527                         break;
2528                 case 2:
2529                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2530                                 return true;
2531                         break;
2532                 case 3:
2533                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2534                                 return true;
2535                         break;
2536                 case 4:
2537                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2538                                 return true;
2539                         break;
2540                 case 5:
2541                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2542                                 return true;
2543                         break;
2544                 case 6:
2545                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2546                                 return true;
2547                         break;
2548                 case 7:
2549                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2550                                 return true;
2551                         break;
2552                 }
2553         }
2554         return false;
2555 }
2556
2557 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2558 {
2559         int i;
2560         const mplane_t *p;
2561         for (i = 0;i < numplanes;i++)
2562         {
2563                 p = planes + i;
2564                 switch(p->signbits)
2565                 {
2566                 default:
2567                 case 0:
2568                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2569                                 return true;
2570                         break;
2571                 case 1:
2572                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2573                                 return true;
2574                         break;
2575                 case 2:
2576                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2577                                 return true;
2578                         break;
2579                 case 3:
2580                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2581                                 return true;
2582                         break;
2583                 case 4:
2584                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2585                                 return true;
2586                         break;
2587                 case 5:
2588                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2589                                 return true;
2590                         break;
2591                 case 6:
2592                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2593                                 return true;
2594                         break;
2595                 case 7:
2596                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2597                                 return true;
2598                         break;
2599                 }
2600         }
2601         return false;
2602 }
2603
2604 //==================================================================================
2605
2606 static void R_View_UpdateEntityLighting (void)
2607 {
2608         int i;
2609         entity_render_t *ent;
2610         vec3_t tempdiffusenormal;
2611
2612         for (i = 0;i < r_refdef.scene.numentities;i++)
2613         {
2614                 ent = r_refdef.scene.entities[i];
2615
2616                 // skip unseen models
2617                 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
2618                         continue;
2619
2620                 // skip bsp models
2621                 if (ent->model && ent->model->brush.num_leafs)
2622                 {
2623                         // TODO: use modellight for r_ambient settings on world?
2624                         VectorSet(ent->modellight_ambient, 0, 0, 0);
2625                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
2626                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
2627                         continue;
2628                 }
2629
2630                 // fetch the lighting from the worldmodel data
2631                 VectorSet(ent->modellight_ambient, r_refdef.scene.ambient * (2.0f / 128.0f), r_refdef.scene.ambient * (2.0f / 128.0f), r_refdef.scene.ambient * (2.0f / 128.0f));
2632                 VectorClear(ent->modellight_diffuse);
2633                 VectorClear(tempdiffusenormal);
2634                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
2635                 {
2636                         vec3_t org;
2637                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2638                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
2639                 }
2640                 else // highly rare
2641                         VectorSet(ent->modellight_ambient, 1, 1, 1);
2642
2643                 // move the light direction into modelspace coordinates for lighting code
2644                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
2645                 if(VectorLength2(ent->modellight_lightdir) == 0)
2646                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
2647                 VectorNormalize(ent->modellight_lightdir);
2648         }
2649 }
2650
2651 static void R_View_UpdateEntityVisible (void)
2652 {
2653         int i, renderimask;
2654         entity_render_t *ent;
2655
2656         if (!r_drawentities.integer)
2657                 return;
2658
2659         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2660         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2661         {
2662                 // worldmodel can check visibility
2663                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
2664                 for (i = 0;i < r_refdef.scene.numentities;i++)
2665                 {
2666                         ent = r_refdef.scene.entities[i];
2667                         if (!(ent->flags & renderimask))
2668                         if (!R_CullBox(ent->mins, ent->maxs) || (ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
2669                         if ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
2670                                 r_refdef.viewcache.entityvisible[i] = true;
2671                 }
2672                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2673                 {
2674                         for (i = 0;i < r_refdef.scene.numentities;i++)
2675                         {
2676                                 ent = r_refdef.scene.entities[i];
2677                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2678                                 {
2679                                         if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.scene.worldmodel, r_refdef.view.origin, ent->mins, ent->maxs))
2680                                                 ent->last_trace_visibility = realtime;
2681                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2682                                                 r_refdef.viewcache.entityvisible[i] = 0;
2683                                 }
2684                         }
2685                 }
2686         }
2687         else
2688         {
2689                 // no worldmodel or it can't check visibility
2690                 for (i = 0;i < r_refdef.scene.numentities;i++)
2691                 {
2692                         ent = r_refdef.scene.entities[i];
2693                         r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
2694                 }
2695         }
2696 }
2697
2698 // only used if skyrendermasked, and normally returns false
2699 int R_DrawBrushModelsSky (void)
2700 {
2701         int i, sky;
2702         entity_render_t *ent;
2703
2704         if (!r_drawentities.integer)
2705                 return false;
2706
2707         sky = false;
2708         for (i = 0;i < r_refdef.scene.numentities;i++)
2709         {
2710                 if (!r_refdef.viewcache.entityvisible[i])
2711                         continue;
2712                 ent = r_refdef.scene.entities[i];
2713                 if (!ent->model || !ent->model->DrawSky)
2714                         continue;
2715                 ent->model->DrawSky(ent);
2716                 sky = true;
2717         }
2718         return sky;
2719 }
2720
2721 static void R_DrawNoModel(entity_render_t *ent);
2722 static void R_DrawModels(void)
2723 {
2724         int i;
2725         entity_render_t *ent;
2726
2727         if (!r_drawentities.integer)
2728                 return;
2729
2730         for (i = 0;i < r_refdef.scene.numentities;i++)
2731         {
2732                 if (!r_refdef.viewcache.entityvisible[i])
2733                         continue;
2734                 ent = r_refdef.scene.entities[i];
2735                 r_refdef.stats.entities++;
2736                 if (ent->model && ent->model->Draw != NULL)
2737                         ent->model->Draw(ent);
2738                 else
2739                         R_DrawNoModel(ent);
2740         }
2741 }
2742
2743 static void R_DrawModelsDepth(void)
2744 {
2745         int i;
2746         entity_render_t *ent;
2747
2748         if (!r_drawentities.integer)
2749                 return;
2750
2751         for (i = 0;i < r_refdef.scene.numentities;i++)
2752         {
2753                 if (!r_refdef.viewcache.entityvisible[i])
2754                         continue;
2755                 ent = r_refdef.scene.entities[i];
2756                 if (ent->model && ent->model->DrawDepth != NULL)
2757                         ent->model->DrawDepth(ent);
2758         }
2759 }
2760
2761 static void R_DrawModelsDebug(void)
2762 {
2763         int i;
2764         entity_render_t *ent;
2765
2766         if (!r_drawentities.integer)
2767                 return;
2768
2769         for (i = 0;i < r_refdef.scene.numentities;i++)
2770         {
2771                 if (!r_refdef.viewcache.entityvisible[i])
2772                         continue;
2773                 ent = r_refdef.scene.entities[i];
2774                 if (ent->model && ent->model->DrawDebug != NULL)
2775                         ent->model->DrawDebug(ent);
2776         }
2777 }
2778
2779 static void R_DrawModelsAddWaterPlanes(void)
2780 {
2781         int i;
2782         entity_render_t *ent;
2783
2784         if (!r_drawentities.integer)
2785                 return;
2786
2787         for (i = 0;i < r_refdef.scene.numentities;i++)
2788         {
2789                 if (!r_refdef.viewcache.entityvisible[i])
2790                         continue;
2791                 ent = r_refdef.scene.entities[i];
2792                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2793                         ent->model->DrawAddWaterPlanes(ent);
2794         }
2795 }
2796
2797 static void R_View_SetFrustum(void)
2798 {
2799         int i;
2800         double slopex, slopey;
2801         vec3_t forward, left, up, origin;
2802
2803         // we can't trust r_refdef.view.forward and friends in reflected scenes
2804         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
2805
2806 #if 0
2807         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2808         r_refdef.view.frustum[0].normal[1] = 0 - 0;
2809         r_refdef.view.frustum[0].normal[2] = -1 - 0;
2810         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2811         r_refdef.view.frustum[1].normal[1] = 0 + 0;
2812         r_refdef.view.frustum[1].normal[2] = -1 + 0;
2813         r_refdef.view.frustum[2].normal[0] = 0 - 0;
2814         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2815         r_refdef.view.frustum[2].normal[2] = -1 - 0;
2816         r_refdef.view.frustum[3].normal[0] = 0 + 0;
2817         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2818         r_refdef.view.frustum[3].normal[2] = -1 + 0;
2819 #endif
2820
2821 #if 0
2822         zNear = r_refdef.nearclip;
2823         nudge = 1.0 - 1.0 / (1<<23);
2824         r_refdef.view.frustum[4].normal[0] = 0 - 0;
2825         r_refdef.view.frustum[4].normal[1] = 0 - 0;
2826         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
2827         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
2828         r_refdef.view.frustum[5].normal[0] = 0 + 0;
2829         r_refdef.view.frustum[5].normal[1] = 0 + 0;
2830         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
2831         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
2832 #endif
2833
2834
2835
2836 #if 0
2837         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
2838         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
2839         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
2840         r_refdef.view.frustum[0].dist = m[15] - m[12];
2841
2842         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
2843         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
2844         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
2845         r_refdef.view.frustum[1].dist = m[15] + m[12];
2846
2847         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
2848         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
2849         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
2850         r_refdef.view.frustum[2].dist = m[15] - m[13];
2851
2852         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
2853         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
2854         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
2855         r_refdef.view.frustum[3].dist = m[15] + m[13];
2856
2857         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
2858         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
2859         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
2860         r_refdef.view.frustum[4].dist = m[15] - m[14];
2861
2862         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
2863         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
2864         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
2865         r_refdef.view.frustum[5].dist = m[15] + m[14];
2866 #endif
2867
2868         if (r_refdef.view.useperspective)
2869         {
2870                 slopex = 1.0 / r_refdef.view.frustum_x;
2871                 slopey = 1.0 / r_refdef.view.frustum_y;
2872                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
2873                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
2874                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
2875                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
2876                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2877
2878                 // Leaving those out was a mistake, those were in the old code, and they
2879                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2880                 // I couldn't reproduce it after adding those normalizations. --blub
2881                 VectorNormalize(r_refdef.view.frustum[0].normal);
2882                 VectorNormalize(r_refdef.view.frustum[1].normal);
2883                 VectorNormalize(r_refdef.view.frustum[2].normal);
2884                 VectorNormalize(r_refdef.view.frustum[3].normal);
2885
2886                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2887                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
2888                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
2889                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left,  1024 * slopey, up, r_refdef.view.frustumcorner[2]);
2890                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * slopex, left,  1024 * slopey, up, r_refdef.view.frustumcorner[3]);
2891
2892                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
2893                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
2894                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
2895                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
2896                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2897         }
2898         else
2899         {
2900                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
2901                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
2902                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
2903                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
2904                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2905                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
2906                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
2907                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
2908                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
2909                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2910         }
2911         r_refdef.view.numfrustumplanes = 5;
2912
2913         if (r_refdef.view.useclipplane)
2914         {
2915                 r_refdef.view.numfrustumplanes = 6;
2916                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
2917         }
2918
2919         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2920                 PlaneClassify(r_refdef.view.frustum + i);
2921
2922         // LordHavoc: note to all quake engine coders, Quake had a special case
2923         // for 90 degrees which assumed a square view (wrong), so I removed it,
2924         // Quake2 has it disabled as well.
2925
2926         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2927         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
2928         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
2929         //PlaneClassify(&frustum[0]);
2930
2931         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2932         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
2933         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
2934         //PlaneClassify(&frustum[1]);
2935
2936         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2937         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
2938         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
2939         //PlaneClassify(&frustum[2]);
2940
2941         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2942         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
2943         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
2944         //PlaneClassify(&frustum[3]);
2945
2946         // nearclip plane
2947         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
2948         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
2949         //PlaneClassify(&frustum[4]);
2950 }
2951
2952 void R_View_Update(void)
2953 {
2954         R_View_SetFrustum();
2955         R_View_WorldVisibility(r_refdef.view.useclipplane);
2956         R_View_UpdateEntityVisible();
2957         R_View_UpdateEntityLighting();
2958 }
2959
2960 void R_SetupView(qboolean allowwaterclippingplane)
2961 {
2962         if (!r_refdef.view.useperspective)
2963                 GL_SetupView_Mode_Ortho(-r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip);
2964         else if (gl_stencil && r_useinfinitefarclip.integer)
2965                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
2966         else
2967                 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2968
2969         GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
2970
2971         if (r_refdef.view.useclipplane && allowwaterclippingplane)
2972         {
2973                 // LordHavoc: couldn't figure out how to make this approach the
2974                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
2975                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
2976                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
2977                         dist = r_refdef.view.clipplane.dist;
2978                 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
2979         }
2980 }
2981
2982 void R_ResetViewRendering2D(void)
2983 {
2984         DrawQ_Finish();
2985
2986         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2987         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2988         GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2989         GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2990         GL_Color(1, 1, 1, 1);
2991         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2992         GL_BlendFunc(GL_ONE, GL_ZERO);
2993         GL_AlphaTest(false);
2994         GL_ScissorTest(false);
2995         GL_DepthMask(false);
2996         GL_DepthRange(0, 1);
2997         GL_DepthTest(false);
2998         R_Mesh_Matrix(&identitymatrix);
2999         R_Mesh_ResetTextureState();
3000         GL_PolygonOffset(0, 0);
3001         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3002         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3003         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3004         qglStencilMask(~0);CHECKGLERROR
3005         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3006         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3007         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3008         R_SetupGenericShader(true);
3009 }
3010
3011 void R_ResetViewRendering3D(void)
3012 {
3013         DrawQ_Finish();
3014
3015         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3016         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3017         R_SetupView(true);
3018         GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
3019         GL_Color(1, 1, 1, 1);
3020         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3021         GL_BlendFunc(GL_ONE, GL_ZERO);
3022         GL_AlphaTest(false);
3023         GL_ScissorTest(true);
3024         GL_DepthMask(true);
3025         GL_DepthRange(0, 1);
3026         GL_DepthTest(true);
3027         R_Mesh_Matrix(&identitymatrix);
3028         R_Mesh_ResetTextureState();
3029         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3030         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3031         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3032         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3033         qglStencilMask(~0);CHECKGLERROR
3034         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3035         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3036         GL_CullFace(r_refdef.view.cullface_back);
3037         R_SetupGenericShader(true);
3038 }
3039
3040 void R_RenderScene(void);
3041 void R_RenderWaterPlanes(void);
3042
3043 static void R_Water_StartFrame(void)
3044 {
3045         int i;
3046         int waterwidth, waterheight, texturewidth, textureheight;
3047         r_waterstate_waterplane_t *p;
3048
3049         // set waterwidth and waterheight to the water resolution that will be
3050         // used (often less than the screen resolution for faster rendering)
3051         waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3052         waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3053
3054         // calculate desired texture sizes
3055         // can't use water if the card does not support the texture size
3056         if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3057                 texturewidth = textureheight = waterwidth = waterheight = 0;
3058         else if (gl_support_arb_texture_non_power_of_two)
3059         {
3060                 texturewidth = waterwidth;
3061                 textureheight = waterheight;
3062         }
3063         else
3064         {
3065                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
3066                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
3067         }
3068
3069         // allocate textures as needed
3070         if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3071         {
3072                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3073                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3074                 {
3075                         if (p->texture_refraction)
3076                                 R_FreeTexture(p->texture_refraction);
3077                         p->texture_refraction = NULL;
3078                         if (p->texture_reflection)
3079                                 R_FreeTexture(p->texture_reflection);
3080                         p->texture_reflection = NULL;
3081                 }
3082                 memset(&r_waterstate, 0, sizeof(r_waterstate));
3083                 r_waterstate.waterwidth = waterwidth;
3084                 r_waterstate.waterheight = waterheight;
3085                 r_waterstate.texturewidth = texturewidth;
3086                 r_waterstate.textureheight = textureheight;
3087         }
3088
3089         if (r_waterstate.waterwidth)
3090         {
3091                 r_waterstate.enabled = true;
3092
3093                 // set up variables that will be used in shader setup
3094                 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3095                 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
3096                 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3097                 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
3098         }
3099
3100         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3101         r_waterstate.numwaterplanes = 0;
3102 }
3103
3104 void R_Water_AddWaterPlane(msurface_t *surface)
3105 {
3106         int triangleindex, planeindex;
3107         const int *e;
3108         vec3_t vert[3];
3109         vec3_t normal;
3110         vec3_t center;
3111         mplane_t plane;
3112         r_waterstate_waterplane_t *p;
3113         texture_t *t = R_GetCurrentTexture(surface->texture);
3114         // just use the first triangle with a valid normal for any decisions
3115         VectorClear(normal);
3116         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3117         {
3118                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3119                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3120                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3121                 TriangleNormal(vert[0], vert[1], vert[2], normal);
3122                 if (VectorLength2(normal) >= 0.001)
3123                         break;
3124         }
3125
3126         VectorCopy(normal, plane.normal);
3127         VectorNormalize(plane.normal);
3128         plane.dist = DotProduct(vert[0], plane.normal);
3129         PlaneClassify(&plane);
3130         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3131         {
3132                 // skip backfaces (except if nocullface is set)
3133                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3134                         return;
3135                 VectorNegate(plane.normal, plane.normal);
3136                 plane.dist *= -1;
3137                 PlaneClassify(&plane);
3138         }
3139
3140
3141         // find a matching plane if there is one
3142         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3143                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3144                         break;
3145         if (planeindex >= r_waterstate.maxwaterplanes)
3146                 return; // nothing we can do, out of planes
3147
3148         // if this triangle does not fit any known plane rendered this frame, add one
3149         if (planeindex >= r_waterstate.numwaterplanes)
3150         {
3151                 // store the new plane
3152                 r_waterstate.numwaterplanes++;
3153                 p->plane = plane;
3154                 // clear materialflags and pvs
3155                 p->materialflags = 0;
3156                 p->pvsvalid = false;
3157         }
3158         // merge this surface's materialflags into the waterplane
3159         p->materialflags |= t->currentmaterialflags;
3160         // merge this surface's PVS into the waterplane
3161         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3162         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3163          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3164         {
3165                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3166                 p->pvsvalid = true;
3167         }
3168 }
3169
3170 static void R_Water_ProcessPlanes(void)
3171 {
3172         r_refdef_view_t originalview;
3173         r_refdef_view_t myview;
3174         int planeindex;
3175         r_waterstate_waterplane_t *p;
3176
3177         originalview = r_refdef.view;
3178
3179         // make sure enough textures are allocated
3180         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3181         {
3182                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3183                 {
3184                         if (!p->texture_refraction)
3185                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
3186                         if (!p->texture_refraction)
3187                                 goto error;
3188                 }
3189
3190                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3191                 {