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