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