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