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