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