implemented real support for QW skins (pants, shirt, glow, cropped pcx
[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 typedef struct r_qwskincache_s
195 {
196         char name[MAX_QPATH];
197         skinframe_t *skinframe;
198 }
199 r_qwskincache_t;
200
201 static r_qwskincache_t *r_qwskincache;
202 static int r_qwskincache_size;
203
204 /// vertex coordinates for a quad that covers the screen exactly
205 const float r_screenvertex3f[12] =
206 {
207         0, 0, 0,
208         1, 0, 0,
209         1, 1, 0,
210         0, 1, 0
211 };
212
213 extern void R_DrawModelShadows(void);
214
215 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
216 {
217         int i;
218         for (i = 0;i < verts;i++)
219         {
220                 out[0] = in[0] * r;
221                 out[1] = in[1] * g;
222                 out[2] = in[2] * b;
223                 out[3] = in[3];
224                 in += 4;
225                 out += 4;
226         }
227 }
228
229 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
230 {
231         int i;
232         for (i = 0;i < verts;i++)
233         {
234                 out[0] = r;
235                 out[1] = g;
236                 out[2] = b;
237                 out[3] = a;
238                 out += 4;
239         }
240 }
241
242 // FIXME: move this to client?
243 void FOG_clear(void)
244 {
245         if (gamemode == GAME_NEHAHRA)
246         {
247                 Cvar_Set("gl_fogenable", "0");
248                 Cvar_Set("gl_fogdensity", "0.2");
249                 Cvar_Set("gl_fogred", "0.3");
250                 Cvar_Set("gl_foggreen", "0.3");
251                 Cvar_Set("gl_fogblue", "0.3");
252         }
253         r_refdef.fog_density = 0;
254         r_refdef.fog_red = 0;
255         r_refdef.fog_green = 0;
256         r_refdef.fog_blue = 0;
257         r_refdef.fog_alpha = 1;
258         r_refdef.fog_start = 0;
259         r_refdef.fog_end = 0;
260 }
261
262 float FogForDistance(vec_t dist)
263 {
264         unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
265         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
266 }
267
268 float FogPoint_World(const vec3_t p)
269 {
270         return FogForDistance(VectorDistance((p), r_refdef.view.origin));
271 }
272
273 float FogPoint_Model(const vec3_t p)
274 {
275         return FogForDistance(VectorDistance((p), rsurface.modelorg) * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
276 }
277
278 static void R_BuildBlankTextures(void)
279 {
280         unsigned char data[4];
281         data[2] = 128; // normal X
282         data[1] = 128; // normal Y
283         data[0] = 255; // normal Z
284         data[3] = 128; // height
285         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
286         data[0] = 255;
287         data[1] = 255;
288         data[2] = 255;
289         data[3] = 255;
290         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
291         data[0] = 128;
292         data[1] = 128;
293         data[2] = 128;
294         data[3] = 255;
295         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
296         data[0] = 0;
297         data[1] = 0;
298         data[2] = 0;
299         data[3] = 255;
300         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
301 }
302
303 static void R_BuildNoTexture(void)
304 {
305         int x, y;
306         unsigned char pix[16][16][4];
307         // this makes a light grey/dark grey checkerboard texture
308         for (y = 0;y < 16;y++)
309         {
310                 for (x = 0;x < 16;x++)
311                 {
312                         if ((y < 8) ^ (x < 8))
313                         {
314                                 pix[y][x][0] = 128;
315                                 pix[y][x][1] = 128;
316                                 pix[y][x][2] = 128;
317                                 pix[y][x][3] = 255;
318                         }
319                         else
320                         {
321                                 pix[y][x][0] = 64;
322                                 pix[y][x][1] = 64;
323                                 pix[y][x][2] = 64;
324                                 pix[y][x][3] = 255;
325                         }
326                 }
327         }
328         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
329 }
330
331 static void R_BuildWhiteCube(void)
332 {
333         unsigned char data[6*1*1*4];
334         memset(data, 255, sizeof(data));
335         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
336 }
337
338 static void R_BuildNormalizationCube(void)
339 {
340         int x, y, side;
341         vec3_t v;
342         vec_t s, t, intensity;
343 #define NORMSIZE 64
344         unsigned char data[6][NORMSIZE][NORMSIZE][4];
345         for (side = 0;side < 6;side++)
346         {
347                 for (y = 0;y < NORMSIZE;y++)
348                 {
349                         for (x = 0;x < NORMSIZE;x++)
350                         {
351                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
352                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
353                                 switch(side)
354                                 {
355                                 default:
356                                 case 0:
357                                         v[0] = 1;
358                                         v[1] = -t;
359                                         v[2] = -s;
360                                         break;
361                                 case 1:
362                                         v[0] = -1;
363                                         v[1] = -t;
364                                         v[2] = s;
365                                         break;
366                                 case 2:
367                                         v[0] = s;
368                                         v[1] = 1;
369                                         v[2] = t;
370                                         break;
371                                 case 3:
372                                         v[0] = s;
373                                         v[1] = -1;
374                                         v[2] = -t;
375                                         break;
376                                 case 4:
377                                         v[0] = s;
378                                         v[1] = -t;
379                                         v[2] = 1;
380                                         break;
381                                 case 5:
382                                         v[0] = -s;
383                                         v[1] = -t;
384                                         v[2] = -1;
385                                         break;
386                                 }
387                                 intensity = 127.0f / sqrt(DotProduct(v, v));
388                                 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
389                                 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
390                                 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
391                                 data[side][y][x][3] = 255;
392                         }
393                 }
394         }
395         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
396 }
397
398 static void R_BuildFogTexture(void)
399 {
400         int x, b;
401 #define FOGWIDTH 256
402         unsigned char data1[FOGWIDTH][4];
403         //unsigned char data2[FOGWIDTH][4];
404         double d, r, alpha;
405
406         r_refdef.fogmasktable_start = r_refdef.fog_start;
407         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
408         r_refdef.fogmasktable_range = r_refdef.fogrange;
409         r_refdef.fogmasktable_density = r_refdef.fog_density;
410
411         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
412         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
413         {
414                 d = (x * r - r_refdef.fogmasktable_start);
415                 if(developer.integer >= 100)
416                         Con_Printf("%f ", d);
417                 d = max(0, d);
418                 if (r_fog_exp2.integer)
419                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
420                 else
421                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
422                 if(developer.integer >= 100)
423                         Con_Printf(" : %f ", alpha);
424                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
425                 if(developer.integer >= 100)
426                         Con_Printf(" = %f\n", alpha);
427                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
428         }
429
430         for (x = 0;x < FOGWIDTH;x++)
431         {
432                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
433                 data1[x][0] = b;
434                 data1[x][1] = b;
435                 data1[x][2] = b;
436                 data1[x][3] = 255;
437                 //data2[x][0] = 255 - b;
438                 //data2[x][1] = 255 - b;
439                 //data2[x][2] = 255 - b;
440                 //data2[x][3] = 255;
441         }
442         if (r_texture_fogattenuation)
443         {
444                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
445                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
446         }
447         else
448         {
449                 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);
450                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
451         }
452 }
453
454 static const char *builtinshaderstring =
455 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
456 "// written by Forest 'LordHavoc' Hale\n"
457 "\n"
458 "// enable various extensions depending on permutation:\n"
459 "\n" 
460 "#ifdef USESHADOWMAPRECT\n"
461 "# extension GL_ARB_texture_rectangle : enable\n"
462 "#endif\n"
463 "\n"
464 "#ifdef USESHADOWMAP2D\n"
465 "# ifdef GL_EXT_gpu_shader4\n"
466 "#   extension GL_EXT_gpu_shader4 : enable\n"
467 "# endif\n"
468 "# ifdef GL_ARB_texture_gather\n"
469 "#   extension GL_ARB_texture_gather : enable\n"
470 "# else\n"
471 "#   ifdef GL_AMD_texture_texture4\n"
472 "#     extension GL_AMD_texture_texture4 : enable\n"
473 "#   endif\n"
474 "# endif\n"
475 "#endif\n"
476 "\n"
477 "#ifdef USESHADOWMAPCUBE\n"
478 "# extension GL_EXT_gpu_shader4 : enable\n"
479 "#endif\n"
480 "\n"
481 "#ifdef USESHADOWSAMPLER\n"
482 "# extension GL_ARB_shadow : enable\n"
483 "#endif\n"
484 "\n"
485 "// common definitions between vertex shader and fragment shader:\n"
486 "\n"
487 "//#ifdef __GLSL_CG_DATA_TYPES\n"
488 "//# define myhalf half\n"
489 "//# define myhalf2 half2\n"
490 "//# define myhalf3half3\n"
491 "//# define myhalf4 half4\n"
492 "//#else\n"
493 "# define myhalf float\n"
494 "# define myhalf2 vec2\n"
495 "# define myhalf3 vec3\n"
496 "# define myhalf4 vec4\n"
497 "//#endif\n"
498 "\n"
499 "#ifdef MODE_DEPTH_OR_SHADOW\n"
500 "\n"
501 "# ifdef VERTEX_SHADER\n"
502 "void main(void)\n"
503 "{\n"
504 "       gl_Position = ftransform();\n"
505 "}\n"
506 "# endif\n"
507 "\n"
508 "#else\n"
509 "#ifdef MODE_SHOWDEPTH\n"
510 "# ifdef VERTEX_SHADER\n"
511 "void main(void)\n"
512 "{\n"
513 "       gl_Position = ftransform();\n"
514 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
515 "}\n"
516 "# endif\n"
517 "# ifdef FRAGMENT_SHADER\n"
518 "void main(void)\n"
519 "{\n"
520 "       gl_FragColor = gl_Color;\n"
521 "}\n"
522 "# endif\n"
523 "\n"
524 "#else // !MODE_SHOWDEPTH\n"
525 "\n"
526 "#ifdef MODE_POSTPROCESS\n"
527 "# ifdef VERTEX_SHADER\n"
528 "void main(void)\n"
529 "{\n"
530 "       gl_FrontColor = gl_Color;\n"
531 "       gl_Position = ftransform();\n"
532 "       gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
533 "#ifdef USEBLOOM\n"
534 "       gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
535 "#endif\n"
536 "}\n"
537 "# endif\n"
538 "# ifdef FRAGMENT_SHADER\n"
539 "\n"
540 "uniform sampler2D Texture_First;\n"
541 "#ifdef USEBLOOM\n"
542 "uniform sampler2D Texture_Second;\n"
543 "#endif\n"
544 "#ifdef USEGAMMARAMPS\n"
545 "uniform sampler2D Texture_GammaRamps;\n"
546 "#endif\n"
547 "#ifdef USESATURATION\n"
548 "uniform float Saturation;\n"
549 "#endif\n"
550 "#ifdef USEVIEWTINT\n"
551 "uniform vec4 TintColor;\n"
552 "#endif\n"
553 "//uncomment these if you want to use them:\n"
554 "uniform vec4 UserVec1;\n"
555 "// uniform vec4 UserVec2;\n"
556 "// uniform vec4 UserVec3;\n"
557 "// uniform vec4 UserVec4;\n"
558 "// uniform float ClientTime;\n"
559 "uniform vec2 PixelSize;\n"
560 "void main(void)\n"
561 "{\n"
562 "       gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
563 "#ifdef USEBLOOM\n"
564 "       gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
565 "#endif\n"
566 "#ifdef USEVIEWTINT\n"
567 "       gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
568 "#endif\n"
569 "\n"
570 "#ifdef USEPOSTPROCESSING\n"
571 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
572 "// 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"
573 "       gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
574 "       gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
575 "       gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
576 "       gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
577 "       gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
578 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
579 "#endif\n"
580 "\n"
581 "#ifdef USESATURATION\n"
582 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
583 "       myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
584 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
585 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
586 "#endif\n"
587 "\n"
588 "#ifdef USEGAMMARAMPS\n"
589 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
590 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
591 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
592 "#endif\n"
593 "}\n"
594 "# endif\n"
595 "\n"
596 "\n"
597 "#else\n"
598 "#ifdef MODE_GENERIC\n"
599 "# ifdef VERTEX_SHADER\n"
600 "void main(void)\n"
601 "{\n"
602 "       gl_FrontColor = gl_Color;\n"
603 "#  ifdef USEDIFFUSE\n"
604 "       gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
605 "#  endif\n"
606 "#  ifdef USESPECULAR\n"
607 "       gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
608 "#  endif\n"
609 "       gl_Position = ftransform();\n"
610 "}\n"
611 "# endif\n"
612 "# ifdef FRAGMENT_SHADER\n"
613 "\n"
614 "#  ifdef USEDIFFUSE\n"
615 "uniform sampler2D Texture_First;\n"
616 "#  endif\n"
617 "#  ifdef USESPECULAR\n"
618 "uniform sampler2D Texture_Second;\n"
619 "#  endif\n"
620 "\n"
621 "void main(void)\n"
622 "{\n"
623 "       gl_FragColor = gl_Color;\n"
624 "#  ifdef USEDIFFUSE\n"
625 "       gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
626 "#  endif\n"
627 "\n"
628 "#  ifdef USESPECULAR\n"
629 "       vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
630 "#  endif\n"
631 "#  ifdef USECOLORMAPPING\n"
632 "       gl_FragColor *= tex2;\n"
633 "#  endif\n"
634 "#  ifdef USEGLOW\n"
635 "       gl_FragColor += tex2;\n"
636 "#  endif\n"
637 "#  ifdef USEVERTEXTEXTUREBLEND\n"
638 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
639 "#  endif\n"
640 "}\n"
641 "# endif\n"
642 "\n"
643 "#else // !MODE_GENERIC\n"
644 "\n"
645 "varying vec2 TexCoord;\n"
646 "#ifdef USEVERTEXTEXTUREBLEND\n"
647 "varying vec2 TexCoord2;\n"
648 "#endif\n"
649 "varying vec2 TexCoordLightmap;\n"
650 "\n"
651 "#ifdef MODE_LIGHTSOURCE\n"
652 "varying vec3 CubeVector;\n"
653 "#endif\n"
654 "\n"
655 "#ifdef MODE_LIGHTSOURCE\n"
656 "varying vec3 LightVector;\n"
657 "#endif\n"
658 "#ifdef MODE_LIGHTDIRECTION\n"
659 "varying vec3 LightVector;\n"
660 "#endif\n"
661 "\n"
662 "varying vec3 EyeVector;\n"
663 "#ifdef USEFOG\n"
664 "varying vec3 EyeVectorModelSpace;\n"
665 "#endif\n"
666 "\n"
667 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
668 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
669 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
670 "\n"
671 "#ifdef MODE_WATER\n"
672 "varying vec4 ModelViewProjectionPosition;\n"
673 "#endif\n"
674 "#ifdef MODE_REFRACTION\n"
675 "varying vec4 ModelViewProjectionPosition;\n"
676 "#endif\n"
677 "#ifdef USEREFLECTION\n"
678 "varying vec4 ModelViewProjectionPosition;\n"
679 "#endif\n"
680 "\n"
681 "\n"
682 "\n"
683 "\n"
684 "\n"
685 "// vertex shader specific:\n"
686 "#ifdef VERTEX_SHADER\n"
687 "\n"
688 "uniform vec3 LightPosition;\n"
689 "uniform vec3 EyePosition;\n"
690 "uniform vec3 LightDir;\n"
691 "\n"
692 "// 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"
693 "\n"
694 "void main(void)\n"
695 "{\n"
696 "       gl_FrontColor = gl_Color;\n"
697 "       // copy the surface texcoord\n"
698 "       TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
699 "#ifdef USEVERTEXTEXTUREBLEND\n"
700 "       TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
701 "#endif\n"
702 "#ifndef MODE_LIGHTSOURCE\n"
703 "# ifndef MODE_LIGHTDIRECTION\n"
704 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
705 "# endif\n"
706 "#endif\n"
707 "\n"
708 "#ifdef MODE_LIGHTSOURCE\n"
709 "       // transform vertex position into light attenuation/cubemap space\n"
710 "       // (-1 to +1 across the light box)\n"
711 "       CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
712 "\n"
713 "       // transform unnormalized light direction into tangent space\n"
714 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
715 "       //  normalize it per pixel)\n"
716 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
717 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
718 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
719 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
720 "#endif\n"
721 "\n"
722 "#ifdef MODE_LIGHTDIRECTION\n"
723 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
724 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
725 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
726 "#endif\n"
727 "\n"
728 "       // transform unnormalized eye direction into tangent space\n"
729 "#ifndef USEFOG\n"
730 "       vec3 EyeVectorModelSpace;\n"
731 "#endif\n"
732 "       EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
733 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
734 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
735 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
736 "\n"
737 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
738 "       VectorS = gl_MultiTexCoord1.xyz;\n"
739 "       VectorT = gl_MultiTexCoord2.xyz;\n"
740 "       VectorR = gl_MultiTexCoord3.xyz;\n"
741 "#endif\n"
742 "\n"
743 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
744 "//     ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
745 "//     //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
746 "//     //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
747 "//#endif\n"
748 "\n"
749 "// transform vertex to camera space, using ftransform to match non-VS\n"
750 "       // rendering\n"
751 "       gl_Position = ftransform();\n"
752 "\n"
753 "#ifdef MODE_WATER\n"
754 "       ModelViewProjectionPosition = gl_Position;\n"
755 "#endif\n"
756 "#ifdef MODE_REFRACTION\n"
757 "       ModelViewProjectionPosition = gl_Position;\n"
758 "#endif\n"
759 "#ifdef USEREFLECTION\n"
760 "       ModelViewProjectionPosition = gl_Position;\n"
761 "#endif\n"
762 "}\n"
763 "\n"
764 "#endif // VERTEX_SHADER\n"
765 "\n"
766 "\n"
767 "\n"
768 "\n"
769 "// fragment shader specific:\n"
770 "#ifdef FRAGMENT_SHADER\n"
771 "\n"
772 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
773 "uniform sampler2D Texture_Normal;\n"
774 "uniform sampler2D Texture_Color;\n"
775 "uniform sampler2D Texture_Gloss;\n"
776 "uniform sampler2D Texture_Glow;\n"
777 "uniform sampler2D Texture_SecondaryNormal;\n"
778 "uniform sampler2D Texture_SecondaryColor;\n"
779 "uniform sampler2D Texture_SecondaryGloss;\n"
780 "uniform sampler2D Texture_SecondaryGlow;\n"
781 "uniform sampler2D Texture_Pants;\n"
782 "uniform sampler2D Texture_Shirt;\n"
783 "uniform sampler2D Texture_FogMask;\n"
784 "uniform sampler2D Texture_Lightmap;\n"
785 "uniform sampler2D Texture_Deluxemap;\n"
786 "uniform sampler2D Texture_Refraction;\n"
787 "uniform sampler2D Texture_Reflection;\n"
788 "uniform sampler2D Texture_Attenuation;\n"
789 "uniform samplerCube Texture_Cube;\n"
790 "\n"
791 "#define showshadowmap 0\n"
792 "\n"
793 "#ifdef USESHADOWMAPRECT\n"
794 "# ifdef USESHADOWSAMPLER\n"
795 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
796 "# else\n"
797 "uniform sampler2DRect Texture_ShadowMapRect;\n"
798 "# endif\n"
799 "#endif\n"
800 "\n"
801 "#ifdef USESHADOWMAP2D\n"
802 "# ifdef USESHADOWSAMPLER\n"
803 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
804 "# else\n"
805 "uniform sampler2D Texture_ShadowMap2D;\n"
806 "# endif\n"
807 "#endif\n"
808 "\n"
809 "#ifdef USESHADOWMAPVSDCT\n"
810 "uniform samplerCube Texture_CubeProjection;\n"
811 "#endif\n"
812 "\n"
813 "#ifdef USESHADOWMAPCUBE\n"
814 "# ifdef USESHADOWSAMPLER\n"
815 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
816 "# else\n"
817 "uniform samplerCube Texture_ShadowMapCube;\n"
818 "# endif\n"
819 "#endif\n"
820 "\n"
821 "uniform myhalf3 LightColor;\n"
822 "uniform myhalf3 AmbientColor;\n"
823 "uniform myhalf3 DiffuseColor;\n"
824 "uniform myhalf3 SpecularColor;\n"
825 "uniform myhalf3 Color_Pants;\n"
826 "uniform myhalf3 Color_Shirt;\n"
827 "uniform myhalf3 FogColor;\n"
828 "\n"
829 "uniform myhalf4 TintColor;\n"
830 "\n"
831 "\n"
832 "//#ifdef MODE_WATER\n"
833 "uniform vec4 DistortScaleRefractReflect;\n"
834 "uniform vec4 ScreenScaleRefractReflect;\n"
835 "uniform vec4 ScreenCenterRefractReflect;\n"
836 "uniform myhalf4 RefractColor;\n"
837 "uniform myhalf4 ReflectColor;\n"
838 "uniform myhalf ReflectFactor;\n"
839 "uniform myhalf ReflectOffset;\n"
840 "//#else\n"
841 "//# ifdef MODE_REFRACTION\n"
842 "//uniform vec4 DistortScaleRefractReflect;\n"
843 "//uniform vec4 ScreenScaleRefractReflect;\n"
844 "//uniform vec4 ScreenCenterRefractReflect;\n"
845 "//uniform myhalf4 RefractColor;\n"
846 "//#  ifdef USEREFLECTION\n"
847 "//uniform myhalf4 ReflectColor;\n"
848 "//#  endif\n"
849 "//# else\n"
850 "//#  ifdef USEREFLECTION\n"
851 "//uniform vec4 DistortScaleRefractReflect;\n"
852 "//uniform vec4 ScreenScaleRefractReflect;\n"
853 "//uniform vec4 ScreenCenterRefractReflect;\n"
854 "//uniform myhalf4 ReflectColor;\n"
855 "//#  endif\n"
856 "//# endif\n"
857 "//#endif\n"
858 "\n"
859 "uniform myhalf3 GlowColor;\n"
860 "uniform myhalf SceneBrightness;\n"
861 "\n"
862 "uniform float OffsetMapping_Scale;\n"
863 "uniform float OffsetMapping_Bias;\n"
864 "uniform float FogRangeRecip;\n"
865 "\n"
866 "uniform myhalf AmbientScale;\n"
867 "uniform myhalf DiffuseScale;\n"
868 "uniform myhalf SpecularScale;\n"
869 "uniform myhalf SpecularPower;\n"
870 "\n"
871 "#ifdef USEOFFSETMAPPING\n"
872 "vec2 OffsetMapping(vec2 TexCoord)\n"
873 "{\n"
874 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
875 "       // 14 sample relief mapping: linear search and then binary search\n"
876 "       // this basically steps forward a small amount repeatedly until it finds\n"
877 "       // itself inside solid, then jitters forward and back using decreasing\n"
878 "       // amounts to find the impact\n"
879 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
880 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
881 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
882 "       vec3 RT = vec3(TexCoord, 1);\n"
883 "       OffsetVector *= 0.1;\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);\n"
887 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
888 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
889 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
890 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
891 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
892 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
893 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
894 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
895 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
896 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
897 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
898 "       return RT.xy;\n"
899 "#else\n"
900 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
901 "       // this basically moves forward the full distance, and then backs up based\n"
902 "       // on height of samples\n"
903 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
904 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
905 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
906 "       TexCoord += OffsetVector;\n"
907 "       OffsetVector *= 0.333;\n"
908 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
909 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
910 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
911 "       return TexCoord;\n"
912 "#endif\n"
913 "}\n"
914 "#endif // USEOFFSETMAPPING\n"
915 "\n"
916 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
917 "uniform vec2 ShadowMap_TextureScale;\n"
918 "uniform vec4 ShadowMap_Parameters;\n"
919 "#endif\n"
920 "\n"
921 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
922 "vec3 GetShadowMapTC2D(vec3 dir)\n"
923 "{\n"
924 "       vec3 adir = abs(dir);\n"
925 "# ifndef USESHADOWMAPVSDCT\n"
926 "       vec2 tc;\n"
927 "       vec2 offset;\n"
928 "       float ma;\n"
929 "       if (adir.x > adir.y)\n"
930 "       {\n"
931 "               if (adir.x > adir.z) // X\n"
932 "               {\n"
933 "                       ma = adir.x;\n"
934 "                       tc = dir.zy;\n"
935 "                       offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
936 "               }\n"
937 "               else // Z\n"
938 "               {\n"
939 "                       ma = adir.z;\n"
940 "                       tc = dir.xy;\n"
941 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
942 "               }\n"
943 "       }\n"
944 "       else\n"
945 "       {\n"
946 "               if (adir.y > adir.z) // Y\n"
947 "               {\n"
948 "                       ma = adir.y;\n"
949 "                       tc = dir.xz;\n"
950 "                       offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
951 "               }\n"
952 "               else // Z\n"
953 "               {\n"
954 "                       ma = adir.z;\n"
955 "                       tc = dir.xy;\n"
956 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
957 "               }\n"
958 "       }\n"
959 "\n"
960 "       vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
961 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
962 "       stc.z += ShadowMap_Parameters.z;\n"
963 "#  if showshadowmap\n"
964 "       stc.xy *= ShadowMap_TextureScale;\n"
965 "#  endif\n"
966 "       return stc;\n"
967 "# else\n"
968 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
969 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
970 "       vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
971 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
972 "       stc.z += ShadowMap_Parameters.z;\n"
973 "#  if showshadowmap\n"
974 "       stc.xy *= ShadowMap_TextureScale;\n"
975 "#  endif\n"
976 "       return stc;\n"
977 "# endif\n"
978 "}\n"
979 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
980 "\n"
981 "#ifdef USESHADOWMAPCUBE\n"
982 "vec4 GetShadowMapTCCube(vec3 dir)\n"
983 "{\n"
984 "    vec3 adir = abs(dir);\n"
985 "    return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
986 "}\n"
987 "#endif\n"
988 "\n"
989 "#if !showshadowmap\n"
990 "# ifdef USESHADOWMAPRECT\n"
991 "float ShadowMapCompare(vec3 dir)\n"
992 "{\n"
993 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
994 "       float f;\n"
995 "#  ifdef USESHADOWSAMPLER\n"
996 "\n"
997 "#    ifdef USESHADOWMAPPCF\n"
998 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
999 "    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"
1000 "#    else\n"
1001 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1002 "#    endif\n"
1003 "\n"
1004 "#  else\n"
1005 "\n"
1006 "#    ifdef USESHADOWMAPPCF\n"
1007 "#      if USESHADOWMAPPCF > 1\n"
1008 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1009 "    vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1010 "    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"
1011 "    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"
1012 "    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"
1013 "    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"
1014 "    vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1015 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1016 "#      else\n"
1017 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1018 "    vec2 offset = fract(shadowmaptc.xy);\n"
1019 "    vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1020 "    vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1021 "    vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1022 "    vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1023 "    f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1024 "#      endif\n"
1025 "#    else\n"
1026 "    f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1027 "#    endif\n"
1028 "\n"
1029 "#  endif\n"
1030 "       return f;\n"
1031 "}\n"
1032 "# endif\n"
1033 "\n"
1034 "# ifdef USESHADOWMAP2D\n"
1035 "float ShadowMapCompare(vec3 dir)\n"
1036 "{\n"
1037 "    vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1038 "    float f;\n"
1039 "\n"
1040 "#  ifdef USESHADOWSAMPLER\n"
1041 "#    ifdef USESHADOWMAPPCF\n"
1042 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1043 "    vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1044 "    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"
1045 "#    else\n"
1046 "    f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1047 "#    endif\n"
1048 "#  else\n"
1049 "#    ifdef USESHADOWMAPPCF\n"
1050 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1051 "#      ifdef GL_ARB_texture_gather\n"
1052 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1053 "#      else\n"
1054 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1055 "#      endif\n"
1056 "    vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1057 "    center *= ShadowMap_TextureScale;\n"
1058 "    vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1059 "    vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1060 "    vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1061 "    vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1062 "    vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1063 "                mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1064 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1065 "#     else\n"
1066 "#      ifdef GL_EXT_gpu_shader4\n"
1067 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1068 "#      else\n"
1069 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1070 "#      endif\n"
1071 "#      if USESHADOWMAPPCF > 1\n"       
1072 "    vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1073 "    center *= ShadowMap_TextureScale;\n"
1074 "    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"
1075 "    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"
1076 "    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"
1077 "    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"
1078 "    vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1079 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1080 "#      else\n"
1081 "    vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1082 "    vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1083 "    vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1084 "    vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1085 "    vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1086 "    f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1087 "#      endif\n"      
1088 "#     endif\n"
1089 "#    else\n"
1090 "    f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1091 "#    endif\n"
1092 "#  endif\n"
1093 "    return f;\n"
1094 "}\n"
1095 "# endif\n"
1096 "\n"
1097 "# ifdef USESHADOWMAPCUBE\n"
1098 "float ShadowMapCompare(vec3 dir)\n"
1099 "{\n"
1100 "    // apply depth texture cubemap as light filter\n"
1101 "    vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1102 "    float f;\n"
1103 "#  ifdef USESHADOWSAMPLER\n"
1104 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1105 "#  else\n"
1106 "    f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1107 "#  endif\n"
1108 "    return f;\n"
1109 "}\n"
1110 "# endif\n"
1111 "#endif\n"
1112 "\n"
1113 "#ifdef MODE_WATER\n"
1114 "\n"
1115 "// water pass\n"
1116 "void main(void)\n"
1117 "{\n"
1118 "#ifdef USEOFFSETMAPPING\n"
1119 "       // apply offsetmapping\n"
1120 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1121 "#define TexCoord TexCoordOffset\n"
1122 "#endif\n"
1123 "\n"
1124 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1125 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1126 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1127 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1128 "       // FIXME temporary hack to detect the case that the reflection\n"
1129 "       // gets blackened at edges due to leaving the area that contains actual\n"
1130 "       // content.\n"
1131 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1132 "       // 'appening.\n"
1133 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1134 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1135 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1136 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1137 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1138 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1139 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1140 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1141 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1142 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1143 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1144 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
1145 "}\n"
1146 "\n"
1147 "#else // !MODE_WATER\n"
1148 "#ifdef MODE_REFRACTION\n"
1149 "\n"
1150 "// refraction pass\n"
1151 "void main(void)\n"
1152 "{\n"
1153 "#ifdef USEOFFSETMAPPING\n"
1154 "       // apply offsetmapping\n"
1155 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1156 "#define TexCoord TexCoordOffset\n"
1157 "#endif\n"
1158 "\n"
1159 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1160 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1161 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1162 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1163 "       // FIXME temporary hack to detect the case that the reflection\n"
1164 "       // gets blackened at edges due to leaving the area that contains actual\n"
1165 "       // content.\n"
1166 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1167 "       // 'appening.\n"
1168 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1169 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1170 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1171 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1172 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1173 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
1174 "}\n"
1175 "\n"
1176 "#else // !MODE_REFRACTION\n"
1177 "void main(void)\n"
1178 "{\n"
1179 "#ifdef USEOFFSETMAPPING\n"
1180 "       // apply offsetmapping\n"
1181 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1182 "#define TexCoord TexCoordOffset\n"
1183 "#endif\n"
1184 "\n"
1185 "       // combine the diffuse textures (base, pants, shirt)\n"
1186 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1187 "#ifdef USECOLORMAPPING\n"
1188 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1189 "#endif\n"
1190 "#ifdef USEVERTEXTEXTUREBLEND\n"
1191 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1192 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1193 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1194 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1195 "       color.a = 1.0;\n"
1196 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1197 "#endif\n"
1198 "\n"
1199 "#ifdef USEDIFFUSE\n"
1200 "       // get the surface normal and the gloss color\n"
1201 "# ifdef USEVERTEXTEXTUREBLEND\n"
1202 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1203 "#  ifdef USESPECULAR\n"
1204 "       myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1205 "#  endif\n"
1206 "# else\n"
1207 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1208 "#  ifdef USESPECULAR\n"
1209 "       myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1210 "#  endif\n"
1211 "# endif\n"
1212 "#endif\n"
1213 "\n"
1214 "\n"
1215 "\n"
1216 "#ifdef MODE_LIGHTSOURCE\n"
1217 "       // light source\n"
1218 "\n"
1219 "       // calculate surface normal, light normal, and specular normal\n"
1220 "       // compute color intensity for the two textures (colormap and glossmap)\n"
1221 "       // scale by light color and attenuation as efficiently as possible\n"
1222 "       // (do as much scalar math as possible rather than vector math)\n"
1223 "# ifdef USEDIFFUSE\n"
1224 "       // get the light normal\n"
1225 "       myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1226 "# endif\n"
1227 "# ifdef USESPECULAR\n"
1228 "#  ifndef USEEXACTSPECULARMATH\n"
1229 "       myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1230 "\n"
1231 "#  endif\n"
1232 "       // calculate directional shading\n"
1233 "#  ifdef USEEXACTSPECULARMATH\n"
1234 "       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"
1235 "#  else\n"
1236 "       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"
1237 "#  endif\n"
1238 "# else\n"
1239 "#  ifdef USEDIFFUSE\n"
1240 "       // calculate directional shading\n"
1241 "       color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
1242 "#  else\n"
1243 "       // calculate directionless shading\n"
1244 "       color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1245 "#  endif\n"
1246 "# endif\n"
1247 "\n"
1248 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1249 "#if !showshadowmap\n"
1250 "    color.rgb *= ShadowMapCompare(CubeVector);\n"
1251 "#endif\n"
1252 "#endif\n"
1253 "\n"
1254 "# ifdef USECUBEFILTER\n"
1255 "       // apply light cubemap filter\n"
1256 "       //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
1257 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1258 "# endif\n"
1259 "#endif // MODE_LIGHTSOURCE\n"
1260 "\n"
1261 "\n"
1262 "\n"
1263 "\n"
1264 "#ifdef MODE_LIGHTDIRECTION\n"
1265 "       // directional model lighting\n"
1266 "# ifdef USEDIFFUSE\n"
1267 "       // get the light normal\n"
1268 "       myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1269 "# endif\n"
1270 "# ifdef USESPECULAR\n"
1271 "       // calculate directional shading\n"
1272 "       color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1273 "#  ifdef USEEXACTSPECULARMATH\n"
1274 "       color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1275 "#  else\n"
1276 "       myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1277 "       color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1278 "#  endif\n"
1279 "# else\n"
1280 "#  ifdef USEDIFFUSE\n"
1281 "\n"
1282 "       // calculate directional shading\n"
1283 "       color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1284 "#  else\n"
1285 "       color.rgb *= AmbientColor;\n"
1286 "#  endif\n"
1287 "# endif\n"
1288 "#endif // MODE_LIGHTDIRECTION\n"
1289 "\n"
1290 "\n"
1291 "\n"
1292 "\n"
1293 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1294 "       // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
1295 "\n"
1296 "       // get the light normal\n"
1297 "       myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1298 "       myhalf3 diffusenormal;\n"
1299 "       diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
1300 "       diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
1301 "       diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
1302 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1303 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1304 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1305 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1306 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1307 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1308 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1309 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1310 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1311 "       myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1312 "               // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1313 "# ifdef USESPECULAR\n"
1314 "#  ifdef USEEXACTSPECULARMATH\n"
1315 "       tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1316 "#  else\n"
1317 "       myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1318 "       tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1319 "#  endif\n"
1320 "# endif\n"
1321 "\n"
1322 "       // apply lightmap color\n"
1323 "       color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1324 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1325 "\n"
1326 "\n"
1327 "\n"
1328 "\n"
1329 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1330 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1331 "\n"
1332 "       // get the light normal\n"
1333 "       myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1334 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1335 "       myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1336 "# ifdef USESPECULAR\n"
1337 "#  ifdef USEEXACTSPECULARMATH\n"
1338 "       tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1339 "#  else\n"
1340 "       myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1341 "       tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1342 "#  endif\n"
1343 "# endif\n"
1344 "\n"
1345 "       // apply lightmap color\n"
1346 "       color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1347 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1348 "\n"
1349 "\n"
1350 "\n"
1351 "\n"
1352 "#ifdef MODE_LIGHTMAP\n"
1353 "       // apply lightmap color\n"
1354 "       color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1355 "#endif // MODE_LIGHTMAP\n"
1356 "\n"
1357 "\n"
1358 "\n"
1359 "\n"
1360 "#ifdef MODE_VERTEXCOLOR\n"
1361 "       // apply lightmap color\n"
1362 "       color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1363 "#endif // MODE_VERTEXCOLOR\n"
1364 "\n"
1365 "\n"
1366 "\n"
1367 "\n"
1368 "#ifdef MODE_FLATCOLOR\n"
1369 "#endif // MODE_FLATCOLOR\n"
1370 "\n"
1371 "\n"
1372 "\n"
1373 "\n"
1374 "\n"
1375 "\n"
1376 "\n"
1377 "       color *= TintColor;\n"
1378 "\n"
1379 "#ifdef USEGLOW\n"
1380 "#ifdef USEVERTEXTEXTUREBLEND\n"
1381 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1382 "#else\n"
1383 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowColor;\n"
1384 "#endif\n"
1385 "#endif\n"
1386 "\n"
1387 "       color.rgb *= SceneBrightness;\n"
1388 "\n"
1389 "       // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1390 "#ifdef USEFOG\n"
1391 "       color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1392 "#endif\n"
1393 "\n"
1394 "       // 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"
1395 "#ifdef USEREFLECTION\n"
1396 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1397 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1398 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1399 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1400 "       // FIXME temporary hack to detect the case that the reflection\n"
1401 "       // gets blackened at edges due to leaving the area that contains actual\n"
1402 "       // content.\n"
1403 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1404 "       // 'appening.\n"
1405 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1406 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1407 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1408 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1409 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1410 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1411 "#endif\n"
1412 "\n"
1413 "       gl_FragColor = vec4(color);\n"
1414 "\n"
1415 "#if showshadowmap\n"
1416 "# ifdef USESHADOWMAPRECT\n"
1417 "#  ifdef USESHADOWSAMPLER\n"
1418 "       gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
1419 "#  else\n"
1420 "       gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
1421 "#  endif\n"
1422 "# endif\n"
1423 "# ifdef USESHADOWMAP2D\n"
1424 "#  ifdef USESHADOWSAMPLER\n"
1425 "    gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
1426 "#  else\n"
1427 "    gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
1428 "#  endif\n"
1429 "# endif\n"
1430 "\n"
1431 "# ifdef USESHADOWMAPCUBE\n"
1432 "#  ifdef USESHADOWSAMPLER\n"
1433 "    gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
1434 "#  else\n"
1435 "    gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
1436 "#  endif\n"
1437 "# endif\n"
1438 "#endif\n"
1439 "}\n"
1440 "#endif // !MODE_REFRACTION\n"
1441 "#endif // !MODE_WATER\n"
1442 "\n"
1443 "#endif // FRAGMENT_SHADER\n"
1444 "\n"
1445 "#endif // !MODE_GENERIC\n"
1446 "#endif // !MODE_POSTPROCESS\n"
1447 "#endif // !MODE_SHOWDEPTH\n"
1448 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1449 ;
1450
1451 typedef struct shaderpermutationinfo_s
1452 {
1453         const char *pretext;
1454         const char *name;
1455 }
1456 shaderpermutationinfo_t;
1457
1458 typedef struct shadermodeinfo_s
1459 {
1460         const char *vertexfilename;
1461         const char *geometryfilename;
1462         const char *fragmentfilename;
1463         const char *pretext;
1464         const char *name;
1465 }
1466 shadermodeinfo_t;
1467
1468 typedef enum shaderpermutation_e
1469 {
1470         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1471         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1472         SHADERPERMUTATION_VIEWTINT = 1<<1, ///< view tint (postprocessing only)
1473         SHADERPERMUTATION_COLORMAPPING = 1<<2, ///< indicates this is a colormapped skin
1474         SHADERPERMUTATION_SATURATION = 1<<2, ///< saturation (postprocessing only)
1475         SHADERPERMUTATION_FOG = 1<<3, ///< tint the color by fog color or black if using additive blend mode
1476         SHADERPERMUTATION_GAMMARAMPS = 1<<3, ///< gamma (postprocessing only)
1477         SHADERPERMUTATION_CUBEFILTER = 1<<4, ///< (lightsource) use cubemap light filter
1478         SHADERPERMUTATION_GLOW = 1<<5, ///< (lightmap) blend in an additive glow texture
1479         SHADERPERMUTATION_BLOOM = 1<<5, ///< bloom (postprocessing only)
1480         SHADERPERMUTATION_SPECULAR = 1<<6, ///< (lightsource or deluxemapping) render specular effects
1481         SHADERPERMUTATION_POSTPROCESSING = 1<<6, ///< user defined postprocessing (postprocessing only)
1482         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<7, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1483         SHADERPERMUTATION_REFLECTION = 1<<8, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1484         SHADERPERMUTATION_OFFSETMAPPING = 1<<9, ///< adjust texcoords to roughly simulate a displacement mapped surface
1485         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1486         SHADERPERMUTATION_SHADOWMAPRECT = 1<<11, ///< (lightsource) use shadowmap rectangle texture as light filter
1487         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<12, ///< (lightsource) use shadowmap cubemap texture as light filter
1488         SHADERPERMUTATION_SHADOWMAP2D = 1<<13, ///< (lightsource) use shadowmap rectangle texture as light filter
1489         SHADERPERMUTATION_SHADOWMAPPCF = 1<<14, //< (lightsource) use percentage closer filtering on shadowmap test results
1490         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<15, //< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1491         SHADERPERMUTATION_SHADOWSAMPLER = 1<<16, //< (lightsource) use hardware shadowmap test
1492         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<17, //< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1493         SHADERPERMUTATION_LIMIT = 1<<18, ///< size of permutations array
1494         SHADERPERMUTATION_COUNT = 18 ///< size of shaderpermutationinfo array
1495 }
1496 shaderpermutation_t;
1497
1498 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1499 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1500 {
1501         {"#define USEDIFFUSE\n", " diffuse"},
1502         {"#define USEVERTEXTEXTUREBLEND\n#define USEVIEWTINT\n", " vertextextureblend/tint"},
1503         {"#define USECOLORMAPPING\n#define USESATURATION\n", " colormapping/saturation"},
1504         {"#define USEFOG\n#define USEGAMMARAMPS\n", " fog/gammaramps"},
1505         {"#define USECUBEFILTER\n", " cubefilter"},
1506         {"#define USEGLOW\n#define USEBLOOM\n", " glow/bloom"},
1507         {"#define USESPECULAR\n#define USEPOSTPROCESSING", " specular/postprocessing"},
1508         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1509         {"#define USEREFLECTION\n", " reflection"},
1510         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1511         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1512         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1513         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1514         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1515         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1516         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1517         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1518         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1519 };
1520
1521 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1522 typedef enum shadermode_e
1523 {
1524         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1525         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1526         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1527         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1528         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1529         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1530         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1531         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1532         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1533         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1534         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1535         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1536         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1537         SHADERMODE_COUNT
1538 }
1539 shadermode_t;
1540
1541 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1542 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1543 {
1544         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1545         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1546         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1547         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1548         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1549         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1550         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1551         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1552         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1553         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1554         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1555         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1556         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1557 };
1558
1559 struct r_glsl_permutation_s;
1560 typedef struct r_glsl_permutation_s
1561 {
1562         /// hash lookup data
1563         struct r_glsl_permutation_s *hashnext;
1564         unsigned int mode;
1565         unsigned int permutation;
1566
1567         /// indicates if we have tried compiling this permutation already
1568         qboolean compiled;
1569         /// 0 if compilation failed
1570         int program;
1571         /// locations of detected uniforms in program object, or -1 if not found
1572         int loc_Texture_First;
1573         int loc_Texture_Second;
1574         int loc_Texture_GammaRamps;
1575         int loc_Texture_Normal;
1576         int loc_Texture_Color;
1577         int loc_Texture_Gloss;
1578         int loc_Texture_Glow;
1579         int loc_Texture_SecondaryNormal;
1580         int loc_Texture_SecondaryColor;
1581         int loc_Texture_SecondaryGloss;
1582         int loc_Texture_SecondaryGlow;
1583         int loc_Texture_Pants;
1584         int loc_Texture_Shirt;
1585         int loc_Texture_FogMask;
1586         int loc_Texture_Lightmap;
1587         int loc_Texture_Deluxemap;
1588         int loc_Texture_Attenuation;
1589         int loc_Texture_Cube;
1590         int loc_Texture_Refraction;
1591         int loc_Texture_Reflection;
1592         int loc_Texture_ShadowMapRect;
1593         int loc_Texture_ShadowMapCube;
1594         int loc_Texture_ShadowMap2D;
1595         int loc_Texture_CubeProjection;
1596         int loc_FogColor;
1597         int loc_LightPosition;
1598         int loc_EyePosition;
1599         int loc_Color_Pants;
1600         int loc_Color_Shirt;
1601         int loc_FogRangeRecip;
1602         int loc_AmbientScale;
1603         int loc_DiffuseScale;
1604         int loc_SpecularScale;
1605         int loc_SpecularPower;
1606         int loc_GlowColor;
1607         int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1608         int loc_OffsetMapping_Scale;
1609         int loc_TintColor;
1610         int loc_AmbientColor;
1611         int loc_DiffuseColor;
1612         int loc_SpecularColor;
1613         int loc_LightDir;
1614         int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1615         int loc_GammaCoeff; ///< 1 / gamma
1616         int loc_DistortScaleRefractReflect;
1617         int loc_ScreenScaleRefractReflect;
1618         int loc_ScreenCenterRefractReflect;
1619         int loc_RefractColor;
1620         int loc_ReflectColor;
1621         int loc_ReflectFactor;
1622         int loc_ReflectOffset;
1623         int loc_UserVec1;
1624         int loc_UserVec2;
1625         int loc_UserVec3;
1626         int loc_UserVec4;
1627         int loc_ClientTime;
1628         int loc_PixelSize;
1629         int loc_Saturation;
1630         int loc_ShadowMap_TextureScale;
1631         int loc_ShadowMap_Parameters;
1632 }
1633 r_glsl_permutation_t;
1634
1635 #define SHADERPERMUTATION_HASHSIZE 4096
1636
1637 /// information about each possible shader permutation
1638 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1639 /// currently selected permutation
1640 r_glsl_permutation_t *r_glsl_permutation;
1641 /// storage for permutations linked in the hash table
1642 memexpandablearray_t r_glsl_permutationarray;
1643
1644 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1645 {
1646         //unsigned int hashdepth = 0;
1647         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1648         r_glsl_permutation_t *p;
1649         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1650         {
1651                 if (p->mode == mode && p->permutation == permutation)
1652                 {
1653                         //if (hashdepth > 10)
1654                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1655                         return p;
1656                 }
1657                 //hashdepth++;
1658         }
1659         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1660         p->mode = mode;
1661         p->permutation = permutation;
1662         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1663         r_glsl_permutationhash[mode][hashindex] = p;
1664         //if (hashdepth > 10)
1665         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1666         return p;
1667 }
1668
1669 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1670 {
1671         char *shaderstring;
1672         if (!filename || !filename[0])
1673                 return NULL;
1674         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1675         if (shaderstring)
1676         {
1677                 if (printfromdisknotice)
1678                         Con_DPrint("from disk... ");
1679                 return shaderstring;
1680         }
1681         else if (!strcmp(filename, "glsl/default.glsl"))
1682         {
1683                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1684                 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1685         }
1686         return shaderstring;
1687 }
1688
1689 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1690 {
1691         int i;
1692         shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1693         int vertstrings_count = 0;
1694         int geomstrings_count = 0;
1695         int fragstrings_count = 0;
1696         char *vertexstring, *geometrystring, *fragmentstring;
1697         const char *vertstrings_list[32+3];
1698         const char *geomstrings_list[32+3];
1699         const char *fragstrings_list[32+3];
1700         char permutationname[256];
1701
1702         if (p->compiled)
1703                 return;
1704         p->compiled = true;
1705         p->program = 0;
1706
1707         permutationname[0] = 0;
1708         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1709         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1710         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1711
1712         strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1713
1714         // the first pretext is which type of shader to compile as
1715         // (later these will all be bound together as a program object)
1716         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1717         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1718         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1719
1720         // the second pretext is the mode (for example a light source)
1721         vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1722         geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1723         fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1724         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1725
1726         // now add all the permutation pretexts
1727         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1728         {
1729                 if (permutation & (1<<i))
1730                 {
1731                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1732                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1733                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1734                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1735                 }
1736                 else
1737                 {
1738                         // keep line numbers correct
1739                         vertstrings_list[vertstrings_count++] = "\n";
1740                         geomstrings_list[geomstrings_count++] = "\n";
1741                         fragstrings_list[fragstrings_count++] = "\n";
1742                 }
1743         }
1744
1745         // now append the shader text itself
1746         vertstrings_list[vertstrings_count++] = vertexstring;
1747         geomstrings_list[geomstrings_count++] = geometrystring;
1748         fragstrings_list[fragstrings_count++] = fragmentstring;
1749
1750         // if any sources were NULL, clear the respective list
1751         if (!vertexstring)
1752                 vertstrings_count = 0;
1753         if (!geometrystring)
1754                 geomstrings_count = 0;
1755         if (!fragmentstring)
1756                 fragstrings_count = 0;
1757
1758         // compile the shader program
1759         if (vertstrings_count + geomstrings_count + fragstrings_count)
1760                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1761         if (p->program)
1762         {
1763                 CHECKGLERROR
1764                 qglUseProgramObjectARB(p->program);CHECKGLERROR
1765                 // look up all the uniform variable names we care about, so we don't
1766                 // have to look them up every time we set them
1767                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
1768                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
1769                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1770                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
1771                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
1772                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1773                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
1774                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1775                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1776                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1777                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1778                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1779                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
1780                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1781                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1782                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1783                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1784                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1785                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1786                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
1787                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1788                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1789                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1790                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");  
1791                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
1792                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
1793                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
1794                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
1795                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
1796                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1797                 p->loc_AmbientScale               = qglGetUniformLocationARB(p->program, "AmbientScale");
1798                 p->loc_DiffuseScale               = qglGetUniformLocationARB(p->program, "DiffuseScale");
1799                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
1800                 p->loc_SpecularScale              = qglGetUniformLocationARB(p->program, "SpecularScale");
1801                 p->loc_GlowColor                  = qglGetUniformLocationARB(p->program, "GlowColor");
1802                 p->loc_SceneBrightness            = qglGetUniformLocationARB(p->program, "SceneBrightness");
1803                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1804                 p->loc_TintColor                  = qglGetUniformLocationARB(p->program, "TintColor");
1805                 p->loc_AmbientColor               = qglGetUniformLocationARB(p->program, "AmbientColor");
1806                 p->loc_DiffuseColor               = qglGetUniformLocationARB(p->program, "DiffuseColor");
1807                 p->loc_SpecularColor              = qglGetUniformLocationARB(p->program, "SpecularColor");
1808                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
1809                 p->loc_ContrastBoostCoeff         = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1810                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1811                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1812                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1813                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
1814                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
1815                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
1816                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
1817                 p->loc_GammaCoeff                 = qglGetUniformLocationARB(p->program, "GammaCoeff");
1818                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
1819                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
1820                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
1821                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
1822                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
1823                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
1824                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
1825                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
1826                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
1827                 // initialize the samplers to refer to the texture units we use
1828                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
1829                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
1830                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
1831                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
1832                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
1833                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
1834                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
1835                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1836                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1837                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1838                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
1839                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
1840                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
1841                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
1842                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
1843                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
1844                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
1845                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
1846                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
1847                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
1848                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , GL20TU_SHADOWMAPRECT);
1849                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
1850                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
1851                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
1852                 CHECKGLERROR
1853                 if (developer.integer)
1854                         Con_Printf("GLSL shader %s compiled.\n", permutationname);
1855         }
1856         else
1857                 Con_Printf("GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1858
1859         // free the strings
1860         if (vertexstring)
1861                 Mem_Free(vertexstring);
1862         if (geometrystring)
1863                 Mem_Free(geometrystring);
1864         if (fragmentstring)
1865                 Mem_Free(fragmentstring);
1866 }
1867
1868 void R_GLSL_Restart_f(void)
1869 {
1870         unsigned int i, limit;
1871         r_glsl_permutation_t *p;
1872         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1873         for (i = 0;i < limit;i++)
1874         {
1875                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1876                 {
1877                         GL_Backend_FreeProgram(p->program);
1878                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1879                 }
1880         }
1881         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1882 }
1883
1884 void R_GLSL_DumpShader_f(void)
1885 {
1886         int i;
1887
1888         qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1889         if(!file)
1890         {
1891                 Con_Printf("failed to write to glsl/default.glsl\n");
1892                 return;
1893         }
1894
1895         FS_Print(file, "/* The engine may define the following macros:\n");
1896         FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1897         for (i = 0;i < SHADERMODE_COUNT;i++)
1898                 FS_Print(file, shadermodeinfo[i].pretext);
1899         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1900                 FS_Print(file, shaderpermutationinfo[i].pretext);
1901         FS_Print(file, "*/\n");
1902         FS_Print(file, builtinshaderstring);
1903         FS_Close(file);
1904
1905         Con_Printf("glsl/default.glsl written\n");
1906 }
1907
1908 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1909 {
1910         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1911         if (r_glsl_permutation != perm)
1912         {
1913                 r_glsl_permutation = perm;
1914                 if (!r_glsl_permutation->program)
1915                 {
1916                         if (!r_glsl_permutation->compiled)
1917                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1918                         if (!r_glsl_permutation->program)
1919                         {
1920                                 // remove features until we find a valid permutation
1921                                 int i;
1922                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1923                                 {
1924                                         // reduce i more quickly whenever it would not remove any bits
1925                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1926                                         if (!(permutation & j))
1927                                                 continue;
1928                                         permutation -= j;
1929                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1930                                         if (!r_glsl_permutation->compiled)
1931                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1932                                         if (r_glsl_permutation->program)
1933                                                 break;
1934                                 }
1935                                 if (i >= SHADERPERMUTATION_COUNT)
1936                                 {
1937                                         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");
1938                                         Cvar_SetValueQuick(&r_glsl, 0);
1939                                         R_GLSL_Restart_f(); // unload shaders
1940                                         return; // no bit left to clear
1941                                 }
1942                         }
1943                 }
1944                 CHECKGLERROR
1945                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1946         }
1947 }
1948
1949 void R_SetupGenericShader(qboolean usetexture)
1950 {
1951         if (gl_support_fragment_shader)
1952         {
1953                 if (r_glsl.integer && r_glsl_usegeneric.integer)
1954                         R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1955                 else if (r_glsl_permutation)
1956                 {
1957                         r_glsl_permutation = NULL;
1958                         qglUseProgramObjectARB(0);CHECKGLERROR
1959                 }
1960         }
1961 }
1962
1963 void R_SetupGenericTwoTextureShader(int texturemode)
1964 {
1965         if (gl_support_fragment_shader)
1966         {
1967                 if (r_glsl.integer && r_glsl_usegeneric.integer)
1968                         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))));
1969                 else if (r_glsl_permutation)
1970                 {
1971                         r_glsl_permutation = NULL;
1972                         qglUseProgramObjectARB(0);CHECKGLERROR
1973                 }
1974         }
1975         if (!r_glsl_permutation)
1976         {
1977                 if (texturemode == GL_DECAL && gl_combine.integer)
1978                         texturemode = GL_INTERPOLATE_ARB;
1979                 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1980         }
1981 }
1982
1983 void R_SetupDepthOrShadowShader(void)
1984 {
1985         if (gl_support_fragment_shader)
1986         {
1987                 if (r_glsl.integer && r_glsl_usegeneric.integer)
1988                         R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1989                 else if (r_glsl_permutation)
1990                 {
1991                         r_glsl_permutation = NULL;
1992                         qglUseProgramObjectARB(0);CHECKGLERROR
1993                 }
1994         }
1995 }
1996
1997 void R_SetupShowDepthShader(void)
1998 {
1999         if (gl_support_fragment_shader)
2000         {
2001                 if (r_glsl.integer && r_glsl_usegeneric.integer)
2002                         R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
2003                 else if (r_glsl_permutation)
2004                 {
2005                         r_glsl_permutation = NULL;
2006                         qglUseProgramObjectARB(0);CHECKGLERROR
2007                 }
2008         }
2009 }
2010
2011 extern rtexture_t *r_shadow_attenuationgradienttexture;
2012 extern rtexture_t *r_shadow_attenuation2dtexture;
2013 extern rtexture_t *r_shadow_attenuation3dtexture;
2014 extern qboolean r_shadow_usingshadowmaprect;
2015 extern qboolean r_shadow_usingshadowmapcube;
2016 extern qboolean r_shadow_usingshadowmap2d;
2017 extern float r_shadow_shadowmap_texturescale[2];
2018 extern float r_shadow_shadowmap_parameters[4];
2019 extern qboolean r_shadow_shadowmapvsdct;
2020 extern qboolean r_shadow_shadowmapsampler;
2021 extern int r_shadow_shadowmappcf;
2022 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2023 {
2024         // select a permutation of the lighting shader appropriate to this
2025         // combination of texture, entity, light source, and fogging, only use the
2026         // minimum features necessary to avoid wasting rendering time in the
2027         // fragment shader on features that are not being used
2028         unsigned int permutation = 0;
2029         unsigned int mode = 0;
2030         // TODO: implement geometry-shader based shadow volumes someday
2031         if (r_glsl_offsetmapping.integer)
2032         {
2033                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2034                 if (r_glsl_offsetmapping_reliefmapping.integer)
2035                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2036         }
2037         if (rsurfacepass == RSURFPASS_BACKGROUND)
2038         {
2039                 // distorted background
2040                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2041                         mode = SHADERMODE_WATER;
2042                 else
2043                         mode = SHADERMODE_REFRACTION;
2044         }
2045         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2046         {
2047                 // light source
2048                 mode = SHADERMODE_LIGHTSOURCE;
2049                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2050                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2051                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2052                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2053                 if (diffusescale > 0)
2054                         permutation |= SHADERPERMUTATION_DIFFUSE;
2055                 if (specularscale > 0)
2056                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2057                 if (r_refdef.fogenabled)
2058                         permutation |= SHADERPERMUTATION_FOG;
2059                 if (rsurface.texture->colormapping)
2060                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2061                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2062                 {
2063                         if (r_shadow_usingshadowmaprect)
2064                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2065                         if (r_shadow_usingshadowmap2d)
2066                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2067                         if (r_shadow_usingshadowmapcube)
2068                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2069                         else if(r_shadow_shadowmapvsdct)
2070                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2071
2072                         if (r_shadow_shadowmapsampler)
2073                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2074                         if (r_shadow_shadowmappcf > 1)
2075                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2076                         else if (r_shadow_shadowmappcf)
2077                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2078                 }
2079         }
2080         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2081         {
2082                 // unshaded geometry (fullbright or ambient model lighting)
2083                 mode = SHADERMODE_FLATCOLOR;
2084                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2085                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2086                 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2087                         permutation |= SHADERPERMUTATION_GLOW;
2088                 if (r_refdef.fogenabled)
2089                         permutation |= SHADERPERMUTATION_FOG;
2090                 if (rsurface.texture->colormapping)
2091                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2092                 if (r_glsl_offsetmapping.integer)
2093                 {
2094                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2095                         if (r_glsl_offsetmapping_reliefmapping.integer)
2096                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2097                 }
2098                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2099                         permutation |= SHADERPERMUTATION_REFLECTION;
2100         }
2101         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2102         {
2103                 // directional model lighting
2104                 mode = SHADERMODE_LIGHTDIRECTION;
2105                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2106                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2107                 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2108                         permutation |= SHADERPERMUTATION_GLOW;
2109                 permutation |= SHADERPERMUTATION_DIFFUSE;
2110                 if (specularscale > 0)
2111                         permutation |= SHADERPERMUTATION_SPECULAR;
2112                 if (r_refdef.fogenabled)
2113                         permutation |= SHADERPERMUTATION_FOG;
2114                 if (rsurface.texture->colormapping)
2115                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2116                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2117                         permutation |= SHADERPERMUTATION_REFLECTION;
2118         }
2119         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2120         {
2121                 // ambient model lighting
2122                 mode = SHADERMODE_LIGHTDIRECTION;
2123                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2124                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2125                 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2126                         permutation |= SHADERPERMUTATION_GLOW;
2127                 if (r_refdef.fogenabled)
2128                         permutation |= SHADERPERMUTATION_FOG;
2129                 if (rsurface.texture->colormapping)
2130                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2131                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2132                         permutation |= SHADERPERMUTATION_REFLECTION;
2133         }
2134         else
2135         {
2136                 // lightmapped wall
2137                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2138                 {
2139                         // deluxemapping (light direction texture)
2140                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2141                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2142                         else
2143                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2144                         permutation |= SHADERPERMUTATION_DIFFUSE;
2145                         if (specularscale > 0)
2146                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2147                 }
2148                 else if (r_glsl_deluxemapping.integer >= 2)
2149                 {
2150                         // fake deluxemapping (uniform light direction in tangentspace)
2151                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2152                         permutation |= SHADERPERMUTATION_DIFFUSE;
2153                         if (specularscale > 0)
2154                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2155                 }
2156                 else if (rsurface.uselightmaptexture)
2157                 {
2158                         // ordinary lightmapping (q1bsp, q3bsp)
2159                         mode = SHADERMODE_LIGHTMAP;
2160                 }
2161                 else
2162                 {
2163                         // ordinary vertex coloring (q3bsp)
2164                         mode = SHADERMODE_VERTEXCOLOR;
2165                 }
2166                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2167                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2168                 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2169                         permutation |= SHADERPERMUTATION_GLOW;
2170                 if (r_refdef.fogenabled)
2171                         permutation |= SHADERPERMUTATION_FOG;
2172                 if (rsurface.texture->colormapping)
2173                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2174                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2175                         permutation |= SHADERPERMUTATION_REFLECTION;
2176         }
2177         if(permutation & SHADERPERMUTATION_SPECULAR)
2178                 if(r_shadow_glossexact.integer)
2179                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2180         R_SetupShader_SetPermutation(mode, permutation);
2181         if (mode == SHADERMODE_LIGHTSOURCE)
2182         {
2183                 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2184                 if (permutation & SHADERPERMUTATION_DIFFUSE)
2185                 {
2186                         if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2187                         if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2188                         if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2189                         if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2190                 }
2191                 else
2192                 {
2193                         // ambient only is simpler
2194                         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]);
2195                         if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2196                         if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2197                         if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2198                 }
2199                 // additive passes are only darkened by fog, not tinted
2200                 if (r_glsl_permutation->loc_FogColor >= 0)
2201                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2202                 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]);
2203                 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]);
2204         }
2205         else
2206         {
2207                 if (mode == SHADERMODE_LIGHTDIRECTION)
2208                 {
2209                         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);
2210                         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);
2211                         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);
2212                         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]);
2213                 }
2214                 else
2215                 {
2216                         if (r_glsl_permutation->loc_AmbientScale  >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
2217                         if (r_glsl_permutation->loc_DiffuseScale  >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
2218                         if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
2219                 }
2220                 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]);
2221                 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);
2222                 // additive passes are only darkened by fog, not tinted
2223                 if (r_glsl_permutation->loc_FogColor >= 0)
2224                 {
2225                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2226                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2227                         else
2228                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2229                 }
2230                 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);
2231                 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]);
2232                 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]);
2233                 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2234                 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2235                 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2236                 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2237         }
2238         if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
2239         if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
2240         if (r_glsl_permutation->loc_Color_Pants >= 0)
2241         {
2242                 if (rsurface.texture->currentskinframe->pants)
2243                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2244                 else
2245                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2246         }
2247         if (r_glsl_permutation->loc_Color_Shirt >= 0)
2248         {
2249                 if (rsurface.texture->currentskinframe->shirt)
2250                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2251                 else
2252                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2253         }
2254         if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
2255         if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
2256         {
2257                 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
2258         }
2259         else
2260         {
2261                 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
2262         }
2263         if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2264         CHECKGLERROR
2265 }
2266
2267 #define SKINFRAME_HASH 1024
2268
2269 typedef struct
2270 {
2271         int loadsequence; // incremented each level change
2272         memexpandablearray_t array;
2273         skinframe_t *hash[SKINFRAME_HASH];
2274 }
2275 r_skinframe_t;
2276 r_skinframe_t r_skinframe;
2277
2278 void R_SkinFrame_PrepareForPurge(void)
2279 {
2280         r_skinframe.loadsequence++;
2281         // wrap it without hitting zero
2282         if (r_skinframe.loadsequence >= 200)
2283                 r_skinframe.loadsequence = 1;
2284 }
2285
2286 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2287 {
2288         if (!skinframe)
2289                 return;
2290         // mark the skinframe as used for the purging code
2291         skinframe->loadsequence = r_skinframe.loadsequence;
2292 }
2293
2294 void R_SkinFrame_Purge(void)
2295 {
2296         int i;
2297         skinframe_t *s;
2298         for (i = 0;i < SKINFRAME_HASH;i++)
2299         {
2300                 for (s = r_skinframe.hash[i];s;s = s->next)
2301                 {
2302                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2303                         {
2304                                 if (s->merged == s->base)
2305                                         s->merged = NULL;
2306                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2307                                 R_PurgeTexture(s->stain );s->stain  = NULL;
2308                                 R_PurgeTexture(s->merged);s->merged = NULL;
2309                                 R_PurgeTexture(s->base  );s->base   = NULL;
2310                                 R_PurgeTexture(s->pants );s->pants  = NULL;
2311                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
2312                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
2313                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
2314                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
2315                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
2316                                 s->loadsequence = 0;
2317                         }
2318                 }
2319         }
2320 }
2321
2322 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2323         skinframe_t *item;
2324         char basename[MAX_QPATH];
2325
2326         Image_StripImageExtension(name, basename, sizeof(basename));
2327
2328         if( last == NULL ) {
2329                 int hashindex;
2330                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2331                 item = r_skinframe.hash[hashindex];
2332         } else {
2333                 item = last->next;
2334         }
2335
2336         // linearly search through the hash bucket
2337         for( ; item ; item = item->next ) {
2338                 if( !strcmp( item->basename, basename ) ) {
2339                         return item;
2340                 }
2341         }
2342         return NULL;
2343 }
2344
2345 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2346 {
2347         skinframe_t *item;
2348         int hashindex;
2349         char basename[MAX_QPATH];
2350
2351         Image_StripImageExtension(name, basename, sizeof(basename));
2352
2353         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2354         for (item = r_skinframe.hash[hashindex];item;item = item->next)
2355                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2356                         break;
2357
2358         if (!item) {
2359                 rtexture_t *dyntexture;
2360                 // check whether its a dynamic texture
2361                 dyntexture = CL_GetDynTexture( basename );
2362                 if (!add && !dyntexture)
2363                         return NULL;
2364                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2365                 memset(item, 0, sizeof(*item));
2366                 strlcpy(item->basename, basename, sizeof(item->basename));
2367                 item->base = dyntexture; // either NULL or dyntexture handle
2368                 item->textureflags = textureflags;
2369                 item->comparewidth = comparewidth;
2370                 item->compareheight = compareheight;
2371                 item->comparecrc = comparecrc;
2372                 item->next = r_skinframe.hash[hashindex];
2373                 r_skinframe.hash[hashindex] = item;
2374         }
2375         else if( item->base == NULL )
2376         {
2377                 rtexture_t *dyntexture;
2378                 // check whether its a dynamic texture
2379                 // 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]
2380                 dyntexture = CL_GetDynTexture( basename );
2381                 item->base = dyntexture; // either NULL or dyntexture handle
2382         }
2383
2384         R_SkinFrame_MarkUsed(item);
2385         return item;
2386 }
2387
2388 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2389         { \
2390                 unsigned long long avgcolor[5], wsum; \
2391                 int pix, comp, w; \
2392                 avgcolor[0] = 0; \
2393                 avgcolor[1] = 0; \
2394                 avgcolor[2] = 0; \
2395                 avgcolor[3] = 0; \
2396                 avgcolor[4] = 0; \
2397                 wsum = 0; \
2398                 for(pix = 0; pix < cnt; ++pix) \
2399                 { \
2400                         w = 0; \
2401                         for(comp = 0; comp < 3; ++comp) \
2402                                 w += getpixel; \
2403                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2404                         { \
2405                                 ++wsum; \
2406                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2407                                 w = getpixel; \
2408                                 for(comp = 0; comp < 3; ++comp) \
2409                                         avgcolor[comp] += getpixel * w; \
2410                                 avgcolor[3] += w; \
2411                         } \
2412                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2413                         avgcolor[4] += getpixel; \
2414                 } \
2415                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2416                         avgcolor[3] = 1; \
2417                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2418                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2419                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2420                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2421         }
2422
2423 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
2424 {
2425         // FIXME: it should be possible to disable loading various layers using
2426         // cvars, to prevent wasted loading time and memory usage if the user does
2427         // not want them
2428         qboolean loadnormalmap = true;
2429         qboolean loadgloss = true;
2430         qboolean loadpantsandshirt = true;
2431         qboolean loadglow = true;
2432         int j;
2433         unsigned char *pixels;
2434         unsigned char *bumppixels;
2435         unsigned char *basepixels = NULL;
2436         int basepixels_width;
2437         int basepixels_height;
2438         skinframe_t *skinframe;
2439
2440         if (has_alpha)
2441                 *has_alpha = false;
2442
2443         if (cls.state == ca_dedicated)
2444                 return NULL;
2445
2446         // return an existing skinframe if already loaded
2447         // if loading of the first image fails, don't make a new skinframe as it
2448         // would cause all future lookups of this to be missing
2449         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2450         if (skinframe && skinframe->base)
2451                 return skinframe;
2452
2453         basepixels = loadimagepixelsbgra(name, complain, true);
2454         if (basepixels == NULL)
2455                 return NULL;
2456
2457         if (developer_loading.integer)
2458                 Con_Printf("loading skin \"%s\"\n", name);
2459
2460         // we've got some pixels to store, so really allocate this new texture now
2461         if (!skinframe)
2462                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2463         skinframe->stain = NULL;
2464         skinframe->merged = NULL;
2465         skinframe->base = r_texture_notexture;
2466         skinframe->pants = NULL;
2467         skinframe->shirt = NULL;
2468         skinframe->nmap = r_texture_blanknormalmap;
2469         skinframe->gloss = NULL;
2470         skinframe->glow = NULL;
2471         skinframe->fog = NULL;
2472
2473         basepixels_width = image_width;
2474         basepixels_height = image_height;
2475         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);
2476
2477         if (textureflags & TEXF_ALPHA)
2478         {
2479                 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2480                         if (basepixels[j] < 255)
2481                                 break;
2482                 if (j < basepixels_width * basepixels_height * 4)
2483                 {
2484                         // has transparent pixels
2485                         if (has_alpha)
2486                                 *has_alpha = true;
2487                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2488                         for (j = 0;j < image_width * image_height * 4;j += 4)
2489                         {
2490                                 pixels[j+0] = 255;
2491                                 pixels[j+1] = 255;
2492                                 pixels[j+2] = 255;
2493                                 pixels[j+3] = basepixels[j+3];
2494                         }
2495                         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);
2496                         Mem_Free(pixels);
2497                 }
2498         }
2499
2500         R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2501         //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]);
2502
2503         // _norm is the name used by tenebrae and has been adopted as standard
2504         if (loadnormalmap)
2505         {
2506                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2507                 {
2508                         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);
2509                         Mem_Free(pixels);
2510                         pixels = NULL;
2511                 }
2512                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2513                 {
2514                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2515                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2516                         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);
2517                         Mem_Free(pixels);
2518                         Mem_Free(bumppixels);
2519                 }
2520                 else if (r_shadow_bumpscale_basetexture.value > 0)
2521                 {
2522                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2523                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2524                         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);
2525                         Mem_Free(pixels);
2526                 }
2527         }
2528         // _luma is supported for tenebrae compatibility
2529         // (I think it's a very stupid name, but oh well)
2530         // _glow is the preferred name
2531         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;}
2532         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;}
2533         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;}
2534         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;}
2535
2536         if (basepixels)
2537                 Mem_Free(basepixels);
2538
2539         return skinframe;
2540 }
2541
2542 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2543 {
2544         return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, NULL);
2545 }
2546
2547 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)
2548 {
2549         int i;
2550         if (!force)
2551         {
2552                 for (i = 0;i < width*height;i++)
2553                         if (((unsigned char *)&palette[in[i]])[3] > 0)
2554                                 break;
2555                 if (i == width*height)
2556                         return NULL;
2557         }
2558         return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2559 }
2560
2561 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2562 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2563 {
2564         int i;
2565         unsigned char *temp1, *temp2;
2566         skinframe_t *skinframe;
2567
2568         if (cls.state == ca_dedicated)
2569                 return NULL;
2570
2571         // if already loaded just return it, otherwise make a new skinframe
2572         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2573         if (skinframe && skinframe->base)
2574                 return skinframe;
2575
2576         skinframe->stain = NULL;
2577         skinframe->merged = NULL;
2578         skinframe->base = r_texture_notexture;
2579         skinframe->pants = NULL;
2580         skinframe->shirt = NULL;
2581         skinframe->nmap = r_texture_blanknormalmap;
2582         skinframe->gloss = NULL;
2583         skinframe->glow = NULL;
2584         skinframe->fog = NULL;
2585
2586         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2587         if (!skindata)
2588                 return NULL;
2589
2590         if (developer_loading.integer)
2591                 Con_Printf("loading 32bit skin \"%s\"\n", name);
2592
2593         if (r_shadow_bumpscale_basetexture.value > 0)
2594         {
2595                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2596                 temp2 = temp1 + width * height * 4;
2597                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2598                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2599                 Mem_Free(temp1);
2600         }
2601         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2602         if (textureflags & TEXF_ALPHA)
2603         {
2604                 for (i = 3;i < width * height * 4;i += 4)
2605                         if (skindata[i] < 255)
2606                                 break;
2607                 if (i < width * height * 4)
2608                 {
2609                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2610                         memcpy(fogpixels, skindata, width * height * 4);
2611                         for (i = 0;i < width * height * 4;i += 4)
2612                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2613                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2614                         Mem_Free(fogpixels);
2615                 }
2616         }
2617
2618         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2619         //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]);
2620
2621         return skinframe;
2622 }
2623
2624 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2625 {
2626         int i;
2627         unsigned char *temp1, *temp2;
2628         unsigned int *palette;
2629         skinframe_t *skinframe;
2630
2631         if (cls.state == ca_dedicated)
2632                 return NULL;
2633
2634         // if already loaded just return it, otherwise make a new skinframe
2635         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2636         if (skinframe && skinframe->base)
2637                 return skinframe;
2638
2639         palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2640
2641         skinframe->stain = NULL;
2642         skinframe->merged = NULL;
2643         skinframe->base = r_texture_notexture;
2644         skinframe->pants = NULL;
2645         skinframe->shirt = NULL;
2646         skinframe->nmap = r_texture_blanknormalmap;
2647         skinframe->gloss = NULL;
2648         skinframe->glow = NULL;
2649         skinframe->fog = NULL;
2650
2651         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2652         if (!skindata)
2653                 return NULL;
2654
2655         if (developer_loading.integer)
2656                 Con_Printf("loading quake skin \"%s\"\n", name);
2657
2658         if (r_shadow_bumpscale_basetexture.value > 0)
2659         {
2660                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2661                 temp2 = temp1 + width * height * 4;
2662                 // use either a custom palette or the quake palette
2663                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2664                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2665                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2666                 Mem_Free(temp1);
2667         }
2668         // use either a custom palette, or the quake palette
2669         skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2670         if (loadglowtexture)
2671                 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2672         if (loadpantsandshirt)
2673         {
2674                 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2675                 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2676         }
2677         if (skinframe->pants || skinframe->shirt)
2678                 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
2679         if (textureflags & TEXF_ALPHA)
2680         {
2681                 for (i = 0;i < width * height;i++)
2682                         if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2683                                 break;
2684                 if (i < width * height)
2685                         skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2686         }
2687
2688         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2689         //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]);
2690
2691         return skinframe;
2692 }
2693
2694 skinframe_t *R_SkinFrame_LoadMissing(void)
2695 {
2696         skinframe_t *skinframe;
2697
2698         if (cls.state == ca_dedicated)
2699                 return NULL;
2700
2701         skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2702         skinframe->stain = NULL;
2703         skinframe->merged = NULL;
2704         skinframe->base = r_texture_notexture;
2705         skinframe->pants = NULL;
2706         skinframe->shirt = NULL;
2707         skinframe->nmap = r_texture_blanknormalmap;
2708         skinframe->gloss = NULL;
2709         skinframe->glow = NULL;
2710         skinframe->fog = NULL;
2711
2712         skinframe->avgcolor[0] = rand() / RAND_MAX;
2713         skinframe->avgcolor[1] = rand() / RAND_MAX;
2714         skinframe->avgcolor[2] = rand() / RAND_MAX;
2715         skinframe->avgcolor[3] = 1;
2716
2717         return skinframe;
2718 }
2719
2720 void gl_main_start(void)
2721 {
2722         r_numqueries = 0;
2723         r_maxqueries = 0;
2724         memset(r_queries, 0, sizeof(r_queries));
2725
2726         r_qwskincache = NULL;
2727         r_qwskincache_size = 0;
2728
2729         // set up r_skinframe loading system for textures
2730         memset(&r_skinframe, 0, sizeof(r_skinframe));
2731         r_skinframe.loadsequence = 1;
2732         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2733
2734         r_main_texturepool = R_AllocTexturePool();
2735         R_BuildBlankTextures();
2736         R_BuildNoTexture();
2737         if (gl_texturecubemap)
2738         {
2739                 R_BuildWhiteCube();
2740                 R_BuildNormalizationCube();
2741         }
2742         r_texture_fogattenuation = NULL;
2743         r_texture_gammaramps = NULL;
2744         //r_texture_fogintensity = NULL;
2745         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2746         memset(&r_waterstate, 0, sizeof(r_waterstate));
2747         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2748         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
2749         memset(&r_svbsp, 0, sizeof (r_svbsp));
2750
2751         r_refdef.fogmasktable_density = 0;
2752 }
2753
2754 extern rtexture_t *loadingscreentexture;
2755 void gl_main_shutdown(void)
2756 {
2757         if (r_maxqueries)
2758                 qglDeleteQueriesARB(r_maxqueries, r_queries);
2759
2760         r_numqueries = 0;
2761         r_maxqueries = 0;
2762         memset(r_queries, 0, sizeof(r_queries));
2763
2764         r_qwskincache = NULL;
2765         r_qwskincache_size = 0;
2766
2767         // clear out the r_skinframe state
2768         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2769         memset(&r_skinframe, 0, sizeof(r_skinframe));
2770
2771         if (r_svbsp.nodes)
2772                 Mem_Free(r_svbsp.nodes);
2773         memset(&r_svbsp, 0, sizeof (r_svbsp));
2774         R_FreeTexturePool(&r_main_texturepool);
2775         loadingscreentexture = NULL;
2776         r_texture_blanknormalmap = NULL;
2777         r_texture_white = NULL;
2778         r_texture_grey128 = NULL;
2779         r_texture_black = NULL;
2780         r_texture_whitecube = NULL;
2781         r_texture_normalizationcube = NULL;
2782         r_texture_fogattenuation = NULL;
2783         r_texture_gammaramps = NULL;
2784         //r_texture_fogintensity = NULL;
2785         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2786         memset(&r_waterstate, 0, sizeof(r_waterstate));
2787         R_GLSL_Restart_f();
2788 }
2789
2790 extern void CL_ParseEntityLump(char *entitystring);
2791 void gl_main_newmap(void)
2792 {
2793         // FIXME: move this code to client
2794         int l;
2795         char *entities, entname[MAX_QPATH];
2796         if (r_qwskincache)
2797                 Mem_Free(r_qwskincache);
2798         r_qwskincache = NULL;
2799         r_qwskincache_size = 0;
2800         if (cl.worldmodel)
2801         {
2802                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2803                 l = (int)strlen(entname) - 4;
2804                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2805                 {
2806                         memcpy(entname + l, ".ent", 5);
2807                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2808                         {
2809                                 CL_ParseEntityLump(entities);
2810                                 Mem_Free(entities);
2811                                 return;
2812                         }
2813                 }
2814                 if (cl.worldmodel->brush.entities)
2815                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
2816         }
2817 }
2818
2819 void GL_Main_Init(void)
2820 {
2821         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2822
2823         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2824         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2825         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2826         if (gamemode == GAME_NEHAHRA)
2827         {
2828                 Cvar_RegisterVariable (&gl_fogenable);
2829                 Cvar_RegisterVariable (&gl_fogdensity);
2830                 Cvar_RegisterVariable (&gl_fogred);
2831                 Cvar_RegisterVariable (&gl_foggreen);
2832                 Cvar_RegisterVariable (&gl_fogblue);
2833                 Cvar_RegisterVariable (&gl_fogstart);
2834                 Cvar_RegisterVariable (&gl_fogend);
2835                 Cvar_RegisterVariable (&gl_skyclip);
2836         }
2837         Cvar_RegisterVariable(&r_motionblur);
2838         Cvar_RegisterVariable(&r_motionblur_maxblur);
2839         Cvar_RegisterVariable(&r_motionblur_bmin);
2840         Cvar_RegisterVariable(&r_motionblur_vmin);
2841         Cvar_RegisterVariable(&r_motionblur_vmax);
2842         Cvar_RegisterVariable(&r_motionblur_vcoeff);
2843         Cvar_RegisterVariable(&r_motionblur_randomize);
2844         Cvar_RegisterVariable(&r_damageblur);
2845         Cvar_RegisterVariable(&r_animcache);
2846         Cvar_RegisterVariable(&r_depthfirst);
2847         Cvar_RegisterVariable(&r_useinfinitefarclip);
2848         Cvar_RegisterVariable(&r_nearclip);
2849         Cvar_RegisterVariable(&r_showbboxes);
2850         Cvar_RegisterVariable(&r_showsurfaces);
2851         Cvar_RegisterVariable(&r_showtris);
2852         Cvar_RegisterVariable(&r_shownormals);
2853         Cvar_RegisterVariable(&r_showlighting);
2854         Cvar_RegisterVariable(&r_showshadowvolumes);
2855         Cvar_RegisterVariable(&r_showcollisionbrushes);
2856         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2857         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2858         Cvar_RegisterVariable(&r_showdisabledepthtest);
2859         Cvar_RegisterVariable(&r_drawportals);
2860         Cvar_RegisterVariable(&r_drawentities);
2861         Cvar_RegisterVariable(&r_cullentities_trace);
2862         Cvar_RegisterVariable(&r_cullentities_trace_samples);
2863         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2864         Cvar_RegisterVariable(&r_cullentities_trace_delay);
2865         Cvar_RegisterVariable(&r_drawviewmodel);
2866         Cvar_RegisterVariable(&r_speeds);
2867         Cvar_RegisterVariable(&r_fullbrights);
2868         Cvar_RegisterVariable(&r_wateralpha);
2869         Cvar_RegisterVariable(&r_dynamic);
2870         Cvar_RegisterVariable(&r_fullbright);
2871         Cvar_RegisterVariable(&r_shadows);
2872         Cvar_RegisterVariable(&r_shadows_darken);
2873         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
2874         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
2875         Cvar_RegisterVariable(&r_shadows_throwdistance);
2876         Cvar_RegisterVariable(&r_shadows_throwdirection);
2877         Cvar_RegisterVariable(&r_q1bsp_skymasking);
2878         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2879         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2880         Cvar_RegisterVariable(&r_fog_exp2);
2881         Cvar_RegisterVariable(&r_drawfog);
2882         Cvar_RegisterVariable(&r_textureunits);
2883         Cvar_RegisterVariable(&r_glsl);
2884         Cvar_RegisterVariable(&r_glsl_deluxemapping);
2885         Cvar_RegisterVariable(&r_glsl_offsetmapping);
2886         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2887         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2888         Cvar_RegisterVariable(&r_glsl_postprocess);
2889         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2890         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2891         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2892         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2893         Cvar_RegisterVariable(&r_glsl_usegeneric);
2894         Cvar_RegisterVariable(&r_water);
2895         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2896         Cvar_RegisterVariable(&r_water_clippingplanebias);
2897         Cvar_RegisterVariable(&r_water_refractdistort);
2898         Cvar_RegisterVariable(&r_water_reflectdistort);
2899         Cvar_RegisterVariable(&r_lerpsprites);
2900         Cvar_RegisterVariable(&r_lerpmodels);
2901         Cvar_RegisterVariable(&r_lerplightstyles);
2902         Cvar_RegisterVariable(&r_waterscroll);
2903         Cvar_RegisterVariable(&r_bloom);
2904         Cvar_RegisterVariable(&r_bloom_colorscale);
2905         Cvar_RegisterVariable(&r_bloom_brighten);
2906         Cvar_RegisterVariable(&r_bloom_blur);
2907         Cvar_RegisterVariable(&r_bloom_resolution);
2908         Cvar_RegisterVariable(&r_bloom_colorexponent);
2909         Cvar_RegisterVariable(&r_bloom_colorsubtract);
2910         Cvar_RegisterVariable(&r_hdr);
2911         Cvar_RegisterVariable(&r_hdr_scenebrightness);
2912         Cvar_RegisterVariable(&r_hdr_glowintensity);
2913         Cvar_RegisterVariable(&r_hdr_range);
2914         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2915         Cvar_RegisterVariable(&developer_texturelogging);
2916         Cvar_RegisterVariable(&gl_lightmaps);
2917         Cvar_RegisterVariable(&r_test);
2918         Cvar_RegisterVariable(&r_batchmode);
2919         Cvar_RegisterVariable(&r_glsl_saturation);
2920         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2921                 Cvar_SetValue("r_fullbrights", 0);
2922         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2923
2924         Cvar_RegisterVariable(&r_track_sprites);
2925         Cvar_RegisterVariable(&r_track_sprites_flags);
2926         Cvar_RegisterVariable(&r_track_sprites_scalew);
2927         Cvar_RegisterVariable(&r_track_sprites_scaleh);
2928 }
2929
2930 extern void R_Textures_Init(void);
2931 extern void GL_Draw_Init(void);
2932 extern void GL_Main_Init(void);
2933 extern void R_Shadow_Init(void);
2934 extern void R_Sky_Init(void);
2935 extern void GL_Surf_Init(void);
2936 extern void R_Particles_Init(void);
2937 extern void R_Explosion_Init(void);
2938 extern void gl_backend_init(void);
2939 extern void Sbar_Init(void);
2940 extern void R_LightningBeams_Init(void);
2941 extern void Mod_RenderInit(void);
2942
2943 void Render_Init(void)
2944 {
2945         gl_backend_init();
2946         R_Textures_Init();
2947         GL_Main_Init();
2948         GL_Draw_Init();
2949         R_Shadow_Init();
2950         R_Sky_Init();
2951         GL_Surf_Init();
2952         Sbar_Init();
2953         R_Particles_Init();
2954         R_Explosion_Init();
2955         R_LightningBeams_Init();
2956         Mod_RenderInit();
2957 }
2958
2959 /*
2960 ===============
2961 GL_Init
2962 ===============
2963 */
2964 extern char *ENGINE_EXTENSIONS;
2965 void GL_Init (void)
2966 {
2967         gl_renderer = (const char *)qglGetString(GL_RENDERER);
2968         gl_vendor = (const char *)qglGetString(GL_VENDOR);
2969         gl_version = (const char *)qglGetString(GL_VERSION);
2970         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2971
2972         if (!gl_extensions)
2973                 gl_extensions = "";
2974         if (!gl_platformextensions)
2975                 gl_platformextensions = "";
2976
2977         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2978         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2979         Con_Printf("GL_VERSION: %s\n", gl_version);
2980         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
2981         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2982
2983         VID_CheckExtensions();
2984
2985         // LordHavoc: report supported extensions
2986         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2987
2988         // clear to black (loading plaque will be seen over this)
2989         CHECKGLERROR
2990         qglClearColor(0,0,0,1);CHECKGLERROR
2991         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2992 }
2993
2994 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2995 {
2996         int i;
2997         mplane_t *p;
2998         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2999         {
3000                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
3001                 if (i == 4)
3002                         continue;
3003                 p = r_refdef.view.frustum + i;
3004                 switch(p->signbits)
3005                 {
3006                 default:
3007                 case 0:
3008                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3009                                 return true;
3010                         break;
3011                 case 1:
3012                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3013                                 return true;
3014                         break;
3015                 case 2:
3016                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3017                                 return true;
3018                         break;
3019                 case 3:
3020                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3021                                 return true;
3022                         break;
3023                 case 4:
3024                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3025                                 return true;
3026                         break;
3027                 case 5:
3028                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3029                                 return true;
3030                         break;
3031                 case 6:
3032                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3033                                 return true;
3034                         break;
3035                 case 7:
3036                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3037                                 return true;
3038                         break;
3039                 }
3040         }
3041         return false;
3042 }
3043
3044 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3045 {
3046         int i;
3047         const mplane_t *p;
3048         for (i = 0;i < numplanes;i++)
3049         {
3050                 p = planes + i;
3051                 switch(p->signbits)
3052                 {
3053                 default:
3054                 case 0:
3055                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3056                                 return true;
3057                         break;
3058                 case 1:
3059                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3060                                 return true;
3061                         break;
3062                 case 2:
3063                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3064                                 return true;
3065                         break;
3066                 case 3:
3067                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3068                                 return true;
3069                         break;
3070                 case 4:
3071                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3072                                 return true;
3073                         break;
3074                 case 5:
3075                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3076                                 return true;
3077                         break;
3078                 case 6:
3079                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3080                                 return true;
3081                         break;
3082                 case 7:
3083                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3084                                 return true;
3085                         break;
3086                 }
3087         }
3088         return false;
3089 }
3090
3091 //==================================================================================
3092
3093 // LordHavoc: animcache written by Echon, refactored and reformatted by me
3094
3095 /**
3096  * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
3097  * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
3098  * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
3099  */
3100
3101 typedef struct r_animcache_entity_s
3102 {
3103         float *vertex3f;
3104         float *normal3f;
3105         float *svector3f;
3106         float *tvector3f;
3107         int maxvertices;
3108         qboolean wantnormals;
3109         qboolean wanttangents;
3110 }
3111 r_animcache_entity_t;
3112
3113 typedef struct r_animcache_s
3114 {
3115         r_animcache_entity_t entity[MAX_EDICTS*2];
3116         int maxindex;
3117         int currentindex;
3118 }
3119 r_animcache_t;
3120
3121 static r_animcache_t r_animcachestate;
3122
3123 void R_AnimCache_Free(void)
3124 {
3125         int idx;
3126         for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
3127         {
3128                 r_animcachestate.entity[idx].maxvertices = 0;
3129                 Mem_Free(r_animcachestate.entity[idx].vertex3f);
3130                 r_animcachestate.entity[idx].vertex3f = NULL;
3131                 r_animcachestate.entity[idx].normal3f = NULL;
3132                 r_animcachestate.entity[idx].svector3f = NULL;
3133                 r_animcachestate.entity[idx].tvector3f = NULL;
3134         }
3135         r_animcachestate.currentindex = 0;
3136         r_animcachestate.maxindex = 0;
3137 }
3138
3139 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
3140 {
3141         int arraySize;
3142         float *base;
3143         r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
3144
3145         if (cache->maxvertices >= numvertices)
3146                 return;
3147
3148         // Release existing memory
3149         if (cache->vertex3f)
3150                 Mem_Free(cache->vertex3f);
3151
3152         // Pad by 1024 verts
3153         cache->maxvertices = (numvertices + 1023) & ~1023;
3154         arraySize = cache->maxvertices * 3;
3155
3156         // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3157         base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3158         r_animcachestate.entity[cacheIdx].vertex3f = base;
3159         r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3160         r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3161         r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3162
3163 //      Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3164 }
3165
3166 void R_AnimCache_NewFrame(void)
3167 {
3168         int i;
3169
3170         if (r_animcache.integer && r_drawentities.integer)
3171                 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3172         else if (r_animcachestate.maxindex)
3173                 R_AnimCache_Free();
3174
3175         r_animcachestate.currentindex = 0;
3176
3177         for (i = 0;i < r_refdef.scene.numentities;i++)
3178                 r_refdef.scene.entities[i]->animcacheindex = -1;
3179 }
3180
3181 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3182 {
3183         dp_model_t *model = ent->model;
3184         r_animcache_entity_t *c;
3185         // see if it's already cached this frame
3186         if (ent->animcacheindex >= 0)
3187         {
3188                 // add normals/tangents if needed
3189                 c = r_animcachestate.entity + ent->animcacheindex;
3190                 if (c->wantnormals)
3191                         wantnormals = false;
3192                 if (c->wanttangents)
3193                         wanttangents = false;
3194                 if (wantnormals || wanttangents)
3195                         model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3196         }
3197         else
3198         {
3199                 // see if this ent is worth caching
3200                 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3201                         return false;
3202                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3203                         return false;
3204                 // assign it a cache entry and make sure the arrays are big enough
3205                 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3206                 ent->animcacheindex = r_animcachestate.currentindex++;
3207                 c = r_animcachestate.entity + ent->animcacheindex;
3208                 c->wantnormals = wantnormals;
3209                 c->wanttangents = wanttangents;
3210                 model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3211         }
3212         return true;
3213 }
3214