r_showtris/r_shownormals/r_showcollisionbrushes are no longer obscured
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "r_shadow.h"
24 #include "polygon.h"
25 #include "image.h"
26
27 mempool_t *r_main_mempool;
28 rtexturepool_t *r_main_texturepool;
29
30 //
31 // screen size info
32 //
33 r_refdef_t r_refdef;
34 r_view_t r_view;
35 r_viewcache_t r_viewcache;
36
37 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "1", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
38 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
39 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
40 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
41 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
42 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
43 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
44 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
45 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
46 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
47 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
48 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
49 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
50 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
51 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
52 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
53 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
54 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
55 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
56 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
57 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
58 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
59 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
60 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
61 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
62 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
63 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
64 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
65 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "2", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
66
67 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
68 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
69 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
70 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
71 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
72 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
73 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
74
75 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
76
77 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
78 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
79 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
80 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
81 cvar_t r_glsl_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);
3218                 if (r_timereport_active)
3219                         R_TimeReport("world");
3220         }
3221
3222         // don't let sound skip if going slow
3223         if (r_refdef.extraupdate)
3224                 S_ExtraUpdate ();
3225
3226         R_DrawModels();
3227         if (r_timereport_active)
3228                 R_TimeReport("models");
3229
3230         // don't let sound skip if going slow
3231         if (r_refdef.extraupdate)
3232                 S_ExtraUpdate ();
3233
3234         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3235         {
3236                 R_DrawModelShadows();
3237
3238                 R_ResetViewRendering3D();
3239
3240                 // don't let sound skip if going slow
3241                 if (r_refdef.extraupdate)
3242                         S_ExtraUpdate ();
3243         }
3244
3245         R_ShadowVolumeLighting(false);
3246         if (r_timereport_active)
3247                 R_TimeReport("rtlights");
3248
3249         // don't let sound skip if going slow
3250         if (r_refdef.extraupdate)
3251                 S_ExtraUpdate ();
3252
3253         if (cl.csqc_vidvars.drawworld)
3254         {
3255                 R_DrawLightningBeams();
3256                 if (r_timereport_active)
3257                         R_TimeReport("lightning");
3258
3259                 R_DrawParticles();
3260                 if (r_timereport_active)
3261                         R_TimeReport("particles");
3262
3263                 R_DrawExplosions();
3264                 if (r_timereport_active)
3265                         R_TimeReport("explosions");
3266         }
3267
3268         if (gl_support_fragment_shader)
3269         {
3270                 qglUseProgramObjectARB(0);CHECKGLERROR
3271         }
3272         VM_CL_AddPolygonsToMeshQueue();
3273
3274         if (r_view.showdebug)
3275         {
3276                 if (cl_locs_show.integer)
3277                 {
3278                         R_DrawLocs();
3279                         if (r_timereport_active)
3280                                 R_TimeReport("showlocs");
3281                 }
3282
3283                 if (r_drawportals.integer)
3284                 {
3285                         R_DrawPortals();
3286                         if (r_timereport_active)
3287                                 R_TimeReport("portals");
3288                 }
3289
3290                 if (r_showbboxes.value > 0)
3291                 {
3292                         R_DrawEntityBBoxes();
3293                         if (r_timereport_active)
3294                                 R_TimeReport("bboxes");
3295                 }
3296         }
3297
3298         if (gl_support_fragment_shader)
3299         {
3300                 qglUseProgramObjectARB(0);CHECKGLERROR
3301         }
3302         R_MeshQueue_RenderTransparent();
3303         if (r_timereport_active)
3304                 R_TimeReport("drawtrans");
3305
3306         if (gl_support_fragment_shader)
3307         {
3308                 qglUseProgramObjectARB(0);CHECKGLERROR
3309         }
3310
3311         if (r_view.showdebug && r_refdef.worldmodel && r_refdef.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3312         {
3313                 r_refdef.worldmodel->DrawDebug(r_refdef.worldentity);
3314                 if (r_timereport_active)
3315                         R_TimeReport("worlddebug");
3316                 R_DrawModelsDebug();
3317                 if (r_timereport_active)
3318                         R_TimeReport("modeldebug");
3319         }
3320
3321         if (gl_support_fragment_shader)
3322         {
3323                 qglUseProgramObjectARB(0);CHECKGLERROR
3324         }
3325
3326         if (cl.csqc_vidvars.drawworld)
3327         {
3328                 R_DrawCoronas();
3329                 if (r_timereport_active)
3330                         R_TimeReport("coronas");
3331         }
3332
3333         // don't let sound skip if going slow
3334         if (r_refdef.extraupdate)
3335                 S_ExtraUpdate ();
3336
3337         R_ResetViewRendering2D();
3338 }
3339
3340 static const int bboxelements[36] =
3341 {
3342         5, 1, 3, 5, 3, 7,
3343         6, 2, 0, 6, 0, 4,
3344         7, 3, 2, 7, 2, 6,
3345         4, 0, 1, 4, 1, 5,
3346         4, 5, 7, 4, 7, 6,
3347         1, 0, 2, 1, 2, 3,
3348 };
3349
3350 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3351 {
3352         int i;
3353         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3354         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3355         GL_DepthMask(false);
3356         GL_DepthRange(0, 1);
3357         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3358         R_Mesh_Matrix(&identitymatrix);
3359         R_Mesh_ResetTextureState();
3360
3361         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3362         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3363         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3364         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3365         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3366         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3367         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3368         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3369         R_FillColors(color4f, 8, cr, cg, cb, ca);
3370         if (r_refdef.fogenabled)
3371         {
3372                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3373                 {
3374                         f1 = FogPoint_World(v);
3375                         f2 = 1 - f1;
3376                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3377                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3378                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3379                 }
3380         }
3381         R_Mesh_VertexPointer(vertex3f, 0, 0);
3382         R_Mesh_ColorPointer(color4f, 0, 0);
3383         R_Mesh_ResetTextureState();
3384         R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3385 }
3386
3387 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3388 {
3389         int i;
3390         float color[4];
3391         prvm_edict_t *edict;
3392         // this function draws bounding boxes of server entities
3393         if (!sv.active)
3394                 return;
3395         SV_VM_Begin();
3396         for (i = 0;i < numsurfaces;i++)
3397         {
3398                 edict = PRVM_EDICT_NUM(surfacelist[i]);
3399                 switch ((int)edict->fields.server->solid)
3400                 {
3401                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
3402                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
3403                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
3404                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3405                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
3406                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
3407                 }
3408                 color[3] *= r_showbboxes.value;
3409                 color[3] = bound(0, color[3], 1);
3410                 GL_DepthTest(!r_showdisabledepthtest.integer);
3411                 GL_CullFace(r_view.cullface_front);
3412                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3413         }
3414         SV_VM_End();
3415 }
3416
3417 static void R_DrawEntityBBoxes(void)
3418 {
3419         int i;
3420         prvm_edict_t *edict;
3421         vec3_t center;
3422         // this function draws bounding boxes of server entities
3423         if (!sv.active)
3424                 return;
3425         SV_VM_Begin();
3426         for (i = 0;i < prog->num_edicts;i++)
3427         {
3428                 edict = PRVM_EDICT_NUM(i);
3429                 if (edict->priv.server->free)
3430                         continue;
3431                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3432                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3433         }
3434         SV_VM_End();
3435 }
3436
3437 int nomodelelements[24] =
3438 {
3439         5, 2, 0,
3440         5, 1, 2,
3441         5, 0, 3,
3442         5, 3, 1,
3443         0, 2, 4,
3444         2, 1, 4,
3445         3, 0, 4,
3446         1, 3, 4
3447 };
3448
3449 float nomodelvertex3f[6*3] =
3450 {
3451         -16,   0,   0,
3452          16,   0,   0,
3453           0, -16,   0,
3454           0,  16,   0,
3455           0,   0, -16,
3456           0,   0,  16
3457 };
3458
3459 float nomodelcolor4f[6*4] =
3460 {
3461         0.0f, 0.0f, 0.5f, 1.0f,
3462         0.0f, 0.0f, 0.5f, 1.0f,
3463         0.0f, 0.5f, 0.0f, 1.0f,
3464         0.0f, 0.5f, 0.0f, 1.0f,
3465         0.5f, 0.0f, 0.0f, 1.0f,
3466         0.5f, 0.0f, 0.0f, 1.0f
3467 };
3468
3469 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3470 {
3471         int i;
3472         float f1, f2, *c;
3473         float color4f[6*4];
3474         // this is only called once per entity so numsurfaces is always 1, and
3475         // surfacelist is always {0}, so this code does not handle batches
3476         R_Mesh_Matrix(&ent->matrix);
3477
3478         if (ent->flags & EF_ADDITIVE)
3479         {
3480                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3481                 GL_DepthMask(false);
3482         }
3483         else if (ent->alpha < 1)
3484         {
3485                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3486                 GL_DepthMask(false);
3487         }
3488         else
3489         {
3490                 GL_BlendFunc(GL_ONE, GL_ZERO);
3491                 GL_DepthMask(true);
3492         }
3493         GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3494         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3495         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3496         GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_view.cullface_back);
3497         R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3498         if (r_refdef.fogenabled)
3499         {
3500                 vec3_t org;
3501                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3502                 R_Mesh_ColorPointer(color4f, 0, 0);
3503                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3504                 f1 = FogPoint_World(org);
3505                 f2 = 1 - f1;
3506                 for (i = 0, c = color4f;i < 6;i++, c += 4)
3507                 {
3508                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3509                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3510                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3511                         c[3] *= ent->alpha;
3512                 }
3513         }
3514         else if (ent->alpha != 1)
3515         {
3516                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3517                 R_Mesh_ColorPointer(color4f, 0, 0);
3518                 for (i = 0, c = color4f;i < 6;i++, c += 4)
3519                         c[3] *= ent->alpha;
3520         }
3521         else
3522                 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3523         R_Mesh_ResetTextureState();
3524         R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3525 }
3526
3527 void R_DrawNoModel(entity_render_t *ent)
3528 {
3529         vec3_t org;
3530         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3531         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3532                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3533         //else
3534         //      R_DrawNoModelCallback(ent, 0);
3535 }
3536
3537 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3538 {
3539         vec3_t right1, right2, diff, normal;
3540
3541         VectorSubtract (org2, org1, normal);
3542
3543         // calculate 'right' vector for start
3544         VectorSubtract (r_view.origin, org1, diff);
3545         CrossProduct (normal, diff, right1);
3546         VectorNormalize (right1);
3547
3548         // calculate 'right' vector for end
3549         VectorSubtract (r_view.origin, org2, diff);
3550         CrossProduct (normal, diff, right2);
3551         VectorNormalize (right2);
3552
3553         vert[ 0] = org1[0] + width * right1[0];
3554         vert[ 1] = org1[1] + width * right1[1];
3555         vert[ 2] = org1[2] + width * right1[2];
3556         vert[ 3] = org1[0] - width * right1[0];
3557         vert[ 4] = org1[1] - width * right1[1];
3558         vert[ 5] = org1[2] - width * right1[2];
3559         vert[ 6] = org2[0] - width * right2[0];
3560         vert[ 7] = org2[1] - width * right2[1];
3561         vert[ 8] = org2[2] - width * right2[2];
3562         vert[ 9] = org2[0] + width * right2[0];
3563         vert[10] = org2[1] + width * right2[1];
3564         vert[11] = org2[2] + width * right2[2];
3565 }
3566
3567 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3568
3569 void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_t *fogtexture, qboolean depthdisable, qboolean depthshort, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2, float cr, float cg, float cb, float ca)
3570 {
3571         float fog = 1.0f;
3572         float vertex3f[12];
3573
3574         if (r_refdef.fogenabled)
3575                 fog = FogPoint_World(origin);
3576
3577         R_Mesh_Matrix(&identitymatrix);
3578         GL_BlendFunc(blendfunc1, blendfunc2);
3579
3580         if(v_flipped_state)
3581         {
3582                 scalex1 = -scalex1;
3583                 scalex2 = -scalex2;
3584                 GL_CullFace(r_view.cullface_front);
3585         }
3586         else
3587                 GL_CullFace(r_view.cullface_back);
3588
3589         GL_DepthMask(false);
3590         GL_DepthRange(0, depthshort ? 0.0625 : 1);
3591         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3592         GL_DepthTest(!depthdisable);
3593
3594         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3595         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3596         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3597         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3598         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3599         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3600         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3601         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3602         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3603         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3604         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3605         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3606
3607         R_Mesh_VertexPointer(vertex3f, 0, 0);
3608         R_Mesh_ColorPointer(NULL, 0, 0);
3609         R_Mesh_ResetTextureState();
3610         R_Mesh_TexBind(0, R_GetTexture(texture));
3611         R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3612         // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3613         GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3614         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3615
3616         if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3617         {
3618                 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3619                 GL_BlendFunc(blendfunc1, GL_ONE);
3620                 fog = 1 - fog;
3621                 GL_Color(r_refdef.fogcolor[0] * fog * r_view.colorscale, r_refdef.fogcolor[1] * fog * r_view.colorscale, r_refdef.fogcolor[2] * fog * r_view.colorscale, ca);
3622                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3623         }
3624 }
3625
3626 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3627 {
3628         int i;
3629         float *vertex3f;
3630         float v[3];
3631         VectorSet(v, x, y, z);
3632         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3633                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3634                         break;
3635         if (i == mesh->numvertices)
3636         {
3637                 if (mesh->numvertices < mesh->maxvertices)
3638                 {
3639                         VectorCopy(v, vertex3f);
3640                         mesh->numvertices++;
3641                 }
3642                 return mesh->numvertices;
3643         }
3644         else
3645                 return i;
3646 }
3647
3648 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3649 {
3650         int i;
3651         int *e, element[3];
3652         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3653         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3654         e = mesh->element3i + mesh->numtriangles * 3;
3655         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3656         {
3657                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3658                 if (mesh->numtriangles < mesh->maxtriangles)
3659                 {
3660                         *e++ = element[0];
3661                         *e++ = element[1];
3662                         *e++ = element[2];
3663                         mesh->numtriangles++;
3664                 }
3665                 element[1] = element[2];
3666         }
3667 }
3668
3669 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3670 {
3671         int i;
3672         int *e, element[3];
3673         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3674         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3675         e = mesh->element3i + mesh->numtriangles * 3;
3676         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3677         {
3678                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3679                 if (mesh->numtriangles < mesh->maxtriangles)
3680                 {
3681                         *e++ = element[0];
3682                         *e++ = element[1];
3683                         *e++ = element[2];
3684                         mesh->numtriangles++;
3685                 }
3686                 element[1] = element[2];
3687         }
3688 }
3689
3690 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3691 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3692 {
3693         int planenum, planenum2;
3694         int w;
3695         int tempnumpoints;
3696         mplane_t *plane, *plane2;
3697         double maxdist;
3698         double temppoints[2][256*3];
3699         // figure out how large a bounding box we need to properly compute this brush
3700         maxdist = 0;
3701         for (w = 0;w < numplanes;w++)
3702                 maxdist = max(maxdist, planes[w].dist);
3703         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3704         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3705         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3706         {
3707                 w = 0;
3708                 tempnumpoints = 4;
3709                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3710                 for (planenum2 = 0, plane2 = planes;planenum2