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