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