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