]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
replaced World_Clear with World_SetSize and World_UnlinkAll
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
30
31 //
32 // screen size info
33 //
34 r_refdef_t r_refdef;
35
36 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "1", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
37 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
38 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
39 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)"};
40 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
41 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
42 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"};
43 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"};
44 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
45 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"};
46 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"};
47 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"};
48 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
49 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
50 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
51 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
52 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
53 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
54 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
55 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
56 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
57 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
58 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
59 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
60 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
61 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
62 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
63 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"};
64 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"};
65 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
66
67 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
68 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
69 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
70 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
71 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
72 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
73 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
74 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
75
76 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
77
78 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
79 cvar_t r_glsl_contrastboost = {CVAR_SAVE, "r_glsl_contrastboost", "1", "by how much to multiply the contrast in dark areas (1 is no change)"};
80 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)"};
81 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
82 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
83 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
84 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
85 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)"};
86 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)"};
87 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)"};
88 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)"};
89 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)"};
90
91 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)"};
92 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
93 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"};
94 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
95 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
96
97 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
98 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
99 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
100 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
101
102 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
103 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
104 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
105 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
106 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
107 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
108 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
109
110 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
111 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
112 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
113 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)"};
114
115 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"};
116
117 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"};
118
119 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
120
121 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
122 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
123 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"};
124 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
125 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
126 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
127
128 extern cvar_t v_glslgamma;
129
130 extern qboolean v_flipped_state;
131
132 static struct r_bloomstate_s
133 {
134         qboolean enabled;
135         qboolean hdr;
136
137         int bloomwidth, bloomheight;
138
139         int screentexturewidth, screentextureheight;
140         rtexture_t *texture_screen;
141
142         int bloomtexturewidth, bloomtextureheight;
143         rtexture_t *texture_bloom;
144
145         // arrays for rendering the screen passes
146         float screentexcoord2f[8];
147         float bloomtexcoord2f[8];
148         float offsettexcoord2f[8];
149 }
150 r_bloomstate;
151
152 r_waterstate_t r_waterstate;
153
154 // shadow volume bsp struct with automatically growing nodes buffer
155 svbsp_t r_svbsp;
156
157 rtexture_t *r_texture_blanknormalmap;
158 rtexture_t *r_texture_white;
159 rtexture_t *r_texture_grey128;
160 rtexture_t *r_texture_black;
161 rtexture_t *r_texture_notexture;
162 rtexture_t *r_texture_whitecube;
163 rtexture_t *r_texture_normalizationcube;
164 rtexture_t *r_texture_fogattenuation;
165 rtexture_t *r_texture_gammaramps;
166 unsigned int r_texture_gammaramps_serial;
167 //rtexture_t *r_texture_fogintensity;
168
169 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
170 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
171
172 // vertex coordinates for a quad that covers the screen exactly
173 const static float r_screenvertex3f[12] =
174 {
175         0, 0, 0,
176         1, 0, 0,
177         1, 1, 0,
178         0, 1, 0
179 };
180
181 extern void R_DrawModelShadows(void);
182
183 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
184 {
185         int i;
186         for (i = 0;i < verts;i++)
187         {
188                 out[0] = in[0] * r;
189                 out[1] = in[1] * g;
190                 out[2] = in[2] * b;
191                 out[3] = in[3];
192                 in += 4;
193                 out += 4;
194         }
195 }
196
197 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
198 {
199         int i;
200         for (i = 0;i < verts;i++)
201         {
202                 out[0] = r;
203                 out[1] = g;
204                 out[2] = b;
205                 out[3] = a;
206                 out += 4;
207         }
208 }
209
210 // FIXME: move this to client?
211 void FOG_clear(void)
212 {
213         if (gamemode == GAME_NEHAHRA)
214         {
215                 Cvar_Set("gl_fogenable", "0");
216                 Cvar_Set("gl_fogdensity", "0.2");
217                 Cvar_Set("gl_fogred", "0.3");
218                 Cvar_Set("gl_foggreen", "0.3");
219                 Cvar_Set("gl_fogblue", "0.3");
220         }
221         r_refdef.fog_density = 0;
222         r_refdef.fog_red = 0;
223         r_refdef.fog_green = 0;
224         r_refdef.fog_blue = 0;
225         r_refdef.fog_alpha = 1;
226         r_refdef.fog_start = 0;
227         r_refdef.fog_end = 0;
228 }
229
230 float FogForDistance(vec_t dist)
231 {
232         unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
233         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
234 }
235
236 float FogPoint_World(const vec3_t p)
237 {
238         return FogForDistance(VectorDistance((p), r_refdef.view.origin));
239 }
240
241 float FogPoint_Model(const vec3_t p)
242 {
243         return FogForDistance(VectorDistance((p), rsurface.modelorg));
244 }
245
246 static void R_BuildBlankTextures(void)
247 {
248         unsigned char data[4];
249         data[2] = 128; // normal X
250         data[1] = 128; // normal Y
251         data[0] = 255; // normal Z
252         data[3] = 128; // height
253         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
254         data[0] = 255;
255         data[1] = 255;
256         data[2] = 255;
257         data[3] = 255;
258         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
259         data[0] = 128;
260         data[1] = 128;
261         data[2] = 128;
262         data[3] = 255;
263         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
264         data[0] = 0;
265         data[1] = 0;
266         data[2] = 0;
267         data[3] = 255;
268         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
269 }
270
271 static void R_BuildNoTexture(void)
272 {
273         int x, y;
274         unsigned char pix[16][16][4];
275         // this makes a light grey/dark grey checkerboard texture
276         for (y = 0;y < 16;y++)
277         {
278                 for (x = 0;x < 16;x++)
279                 {
280                         if ((y < 8) ^ (x < 8))
281                         {
282                                 pix[y][x][0] = 128;
283                                 pix[y][x][1] = 128;
284                                 pix[y][x][2] = 128;
285                                 pix[y][x][3] = 255;
286                         }
287                         else
288                         {
289                                 pix[y][x][0] = 64;
290                                 pix[y][x][1] = 64;
291                                 pix[y][x][2] = 64;
292                                 pix[y][x][3] = 255;
293                         }
294                 }
295         }
296         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
297 }
298
299 static void R_BuildWhiteCube(void)
300 {
301         unsigned char data[6*1*1*4];
302         memset(data, 255, sizeof(data));
303         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
304 }
305
306 static void R_BuildNormalizationCube(void)
307 {
308         int x, y, side;
309         vec3_t v;
310         vec_t s, t, intensity;
311 #define NORMSIZE 64
312         unsigned char data[6][NORMSIZE][NORMSIZE][4];
313         for (side = 0;side < 6;side++)
314         {
315                 for (y = 0;y < NORMSIZE;y++)
316                 {
317                         for (x = 0;x < NORMSIZE;x++)
318                         {
319                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
320                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
321                                 switch(side)
322                                 {
323                                 default:
324                                 case 0:
325                                         v[0] = 1;
326                                         v[1] = -t;
327                                         v[2] = -s;
328                                         break;
329                                 case 1:
330                                         v[0] = -1;
331                                         v[1] = -t;
332                                         v[2] = s;
333                                         break;
334                                 case 2:
335                                         v[0] = s;
336                                         v[1] = 1;
337                                         v[2] = t;
338                                         break;
339                                 case 3:
340                                         v[0] = s;
341                                         v[1] = -1;
342                                         v[2] = -t;
343                                         break;
344                                 case 4:
345                                         v[0] = s;
346                                         v[1] = -t;
347                                         v[2] = 1;
348                                         break;
349                                 case 5:
350                                         v[0] = -s;
351                                         v[1] = -t;
352                                         v[2] = -1;
353                                         break;
354                                 }
355                                 intensity = 127.0f / sqrt(DotProduct(v, v));
356                                 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
357                                 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
358                                 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
359                                 data[side][y][x][3] = 255;
360                         }
361                 }
362         }
363         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
364 }
365
366 static void R_BuildFogTexture(void)
367 {
368         int x, b;
369 #define FOGWIDTH 256
370         unsigned char data1[FOGWIDTH][4];
371         //unsigned char data2[FOGWIDTH][4];
372         double d, r, alpha;
373
374         r_refdef.fogmasktable_start = r_refdef.fog_start;
375         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
376         r_refdef.fogmasktable_range = r_refdef.fogrange;
377         r_refdef.fogmasktable_density = r_refdef.fog_density;
378
379         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
380         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
381         {
382                 d = (x * r - r_refdef.fogmasktable_start);
383                 if(developer.integer >= 100)
384                         Con_Printf("%f ", d);
385                 d = max(0, d);
386                 if (r_fog_exp2.integer)
387                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
388                 else
389                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
390                 if(developer.integer >= 100)
391                         Con_Printf(" : %f ", alpha);
392                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
393                 if(developer.integer >= 100)
394                         Con_Printf(" = %f\n", alpha);
395                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
396         }
397
398         for (x = 0;x < FOGWIDTH;x++)
399         {
400                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
401                 data1[x][0] = b;
402                 data1[x][1] = b;
403                 data1[x][2] = b;
404                 data1[x][3] = 255;
405                 //data2[x][0] = 255 - b;
406                 //data2[x][1] = 255 - b;
407                 //data2[x][2] = 255 - b;
408                 //data2[x][3] = 255;
409         }
410         if (r_texture_fogattenuation)
411         {
412                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
413                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
414         }
415         else
416         {
417                 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);
418                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
419         }
420 }
421
422 static const char *builtinshaderstring =
423 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
424 "// written by Forest 'LordHavoc' Hale\n"
425 "\n"
426 "// common definitions between vertex shader and fragment shader:\n"
427 "\n"
428 "//#ifdef __GLSL_CG_DATA_TYPES\n"
429 "//# define myhalf half\n"
430 "//# define myhalf2 half2\n"
431 "//# define myhalf3 half3\n"
432 "//# define myhalf4 half4\n"
433 "//#else\n"
434 "# define myhalf float\n"
435 "# define myhalf2 vec2\n"
436 "# define myhalf3 vec3\n"
437 "# define myhalf4 vec4\n"
438 "//#endif\n"
439 "\n"
440 "#ifdef MODE_DEPTH_OR_SHADOW\n"
441 "\n"
442 "# ifdef VERTEX_SHADER\n"
443 "void main(void)\n"
444 "{\n"
445 "       gl_Position = ftransform();\n"
446 "}\n"
447 "# endif\n"
448 "\n"
449 "#else\n"
450 "\n"
451 "#ifdef MODE_POSTPROCESS\n"
452 "# ifdef VERTEX_SHADER\n"
453 "void main(void)\n"
454 "{\n"
455 "       gl_FrontColor = gl_Color;\n"
456 "       gl_Position = ftransform();\n"
457 "       gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
458 "#ifdef USEGLOW\n"
459 "       gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
460 "#endif\n"
461 "}\n"
462 "# endif\n"
463 "# ifdef FRAGMENT_SHADER\n"
464 "\n"
465 "uniform sampler2D Texture_First;\n"
466 "#ifdef USEGLOW\n"
467 "uniform sampler2D Texture_Second;\n"
468 "#endif\n"
469 "#ifdef USEGAMMARAMPS\n"
470 "uniform sampler2D Texture_GammaRamps;\n"
471 "#endif\n"
472 "#ifdef USEVERTEXTEXTUREBLEND\n"
473 "uniform vec4 TintColor;\n"
474 "#endif\n"
475 "#ifdef USECOLORMOD\n"
476 "uniform vec3 Gamma;\n"
477 "#endif\n"
478 "//uncomment these if you want to use them:\n"
479 "// uniform vec4 UserVec1;\n"
480 "// uniform vec4 UserVec2;\n"
481 "// uniform vec4 UserVec3;\n"
482 "// uniform vec4 UserVec4;\n"
483 "// uniform float ClientTime;\n"
484 "// uniform vec2 PixelSize;\n"
485 "void main(void)\n"
486 "{\n"
487 "       gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
488 "#ifdef USEGLOW\n"
489 "       gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
490 "#endif\n"
491 "#ifdef USEVERTEXTEXTUREBLEND\n"
492 "       gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
493 "#endif\n"
494 "\n"
495 "#ifdef USEPOSTPROCESSING\n"
496 "// add your own postprocessing here or make your own ifdef for it\n"
497 "#endif\n"
498 "\n"
499 "#ifdef USEGAMMARAMPS\n"
500 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
501 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
502 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
503 "#endif\n"
504 "}\n"
505 "# endif\n"
506 "\n"
507 "\n"
508 "#else\n"
509 "#ifdef MODE_GENERIC\n"
510 "# ifdef VERTEX_SHADER\n"
511 "void main(void)\n"
512 "{\n"
513 "       gl_FrontColor = gl_Color;\n"
514 "#  ifdef USEDIFFUSE\n"
515 "       gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
516 "#  endif\n"
517 "#  ifdef USESPECULAR\n"
518 "       gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
519 "#  endif\n"
520 "       gl_Position = ftransform();\n"
521 "}\n"
522 "# endif\n"
523 "# ifdef FRAGMENT_SHADER\n"
524 "\n"
525 "#  ifdef USEDIFFUSE\n"
526 "uniform sampler2D Texture_First;\n"
527 "#  endif\n"
528 "#  ifdef USESPECULAR\n"
529 "uniform sampler2D Texture_Second;\n"
530 "#  endif\n"
531 "\n"
532 "void main(void)\n"
533 "{\n"
534 "       gl_FragColor = gl_Color;\n"
535 "#  ifdef USEDIFFUSE\n"
536 "       gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
537 "#  endif\n"
538 "\n"
539 "#  ifdef USESPECULAR\n"
540 "       vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
541 "#  endif\n"
542 "#  ifdef USECOLORMAPPING\n"
543 "       gl_FragColor *= tex2;\n"
544 "#  endif\n"
545 "#  ifdef USEGLOW\n"
546 "       gl_FragColor += tex2;\n"
547 "#  endif\n"
548 "#  ifdef USEVERTEXTEXTUREBLEND\n"
549 "       gl_FragColor = mix(tex2, gl_FragColor, tex2.a);\n"
550 "#  endif\n"
551 "}\n"
552 "# endif\n"
553 "\n"
554 "#else // !MODE_GENERIC\n"
555 "\n"
556 "varying vec2 TexCoord;\n"
557 "varying vec2 TexCoordLightmap;\n"
558 "\n"
559 "#ifdef MODE_LIGHTSOURCE\n"
560 "varying vec3 CubeVector;\n"
561 "#endif\n"
562 "\n"
563 "#ifdef MODE_LIGHTSOURCE\n"
564 "varying vec3 LightVector;\n"
565 "#endif\n"
566 "#ifdef MODE_LIGHTDIRECTION\n"
567 "varying vec3 LightVector;\n"
568 "#endif\n"
569 "\n"
570 "varying vec3 EyeVector;\n"
571 "#ifdef USEFOG\n"
572 "varying vec3 EyeVectorModelSpace;\n"
573 "#endif\n"
574 "\n"
575 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
576 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
577 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
578 "\n"
579 "#ifdef MODE_WATER\n"
580 "varying vec4 ModelViewProjectionPosition;\n"
581 "#endif\n"
582 "#ifdef MODE_REFRACTION\n"
583 "varying vec4 ModelViewProjectionPosition;\n"
584 "#endif\n"
585 "#ifdef USEREFLECTION\n"
586 "varying vec4 ModelViewProjectionPosition;\n"
587 "#endif\n"
588 "\n"
589 "\n"
590 "\n"
591 "\n"
592 "\n"
593 "// vertex shader specific:\n"
594 "#ifdef VERTEX_SHADER\n"
595 "\n"
596 "uniform vec3 LightPosition;\n"
597 "uniform vec3 EyePosition;\n"
598 "uniform vec3 LightDir;\n"
599 "\n"
600 "// 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"
601 "\n"
602 "void main(void)\n"
603 "{\n"
604 "       gl_FrontColor = gl_Color;\n"
605 "       // copy the surface texcoord\n"
606 "       TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
607 "#ifndef MODE_LIGHTSOURCE\n"
608 "# ifndef MODE_LIGHTDIRECTION\n"
609 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
610 "# endif\n"
611 "#endif\n"
612 "\n"
613 "#ifdef MODE_LIGHTSOURCE\n"
614 "       // transform vertex position into light attenuation/cubemap space\n"
615 "       // (-1 to +1 across the light box)\n"
616 "       CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
617 "\n"
618 "       // transform unnormalized light direction into tangent space\n"
619 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
620 "       //  normalize it per pixel)\n"
621 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
622 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
623 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
624 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
625 "#endif\n"
626 "\n"
627 "#ifdef MODE_LIGHTDIRECTION\n"
628 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
629 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
630 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
631 "#endif\n"
632 "\n"
633 "       // transform unnormalized eye direction into tangent space\n"
634 "#ifndef USEFOG\n"
635 "       vec3 EyeVectorModelSpace;\n"
636 "#endif\n"
637 "       EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
638 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
639 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
640 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
641 "\n"
642 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
643 "       VectorS = gl_MultiTexCoord1.xyz;\n"
644 "       VectorT = gl_MultiTexCoord2.xyz;\n"
645 "       VectorR = gl_MultiTexCoord3.xyz;\n"
646 "#endif\n"
647 "\n"
648 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
649 "//     ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
650 "//     //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
651 "//     //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
652 "//#endif\n"
653 "\n"
654 "// transform vertex to camera space, using ftransform to match non-VS\n"
655 "       // rendering\n"
656 "       gl_Position = ftransform();\n"
657 "\n"
658 "#ifdef MODE_WATER\n"
659 "       ModelViewProjectionPosition = gl_Position;\n"
660 "#endif\n"
661 "#ifdef MODE_REFRACTION\n"
662 "       ModelViewProjectionPosition = gl_Position;\n"
663 "#endif\n"
664 "#ifdef USEREFLECTION\n"
665 "       ModelViewProjectionPosition = gl_Position;\n"
666 "#endif\n"
667 "}\n"
668 "\n"
669 "#endif // VERTEX_SHADER\n"
670 "\n"
671 "\n"
672 "\n"
673 "\n"
674 "// fragment shader specific:\n"
675 "#ifdef FRAGMENT_SHADER\n"
676 "\n"
677 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
678 "uniform sampler2D Texture_Normal;\n"
679 "uniform sampler2D Texture_Color;\n"
680 "uniform sampler2D Texture_Gloss;\n"
681 "uniform sampler2D Texture_Glow;\n"
682 "uniform sampler2D Texture_SecondaryNormal;\n"
683 "uniform sampler2D Texture_SecondaryColor;\n"
684 "uniform sampler2D Texture_SecondaryGloss;\n"
685 "uniform sampler2D Texture_SecondaryGlow;\n"
686 "uniform sampler2D Texture_Pants;\n"
687 "uniform sampler2D Texture_Shirt;\n"
688 "uniform sampler2D Texture_FogMask;\n"
689 "uniform sampler2D Texture_Lightmap;\n"
690 "uniform sampler2D Texture_Deluxemap;\n"
691 "uniform sampler2D Texture_Refraction;\n"
692 "uniform sampler2D Texture_Reflection;\n"
693 "uniform sampler2D Texture_Attenuation;\n"
694 "uniform samplerCube Texture_Cube;\n"
695 "\n"
696 "uniform myhalf3 LightColor;\n"
697 "uniform myhalf3 AmbientColor;\n"
698 "uniform myhalf3 DiffuseColor;\n"
699 "uniform myhalf3 SpecularColor;\n"
700 "uniform myhalf3 Color_Pants;\n"
701 "uniform myhalf3 Color_Shirt;\n"
702 "uniform myhalf3 FogColor;\n"
703 "\n"
704 "uniform myhalf4 TintColor;\n"
705 "\n"
706 "\n"
707 "//#ifdef MODE_WATER\n"
708 "uniform vec4 DistortScaleRefractReflect;\n"
709 "uniform vec4 ScreenScaleRefractReflect;\n"
710 "uniform vec4 ScreenCenterRefractReflect;\n"
711 "uniform myhalf4 RefractColor;\n"
712 "uniform myhalf4 ReflectColor;\n"
713 "uniform myhalf ReflectFactor;\n"
714 "uniform myhalf ReflectOffset;\n"
715 "//#else\n"
716 "//# ifdef MODE_REFRACTION\n"
717 "//uniform vec4 DistortScaleRefractReflect;\n"
718 "//uniform vec4 ScreenScaleRefractReflect;\n"
719 "//uniform vec4 ScreenCenterRefractReflect;\n"
720 "//uniform myhalf4 RefractColor;\n"
721 "//#  ifdef USEREFLECTION\n"
722 "//uniform myhalf4 ReflectColor;\n"
723 "//#  endif\n"
724 "//# else\n"
725 "//#  ifdef USEREFLECTION\n"
726 "//uniform vec4 DistortScaleRefractReflect;\n"
727 "//uniform vec4 ScreenScaleRefractReflect;\n"
728 "//uniform vec4 ScreenCenterRefractReflect;\n"
729 "//uniform myhalf4 ReflectColor;\n"
730 "//#  endif\n"
731 "//# endif\n"
732 "//#endif\n"
733 "\n"
734 "uniform myhalf GlowScale;\n"
735 "uniform myhalf SceneBrightness;\n"
736 "#ifdef USECONTRASTBOOST\n"
737 "uniform myhalf ContrastBoostCoeff;\n"
738 "#endif\n"
739 "\n"
740 "uniform float OffsetMapping_Scale;\n"
741 "uniform float OffsetMapping_Bias;\n"
742 "uniform float FogRangeRecip;\n"
743 "\n"
744 "uniform myhalf AmbientScale;\n"
745 "uniform myhalf DiffuseScale;\n"
746 "uniform myhalf SpecularScale;\n"
747 "uniform myhalf SpecularPower;\n"
748 "\n"
749 "#ifdef USEOFFSETMAPPING\n"
750 "vec2 OffsetMapping(vec2 TexCoord)\n"
751 "{\n"
752 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
753 "       // 14 sample relief mapping: linear search and then binary search\n"
754 "       // this basically steps forward a small amount repeatedly until it finds\n"
755 "       // itself inside solid, then jitters forward and back using decreasing\n"
756 "       // amounts to find the impact\n"
757 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
758 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
759 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
760 "       vec3 RT = vec3(TexCoord, 1);\n"
761 "       OffsetVector *= 0.1;\n"
762 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
763 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
764 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
765 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
766 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
767 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
768 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
769 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
770 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
771 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
772 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
773 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
774 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
775 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
776 "       return RT.xy;\n"
777 "#else\n"
778 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
779 "       // this basically moves forward the full distance, and then backs up based\n"
780 "       // on height of samples\n"
781 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
782 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
783 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
784 "       TexCoord += OffsetVector;\n"
785 "       OffsetVector *= 0.333;\n"
786 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
787 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
788 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
789 "       return TexCoord;\n"
790 "#endif\n"
791 "}\n"
792 "#endif // USEOFFSETMAPPING\n"
793 "\n"
794 "#ifdef MODE_WATER\n"
795 "\n"
796 "// water pass\n"
797 "void main(void)\n"
798 "{\n"
799 "#ifdef USEOFFSETMAPPING\n"
800 "       // apply offsetmapping\n"
801 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
802 "#define TexCoord TexCoordOffset\n"
803 "#endif\n"
804 "\n"
805 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
806 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
807 "       vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
808 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
809 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
810 "}\n"
811 "\n"
812 "#else // !MODE_WATER\n"
813 "#ifdef MODE_REFRACTION\n"
814 "\n"
815 "// refraction pass\n"
816 "void main(void)\n"
817 "{\n"
818 "#ifdef USEOFFSETMAPPING\n"
819 "       // apply offsetmapping\n"
820 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
821 "#define TexCoord TexCoordOffset\n"
822 "#endif\n"
823 "\n"
824 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
825 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
826 "       vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
827 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
828 "}\n"
829 "\n"
830 "#else // !MODE_REFRACTION\n"
831 "void main(void)\n"
832 "{\n"
833 "#ifdef USEOFFSETMAPPING\n"
834 "       // apply offsetmapping\n"
835 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
836 "#define TexCoord TexCoordOffset\n"
837 "#endif\n"
838 "\n"
839 "       // combine the diffuse textures (base, pants, shirt)\n"
840 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
841 "#ifdef USECOLORMAPPING\n"
842 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
843 "#endif\n"
844 "#ifdef USEVERTEXTEXTUREBLEND\n"
845 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
846 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
847 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
848 "       color = mix(myhalf4(texture2D(Texture_SecondaryColor, TexCoord)), color, terrainblend);\n"
849 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
850 "#endif\n"
851 "\n"
852 "#ifdef USEDIFFUSE\n"
853 "       // get the surface normal and the gloss color\n"
854 "# ifdef USEVERTEXTEXTUREBLEND\n"
855 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
856 "#  ifdef USESPECULAR\n"
857 "       myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
858 "#  endif\n"
859 "# else\n"
860 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5));\n"
861 "#  ifdef USESPECULAR\n"
862 "       myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
863 "#  endif\n"
864 "# endif\n"
865 "#endif\n"
866 "\n"
867 "\n"
868 "\n"
869 "#ifdef MODE_LIGHTSOURCE\n"
870 "       // light source\n"
871 "\n"
872 "       // calculate surface normal, light normal, and specular normal\n"
873 "       // compute color intensity for the two textures (colormap and glossmap)\n"
874 "       // scale by light color and attenuation as efficiently as possible\n"
875 "       // (do as much scalar math as possible rather than vector math)\n"
876 "# ifdef USEDIFFUSE\n"
877 "       // get the light normal\n"
878 "       myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
879 "# endif\n"
880 "# ifdef USESPECULAR\n"
881 "       myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
882 "\n"
883 "       // calculate directional shading\n"
884 "       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"
885 "# else\n"
886 "#  ifdef USEDIFFUSE\n"
887 "       // calculate directional shading\n"
888 "       color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
889 "#  else\n"
890 "       // calculate directionless shading\n"
891 "       color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
892 "#  endif\n"
893 "# endif\n"
894 "\n"
895 "# ifdef USECUBEFILTER\n"
896 "       // apply light cubemap filter\n"
897 "       //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
898 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
899 "# endif\n"
900 "#endif // MODE_LIGHTSOURCE\n"
901 "\n"
902 "\n"
903 "\n"
904 "\n"
905 "#ifdef MODE_LIGHTDIRECTION\n"
906 "       // directional model lighting\n"
907 "# ifdef USEDIFFUSE\n"
908 "       // get the light normal\n"
909 "       myhalf3 diffusenormal = myhalf3(LightVector);\n"
910 "# endif\n"
911 "# ifdef USESPECULAR\n"
912 "       // calculate directional shading\n"
913 "       color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
914 "       myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
915 "       color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
916 "# else\n"
917 "#  ifdef USEDIFFUSE\n"
918 "\n"
919 "       // calculate directional shading\n"
920 "       color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
921 "#  else\n"
922 "       color.rgb *= AmbientColor;\n"
923 "#  endif\n"
924 "# endif\n"
925 "#endif // MODE_LIGHTDIRECTION\n"
926 "\n"
927 "\n"
928 "\n"
929 "\n"
930 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
931 "       // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
932 "\n"
933 "       // get the light normal\n"
934 "       myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5);\n"
935 "       myhalf3 diffusenormal = normalize(myhalf3(dot(diffusenormal_modelspace, myhalf3(VectorS)), dot(diffusenormal_modelspace, myhalf3(VectorT)), dot(diffusenormal_modelspace, myhalf3(VectorR))));\n"
936 "       // calculate directional shading\n"
937 "       myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
938 "# ifdef USESPECULAR\n"
939 "       myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
940 "       tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
941 "# endif\n"
942 "\n"
943 "       // apply lightmap color\n"
944 "       color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
945 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
946 "\n"
947 "\n"
948 "\n"
949 "\n"
950 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
951 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
952 "\n"
953 "       // get the light normal\n"
954 "       myhalf3 diffusenormal = normalize(myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5));\n"
955 "       // calculate directional shading\n"
956 "       myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
957 "# ifdef USESPECULAR\n"
958 "       myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
959 "       tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
960 "# endif\n"
961 "\n"
962 "       // apply lightmap color\n"
963 "       color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
964 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
965 "\n"
966 "\n"
967 "\n"
968 "\n"
969 "#ifdef MODE_LIGHTMAP\n"
970 "       // apply lightmap color\n"
971 "       color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
972 "#endif // MODE_LIGHTMAP\n"
973 "\n"
974 "\n"
975 "\n"
976 "\n"
977 "#ifdef MODE_VERTEXCOLOR\n"
978 "       // apply lightmap color\n"
979 "       color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
980 "#endif // MODE_VERTEXCOLOR\n"
981 "\n"
982 "\n"
983 "\n"
984 "\n"
985 "#ifdef MODE_FLATCOLOR\n"
986 "#endif // MODE_FLATCOLOR\n"
987 "\n"
988 "\n"
989 "\n"
990 "\n"
991 "\n"
992 "\n"
993 "\n"
994 "       color *= TintColor;\n"
995 "\n"
996 "#ifdef USEGLOW\n"
997 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
998 "#endif\n"
999 "\n"
1000 "#ifdef USECONTRASTBOOST\n"
1001 "       color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n"
1002 "#endif\n"
1003 "\n"
1004 "       color.rgb *= SceneBrightness;\n"
1005 "\n"
1006 "       // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1007 "#ifdef USEFOG\n"
1008 "       color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1009 "#endif\n"
1010 "\n"
1011 "       // 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"
1012 "#ifdef USEREFLECTION\n"
1013 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1014 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1015 "       vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1016 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
1017 "#endif\n"
1018 "\n"
1019 "       gl_FragColor = vec4(color);\n"
1020 "}\n"
1021 "#endif // !MODE_REFRACTION\n"
1022 "#endif // !MODE_WATER\n"
1023 "\n"
1024 "#endif // FRAGMENT_SHADER\n"
1025 "\n"
1026 "#endif // !MODE_GENERIC\n"
1027 "#endif // !MODE_POSTPROCESS\n"
1028 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1029 ;
1030
1031 typedef struct shaderpermutationinfo_s
1032 {
1033         const char *pretext;
1034         const char *name;
1035 }
1036 shaderpermutationinfo_t;
1037
1038 typedef struct shadermodeinfo_s
1039 {
1040         const char *vertexfilename;
1041         const char *geometryfilename;
1042         const char *fragmentfilename;
1043         const char *pretext;
1044         const char *name;
1045 }
1046 shadermodeinfo_t;
1047
1048 typedef enum shaderpermutation_e
1049 {
1050         SHADERPERMUTATION_DIFFUSE = 1<<0, // (lightsource) whether to use directional shading
1051         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, // indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1052         SHADERPERMUTATION_COLORMAPPING = 1<<2, // indicates this is a colormapped skin
1053         SHADERPERMUTATION_CONTRASTBOOST = 1<<3, // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
1054         SHADERPERMUTATION_FOG = 1<<4, // tint the color by fog color or black if using additive blend mode
1055         SHADERPERMUTATION_CUBEFILTER = 1<<5, // (lightsource) use cubemap light filter
1056         SHADERPERMUTATION_GLOW = 1<<6, // (lightmap) blend in an additive glow texture
1057         SHADERPERMUTATION_SPECULAR = 1<<7, // (lightsource or deluxemapping) render specular effects
1058         SHADERPERMUTATION_REFLECTION = 1<<8, // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1059         SHADERPERMUTATION_OFFSETMAPPING = 1<<9, // adjust texcoords to roughly simulate a displacement mapped surface
1060         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1061         SHADERPERMUTATION_GAMMARAMPS = 1<<11, // gamma (postprocessing only)
1062         SHADERPERMUTATION_POSTPROCESSING = 1<<12, // user defined postprocessing
1063         SHADERPERMUTATION_LIMIT = 1<<13, // size of permutations array
1064         SHADERPERMUTATION_COUNT = 13 // size of shaderpermutationinfo array
1065 }
1066 shaderpermutation_t;
1067
1068 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1069 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1070 {
1071         {"#define USEDIFFUSE\n", " diffuse"},
1072         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1073         {"#define USECOLORMAPPING\n", " colormapping"},
1074         {"#define USECONTRASTBOOST\n", " contrastboost"},
1075         {"#define USEFOG\n", " fog"},
1076         {"#define USECUBEFILTER\n", " cubefilter"},
1077         {"#define USEGLOW\n", " glow"},
1078         {"#define USESPECULAR\n", " specular"},
1079         {"#define USEREFLECTION\n", " reflection"},
1080         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1081         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1082         {"#define USEGAMMARAMPS\n", " gammaramps"},
1083         {"#define USEPOSTPROCESSING\n", " postprocessing"},
1084 };
1085
1086 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
1087 typedef enum shadermode_e
1088 {
1089         SHADERMODE_GENERIC, // (particles/HUD/etc) vertex color, optionally multiplied by one texture
1090         SHADERMODE_POSTPROCESS, // postprocessing shader (r_glsl_postprocess)
1091         SHADERMODE_DEPTH_OR_SHADOW, // (depthfirst/shadows) vertex shader only
1092         SHADERMODE_FLATCOLOR, // (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1093         SHADERMODE_VERTEXCOLOR, // (lightmap) modulate texture by vertex colors (q3bsp)
1094         SHADERMODE_LIGHTMAP, // (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1095         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1096         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1097         SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1098         SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
1099         SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
1100         SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
1101         SHADERMODE_COUNT
1102 }
1103 shadermode_t;
1104
1105 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1106 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1107 {
1108         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1109         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1110         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1111         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1112         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1113         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1114         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1115         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1116         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1117         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1118         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1119         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1120 };
1121
1122 typedef struct r_glsl_permutation_s
1123 {
1124         // indicates if we have tried compiling this permutation already
1125         qboolean compiled;
1126         // 0 if compilation failed
1127         int program;
1128         // locations of detected uniforms in program object, or -1 if not found
1129         int loc_Texture_First;
1130         int loc_Texture_Second;
1131         int loc_Texture_GammaRamps;
1132         int loc_Texture_Normal;
1133         int loc_Texture_Color;
1134         int loc_Texture_Gloss;
1135         int loc_Texture_Glow;
1136         int loc_Texture_SecondaryNormal;
1137         int loc_Texture_SecondaryColor;
1138         int loc_Texture_SecondaryGloss;
1139         int loc_Texture_SecondaryGlow;
1140         int loc_Texture_Pants;
1141         int loc_Texture_Shirt;
1142         int loc_Texture_FogMask;
1143         int loc_Texture_Lightmap;
1144         int loc_Texture_Deluxemap;
1145         int loc_Texture_Attenuation;
1146         int loc_Texture_Cube;
1147         int loc_Texture_Refraction;
1148         int loc_Texture_Reflection;
1149         int loc_FogColor;
1150         int loc_LightPosition;
1151         int loc_EyePosition;
1152         int loc_Color_Pants;
1153         int loc_Color_Shirt;
1154         int loc_FogRangeRecip;
1155         int loc_AmbientScale;
1156         int loc_DiffuseScale;
1157         int loc_SpecularScale;
1158         int loc_SpecularPower;
1159         int loc_GlowScale;
1160         int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1161         int loc_OffsetMapping_Scale;
1162         int loc_TintColor;
1163         int loc_AmbientColor;
1164         int loc_DiffuseColor;
1165         int loc_SpecularColor;
1166         int loc_LightDir;
1167         int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
1168         int loc_GammaCoeff; // 1 / gamma
1169         int loc_DistortScaleRefractReflect;
1170         int loc_ScreenScaleRefractReflect;
1171         int loc_ScreenCenterRefractReflect;
1172         int loc_RefractColor;
1173         int loc_ReflectColor;
1174         int loc_ReflectFactor;
1175         int loc_ReflectOffset;
1176         int loc_UserVec1;
1177         int loc_UserVec2;
1178         int loc_UserVec3;
1179         int loc_UserVec4;
1180         int loc_ClientTime;
1181         int loc_PixelSize;
1182 }
1183 r_glsl_permutation_t;
1184
1185 // information about each possible shader permutation
1186 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1187 // currently selected permutation
1188 r_glsl_permutation_t *r_glsl_permutation;
1189
1190 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1191 {
1192         char *shaderstring;
1193         if (!filename || !filename[0])
1194                 return NULL;
1195         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1196         if (shaderstring)
1197         {
1198                 if (printfromdisknotice)
1199                         Con_DPrint("from disk... ");
1200                 return shaderstring;
1201         }
1202         else if (!strcmp(filename, "glsl/default.glsl"))
1203         {
1204                 shaderstring = Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1205                 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1206         }
1207         return shaderstring;
1208 }
1209
1210 static void R_GLSL_CompilePermutation(shadermode_t mode, shaderpermutation_t permutation)
1211 {
1212         int i;
1213         shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1214         r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1215         int vertstrings_count = 0;
1216         int geomstrings_count = 0;
1217         int fragstrings_count = 0;
1218         char *vertexstring, *geometrystring, *fragmentstring;
1219         const char *vertstrings_list[32+3];
1220         const char *geomstrings_list[32+3];
1221         const char *fragstrings_list[32+3];
1222         char permutationname[256];
1223
1224         if (p->compiled)
1225                 return;
1226         p->compiled = true;
1227         p->program = 0;
1228
1229         permutationname[0] = 0;
1230         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1231         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1232         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1233
1234         strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1235
1236         // the first pretext is which type of shader to compile as
1237         // (later these will all be bound together as a program object)
1238         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1239         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1240         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1241
1242         // the second pretext is the mode (for example a light source)
1243         vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1244         geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1245         fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1246         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1247
1248         // now add all the permutation pretexts
1249         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1250         {
1251                 if (permutation & (1<<i))
1252                 {
1253                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1254                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1255                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1256                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1257                 }
1258                 else
1259                 {
1260                         // keep line numbers correct
1261                         vertstrings_list[vertstrings_count++] = "\n";
1262                         geomstrings_list[geomstrings_count++] = "\n";
1263                         fragstrings_list[fragstrings_count++] = "\n";
1264                 }
1265         }
1266
1267         // now append the shader text itself
1268         vertstrings_list[vertstrings_count++] = vertexstring;
1269         geomstrings_list[geomstrings_count++] = geometrystring;
1270         fragstrings_list[fragstrings_count++] = fragmentstring;
1271
1272         // if any sources were NULL, clear the respective list
1273         if (!vertexstring)
1274                 vertstrings_count = 0;
1275         if (!geometrystring)
1276                 geomstrings_count = 0;
1277         if (!fragmentstring)
1278                 fragstrings_count = 0;
1279
1280         // compile the shader program
1281         if (vertstrings_count + geomstrings_count + fragstrings_count)
1282                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1283         if (p->program)
1284         {
1285                 CHECKGLERROR
1286                 qglUseProgramObjectARB(p->program);CHECKGLERROR
1287                 // look up all the uniform variable names we care about, so we don't
1288                 // have to look them up every time we set them
1289                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
1290                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
1291                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1292                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
1293                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
1294                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1295                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
1296                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1297                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1298                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1299                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1300                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1301                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
1302                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1303                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1304                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1305                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1306                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1307                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1308                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
1309                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
1310                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
1311                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
1312                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
1313                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
1314                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1315                 p->loc_AmbientScale               = qglGetUniformLocationARB(p->program, "AmbientScale");
1316                 p->loc_DiffuseScale               = qglGetUniformLocationARB(p->program, "DiffuseScale");
1317                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
1318                 p->loc_SpecularScale              = qglGetUniformLocationARB(p->program, "SpecularScale");
1319                 p->loc_GlowScale                  = qglGetUniformLocationARB(p->program, "GlowScale");
1320                 p->loc_SceneBrightness            = qglGetUniformLocationARB(p->program, "SceneBrightness");
1321                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1322                 p->loc_TintColor                  = qglGetUniformLocationARB(p->program, "TintColor");
1323                 p->loc_AmbientColor               = qglGetUniformLocationARB(p->program, "AmbientColor");
1324                 p->loc_DiffuseColor               = qglGetUniformLocationARB(p->program, "DiffuseColor");
1325                 p->loc_SpecularColor              = qglGetUniformLocationARB(p->program, "SpecularColor");
1326                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
1327                 p->loc_ContrastBoostCoeff         = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1328                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1329                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1330                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1331                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
1332                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
1333                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
1334                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
1335                 p->loc_GammaCoeff                 = qglGetUniformLocationARB(p->program, "GammaCoeff");
1336                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
1337                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
1338                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
1339                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
1340                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
1341                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
1342                 // initialize the samplers to refer to the texture units we use
1343                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
1344                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
1345                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
1346                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
1347                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
1348                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
1349                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
1350                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1351                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1352                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1353                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
1354                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
1355                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
1356                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
1357                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
1358                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
1359                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
1360                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
1361                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
1362                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
1363                 CHECKGLERROR
1364                 if (developer.integer)
1365                         Con_Printf("GLSL shader %s compiled.\n", permutationname);
1366         }
1367         else
1368                 Con_Printf("GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1369
1370         // free the strings
1371         if (vertexstring)
1372                 Mem_Free(vertexstring);
1373         if (geometrystring)
1374                 Mem_Free(geometrystring);
1375         if (fragmentstring)
1376                 Mem_Free(fragmentstring);
1377 }
1378
1379 void R_GLSL_Restart_f(void)
1380 {
1381         shadermode_t mode;
1382         shaderpermutation_t permutation;
1383         for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1384                 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1385                         if (r_glsl_permutations[mode][permutation].program)
1386                                 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1387         memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1388 }
1389
1390 void R_GLSL_DumpShader_f(void)
1391 {
1392         int i;
1393
1394         qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
1395         if(!file)
1396         {
1397                 Con_Printf("failed to write to glsl/default.glsl\n");
1398                 return;
1399         }
1400
1401         FS_Print(file, "// The engine may define the following macros:\n");
1402         FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1403         for (i = 0;i < SHADERMODE_COUNT;i++)
1404                 FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
1405         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1406                 FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
1407         FS_Print(file, "\n");
1408         FS_Print(file, builtinshaderstring);
1409         FS_Close(file);
1410
1411         Con_Printf("glsl/default.glsl written\n");
1412 }
1413
1414 void R_SetupShader_SetPermutation(shadermode_t mode, unsigned int permutation)
1415 {
1416         r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1417         if (r_glsl_permutation != perm)
1418         {
1419                 r_glsl_permutation = perm;
1420                 if (!r_glsl_permutation->program)
1421                 {
1422                         if (!r_glsl_permutation->compiled)
1423                                 R_GLSL_CompilePermutation(mode, permutation);
1424                         if (!r_glsl_permutation->program)
1425                         {
1426                                 // remove features until we find a valid permutation
1427                                 int i;
1428                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1429                                 {
1430                                         // reduce i more quickly whenever it would not remove any bits
1431                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1432                                         if (!(permutation & j))
1433                                                 continue;
1434                                         permutation -= j;
1435                                         r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1436                                         if (!r_glsl_permutation->compiled)
1437                                                 R_GLSL_CompilePermutation(mode, permutation);
1438                                         if (r_glsl_permutation->program)
1439                                                 break;
1440                                 }
1441                                 if (i >= SHADERPERMUTATION_COUNT)
1442                                 {
1443                                         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");
1444                                         Cvar_SetValueQuick(&r_glsl, 0);
1445                                         R_GLSL_Restart_f(); // unload shaders
1446                                         return; // no bit left to clear
1447                                 }
1448                         }
1449                 }
1450                 CHECKGLERROR
1451                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1452         }
1453 }
1454
1455 void R_SetupGenericShader(qboolean usetexture)
1456 {
1457         if (gl_support_fragment_shader)
1458         {
1459                 if (r_glsl.integer && r_glsl_usegeneric.integer)
1460                         R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1461                 else if (r_glsl_permutation)
1462                 {
1463                         r_glsl_permutation = NULL;
1464                         qglUseProgramObjectARB(0);CHECKGLERROR
1465                 }
1466         }
1467 }
1468
1469 void R_SetupGenericTwoTextureShader(int texturemode)
1470 {
1471         if (gl_support_fragment_shader)
1472         {
1473                 if (r_glsl.integer && r_glsl_usegeneric.integer)
1474                         R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1475                 else if (r_glsl_permutation)
1476                 {
1477                         r_glsl_permutation = NULL;
1478                         qglUseProgramObjectARB(0);CHECKGLERROR
1479                 }
1480         }
1481         if (!r_glsl_permutation)
1482         {
1483                 if (texturemode == GL_DECAL && gl_combine.integer)
1484                         texturemode = GL_INTERPOLATE_ARB;
1485                 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1486         }
1487 }
1488
1489 void R_SetupDepthOrShadowShader(void)
1490 {
1491         if (gl_support_fragment_shader)
1492         {
1493                 if (r_glsl.integer && r_glsl_usegeneric.integer)
1494                         R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1495                 else if (r_glsl_permutation)
1496                 {
1497                         r_glsl_permutation = NULL;
1498                         qglUseProgramObjectARB(0);CHECKGLERROR
1499                 }
1500         }
1501 }
1502
1503 extern rtexture_t *r_shadow_attenuationgradienttexture;
1504 extern rtexture_t *r_shadow_attenuation2dtexture;
1505 extern rtexture_t *r_shadow_attenuation3dtexture;
1506 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1507 {
1508         // select a permutation of the lighting shader appropriate to this
1509         // combination of texture, entity, light source, and fogging, only use the
1510         // minimum features necessary to avoid wasting rendering time in the
1511         // fragment shader on features that are not being used
1512         unsigned int permutation = 0;
1513         shadermode_t mode = 0;
1514         // TODO: implement geometry-shader based shadow volumes someday
1515         if (r_glsl_offsetmapping.integer)
1516         {
1517                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1518                 if (r_glsl_offsetmapping_reliefmapping.integer)
1519                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1520         }
1521         if (rsurfacepass == RSURFPASS_BACKGROUND)
1522         {
1523                 // distorted background
1524                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1525                         mode = SHADERMODE_WATER;
1526                 else
1527                         mode = SHADERMODE_REFRACTION;
1528         }
1529         else if (rsurfacepass == RSURFPASS_RTLIGHT)
1530         {
1531                 // light source
1532                 mode = SHADERMODE_LIGHTSOURCE;
1533                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1534                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1535                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1536                         permutation |= SHADERPERMUTATION_CUBEFILTER;
1537                 if (diffusescale > 0)
1538                         permutation |= SHADERPERMUTATION_DIFFUSE;
1539                 if (specularscale > 0)
1540                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1541                 if (r_refdef.fogenabled)
1542                         permutation |= SHADERPERMUTATION_FOG;
1543                 if (rsurface.texture->colormapping)
1544                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1545                 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1546                         permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1547         }
1548         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1549         {
1550                 // unshaded geometry (fullbright or ambient model lighting)
1551                 mode = SHADERMODE_FLATCOLOR;
1552                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1553                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1554                 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1555                         permutation |= SHADERPERMUTATION_GLOW;
1556                 if (r_refdef.fogenabled)
1557                         permutation |= SHADERPERMUTATION_FOG;
1558                 if (rsurface.texture->colormapping)
1559                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1560                 if (r_glsl_offsetmapping.integer)
1561                 {
1562                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1563                         if (r_glsl_offsetmapping_reliefmapping.integer)
1564                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1565                 }
1566                 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1567                         permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1568                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1569                         permutation |= SHADERPERMUTATION_REFLECTION;
1570         }
1571         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1572         {
1573                 // directional model lighting
1574                 mode = SHADERMODE_LIGHTDIRECTION;
1575                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1576                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1577                 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1578                         permutation |= SHADERPERMUTATION_GLOW;
1579                 permutation |= SHADERPERMUTATION_DIFFUSE;
1580                 if (specularscale > 0)
1581                         permutation |= SHADERPERMUTATION_SPECULAR;
1582                 if (r_refdef.fogenabled)
1583                         permutation |= SHADERPERMUTATION_FOG;
1584                 if (rsurface.texture->colormapping)
1585                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1586                 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1587                         permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1588                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1589                         permutation |= SHADERPERMUTATION_REFLECTION;
1590         }
1591         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1592         {
1593                 // ambient model lighting
1594                 mode = SHADERMODE_LIGHTDIRECTION;
1595                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1596                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1597                 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1598                         permutation |= SHADERPERMUTATION_GLOW;
1599                 if (r_refdef.fogenabled)
1600                         permutation |= SHADERPERMUTATION_FOG;
1601                 if (rsurface.texture->colormapping)
1602                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1603                 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1604                         permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1605                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1606                         permutation |= SHADERPERMUTATION_REFLECTION;
1607         }
1608         else
1609         {
1610                 // lightmapped wall
1611                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1612                 {
1613                         // deluxemapping (light direction texture)
1614                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1615                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1616                         else
1617                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1618                         permutation |= SHADERPERMUTATION_DIFFUSE;
1619                         if (specularscale > 0)
1620                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1621                 }
1622                 else if (r_glsl_deluxemapping.integer >= 2)
1623                 {
1624                         // fake deluxemapping (uniform light direction in tangentspace)
1625                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1626                         permutation |= SHADERPERMUTATION_DIFFUSE;
1627                         if (specularscale > 0)
1628                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1629                 }
1630                 else if (rsurface.uselightmaptexture)
1631                 {
1632                         // ordinary lightmapping (q1bsp, q3bsp)
1633                         mode = SHADERMODE_LIGHTMAP;
1634                 }
1635                 else
1636                 {
1637                         // ordinary vertex coloring (q3bsp)
1638                         mode = SHADERMODE_VERTEXCOLOR;
1639                 }
1640                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1641                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1642                 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1643                         permutation |= SHADERPERMUTATION_GLOW;
1644                 if (r_refdef.fogenabled)
1645                         permutation |= SHADERPERMUTATION_FOG;
1646                 if (rsurface.texture->colormapping)
1647                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1648                 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1649                         permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1650                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1651                         permutation |= SHADERPERMUTATION_REFLECTION;
1652         }
1653         R_SetupShader_SetPermutation(mode, permutation);
1654         if (mode == SHADERMODE_LIGHTSOURCE)
1655         {
1656                 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1657                 if (permutation & SHADERPERMUTATION_DIFFUSE)
1658                 {
1659                         if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
1660                         if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1661                         if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1662                         if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1663                 }
1664                 else
1665                 {
1666                         // ambient only is simpler
1667                         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]);
1668                         if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1669                         if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1670                         if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1671                 }
1672                 // additive passes are only darkened by fog, not tinted
1673                 if (r_glsl_permutation->loc_FogColor >= 0)
1674                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1675         }
1676         else
1677         {
1678                 if (mode == SHADERMODE_LIGHTDIRECTION)
1679                 {
1680                         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);
1681                         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);
1682                         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);
1683                         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]);
1684                 }
1685                 else
1686                 {
1687                         if (r_glsl_permutation->loc_AmbientScale  >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 1.0f / 128.0f);
1688                         if (r_glsl_permutation->loc_DiffuseScale  >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1689                         if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1690                 }
1691                 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]);
1692                 if (r_glsl_permutation->loc_GlowScale     >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1693                 // additive passes are only darkened by fog, not tinted
1694                 if (r_glsl_permutation->loc_FogColor >= 0)
1695                 {
1696                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
1697                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1698                         else
1699                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1700                 }
1701                 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);
1702                 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]);
1703                 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]);
1704                 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1705                 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1706                 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1707                 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1708         }
1709         if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1710         {
1711                 // The formula used is actually:
1712                 //   color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1713                 //   color.rgb *= SceneBrightness;
1714                 // simplified:
1715                 //   color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1716                 // and do [[calculations]] here in the engine
1717                 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1718                 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
1719         }
1720         else
1721                 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
1722         if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1723         if (r_glsl_permutation->loc_Color_Pants >= 0)
1724         {
1725                 if (rsurface.texture->currentskinframe->pants)
1726                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1727                 else
1728                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1729         }
1730         if (r_glsl_permutation->loc_Color_Shirt >= 0)
1731         {
1732                 if (rsurface.texture->currentskinframe->shirt)
1733                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1734                 else
1735                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1736         }
1737         if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1738         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1739         if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1740         CHECKGLERROR
1741 }
1742
1743 #define SKINFRAME_HASH 1024
1744
1745 struct
1746 {
1747         int loadsequence; // incremented each level change
1748         memexpandablearray_t array;
1749         skinframe_t *hash[SKINFRAME_HASH];
1750 }
1751 r_skinframe;
1752
1753 void R_SkinFrame_PrepareForPurge(void)
1754 {
1755         r_skinframe.loadsequence++;
1756         // wrap it without hitting zero
1757         if (r_skinframe.loadsequence >= 200)
1758                 r_skinframe.loadsequence = 1;
1759 }
1760
1761 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1762 {
1763         if (!skinframe)
1764                 return;
1765         // mark the skinframe as used for the purging code
1766         skinframe->loadsequence = r_skinframe.loadsequence;
1767 }
1768
1769 void R_SkinFrame_Purge(void)
1770 {
1771         int i;
1772         skinframe_t *s;
1773         for (i = 0;i < SKINFRAME_HASH;i++)
1774         {
1775                 for (s = r_skinframe.hash[i];s;s = s->next)
1776                 {
1777                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1778                         {
1779                                 if (s->merged == s->base)
1780                                         s->merged = NULL;
1781                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1782                                 R_PurgeTexture(s->stain );s->stain  = NULL;
1783                                 R_PurgeTexture(s->merged);s->merged = NULL;
1784                                 R_PurgeTexture(s->base  );s->base   = NULL;
1785                                 R_PurgeTexture(s->pants );s->pants  = NULL;
1786                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
1787                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
1788                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
1789                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
1790                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
1791                                 s->loadsequence = 0;
1792                         }
1793                 }
1794         }
1795 }
1796
1797 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1798         skinframe_t *item;
1799         char basename[MAX_QPATH];
1800
1801         Image_StripImageExtension(name, basename, sizeof(basename));
1802
1803         if( last == NULL ) {
1804                 int hashindex;
1805                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1806                 item = r_skinframe.hash[hashindex];
1807         } else {
1808                 item = last->next;
1809         }
1810
1811         // linearly search through the hash bucket
1812         for( ; item ; item = item->next ) {
1813                 if( !strcmp( item->basename, basename ) ) {
1814                         return item;
1815                 }
1816         }
1817         return NULL;
1818 }
1819
1820 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1821 {
1822         skinframe_t *item;
1823         int hashindex;
1824         char basename[MAX_QPATH];
1825
1826         Image_StripImageExtension(name, basename, sizeof(basename));
1827
1828         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1829         for (item = r_skinframe.hash[hashindex];item;item = item->next)
1830                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1831                         break;
1832
1833         if (!item) {
1834                 rtexture_t *dyntexture;
1835                 // check whether its a dynamic texture
1836                 dyntexture = CL_GetDynTexture( basename );
1837                 if (!add && !dyntexture)
1838                         return NULL;
1839                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1840                 memset(item, 0, sizeof(*item));
1841                 strlcpy(item->basename, basename, sizeof(item->basename));
1842                 item->base = dyntexture; // either NULL or dyntexture handle
1843                 item->textureflags = textureflags;
1844                 item->comparewidth = comparewidth;
1845                 item->compareheight = compareheight;
1846                 item->comparecrc = comparecrc;
1847                 item->next = r_skinframe.hash[hashindex];
1848                 r_skinframe.hash[hashindex] = item;
1849         }
1850         else if( item->base == NULL )
1851         {
1852                 rtexture_t *dyntexture;
1853                 // check whether its a dynamic texture
1854                 // 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]
1855                 dyntexture = CL_GetDynTexture( basename );
1856                 item->base = dyntexture; // either NULL or dyntexture handle
1857         }
1858
1859         R_SkinFrame_MarkUsed(item);
1860         return item;
1861 }
1862
1863 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1864 {
1865         // FIXME: it should be possible to disable loading various layers using
1866         // cvars, to prevent wasted loading time and memory usage if the user does
1867         // not want them
1868         qboolean loadnormalmap = true;
1869         qboolean loadgloss = true;
1870         qboolean loadpantsandshirt = true;
1871         qboolean loadglow = true;
1872         int j;
1873         unsigned char *pixels;
1874         unsigned char *bumppixels;
1875         unsigned char *basepixels = NULL;
1876         int basepixels_width;
1877         int basepixels_height;
1878         skinframe_t *skinframe;
1879
1880         if (cls.state == ca_dedicated)
1881                 return NULL;
1882
1883         // return an existing skinframe if already loaded
1884         // if loading of the first image fails, don't make a new skinframe as it
1885         // would cause all future lookups of this to be missing
1886         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1887         if (skinframe && skinframe->base)
1888                 return skinframe;
1889
1890         basepixels = loadimagepixelsbgra(name, complain, true);
1891         if (basepixels == NULL)
1892                 return NULL;
1893
1894         // we've got some pixels to store, so really allocate this new texture now
1895         if (!skinframe)
1896                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1897         skinframe->stain = NULL;
1898         skinframe->merged = NULL;
1899         skinframe->base = r_texture_notexture;
1900         skinframe->pants = NULL;
1901         skinframe->shirt = NULL;
1902         skinframe->nmap = r_texture_blanknormalmap;
1903         skinframe->gloss = NULL;
1904         skinframe->glow = NULL;
1905         skinframe->fog = NULL;
1906
1907         basepixels_width = image_width;
1908         basepixels_height = image_height;
1909         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);
1910
1911         if (textureflags & TEXF_ALPHA)
1912         {
1913                 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1914                         if (basepixels[j] < 255)
1915                                 break;
1916                 if (j < basepixels_width * basepixels_height * 4)
1917                 {
1918                         // has transparent pixels
1919                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1920                         for (j = 0;j < image_width * image_height * 4;j += 4)
1921                         {
1922                                 pixels[j+0] = 255;
1923                                 pixels[j+1] = 255;
1924                                 pixels[j+2] = 255;
1925                                 pixels[j+3] = basepixels[j+3];
1926                         }
1927                         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);
1928                         Mem_Free(pixels);
1929                 }
1930         }
1931
1932         // _norm is the name used by tenebrae and has been adopted as standard
1933         if (loadnormalmap)
1934         {
1935                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
1936                 {
1937                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1938                         Mem_Free(pixels);
1939                         pixels = NULL;
1940                 }
1941                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
1942                 {
1943                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1944                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1945                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1946                         Mem_Free(pixels);
1947                         Mem_Free(bumppixels);
1948                 }
1949                 else if (r_shadow_bumpscale_basetexture.value > 0)
1950                 {
1951                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1952                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1953                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1954                         Mem_Free(pixels);
1955                 }
1956         }
1957         // _luma is supported for tenebrae compatibility
1958         // (I think it's a very stupid name, but oh well)
1959         // _glow is the preferred name
1960         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;}
1961         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;}
1962         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;}
1963         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;}
1964
1965         if (basepixels)
1966                 Mem_Free(basepixels);
1967
1968         return skinframe;
1969 }
1970
1971 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)
1972 {
1973         int i;
1974         if (!force)
1975         {
1976                 for (i = 0;i < width*height;i++)
1977                         if (((unsigned char *)&palette[in[i]])[3] > 0)
1978                                 break;
1979                 if (i == width*height)
1980                         return NULL;
1981         }
1982         return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1983 }
1984
1985 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
1986 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
1987 {
1988         int i;
1989         unsigned char *temp1, *temp2;
1990         skinframe_t *skinframe;
1991
1992         if (cls.state == ca_dedicated)
1993                 return NULL;
1994
1995         // if already loaded just return it, otherwise make a new skinframe
1996         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
1997         if (skinframe && skinframe->base)
1998                 return skinframe;
1999
2000         skinframe->stain = NULL;
2001         skinframe->merged = NULL;
2002         skinframe->base = r_texture_notexture;
2003         skinframe->pants = NULL;
2004         skinframe->shirt = NULL;
2005         skinframe->nmap = r_texture_blanknormalmap;
2006         skinframe->gloss = NULL;
2007         skinframe->glow = NULL;
2008         skinframe->fog = NULL;
2009
2010         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2011         if (!skindata)
2012                 return NULL;
2013
2014         if (r_shadow_bumpscale_basetexture.value > 0)
2015         {
2016                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2017                 temp2 = temp1 + width * height * 4;
2018                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2019                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2020                 Mem_Free(temp1);
2021         }
2022         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2023         if (textureflags & TEXF_ALPHA)
2024         {
2025                 for (i = 3;i < width * height * 4;i += 4)
2026                         if (skindata[i] < 255)
2027                                 break;
2028                 if (i < width * height * 4)
2029                 {
2030                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2031                         memcpy(fogpixels, skindata, width * height * 4);
2032                         for (i = 0;i < width * height * 4;i += 4)
2033                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2034                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2035                         Mem_Free(fogpixels);
2036                 }
2037         }
2038
2039         return skinframe;
2040 }
2041
2042 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2043 {
2044         int i;
2045         unsigned char *temp1, *temp2;
2046         skinframe_t *skinframe;
2047
2048         if (cls.state == ca_dedicated)
2049                 return NULL;
2050
2051         // if already loaded just return it, otherwise make a new skinframe
2052         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2053         if (skinframe && skinframe->base)
2054                 return skinframe;
2055
2056         skinframe->stain = NULL;
2057         skinframe->merged = NULL;
2058         skinframe->base = r_texture_notexture;
2059         skinframe->pants = NULL;
2060         skinframe->shirt = NULL;
2061         skinframe->nmap = r_texture_blanknormalmap;
2062         skinframe->gloss = NULL;
2063         skinframe->glow = NULL;
2064         skinframe->fog = NULL;
2065
2066         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2067         if (!skindata)
2068                 return NULL;
2069
2070         if (r_shadow_bumpscale_basetexture.value > 0)
2071         {
2072                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2073                 temp2 = temp1 + width * height * 4;
2074                 // use either a custom palette or the quake palette
2075                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2076                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2077                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2078                 Mem_Free(temp1);
2079         }
2080         // use either a custom palette, or the quake palette
2081         skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete)), skinframe->textureflags, true); // all
2082         if (loadglowtexture)
2083                 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2084         if (loadpantsandshirt)
2085         {
2086                 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2087                 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2088         }
2089         if (skinframe->pants || skinframe->shirt)
2090                 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
2091         if (textureflags & TEXF_ALPHA)
2092         {
2093                 for (i = 0;i < width * height;i++)
2094                         if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2095                                 break;
2096                 if (i < width * height)
2097                         skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2098         }
2099
2100         return skinframe;
2101 }
2102
2103 skinframe_t *R_SkinFrame_LoadMissing(void)
2104 {
2105         skinframe_t *skinframe;
2106
2107         if (cls.state == ca_dedicated)
2108                 return NULL;
2109
2110         skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
2111         skinframe->stain = NULL;
2112         skinframe->merged = NULL;
2113         skinframe->base = r_texture_notexture;
2114         skinframe->pants = NULL;
2115         skinframe->shirt = NULL;
2116         skinframe->nmap = r_texture_blanknormalmap;
2117         skinframe->gloss = NULL;
2118         skinframe->glow = NULL;
2119         skinframe->fog = NULL;
2120
2121         return skinframe;
2122 }
2123
2124 void gl_main_start(void)
2125 {
2126         memset(r_qwskincache, 0, sizeof(r_qwskincache));
2127         memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2128
2129         // set up r_skinframe loading system for textures
2130         memset(&r_skinframe, 0, sizeof(r_skinframe));
2131         r_skinframe.loadsequence = 1;
2132         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2133
2134         r_main_texturepool = R_AllocTexturePool();
2135         R_BuildBlankTextures();
2136         R_BuildNoTexture();
2137         if (gl_texturecubemap)
2138         {
2139                 R_BuildWhiteCube();
2140                 R_BuildNormalizationCube();
2141         }
2142         r_texture_fogattenuation = NULL;
2143         r_texture_gammaramps = NULL;
2144         //r_texture_fogintensity = NULL;
2145         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2146         memset(&r_waterstate, 0, sizeof(r_waterstate));
2147         memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2148         memset(&r_svbsp, 0, sizeof (r_svbsp));
2149
2150         r_refdef.fogmasktable_density = 0;
2151 }
2152
2153 void gl_main_shutdown(void)
2154 {
2155         memset(r_qwskincache, 0, sizeof(r_qwskincache));
2156         memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2157
2158         // clear out the r_skinframe state
2159         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2160         memset(&r_skinframe, 0, sizeof(r_skinframe));
2161
2162         if (r_svbsp.nodes)
2163                 Mem_Free(r_svbsp.nodes);
2164         memset(&r_svbsp, 0, sizeof (r_svbsp));
2165         R_FreeTexturePool(&r_main_texturepool);
2166         r_texture_blanknormalmap = NULL;
2167         r_texture_white = NULL;
2168         r_texture_grey128 = NULL;
2169         r_texture_black = NULL;
2170         r_texture_whitecube = NULL;
2171         r_texture_normalizationcube = NULL;
2172         r_texture_fogattenuation = NULL;
2173         r_texture_gammaramps = NULL;
2174         //r_texture_fogintensity = NULL;
2175         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2176         memset(&r_waterstate, 0, sizeof(r_waterstate));
2177         R_GLSL_Restart_f();
2178 }
2179
2180 extern void CL_ParseEntityLump(char *entitystring);
2181 void gl_main_newmap(void)
2182 {
2183         // FIXME: move this code to client
2184         int l;
2185         char *entities, entname[MAX_QPATH];
2186         if (cl.worldmodel)
2187         {
2188                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2189                 l = (int)strlen(entname) - 4;
2190                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2191                 {
2192                         memcpy(entname + l, ".ent", 5);
2193                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2194                         {
2195                                 CL_ParseEntityLump(entities);
2196                                 Mem_Free(entities);
2197                                 return;
2198                         }
2199                 }
2200                 if (cl.worldmodel->brush.entities)
2201                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
2202         }
2203 }
2204
2205 void GL_Main_Init(void)
2206 {
2207         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2208
2209         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2210         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2211         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2212         if (gamemode == GAME_NEHAHRA)
2213         {
2214                 Cvar_RegisterVariable (&gl_fogenable);
2215                 Cvar_RegisterVariable (&gl_fogdensity);
2216                 Cvar_RegisterVariable (&gl_fogred);
2217                 Cvar_RegisterVariable (&gl_foggreen);
2218                 Cvar_RegisterVariable (&gl_fogblue);
2219                 Cvar_RegisterVariable (&gl_fogstart);
2220                 Cvar_RegisterVariable (&gl_fogend);
2221                 Cvar_RegisterVariable (&gl_skyclip);
2222         }
2223         Cvar_RegisterVariable(&r_depthfirst);
2224         Cvar_RegisterVariable(&r_nearclip);
2225         Cvar_RegisterVariable(&r_showbboxes);
2226         Cvar_RegisterVariable(&r_showsurfaces);
2227         Cvar_RegisterVariable(&r_showtris);
2228         Cvar_RegisterVariable(&r_shownormals);
2229         Cvar_RegisterVariable(&r_showlighting);
2230         Cvar_RegisterVariable(&r_showshadowvolumes);
2231         Cvar_RegisterVariable(&r_showcollisionbrushes);
2232         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2233         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2234         Cvar_RegisterVariable(&r_showdisabledepthtest);
2235         Cvar_RegisterVariable(&r_drawportals);
2236         Cvar_RegisterVariable(&r_drawentities);
2237         Cvar_RegisterVariable(&r_cullentities_trace);
2238         Cvar_RegisterVariable(&r_cullentities_trace_samples);
2239         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2240         Cvar_RegisterVariable(&r_cullentities_trace_delay);
2241         Cvar_RegisterVariable(&r_drawviewmodel);
2242         Cvar_RegisterVariable(&r_speeds);
2243         Cvar_RegisterVariable(&r_fullbrights);
2244         Cvar_RegisterVariable(&r_wateralpha);
2245         Cvar_RegisterVariable(&r_dynamic);
2246         Cvar_RegisterVariable(&r_fullbright);
2247         Cvar_RegisterVariable(&r_shadows);
2248         Cvar_RegisterVariable(&r_shadows_throwdistance);
2249         Cvar_RegisterVariable(&r_q1bsp_skymasking);
2250         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2251         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2252         Cvar_RegisterVariable(&r_fog_exp2);
2253         Cvar_RegisterVariable(&r_textureunits);
2254         Cvar_RegisterVariable(&r_glsl);
2255         Cvar_RegisterVariable(&r_glsl_contrastboost);
2256         Cvar_RegisterVariable(&r_glsl_deluxemapping);
2257         Cvar_RegisterVariable(&r_glsl_offsetmapping);
2258         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2259         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2260         Cvar_RegisterVariable(&r_glsl_postprocess);
2261         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2262         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2263         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2264         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2265         Cvar_RegisterVariable(&r_glsl_usegeneric);
2266         Cvar_RegisterVariable(&r_water);
2267         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2268         Cvar_RegisterVariable(&r_water_clippingplanebias);
2269         Cvar_RegisterVariable(&r_water_refractdistort);
2270         Cvar_RegisterVariable(&r_water_reflectdistort);
2271         Cvar_RegisterVariable(&r_lerpsprites);
2272         Cvar_RegisterVariable(&r_lerpmodels);
2273         Cvar_RegisterVariable(&r_lerplightstyles);
2274         Cvar_RegisterVariable(&r_waterscroll);
2275         Cvar_RegisterVariable(&r_bloom);
2276         Cvar_RegisterVariable(&r_bloom_colorscale);
2277         Cvar_RegisterVariable(&r_bloom_brighten);
2278         Cvar_RegisterVariable(&r_bloom_blur);
2279         Cvar_RegisterVariable(&r_bloom_resolution);
2280         Cvar_RegisterVariable(&r_bloom_colorexponent);
2281         Cvar_RegisterVariable(&r_bloom_colorsubtract);
2282         Cvar_RegisterVariable(&r_hdr);
2283         Cvar_RegisterVariable(&r_hdr_scenebrightness);
2284         Cvar_RegisterVariable(&r_hdr_glowintensity);
2285         Cvar_RegisterVariable(&r_hdr_range);
2286         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2287         Cvar_RegisterVariable(&developer_texturelogging);
2288         Cvar_RegisterVariable(&gl_lightmaps);
2289         Cvar_RegisterVariable(&r_test);
2290         Cvar_RegisterVariable(&r_batchmode);
2291         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2292                 Cvar_SetValue("r_fullbrights", 0);
2293         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2294
2295         Cvar_RegisterVariable(&r_track_sprites);
2296         Cvar_RegisterVariable(&r_track_sprites_flags);
2297         Cvar_RegisterVariable(&r_track_sprites_scalew);
2298         Cvar_RegisterVariable(&r_track_sprites_scaleh);
2299 }
2300
2301 extern void R_Textures_Init(void);
2302 extern void GL_Draw_Init(void);
2303 extern void GL_Main_Init(void);
2304 extern void R_Shadow_Init(void);
2305 extern void R_Sky_Init(void);
2306 extern void GL_Surf_Init(void);
2307 extern void R_Particles_Init(void);
2308 extern void R_Explosion_Init(void);
2309 extern void gl_backend_init(void);
2310 extern void Sbar_Init(void);
2311 extern void R_LightningBeams_Init(void);
2312 extern void Mod_RenderInit(void);
2313
2314 void Render_Init(void)
2315 {
2316         gl_backend_init();
2317         R_Textures_Init();
2318         GL_Main_Init();
2319         GL_Draw_Init();
2320         R_Shadow_Init();
2321         R_Sky_Init();
2322         GL_Surf_Init();
2323         Sbar_Init();
2324         R_Particles_Init();
2325         R_Explosion_Init();
2326         R_LightningBeams_Init();
2327         Mod_RenderInit();
2328 }
2329
2330 /*
2331 ===============
2332 GL_Init
2333 ===============
2334 */
2335 extern char *ENGINE_EXTENSIONS;
2336 void GL_Init (void)
2337 {
2338         VID_CheckExtensions();
2339
2340         // LordHavoc: report supported extensions
2341         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2342
2343         // clear to black (loading plaque will be seen over this)
2344         CHECKGLERROR
2345         qglClearColor(0,0,0,1);CHECKGLERROR
2346         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2347 }
2348
2349 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2350 {
2351         int i;
2352         mplane_t *p;
2353         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2354         {
2355                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2356                 if (i == 4)
2357                         continue;
2358                 p = r_refdef.view.frustum + i;
2359                 switch(p->signbits)
2360                 {
2361                 default:
2362                 case 0:
2363                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2364                                 return true;
2365                         break;
2366                 case 1:
2367                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2368                                 return true;
2369                         break;
2370                 case 2:
2371                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2372                                 return true;
2373                         break;
2374                 case 3:
2375                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2376                                 return true;
2377                         break;
2378                 case 4:
2379                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2380                                 return true;
2381                         break;
2382                 case 5:
2383                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2384                                 return true;
2385                         break;
2386                 case 6:
2387                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2388                                 return true;
2389                         break;
2390                 case 7:
2391                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2392                                 return true;
2393                         break;
2394                 }
2395         }
2396         return false;
2397 }
2398
2399 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2400 {
2401         int i;
2402         const mplane_t *p;
2403         for (i = 0;i < numplanes;i++)
2404         {
2405                 p = planes + i;
2406                 switch(p->signbits)
2407                 {
2408                 default:
2409                 case 0:
2410                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2411                                 return true;
2412                         break;
2413                 case 1:
2414                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2415                                 return true;
2416                         break;
2417                 case 2:
2418                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2419                                 return true;
2420                         break;
2421                 case 3:
2422                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2423                                 return true;
2424                         break;
2425                 case 4:
2426                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2427                                 return true;
2428                         break;
2429                 case 5:
2430                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2431                                 return true;
2432                         break;
2433                 case 6:
2434                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2435                                 return true;
2436                         break;
2437                 case 7:
2438                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2439                                 return true;
2440                         break;
2441                 }
2442         }
2443         return false;
2444 }
2445
2446 //==================================================================================
2447
2448 static void R_View_UpdateEntityVisible (void)
2449 {
2450         int i, renderimask;
2451         entity_render_t *ent;
2452
2453         if (!r_drawentities.integer)
2454                 return;
2455
2456         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2457         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2458         {
2459                 // worldmodel can check visibility
2460                 for (i = 0;i < r_refdef.scene.numentities;i++)
2461                 {
2462                         ent = r_refdef.scene.entities[i];
2463                         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)) && ((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));
2464
2465                 }
2466                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2467                 {
2468                         for (i = 0;i < r_refdef.scene.numentities;i++)
2469                         {
2470                                 ent = r_refdef.scene.entities[i];
2471                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2472                                 {
2473                                         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))
2474                                                 ent->last_trace_visibility = realtime;
2475                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2476                                                 r_refdef.viewcache.entityvisible[i] = 0;
2477                                 }
2478                         }
2479                 }
2480         }
2481         else
2482         {
2483                 // no worldmodel or it can't check visibility
2484                 for (i = 0;i < r_refdef.scene.numentities;i++)
2485                 {
2486                         ent = r_refdef.scene.entities[i];
2487                         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));
2488                 }
2489         }
2490 }
2491
2492 // only used if skyrendermasked, and normally returns false
2493 int R_DrawBrushModelsSky (void)
2494 {
2495         int i, sky;
2496         entity_render_t *ent;
2497
2498         if (!r_drawentities.integer)
2499                 return false;
2500
2501         sky = false;
2502         for (i = 0;i < r_refdef.scene.numentities;i++)
2503         {
2504                 if (!r_refdef.viewcache.entityvisible[i])
2505                         continue;
2506                 ent = r_refdef.scene.entities[i];
2507                 if (!ent->model || !ent->model->DrawSky)
2508                         continue;
2509                 ent->model->DrawSky(ent);
2510                 sky = true;
2511         }
2512         return sky;
2513 }
2514
2515 static void R_DrawNoModel(entity_render_t *ent);
2516 static void R_DrawModels(void)
2517 {
2518         int i;
2519         entity_render_t *ent;
2520
2521         if (!r_drawentities.integer)
2522                 return;
2523
2524         for (i = 0;i < r_refdef.scene.numentities;i++)
2525         {
2526                 if (!r_refdef.viewcache.entityvisible[i])
2527                         continue;
2528                 ent = r_refdef.scene.entities[i];
2529                 r_refdef.stats.entities++;
2530                 if (ent->model && ent->model->Draw != NULL)
2531                         ent->model->Draw(ent);
2532                 else
2533                         R_DrawNoModel(ent);
2534         }
2535 }
2536
2537 static void R_DrawModelsDepth(void)
2538 {
2539         int i;
2540         entity_render_t *ent;
2541
2542         if (!r_drawentities.integer)
2543                 return;
2544
2545         for (i = 0;i < r_refdef.scene.numentities;i++)
2546         {
2547                 if (!r_refdef.viewcache.entityvisible[i])
2548                         continue;
2549                 ent = r_refdef.scene.entities[i];
2550                 if (ent->model && ent->model->DrawDepth != NULL)
2551                         ent->model->DrawDepth(ent);
2552         }
2553 }
2554
2555 static void R_DrawModelsDebug(void)
2556 {
2557         int i;
2558         entity_render_t *ent;
2559
2560         if (!r_drawentities.integer)
2561                 return;
2562
2563         for (i = 0;i < r_refdef.scene.numentities;i++)
2564         {
2565                 if (!r_refdef.viewcache.entityvisible[i])
2566                         continue;
2567                 ent = r_refdef.scene.entities[i];
2568                 if (ent->model && ent->model->DrawDebug != NULL)
2569                         ent->model->DrawDebug(ent);
2570         }
2571 }
2572
2573 static void R_DrawModelsAddWaterPlanes(void)
2574 {
2575         int i;
2576         entity_render_t *ent;
2577
2578         if (!r_drawentities.integer)
2579                 return;
2580
2581         for (i = 0;i < r_refdef.scene.numentities;i++)
2582         {
2583                 if (!r_refdef.viewcache.entityvisible[i])
2584                         continue;
2585                 ent = r_refdef.scene.entities[i];
2586                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2587                         ent->model->DrawAddWaterPlanes(ent);
2588         }
2589 }
2590
2591 static void R_View_SetFrustum(void)
2592 {
2593         int i;
2594         double slopex, slopey;
2595         vec3_t forward, left, up, origin;
2596
2597         // we can't trust r_refdef.view.forward and friends in reflected scenes
2598         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
2599
2600 #if 0
2601         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2602         r_refdef.view.frustum[0].normal[1] = 0 - 0;
2603         r_refdef.view.frustum[0].normal[2] = -1 - 0;
2604         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2605         r_refdef.view.frustum[1].normal[1] = 0 + 0;
2606         r_refdef.view.frustum[1].normal[2] = -1 + 0;
2607         r_refdef.view.frustum[2].normal[0] = 0 - 0;
2608         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2609         r_refdef.view.frustum[2].normal[2] = -1 - 0;
2610         r_refdef.view.frustum[3].normal[0] = 0 + 0;
2611         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2612         r_refdef.view.frustum[3].normal[2] = -1 + 0;
2613 #endif
2614
2615 #if 0
2616         zNear = r_refdef.nearclip;
2617         nudge = 1.0 - 1.0 / (1<<23);
2618         r_refdef.view.frustum[4].normal[0] = 0 - 0;
2619         r_refdef.view.frustum[4].normal[1] = 0 - 0;
2620         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
2621         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
2622         r_refdef.view.frustum[5].normal[0] = 0 + 0;
2623         r_refdef.view.frustum[5].normal[1] = 0 + 0;
2624         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
2625         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
2626 #endif
2627
2628
2629
2630 #if 0
2631         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
2632         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
2633         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
2634         r_refdef.view.frustum[0].dist = m[15] - m[12];
2635
2636         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
2637         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
2638         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
2639         r_refdef.view.frustum[1].dist = m[15] + m[12];
2640
2641         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
2642         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
2643         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
2644         r_refdef.view.frustum[2].dist = m[15] - m[13];
2645
2646         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
2647         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
2648         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
2649         r_refdef.view.frustum[3].dist = m[15] + m[13];
2650
2651         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
2652         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
2653         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
2654         r_refdef.view.frustum[4].dist = m[15] - m[14];
2655
2656         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
2657         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
2658         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
2659         r_refdef.view.frustum[5].dist = m[15] + m[14];
2660 #endif
2661
2662         if (r_refdef.view.useperspective)
2663         {
2664                 slopex = 1.0 / r_refdef.view.frustum_x;
2665                 slopey = 1.0 / r_refdef.view.frustum_y;
2666                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
2667                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
2668                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
2669                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
2670                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2671
2672                 // Leaving those out was a mistake, those were in the old code, and they
2673                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2674                 // I couldn't reproduce it after adding those normalizations. --blub
2675                 VectorNormalize(r_refdef.view.frustum[0].normal);
2676                 VectorNormalize(r_refdef.view.frustum[1].normal);
2677                 VectorNormalize(r_refdef.view.frustum[2].normal);
2678                 VectorNormalize(r_refdef.view.frustum[3].normal);
2679
2680                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2681                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
2682                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
2683                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left,  1024 * slopey, up, r_refdef.view.frustumcorner[2]);
2684                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * slopex, left,  1024 * slopey, up, r_refdef.view.frustumcorner[3]);
2685
2686                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
2687                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
2688                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
2689                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
2690                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2691         }
2692         else
2693         {
2694                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
2695                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
2696                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
2697                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
2698                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2699                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
2700                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
2701                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
2702                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
2703                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2704         }
2705         r_refdef.view.numfrustumplanes = 5;
2706
2707         if (r_refdef.view.useclipplane)
2708         {
2709                 r_refdef.view.numfrustumplanes = 6;
2710                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
2711         }
2712
2713         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2714                 PlaneClassify(r_refdef.view.frustum + i);
2715
2716         // LordHavoc: note to all quake engine coders, Quake had a special case
2717         // for 90 degrees which assumed a square view (wrong), so I removed it,
2718         // Quake2 has it disabled as well.
2719
2720         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2721         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
2722         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
2723         //PlaneClassify(&frustum[0]);
2724
2725         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2726         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
2727         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
2728         //PlaneClassify(&frustum[1]);
2729
2730         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2731         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
2732         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
2733         //PlaneClassify(&frustum[2]);
2734
2735         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2736         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
2737         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
2738         //PlaneClassify(&frustum[3]);
2739
2740         // nearclip plane
2741         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
2742         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
2743         //PlaneClassify(&frustum[4]);
2744 }
2745
2746 void R_View_Update(void)
2747 {
2748         R_View_SetFrustum();
2749         R_View_WorldVisibility(r_refdef.view.useclipplane);
2750         R_View_UpdateEntityVisible();
2751 }
2752
2753 void R_SetupView(qboolean allowwaterclippingplane)
2754 {
2755         if (!r_refdef.view.useperspective)
2756                 GL_SetupView_Mode_Ortho(-r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip);
2757         else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2758                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
2759         else
2760                 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2761
2762         GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
2763
2764         if (r_refdef.view.useclipplane && allowwaterclippingplane)
2765         {
2766                 // LordHavoc: couldn't figure out how to make this approach the
2767                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
2768                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
2769                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
2770                         dist = r_refdef.view.clipplane.dist;
2771                 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
2772         }
2773 }
2774
2775 void R_ResetViewRendering2D(void)
2776 {
2777         DrawQ_Finish();
2778
2779         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2780         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2781         GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2782         GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2783         GL_Color(1, 1, 1, 1);
2784         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2785         GL_BlendFunc(GL_ONE, GL_ZERO);
2786         GL_AlphaTest(false);
2787         GL_ScissorTest(false);
2788         GL_DepthMask(false);
2789         GL_DepthRange(0, 1);
2790         GL_DepthTest(false);
2791         R_Mesh_Matrix(&identitymatrix);
2792         R_Mesh_ResetTextureState();
2793         GL_PolygonOffset(0, 0);
2794         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2795         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2796         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2797         qglStencilMask(~0);CHECKGLERROR
2798         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2799         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2800         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2801         R_SetupGenericShader(true);
2802 }
2803
2804 void R_ResetViewRendering3D(void)
2805 {
2806         DrawQ_Finish();
2807
2808         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2809         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2810         R_SetupView(true);
2811         GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2812         GL_Color(1, 1, 1, 1);
2813         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2814         GL_BlendFunc(GL_ONE, GL_ZERO);
2815         GL_AlphaTest(false);
2816         GL_ScissorTest(true);
2817         GL_DepthMask(true);
2818         GL_DepthRange(0, 1);
2819         GL_DepthTest(true);
2820         R_Mesh_Matrix(&identitymatrix);
2821         R_Mesh_ResetTextureState();
2822         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2823         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2824         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2825         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2826         qglStencilMask(~0);CHECKGLERROR
2827         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2828         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2829         GL_CullFace(r_refdef.view.cullface_back);
2830         R_SetupGenericShader(true);
2831 }
2832
2833 void R_RenderScene(qboolean addwaterplanes);
2834
2835 static void R_Water_StartFrame(void)
2836 {
2837         int i;
2838         int waterwidth, waterheight, texturewidth, textureheight;
2839         r_waterstate_waterplane_t *p;
2840
2841         // set waterwidth and waterheight to the water resolution that will be
2842         // used (often less than the screen resolution for faster rendering)
2843         waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
2844         waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
2845
2846         // calculate desired texture sizes
2847         // can't use water if the card does not support the texture size
2848         if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2849                 texturewidth = textureheight = waterwidth = waterheight = 0;
2850         else if (gl_support_arb_texture_non_power_of_two)
2851         {
2852                 texturewidth = waterwidth;
2853                 textureheight = waterheight;
2854         }
2855         else
2856         {
2857                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
2858                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
2859         }
2860
2861         // allocate textures as needed
2862         if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2863         {
2864                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2865                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2866                 {
2867                         if (p->texture_refraction)
2868                                 R_FreeTexture(p->texture_refraction);
2869                         p->texture_refraction = NULL;
2870                         if (p->texture_reflection)
2871                                 R_FreeTexture(p->texture_reflection);
2872                         p->texture_reflection = NULL;
2873                 }
2874                 memset(&r_waterstate, 0, sizeof(r_waterstate));
2875                 r_waterstate.waterwidth = waterwidth;
2876                 r_waterstate.waterheight = waterheight;
2877                 r_waterstate.texturewidth = texturewidth;
2878                 r_waterstate.textureheight = textureheight;
2879         }
2880
2881         if (r_waterstate.waterwidth)
2882         {
2883                 r_waterstate.enabled = true;
2884
2885                 // set up variables that will be used in shader setup
2886                 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2887                 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2888                 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2889                 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2890         }
2891
2892         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2893         r_waterstate.numwaterplanes = 0;
2894 }
2895
2896 static void R_Water_AddWaterPlane(msurface_t *surface)
2897 {
2898         int triangleindex, planeindex;
2899         const int *e;
2900         vec3_t vert[3];
2901         vec3_t normal;
2902         vec3_t center;
2903         mplane_t plane;
2904         r_waterstate_waterplane_t *p;
2905         // just use the first triangle with a valid normal for any decisions
2906         VectorClear(normal);
2907         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2908         {
2909                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2910                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2911                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2912                 TriangleNormal(vert[0], vert[1], vert[2], normal);
2913                 if (VectorLength2(normal) >= 0.001)
2914                         break;
2915         }
2916
2917         VectorCopy(normal, plane.normal);
2918         VectorNormalize(plane.normal);
2919         plane.dist = DotProduct(vert[0], plane.normal);
2920         PlaneClassify(&plane);
2921         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
2922         {
2923                 // skip backfaces (except if nocullface is set)
2924                 if (!(surface->texture->currentframe->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
2925                         return;
2926                 VectorNegate(plane.normal, plane.normal);
2927                 plane.dist *= -1;
2928                 PlaneClassify(&plane);
2929         }
2930
2931
2932         // find a matching plane if there is one
2933         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2934                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2935                         break;
2936         if (planeindex >= r_waterstate.maxwaterplanes)
2937                 return; // nothing we can do, out of planes
2938
2939         // if this triangle does not fit any known plane rendered this frame, add one
2940         if (planeindex >= r_waterstate.numwaterplanes)
2941         {
2942                 // store the new plane
2943                 r_waterstate.numwaterplanes++;
2944                 p->plane = plane;
2945                 // clear materialflags and pvs
2946                 p->materialflags = 0;
2947                 p->pvsvalid = false;
2948         }
2949         // merge this surface's materialflags into the waterplane
2950         p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2951         // merge this surface's PVS into the waterplane
2952         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
2953         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
2954          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
2955         {
2956                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2957                 p->pvsvalid = true;
2958         }
2959 }
2960
2961 static void R_Water_ProcessPlanes(void)
2962 {
2963         r_refdef_view_t originalview;
2964         int planeindex;
2965         r_waterstate_waterplane_t *p;
2966
2967         originalview = r_refdef.view;
2968
2969         // make sure enough textures are allocated
2970         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2971         {
2972                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2973                 {
2974                         if (!p->texture_refraction)
2975                                 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);
2976                         if (!p->texture_refraction)
2977                                 goto error;
2978                 }
2979
2980                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2981                 {
2982                         if (!p->texture_reflection)
2983                                 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);
2984                         if (!p->texture_reflection)
2985                                 goto error;
2986                 }
2987         }
2988
2989         // render views
2990         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2991         {
2992                 r_refdef.view.showdebug = false;
2993                 r_refdef.view.width = r_waterstate.waterwidth;
2994                 r_refdef.view.height = r_waterstate.waterheight;
2995                 r_refdef.view.useclipplane = true;
2996                 r_waterstate.renderingscene = true;
2997
2998                 // render the normal view scene and copy into texture
2999                 // (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)
3000                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3001                 {
3002                         r_refdef.view.clipplane = p->plane;
3003                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3004                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3005                         PlaneClassify(&r_refdef.view.clipplane);
3006
3007                         R_RenderScene(false);
3008
3009                         // copy view into the screen texture
3010                         R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3011                         GL_ActiveTexture(0);
3012                         CHECKGLERROR
3013                         qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3014                 }
3015
3016                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3017                 {
3018                         // render reflected scene and copy into texture
3019                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3020                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3021                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3022                         r_refdef.view.clipplane = p->plane;
3023                         // reverse the cullface settings for this render
3024                         r_refdef.view.cullface_front = GL_FRONT;
3025                         r_refdef.view.cullface_back = GL_BACK;
3026                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3027                         {
3028                                 r_refdef.view.usecustompvs = true;
3029                                 if (p->pvsvalid)
3030                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3031                                 else
3032                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3033                         }
3034
3035                         R_ResetViewRendering3D();
3036                         R_ClearScreen(r_refdef.fogenabled);
3037                         if (r_timereport_active)
3038                                 R_TimeReport("viewclear");
3039
3040                         R_RenderScene(false);
3041
3042                         R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3043                         GL_ActiveTexture(0);
3044                         CHECKGLERROR
3045                         qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3046
3047                         R_ResetViewRendering3D();
3048                         R_ClearScreen(r_refdef.fogenabled);
3049                         if (r_timereport_active)
3050                                 R_TimeReport("viewclear");
3051                 }
3052
3053                 r_refdef.view = originalview;
3054                 r_refdef.view.clear = true;
3055                 r_waterstate.renderingscene = false;
3056         }
3057         return;
3058 error:
3059         r_refdef.view = originalview;
3060         r_waterstate.renderingscene = false;
3061         Cvar_SetValueQuick(&r_water, 0);
3062         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
3063         return;
3064 }
3065
3066 void R_Bloom_StartFrame(void)
3067 {
3068         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3069
3070         // set bloomwidth and bloomheight to the bloom resolution that will be
3071         // used (often less than the screen resolution for faster rendering)
3072         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3073         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3074         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3075         r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3076         r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3077
3078         // calculate desired texture sizes
3079         if (gl_support_arb_texture_non_power_of_two)
3080         {
3081                 screentexturewidth = r_refdef.view.width;
3082                 screentextureheight = r_refdef.view.height;
3083                 bloomtexturewidth = r_bloomstate.bloomwidth;
3084                 bloomtextureheight = r_bloomstate.bloomheight;
3085         }
3086         else
3087         {
3088                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
3089                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
3090                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
3091                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
3092         }
3093
3094         if ((r_hdr.integer || r_bloom.integer) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > gl_max_texture_size || r_refdef.view.height > gl_max_texture_size))
3095         {
3096                 Cvar_SetValueQuick(&r_hdr, 0);
3097                 Cvar_SetValueQuick(&r_bloom, 0);
3098         }
3099
3100         if (!(r_glsl.integer && (r_glsl_postprocess.integer || (v_glslgamma.integer && !vid_gammatables_trivial) || r_bloom.integer || r_hdr.integer)) && !r_bloom.integer)
3101                 screentexturewidth = screentextureheight = 0;
3102         if (!r_hdr.integer && !r_bloom.integer)
3103                 bloomtexturewidth = bloomtextureheight = 0;
3104
3105         // allocate textures as needed
3106         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3107         {
3108                 if (r_bloomstate.texture_screen)
3109                         R_FreeTexture(r_bloomstate.texture_screen);
3110                 r_bloomstate.texture_screen = NULL;
3111                 r_bloomstate.screentexturewidth = screentexturewidth;
3112                 r_bloomstate.screentextureheight = screentextureheight;
3113                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3114                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
3115         }
3116         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3117         {
3118                 if (r_bloomstate.texture_bloom)
3119                         R_FreeTexture(r_bloomstate.texture_bloom);
3120                 r_bloomstate.texture_bloom = NULL;
3121                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3122                 r_bloomstate.bloomtextureheight = bloomtextureheight;
3123                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3124                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
3125         }
3126
3127         // set up a texcoord array for the full resolution screen image
3128         // (we have to keep this around to copy back during final render)
3129         r_bloomstate.screentexcoord2f[0] = 0;
3130         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
3131         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
3132         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
3133         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
3134         r_bloomstate.screentexcoord2f[5] = 0;
3135         r_bloomstate.screentexcoord2f[6] = 0;
3136         r_bloomstate.screentexcoord2f[7] = 0;
3137
3138         // set up a texcoord array for the reduced resolution bloom image
3139         // (which will be additive blended over the screen image)
3140         r_bloomstate.bloomtexcoord2f[0] = 0;
3141         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3142         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
3143         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3144         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
3145         r_bloomstate.bloomtexcoord2f[5] = 0;
3146         r_bloomstate.bloomtexcoord2f[6] = 0;
3147         r_bloomstate.bloomtexcoord2f[7] = 0;
3148
3149         if (r_hdr.integer || r_bloom.integer)
3150         {
3151                 r_bloomstate.enabled = true;
3152                 r_bloomstate.hdr = r_hdr.integer != 0;
3153         }
3154 }
3155
3156 void R_Bloom_CopyBloomTexture(float colorscale)
3157 {
3158         r_refdef.stats.bloom++;
3159
3160         // scale down screen texture to the bloom texture size
3161         CHECKGLERROR
3162         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3163         GL_BlendFunc(GL_ONE, GL_ZERO);
3164         GL_Color(colorscale, colorscale, colorscale, 1);
3165         // TODO: optimize with multitexture or GLSL
3166         R_SetupGenericShader(true);
3167         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3168         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3169         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3170         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3171
3172         // we now have a bloom image in the framebuffer
3173         // copy it into the bloom image texture for later processing
3174         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3175         GL_ActiveTexture(0);
3176         CHECKGLERROR
3177         qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3178         r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3179 }
3180
3181 void R_Bloom_CopyHDRTexture(void)
3182 {
3183         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3184         GL_ActiveTexture(0);
3185         CHECKGLERROR
3186         qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3187         r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3188 }
3189
3190 void R_Bloom_MakeTexture(void)
3191 {
3192         int x, range, dir;
3193         float xoffset, yoffset, r, brighten;
3194
3195         r_refdef.stats.bloom++;
3196
3197         R_ResetViewRendering2D();
3198         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3199         R_Mesh_ColorPointer(NULL, 0, 0);
3200         R_SetupGenericShader(true);
3201
3202         // we have a bloom image in the framebuffer
3203         CHECKGLERROR
3204         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3205
3206         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3207         {
3208                 x *= 2;
3209                 r = bound(0, r_bloom_colorexponent.value / x, 1);
3210                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3211                 GL_Color(r, r, r, 1);
3212                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3213                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3214                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3215                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3216
3217                 // copy the vertically blurred bloom view to a texture
3218                 GL_ActiveTexture(0);
3219                 CHECKGLERROR
3220                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3221                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3222         }
3223
3224         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3225         brighten = r_bloom_brighten.value;
3226         if (r_hdr.integer)
3227                 brighten *= r_hdr_range.value;
3228         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3229         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3230
3231         for (dir = 0;dir < 2;dir++)
3232         {
3233                 // blend on at multiple vertical offsets to achieve a vertical blur
3234                 // TODO: do offset blends using GLSL
3235                 GL_BlendFunc(GL_ONE, GL_ZERO);
3236                 for (x = -range;x <= range;x++)
3237                 {
3238                         if (!dir){xoffset = 0;yoffset = x;}
3239                         else {xoffset = x;yoffset = 0;}
3240                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
3241                         yoffset /= (float)r_bloomstate.bloomtextureheight;
3242                         // compute a texcoord array with the specified x and y offset
3243                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3244                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3245                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3246                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3247                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3248                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3249                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3250                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3251                         // this r value looks like a 'dot' particle, fading sharply to
3252                         // black at the edges
3253                         // (probably not realistic but looks good enough)
3254                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3255                         //r = (dir ? 1.0f : brighten)/(range*2+1);
3256                         r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3257                         GL_Color(r, r, r, 1);
3258                         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3259                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3260                         GL_BlendFunc(GL_ONE, GL_ONE);
3261                 }
3262
3263                 // copy the vertically blurred bloom view to a texture
3264                 GL_ActiveTexture(0);
3265                 CHECKGLERROR
3266                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3267                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3268         }
3269
3270         // apply subtract last
3271         // (just like it would be in a GLSL shader)
3272         if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3273         {
3274                 GL_BlendFunc(GL_ONE, GL_ZERO);
3275                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3276                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3277                 GL_Color(1, 1, 1, 1);
3278                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3279                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3280
3281                 GL_BlendFunc(GL_ONE, GL_ONE);
3282                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3283                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3284                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3285                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3286                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3287                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3288                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3289
3290                 // copy the darkened bloom view to a texture
3291                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3292                 GL_ActiveTexture(0);
3293                 CHECKGLERROR
3294                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3295                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3296         }
3297 }
3298
3299 void R_HDR_RenderBloomTexture(void)
3300 {
3301         int oldwidth, oldheight;
3302         float oldcolorscale;
3303
3304         oldcolorscale = r_refdef.view.colorscale;
3305         oldwidth = r_refdef.view.width;
3306         oldheight = r_refdef.view.height;
3307         r_refdef.view.width = r_bloomstate.bloomwidth;
3308         r_refdef.view.height = r_bloomstate.bloomheight;
3309
3310         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
3311         // TODO: add exposure compensation features
3312         // TODO: add fp16 framebuffer support
3313
3314         r_refdef.view.showdebug = false;
3315         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3316
3317         R_ClearScreen(r_refdef.fogenabled);
3318         if (r_timereport_active)
3319                 R_TimeReport("HDRclear");
3320
3321         r_waterstate.numwaterplanes = 0;
3322         R_RenderScene(r_waterstate.enabled);
3323         r_refdef.view.showdebug = true;
3324
3325         R_ResetViewRendering2D();
3326
3327         R_Bloom_CopyHDRTexture();
3328         R_Bloom_MakeTexture();
3329
3330         // restore the view settings
3331         r_refdef.view.width = oldwidth;
3332         r_refdef.view.height = oldheight;
3333         r_refdef.view.colorscale = oldcolorscale;
3334
3335         R_ResetViewRendering3D();
3336
3337         R_ClearScreen(r_refdef.fogenabled);
3338         if (r_timereport_active)
3339                 R_TimeReport("viewclear");
3340 }
3341
3342 static void R_BlendView(void)
3343 {
3344         if (r_bloomstate.texture_screen)
3345         {
3346                 // copy view into the screen texture
3347                 R_ResetViewRendering2D();
3348                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3349                 R_Mesh_ColorPointer(NULL, 0, 0);
3350                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3351                 GL_ActiveTexture(0);CHECKGLERROR
3352                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3353                 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3354         }
3355
3356         if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
3357         {
3358                 unsigned int permutation =
3359                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
3360                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)
3361                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
3362                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0);
3363
3364                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
3365                 {
3366                         // render simple bloom effect
3367                         // copy the screen and shrink it and darken it for the bloom process
3368                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3369                         // make the bloom texture
3370                         R_Bloom_MakeTexture();
3371                 }
3372
3373                 R_ResetViewRendering2D();
3374                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3375                 R_Mesh_ColorPointer(NULL, 0, 0);
3376                 GL_Color(1, 1, 1, 1);
3377                 GL_BlendFunc(GL_ONE, GL_ZERO);
3378                 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
3379                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3380                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3381                 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
3382                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3383                 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
3384                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
3385                 if (r_glsl_permutation->loc_TintColor >= 0)
3386                         qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3387                 if (r_glsl_permutation->loc_ClientTime >= 0)
3388                         qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3389                 if (r_glsl_permutation->loc_PixelSize >= 0)
3390                         qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
3391                 if (r_glsl_permutation->loc_UserVec1 >= 0)
3392                 {
3393                         float a=0, b=0, c=0, d=0;
3394                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
3395                         qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
3396                 }
3397                 if (r_glsl_permutation->loc_UserVec2 >= 0)
3398                 {
3399                         float a=0, b=0, c=0, d=0;
3400                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
3401                         qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
3402                 }
3403                 if (r_glsl_permutation->loc_UserVec3 >= 0)
3404                 {
3405                         float a=0, b=0, c=0, d=0;
3406                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
3407                         qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
3408                 }
3409                 if (r_glsl_permutation->loc_UserVec4 >= 0)
3410                 {
3411                         float a=0, b=0, c=0, d=0;
3412                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
3413                         qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
3414                 }
3415                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3416                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3417                 return;
3418         }
3419
3420
3421
3422         if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
3423         {
3424                 // render high dynamic range bloom effect
3425                 // the bloom texture was made earlier this render, so we just need to
3426                 // blend it onto the screen...
3427                 R_ResetViewRendering2D();
3428                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3429                 R_Mesh_ColorPointer(NULL, 0, 0);
3430                 R_SetupGenericShader(true);
3431                 GL_Color(1, 1, 1, 1);
3432                 GL_BlendFunc(GL_ONE, GL_ONE);
3433                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3434                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3435                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3436                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3437         }
3438         else if (r_bloomstate.texture_bloom)
3439         {
3440                 // render simple bloom effect
3441                 // copy the screen and shrink it and darken it for the bloom process
3442                 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3443                 // make the bloom texture
3444                 R_Bloom_MakeTexture();
3445                 // put the original screen image back in place and blend the bloom
3446                 // texture on it
3447                 R_ResetViewRendering2D();
3448                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3449                 R_Mesh_ColorPointer(NULL, 0, 0);
3450                 GL_Color(1, 1, 1, 1);
3451                 GL_BlendFunc(GL_ONE, GL_ZERO);
3452                 // do both in one pass if possible
3453                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3454                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3455                 if (r_textureunits.integer >= 2 && gl_combine.integer)
3456                 {
3457                         R_SetupGenericTwoTextureShader(GL_ADD);
3458                         R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3459                         R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3460                 }
3461                 else
3462                 {
3463                         R_SetupGenericShader(true);
3464                         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3465                         r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3466                         // now blend on the bloom texture
3467                         GL_BlendFunc(GL_ONE, GL_ONE);
3468                         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3469                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3470                 }
3471                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3472                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3473         }
3474         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3475         {
3476                 // apply a color tint to the whole view
3477                 R_ResetViewRendering2D();
3478                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3479                 R_Mesh_ColorPointer(NULL, 0, 0);
3480                 R_SetupGenericShader(false);
3481                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3482                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3483                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3484         }
3485 }
3486
3487 void R_RenderScene(qboolean addwaterplanes);
3488
3489 matrix4x4_t r_waterscrollmatrix;
3490
3491 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3492 {
3493         if (r_refdef.fog_density)
3494         {
3495                 r_refdef.fogcolor[0] = r_refdef.fog_red;
3496                 r_refdef.fogcolor[1] = r_refdef.fog_green;
3497                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3498
3499                 {
3500                         vec3_t fogvec;
3501                         VectorCopy(r_refdef.fogcolor, fogvec);
3502                         if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3503                         {
3504                                 //   color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3505                                 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3506                                 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3507                                 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3508                         }
3509                         //   color.rgb *= ContrastBoost * SceneBrightness;
3510                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3511                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3512                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3513                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3514                 }
3515         }
3516 }
3517
3518 void R_UpdateVariables(void)
3519 {
3520         R_Textures_Frame();
3521
3522         r_refdef.farclip = 4096;
3523         if (r_refdef.scene.worldmodel)
3524                 r_refdef.farclip += VectorDistance(r_refdef.scene.worldmodel->normalmins, r_refdef.scene.worldmodel->normalmaxs);
3525         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3526
3527         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3528                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3529         r_refdef.polygonfactor = 0;
3530         r_refdef.polygonoffset = 0;
3531         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3532         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3533
3534         r_refdef.rtworld = r_shadow_realtime_world.integer;
3535         r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3536         r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3537         r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3538         r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3539         if (r_showsurfaces.integer)
3540         {
3541                 r_refdef.rtworld = false;
3542                 r_refdef.rtworldshadows = false;
3543                 r_refdef.rtdlight = false;
3544                 r_refdef.rtdlightshadows = false;
3545                 r_refdef.lightmapintensity = 0;
3546         }
3547
3548         if (gamemode == GAME_NEHAHRA)
3549         {
3550                 if (gl_fogenable.integer)
3551                 {
3552                         r_refdef.oldgl_fogenable = true;
3553                         r_refdef.fog_density = gl_fogdensity.value;
3554                         r_refdef.fog_red = gl_fogred.value;
3555                         r_refdef.fog_green = gl_foggreen.value;
3556                         r_refdef.fog_blue = gl_fogblue.value;
3557                         r_refdef.fog_alpha = 1;
3558                         r_refdef.fog_start = 0;
3559                         r_refdef.fog_end = gl_skyclip.value;
3560                 }
3561                 else if (r_refdef.oldgl_fogenable)
3562                 {
3563                         r_refdef.oldgl_fogenable = false;
3564                         r_refdef.fog_density = 0;
3565                         r_refdef.fog_red = 0;
3566                         r_refdef.fog_green = 0;
3567                         r_refdef.fog_blue = 0;
3568                         r_refdef.fog_alpha = 0;
3569                         r_refdef.fog_start = 0;
3570                         r_refdef.fog_end = 0;
3571                 }
3572         }
3573
3574         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
3575         r_refdef.fog_start = max(0, r_refdef.fog_start);
3576         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
3577
3578         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
3579
3580         if (r_refdef.fog_density)
3581         {
3582                 r_refdef.fogenabled = true;
3583                 // this is the point where the fog reaches 0.9986 alpha, which we
3584                 // consider a good enough cutoff point for the texture
3585                 // (0.9986 * 256 == 255.6)
3586                 if (r_fog_exp2.integer)
3587                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
3588                 else
3589                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
3590                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
3591                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3592                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3593                 // fog color was already set
3594                 // update the fog texture
3595                 if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange)
3596                         R_BuildFogTexture();
3597         }
3598         else
3599                 r_refdef.fogenabled = false;
3600
3601         if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
3602         {
3603                 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
3604                 {
3605                         // build GLSL gamma texture
3606 #define RAMPWIDTH 256
3607                         unsigned short ramp[RAMPWIDTH * 3];
3608                         unsigned char ramprgb[RAMPWIDTH][4];
3609                         int i;
3610
3611                         r_texture_gammaramps_serial = vid_gammatables_serial;
3612
3613                         VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
3614                         for(i = 0; i < RAMPWIDTH; ++i)
3615                         {
3616                                 ramprgb[i][0] = ramp[i] >> 8;
3617                                 ramprgb[i][1] = ramp[i + RAMPWIDTH] >> 8;
3618                                 ramprgb[i][2] = ramp[i + 2 * RAMPWIDTH] >> 8;
3619                                 ramprgb[i][3] = 0;
3620                         }
3621                         if (r_texture_gammaramps)
3622                         {
3623                                 R_UpdateTexture(r_texture_gammaramps, &ramprgb[0][0], 0, 0, RAMPWIDTH, 1);
3624                         }
3625                         else
3626                         {
3627                                 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &ramprgb[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
3628                         }
3629                 }
3630         }
3631         else
3632         {
3633                 // remove GLSL gamma texture
3634         }
3635 }
3636
3637 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
3638 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
3639 /*
3640 ================
3641 R_SelectScene
3642 ================
3643 */
3644 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
3645         if( scenetype != r_currentscenetype ) {
3646                 // store the old scenetype
3647                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
3648                 r_currentscenetype = scenetype;
3649                 // move in the new scene
3650                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
3651         }
3652 }
3653
3654 /*
3655 ================
3656 R_GetScenePointer
3657 ================
3658 */
3659 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
3660 {
3661         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
3662         if( scenetype == r_currentscenetype ) {
3663                 return &r_refdef.scene;
3664         } else {
3665                 return &r_scenes_store[ scenetype ];
3666         }
3667 }
3668
3669 /*
3670 ================
3671 R_RenderView
3672 ================
3673 */
3674 void R_RenderView(void)
3675 {
3676         if (!r_refdef.scene.entities/* || !r_refdef.scene.worldmodel*/)
3677                 return; //Host_Error ("R_RenderView: NULL worldmodel");
3678
3679         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
3680
3681         // break apart the view matrix into vectors for various purposes
3682         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
3683         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
3684         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
3685         VectorNegate(r_refdef.view.left, r_refdef.view.right);
3686         // make an inverted copy of the view matrix for tracking sprites
3687         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
3688
3689         R_Shadow_UpdateWorldLightSelection();
3690
3691         R_Bloom_StartFrame();
3692         R_Water_StartFrame();
3693
3694         CHECKGLERROR
3695         if (r_timereport_active)
3696                 R_TimeReport("viewsetup");
3697
3698         R_ResetViewRendering3D();
3699
3700         if (r_refdef.view.clear || r_refdef.fogenabled)
3701         {
3702                 R_ClearScreen(r_refdef.fogenabled);
3703                 if (r_timereport_active)
3704                         R_TimeReport("viewclear");
3705         }
3706         r_refdef.view.clear = true;
3707
3708         r_refdef.view.showdebug = true;
3709
3710         // this produces a bloom texture to be used in R_BlendView() later
3711         if (r_hdr.integer)
3712                 R_HDR_RenderBloomTexture();
3713
3714         r_waterstate.numwaterplanes = 0;
3715         R_RenderScene(r_waterstate.enabled);
3716
3717         R_BlendView();
3718         if (r_timereport_active)
3719                 R_TimeReport("blendview");
3720
3721         GL_Scissor(0, 0, vid.width, vid.height);
3722         GL_ScissorTest(false);
3723         CHECKGLERROR
3724 }
3725
3726 extern void R_DrawLightningBeams (void);
3727 extern void VM_CL_AddPolygonsToMeshQueue (void);
3728 extern void R_DrawPortals (void);
3729 extern cvar_t cl_locs_show;
3730 static void R_DrawLocs(void);
3731 static void R_DrawEntityBBoxes(void);
3732 void R_RenderScene(qboolean addwaterplanes)
3733 {
3734         r_refdef.stats.renders++;
3735
3736         R_UpdateFogColor();
3737
3738         if (addwaterplanes)
3739         {
3740                 R_ResetViewRendering3D();
3741
3742                 R_View_Update();
3743                 if (r_timereport_active)
3744                         R_TimeReport("watervis");
3745
3746                 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
3747                 {
3748                         r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
3749                         if (r_timereport_active)
3750                                 R_TimeReport("waterworld");
3751                 }
3752
3753                 // don't let sound skip if going slow
3754                 if (r_refdef.scene.extraupdate)
3755                         S_ExtraUpdate ();
3756
3757                 R_DrawModelsAddWaterPlanes();
3758                 if (r_timereport_active)
3759                         R_TimeReport("watermodels");
3760
3761                 R_Water_ProcessPlanes();
3762                 if (r_timereport_active)
3763                         R_TimeReport("waterscenes");
3764         }
3765
3766         R_ResetViewRendering3D();
3767
3768         // don't let sound skip if going slow
3769         if (r_refdef.scene.extraupdate)
3770                 S_ExtraUpdate ();
3771
3772         R_MeshQueue_BeginScene();
3773
3774         R_SkyStartFrame();
3775
3776         R_View_Update();
3777         if (r_timereport_active)
3778                 R_TimeReport("visibility");
3779
3780         Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
3781
3782         if (cl.csqc_vidvars.drawworld)
3783         {
3784                 // don't let sound skip if going slow
3785                 if (r_refdef.scene.extraupdate)
3786                         S_ExtraUpdate ();
3787
3788                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
3789                 {
3790                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
3791                         if (r_timereport_active)
3792                                 R_TimeReport("worldsky");
3793                 }
3794
3795                 if (R_DrawBrushModelsSky() && r_timereport_active)
3796                         R_TimeReport("bmodelsky");
3797         }
3798
3799         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
3800         {
3801                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
3802                 if (r_timereport_active)
3803                         R_TimeReport("worlddepth");
3804         }
3805         if (r_depthfirst.integer >= 2)
3806         {
3807                 R_DrawModelsDepth();
3808                 if (r_timereport_active)
3809                         R_TimeReport("modeldepth");
3810         }
3811
3812         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
3813         {
3814                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
3815                 if (r_timereport_active)
3816                         R_TimeReport("world");
3817         }
3818
3819         // don't let sound skip if going slow
3820         if (r_refdef.scene.extraupdate)
3821                 S_ExtraUpdate ();
3822
3823         R_DrawModels();
3824         if (r_timereport_active)
3825                 R_TimeReport("models");
3826
3827         // don't let sound skip if going slow
3828         if (r_refdef.scene.extraupdate)
3829                 S_ExtraUpdate ();
3830
3831         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3832         {
3833                 R_DrawModelShadows();
3834
3835                 R_ResetViewRendering3D();
3836
3837                 // don't let sound skip if going slow
3838                 if (r_refdef.scene.extraupdate)
3839                         S_ExtraUpdate ();
3840         }
3841
3842         R_ShadowVolumeLighting(false);
3843         if (r_timereport_active)
3844                 R_TimeReport("rtlights");
3845
3846         // don't let sound skip if going slow
3847         if (r_refdef.scene.extraupdate)
3848                 S_ExtraUpdate ();
3849
3850         if (cl.csqc_vidvars.drawworld)
3851         {
3852                 R_DrawLightningBeams();
3853                 if (r_timereport_active)
3854                         R_TimeReport("lightning");
3855
3856                 R_DrawDecals();
3857                 if (r_timereport_active)
3858                         R_TimeReport("decals");
3859
3860                 R_DrawParticles();
3861                 if (r_timereport_active)
3862                         R_TimeReport("particles");
3863
3864                 R_DrawExplosions();
3865                 if (r_timereport_active)
3866                         R_TimeReport("explosions");
3867         }
3868
3869         R_SetupGenericShader(true);
3870         VM_CL_AddPolygonsToMeshQueue();
3871
3872         if (r_refdef.view.showdebug)
3873         {
3874                 if (cl_locs_show.integer)
3875                 {
3876                         R_DrawLocs();
3877                         if (r_timereport_active)
3878                                 R_TimeReport("showlocs");
3879                 }
3880
3881                 if (r_drawportals.integer)
3882                 {
3883                         R_DrawPortals();
3884                         if (r_timereport_active)
3885                                 R_TimeReport("portals");
3886                 }
3887
3888                 if (r_showbboxes.value > 0)
3889                 {
3890                         R_DrawEntityBBoxes();
3891                         if (r_timereport_active)
3892                                 R_TimeReport("bboxes");
3893                 }
3894         }
3895
3896         R_SetupGenericShader(true);
3897         R_MeshQueue_RenderTransparent();
3898         if (r_timereport_active)
3899                 R_TimeReport("drawtrans");
3900
3901         R_SetupGenericShader(true);
3902
3903         if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3904         {
3905                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
3906                 if (r_timereport_active)
3907                         R_TimeReport("worlddebug");
3908                 R_DrawModelsDebug();
3909                 if (r_timereport_active)
3910                         R_TimeReport("modeldebug");
3911         }
3912
3913         R_SetupGenericShader(true);
3914
3915         if (cl.csqc_vidvars.drawworld)
3916         {
3917                 R_DrawCoronas();
3918                 if (r_timereport_active)
3919                         R_TimeReport("coronas");
3920         }
3921
3922         // don't let sound skip if going slow
3923         if (r_refdef.scene.extraupdate)
3924                 S_ExtraUpdate ();
3925
3926         R_ResetViewRendering2D();
3927 }
3928
3929 static const int bboxelements[36] =
3930 {
3931         5, 1, 3, 5, 3, 7,
3932         6, 2, 0, 6, 0, 4,
3933         7, 3, 2, 7, 2, 6,
3934         4, 0, 1, 4, 1, 5,
3935         4, 5, 7, 4, 7, 6,
3936         1, 0, 2, 1, 2, 3,
3937 };
3938
3939 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3940 {
3941         int i;
3942         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3943         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3944         GL_DepthMask(false);
3945         GL_DepthRange(0, 1);
3946         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3947         R_Mesh_Matrix(&identitymatrix);
3948         R_Mesh_ResetTextureState();
3949
3950         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3951         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3952         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3953         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3954         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3955         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3956         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3957         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3958         R_FillColors(color4f, 8, cr, cg, cb, ca);
3959         if (r_refdef.fogenabled)
3960         {
3961                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3962                 {
3963                         f1 = FogPoint_World(v);
3964                         f2 = 1 - f1;
3965                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3966                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3967                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3968                 }
3969         }
3970         R_Mesh_VertexPointer(vertex3f, 0, 0);
3971         R_Mesh_ColorPointer(color4f, 0, 0);
3972         R_Mesh_ResetTextureState();
3973         R_SetupGenericShader(false);
3974         R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3975 }
3976
3977 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3978 {
3979         int i;
3980         float color[4];
3981         prvm_edict_t *edict;
3982         // this function draws bounding boxes of server entities
3983         if (!sv.active)
3984                 return;
3985         R_SetupGenericShader(false);
3986         SV_VM_Begin();
3987         for (i = 0;i < numsurfaces;i++)
3988         {
3989                 edict = PRVM_EDICT_NUM(surfacelist[i]);
3990                 switch ((int)edict->fields.server->solid)
3991                 {
3992                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
3993                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
3994                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
3995                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3996                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
3997                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
3998                 }
3999                 color[3] *= r_showbboxes.value;
4000                 color[3] = bound(0, color[3], 1);
4001                 GL_DepthTest(!r_showdisabledepthtest.integer);
4002                 GL_CullFace(r_refdef.view.cullface_front);
4003                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4004         }
4005         SV_VM_End();
4006 }
4007
4008 static void R_DrawEntityBBoxes(void)
4009 {
4010         int i;
4011         prvm_edict_t *edict;
4012         vec3_t center;
4013         // this function draws bounding boxes of server entities
4014         if (!sv.active)
4015                 return;
4016         SV_VM_Begin();
4017         for (i = 0;i < prog->num_edicts;i++)
4018         {
4019                 edict = PRVM_EDICT_NUM(i);
4020                 if (edict->priv.server->free)
4021                         continue;
4022                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4023                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4024         }
4025         SV_VM_End();
4026 }
4027
4028 int nomodelelements[24] =
4029 {
4030         5, 2, 0,
4031         5, 1, 2,
4032         5, 0, 3,
4033         5, 3, 1,
4034         0, 2, 4,
4035         2, 1, 4,
4036         3, 0, 4,
4037         1, 3, 4
4038 };
4039
4040 float nomodelvertex3f[6*3] =
4041 {
4042         -16,   0,   0,
4043          16,   0,   0,
4044           0, -16,   0,
4045           0,  16,   0,
4046           0,   0, -16,
4047           0,   0,  16
4048 };
4049
4050 float nomodelcolor4f[6*4] =
4051 {
4052         0.0f, 0.0f, 0.5f, 1.0f,
4053         0.0f, 0.0f, 0.5f, 1.0f,
4054         0.0f, 0.5f, 0.0f, 1.0f,
4055         0.0f, 0.5f, 0.0f, 1.0f,
4056         0.5f, 0.0f, 0.0f, 1.0f,
4057         0.5f, 0.0f, 0.0f, 1.0f
4058 };
4059
4060 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4061 {
4062         int i;
4063         float f1, f2, *c;
4064         float color4f[6*4];
4065         // this is only called once per entity so numsurfaces is always 1, and
4066         // surfacelist is always {0}, so this code does not handle batches
4067         R_Mesh_Matrix(&ent->matrix);
4068
4069         if (ent->flags & EF_ADDITIVE)
4070         {
4071                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4072                 GL_DepthMask(false);
4073         }
4074         else if (ent->alpha < 1)
4075         {
4076                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4077                 GL_DepthMask(false);
4078         }
4079         else
4080         {
4081                 GL_BlendFunc(GL_ONE, GL_ZERO);
4082                 GL_DepthMask(true);
4083         }
4084         GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4085         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4086         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4087         GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4088         R_SetupGenericShader(false);
4089         R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4090         if (r_refdef.fogenabled)
4091         {
4092                 vec3_t org;
4093                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4094                 R_Mesh_ColorPointer(color4f, 0, 0);
4095                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4096                 f1 = FogPoint_World(org);
4097                 f2 = 1 - f1;
4098                 for (i = 0, c = color4f;i < 6;i++, c += 4)
4099                 {
4100                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4101                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4102                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4103                         c[3] *= ent->alpha;
4104                 }
4105         }
4106         else if (ent->alpha != 1)
4107         {
4108                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4109                 R_Mesh_ColorPointer(color4f, 0, 0);
4110                 for (i = 0, c = color4f;i < 6;i++, c += 4)
4111                         c[3] *= ent->alpha;
4112         }
4113         else
4114                 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4115         R_Mesh_ResetTextureState();
4116         R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
4117 }
4118
4119 void R_DrawNoModel(entity_render_t *ent)
4120 {
4121         vec3_t org;
4122         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4123         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4124                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4125         //else
4126         //      R_DrawNoModelCallback(ent, 0);
4127 }
4128
4129 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4130 {
4131         vec3_t right1, right2, diff, normal;
4132
4133         VectorSubtract (org2, org1, normal);
4134
4135         // calculate 'right' vector for start
4136         VectorSubtract (r_refdef.view.origin, org1, diff);
4137         CrossProduct (normal, diff, right1);
4138         VectorNormalize (right1);
4139
4140         // calculate 'right' vector for end
4141         VectorSubtract (r_refdef.view.origin, org2, diff);
4142         CrossProduct (normal, diff, right2);
4143         VectorNormalize (right2);
4144
4145         vert[ 0] = org1[0] + width * right1[0];
4146         vert[ 1] = org1[1] + width * right1[1];
4147         vert[ 2] = org1[2] + width * right1[2];
4148         vert[ 3] = org1[0] - width * right1[0];
4149         vert[ 4] = org1[1] - width * right1[1];
4150         vert[ 5] = org1[2] - width * right1[2];
4151         vert[ 6] = org2[0] - width * right2[0];
4152         vert[ 7] = org2[1] - width * right2[1];
4153         vert[ 8] = org2[2] - width * right2[2];
4154         vert[ 9] = org2[0] + width * right2[0];
4155         vert[10] = org2[1] + width * right2[1];
4156         vert[11] = org2[2] + width * right2[2];
4157 }
4158
4159 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4160
4161 void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_t *fogtexture, qboolean depthdisable, qboolean depthshort, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2, float cr, float cg, float cb, float ca)
4162 {
4163         float fog = 1.0f;
4164         float vertex3f[12];
4165
4166         if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4167                 fog = FogPoint_World(origin);
4168
4169         R_Mesh_Matrix(&identitymatrix);
4170         GL_BlendFunc(blendfunc1, blendfunc2);
4171
4172         if(v_flipped_state)
4173         {
4174                 scalex1 = -scalex1;
4175                 scalex2 = -scalex2;
4176                 GL_CullFace(r_refdef.view.cullface_front);
4177         }
4178         else
4179                 GL_CullFace(r_refdef.view.cullface_back);
4180         GL_CullFace(GL_NONE);
4181
4182         GL_DepthMask(false);
4183         GL_DepthRange(0, depthshort ? 0.0625 : 1);
4184         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4185         GL_DepthTest(!depthdisable);
4186
4187         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4188         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4189         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4190         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
4191         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
4192         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
4193         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
4194         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
4195         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
4196         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
4197         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
4198         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
4199
4200         R_Mesh_VertexPointer(vertex3f, 0, 0);
4201         R_Mesh_ColorPointer(NULL, 0, 0);
4202         R_Mesh_ResetTextureState();
4203         R_SetupGenericShader(true);
4204         R_Mesh_TexBind(0, R_GetTexture(texture));
4205         R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
4206         // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
4207         GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
4208         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
4209
4210         if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
4211         {
4212                 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
4213                 GL_BlendFunc(blendfunc1, GL_ONE);
4214                 fog = 1 - fog;
4215                 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
4216                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
4217         }
4218 }
4219
4220 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
4221 {
4222         int i;
4223         float *vertex3f;
4224         float v[3];
4225         VectorSet(v, x, y, z);
4226         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
4227                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
4228                         break;
4229         if (i == mesh->numvertices)
4230         {
4231                 if (mesh->numvertices < mesh->maxvertices)
4232                 {
4233                         VectorCopy(v, vertex3f);
4234                         mesh->numvertices++;
4235                 }
4236                 return mesh->numvertices;
4237         }
4238         else
4239                 return i;
4240 }
4241
4242 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
4243 {
4244         int i;
4245         int *e, element[3];
4246         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4247         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4248         e = mesh->element3i + mesh->numtriangles * 3;
4249         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
4250         {
4251                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
4252                 if (mesh->numtriangles < mesh->maxtriangles)
4253                 {
4254                         *e++ = element[0];
4255                         *e++ = element[1];
4256                         *e++ = element[2];
4257                         mesh->numtriangles++;
4258                 }
4259                 element[1] = element[2];
4260         }
4261 }
4262
4263 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
4264 {
4265         int i;
4266         int *e, element[3];
4267         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4268         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4269         e = mesh->element3i + mesh->numtriangles * 3;
4270         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
4271         {
4272                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
4273                 if (mesh->numtriangles < mesh->maxtriangles)
4274                 {
4275                         *e++ = element[0];
4276                         *e++ = element[1];
4277                         *e++ = element[2];
4278                         mesh->numtriangles++;
4279                 }
4280                 element[1] = element[2];
4281         }
4282 }
4283
4284 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
4285 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
4286 {
4287         int planenum, planenum2;
4288         int w;
4289         int tempnumpoints;
4290         mplane_t *plane, *plane2;
4291         double maxdist;
4292         double temppoints[2][256*3];
4293         // figure out how large a bounding box we need to properly compute this brush
4294         maxdist = 0;
4295         for (w = 0;w < numplanes;w++)
4296                 maxdist = max(maxdist, planes[w].dist);
4297         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4298         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4299         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4300         {
4301                 w = 0;
4302                 tempnumpoints = 4;
4303                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4304                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4305                 {
4306                         if (planenum2 == planenum)
4307                                 continue;
4308                         PolygonD_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, R_MESH_PLANE_DIST_EPSILON, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
4309                         w = !w;
4310                 }
4311                 if (tempnumpoints < 3)
4312                         continue;
4313                 // generate elements forming a triangle fan for this polygon
4314                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4315         }
4316 }
4317
4318 static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, const matrix4x4_t *matrix, float r, float g, float b, float a)
4319 {
4320         texturelayer_t *layer;
4321         layer = t->currentlayers + t->currentnumlayers++;
4322         layer->type = type;
4323         layer->depthmask = depthmask;
4324         layer->blendfunc1 = blendfunc1;
4325         layer->blendfunc2 = blendfunc2;
4326         layer->texture = texture;
4327         layer->texmatrix = *matrix;
4328         layer->color[0] = r * r_refdef.view.colorscale;
4329         layer->color[1] = g * r_refdef.view.colorscale;
4330         layer->color[2] = b * r_refdef.view.colorscale;
4331         layer->color[3] = a;
4332 }
4333
4334 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4335 {
4336         double index, f;
4337         index = parms[2] + r_refdef.scene.time * parms[3];
4338         index -= floor(index);
4339         switch (func)
4340         {
4341         default:
4342         case Q3WAVEFUNC_NONE:
4343         case Q3WAVEFUNC_NOISE:
4344         case Q3WAVEFUNC_COUNT:
4345                 f = 0;
4346                 break;
4347         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4348         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4349         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4350         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4351         case Q3WAVEFUNC_TRIANGLE:
4352                 index *= 4;
4353                 f = index - floor(index);
4354                 if (index < 1)
4355                         f = f;
4356                 else if (index < 2)
4357                         f = 1 - f;
4358                 else if (index < 3)
4359                         f = -f;
4360                 else
4361                         f = -(1 - f);
4362                 break;
4363         }
4364         return (float)(parms[0] + parms[1] * f);
4365 }
4366
4367 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
4368 {
4369         int i;
4370         model_t *model = ent->model;
4371         float f;
4372         float tcmat[12];
4373         q3shaderinfo_layer_tcmod_t *tcmod;
4374
4375         if (t->basematerialflags & MATERIALFLAG_NODRAW)
4376         {
4377                 t->currentmaterialflags = MATERIALFLAG_NODRAW;
4378                 return;
4379         }
4380
4381         // switch to an alternate material if this is a q1bsp animated material
4382         {
4383                 texture_t *texture = t;
4384                 int s = ent->skinnum;
4385                 if ((unsigned int)s >= (unsigned int)model->numskins)
4386                         s = 0;
4387                 if (model->skinscenes)
4388                 {
4389                         if (model->skinscenes[s].framecount > 1)
4390                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4391                         else
4392                                 s = model->skinscenes[s].firstframe;
4393                 }
4394                 if (s > 0)
4395                         t = t + s * model->num_surfaces;
4396                 if (t->animated)
4397                 {
4398                         // use an alternate animation if the entity's frame is not 0,
4399                         // and only if the texture has an alternate animation
4400                         if (ent->frame2 != 0 && t->anim_total[1])
4401                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4402                         else
4403                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4404                 }
4405                 texture->currentframe = t;
4406         }
4407
4408         // update currentskinframe to be a qw skin or animation frame
4409         if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
4410         {
4411                 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4412                 {
4413                         strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4414                         Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
4415                         r_qwskincache_skinframe[i] = R_SkinFrame_LoadExternal(va("skins/%s", r_qwskincache[i]), TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS, developer.integer > 0);
4416                 }
4417                 t->currentskinframe = r_qwskincache_skinframe[i];
4418                 if (t->currentskinframe == NULL)
4419                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4420         }
4421         else if (t->numskinframes >= 2)
4422                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4423         if (t->backgroundnumskinframes >= 2)
4424                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
4425
4426         t->currentmaterialflags = t->basematerialflags;
4427         t->currentalpha = ent->alpha;
4428         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4429         {
4430                 t->currentalpha *= r_wateralpha.value;
4431                 /*
4432                  * FIXME what is this supposed to do?
4433                 // if rendering refraction/reflection, disable transparency
4434                 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
4435                         t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
4436                 */
4437         }
4438         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled)
4439                 t->currentalpha *= t->r_water_wateralpha;
4440         if(!r_waterstate.enabled)
4441                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4442         if (!(ent->flags & RENDER_LIGHT))
4443                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4444         else if (rsurface.modeltexcoordlightmap2f == NULL)
4445         {
4446                 // pick a model lighting mode
4447                 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4448                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4449                 else
4450                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4451         }
4452         if (ent->effects & EF_ADDITIVE)
4453                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4454         else if (t->currentalpha < 1)
4455                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4456         if (ent->effects & EF_DOUBLESIDED)
4457                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4458         if (ent->effects & EF_NODEPTHTEST)
4459                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4460         if (ent->flags & RENDER_VIEWMODEL)
4461                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4462         if (t->backgroundnumskinframes)
4463                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4464         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
4465         {
4466                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
4467                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
4468         }
4469         else
4470                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
4471
4472         // there is no tcmod
4473         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4474                 t->currenttexmatrix = r_waterscrollmatrix;
4475
4476         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4477         {
4478                 matrix4x4_t matrix;
4479                 switch(tcmod->tcmod)
4480                 {
4481                 case Q3TCMOD_COUNT:
4482                 case Q3TCMOD_NONE:
4483                         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4484                                 matrix = r_waterscrollmatrix;
4485                         else
4486                                 matrix = identitymatrix;
4487                         break;
4488                 case Q3TCMOD_ENTITYTRANSLATE:
4489                         // this is used in Q3 to allow the gamecode to control texcoord
4490                         // scrolling on the entity, which is not supported in darkplaces yet.
4491                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4492                         break;
4493                 case Q3TCMOD_ROTATE:
4494                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4495                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4496                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4497                         break;
4498                 case Q3TCMOD_SCALE:
4499                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4500                         break;
4501                 case Q3TCMOD_SCROLL:
4502                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4503                         break;
4504                 case Q3TCMOD_STRETCH:
4505                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4506                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4507                         break;
4508                 case Q3TCMOD_TRANSFORM:
4509                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
4510                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
4511                         VectorSet(tcmat +  6, 0                   , 0                , 1);
4512                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
4513                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4514                         break;
4515                 case Q3TCMOD_TURBULENT:
4516                         // this is handled in the RSurf_PrepareVertices function
4517                         matrix = identitymatrix;
4518                         break;
4519                 }
4520                 // either replace or concatenate the transformation
4521                 if (i < 1)
4522                         t->currenttexmatrix = matrix;
4523                 else
4524                 {
4525                         matrix4x4_t temp = t->currenttexmatrix;
4526                         Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4527                 }
4528         }
4529
4530         t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4531         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4532         t->glosstexture = r_texture_black;
4533         t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4534         t->backgroundglosstexture = r_texture_black;
4535         t->specularpower = r_shadow_glossexponent.value;
4536         // TODO: store reference values for these in the texture?
4537         t->specularscale = 0;
4538         if (r_shadow_gloss.integer > 0)
4539         {
4540                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4541                 {
4542                         if (r_shadow_glossintensity.value > 0)
4543                         {
4544                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4545                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4546                                 t->specularscale = r_shadow_glossintensity.value;
4547                         }
4548                 }
4549                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4550                 {
4551                         t->glosstexture = r_texture_white;
4552                         t->backgroundglosstexture = r_texture_white;
4553                         t->specularscale = r_shadow_gloss2intensity.value;
4554                 }
4555         }
4556
4557         // lightmaps mode looks bad with dlights using actual texturing, so turn
4558         // off the colormap and glossmap, but leave the normalmap on as it still
4559         // accurately represents the shading involved
4560         if (gl_lightmaps.integer)
4561         {
4562                 t->basetexture = r_texture_grey128;
4563                 t->backgroundbasetexture = NULL;
4564                 t->specularscale = 0;
4565                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
4566         }
4567
4568         Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4569         VectorClear(t->dlightcolor);
4570         t->currentnumlayers = 0;
4571         if (t->currentmaterialflags & MATERIALFLAG_WALL)
4572         {
4573                 int layerflags = 0;
4574                 int blendfunc1, blendfunc2, depthmask;
4575                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4576                 {
4577                         blendfunc1 = GL_SRC_ALPHA;
4578                         blendfunc2 = GL_ONE;
4579                 }
4580                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4581                 {
4582                         blendfunc1 = GL_SRC_ALPHA;
4583                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4584                 }
4585                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4586                 {
4587                         blendfunc1 = t->customblendfunc[0];
4588                         blendfunc2 = t->customblendfunc[1];
4589                 }
4590                 else
4591                 {
4592                         blendfunc1 = GL_ONE;
4593                         blendfunc2 = GL_ZERO;
4594                 }
4595                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4596                 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4597                         layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4598                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4599                 {
4600                         // fullbright is not affected by r_refdef.lightmapintensity
4601                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
4602                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4603                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4604                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4605                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4606                 }
4607                 else
4608                 {
4609                         vec3_t ambientcolor;
4610                         float colorscale;
4611                         // set the color tint used for lights affecting this surface
4612                         VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
4613                         colorscale = 2;
4614                         // q3bsp has no lightmap updates, so the lightstylevalue that
4615                         // would normally be baked into the lightmap must be
4616                         // applied to the color
4617                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4618                         if (ent->model->type == mod_brushq3)
4619                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
4620                         colorscale *= r_refdef.lightmapintensity;
4621                         VectorScale(t->lightmapcolor, r_ambient.value * (1.0f / 64.0f), ambientcolor);
4622                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4623                         // basic lit geometry
4624                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
4625                         // add pants/shirt if needed
4626                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4627                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2]  * t->lightmapcolor[2], t->lightmapcolor[3]);
4628                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4629                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4630                         // now add ambient passes if needed
4631                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
4632                         {
4633                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
4634                                 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4635                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ambientcolor[0], ent->colormap_pantscolor[1] * ambientcolor[1], ent->colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
4636                                 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4637                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ambientcolor[0], ent->colormap_shirtcolor[1] * ambientcolor[1], ent->colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
4638                         }
4639                 }
4640                 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
4641                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->lightmapcolor[3]);
4642                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4643                 {
4644                         // if this is opaque use alpha blend which will darken the earlier
4645                         // passes cheaply.
4646                         //
4647                         // if this is an alpha blended material, all the earlier passes
4648                         // were darkened by fog already, so we only need to add the fog
4649                         // color ontop through the fog mask texture
4650                         //
4651                         // if this is an additive blended material, all the earlier passes
4652                         // were darkened by fog already, and we should not add fog color
4653                         // (because the background was not darkened, there is no fog color
4654                         // that was lost behind it).
4655                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &identitymatrix, r_refdef.fogcolor[0] / r_refdef.view.colorscale, r_refdef.fogcolor[1] / r_refdef.view.colorscale, r_refdef.fogcolor[2] / r_refdef.view.colorscale, t->lightmapcolor[3]);
4656                 }
4657         }
4658 }
4659
4660 void R_UpdateAllTextureInfo(entity_render_t *ent)
4661 {
4662         int i;
4663         if (ent->model)
4664                 for (i = 0;i < ent->model->num_texturesperskin;i++)
4665                         R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4666 }
4667
4668 rsurfacestate_t rsurface;
4669
4670 void R_Mesh_ResizeArrays(int newvertices)
4671 {
4672         float *base;
4673         if (rsurface.array_size >= newvertices)
4674                 return;
4675         if (rsurface.array_modelvertex3f)
4676                 Mem_Free(rsurface.array_modelvertex3f);
4677         rsurface.array_size = (newvertices + 1023) & ~1023;
4678         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4679         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
4680         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
4681         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
4682         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
4683         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
4684         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4685         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4686         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
4687         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
4688         rsurface.array_color4f           = base + rsurface.array_size * 27;
4689         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4690 }
4691
4692 void RSurf_ActiveWorldEntity(void)
4693 {
4694         model_t *model = r_refdef.scene.worldmodel;
4695         if (rsurface.array_size < model->surfmesh.num_vertices)
4696                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4697         rsurface.matrix = identitymatrix;
4698         rsurface.inversematrix = identitymatrix;
4699         R_Mesh_Matrix(&identitymatrix);
4700         VectorCopy(r_refdef.view.origin, rsurface.modelorg);
4701         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4702         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4703         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4704         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4705         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4706         rsurface.frameblend[0].frame = 0;
4707         rsurface.frameblend[0].lerp = 1;
4708         rsurface.frameblend[1].frame = 0;
4709         rsurface.frameblend[1].lerp = 0;
4710         rsurface.frameblend[2].frame = 0;
4711         rsurface.frameblend[2].lerp = 0;
4712         rsurface.frameblend[3].frame = 0;
4713         rsurface.frameblend[3].lerp = 0;
4714         rsurface.basepolygonfactor = r_refdef.polygonfactor;
4715         rsurface.basepolygonoffset = r_refdef.polygonoffset;
4716         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
4717         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4718         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4719         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4720         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4721         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4722         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4723         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4724         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4725         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
4726         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4727         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4728         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
4729         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4730         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4731         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
4732         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4733         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4734         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
4735         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4736         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4737         rsurface.modelelement3i = model->surfmesh.data_element3i;
4738         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4739         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4740         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4741         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4742         rsurface.modelsurfaces = model->data_surfaces;
4743         rsurface.generatedvertex = false;
4744         rsurface.vertex3f  = rsurface.modelvertex3f;
4745         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4746         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4747         rsurface.svector3f = rsurface.modelsvector3f;
4748         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4749         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4750         rsurface.tvector3f = rsurface.modeltvector3f;
4751         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4752         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4753         rsurface.normal3f  = rsurface.modelnormal3f;
4754         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4755         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4756         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4757 }
4758
4759 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4760 {
4761         model_t *model = ent->model;
4762         if (rsurface.array_size < model->surfmesh.num_vertices)
4763                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4764         rsurface.matrix = ent->matrix;
4765         rsurface.inversematrix = ent->inversematrix;
4766         R_Mesh_Matrix(&rsurface.matrix);
4767         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
4768         rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
4769         rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
4770         rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
4771         rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
4772         rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
4773         rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
4774         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4775         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4776         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4777         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4778         rsurface.frameblend[0] = ent->frameblend[0];
4779         rsurface.frameblend[1] = ent->frameblend[1];
4780         rsurface.frameblend[2] = ent->frameblend[2];
4781         rsurface.frameblend[3] = ent->frameblend[3];
4782         rsurface.basepolygonfactor = r_refdef.polygonfactor;
4783         rsurface.basepolygonoffset = r_refdef.polygonoffset;
4784         if (ent->model->brush.submodel)
4785         {
4786                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
4787                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
4788         }
4789         if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4790         {
4791                 if (wanttangents)
4792                 {
4793                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4794                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4795                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4796                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4797                         Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4798                 }
4799                 else if (wantnormals)
4800                 {
4801                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4802                         rsurface.modelsvector3f = NULL;
4803                         rsurface.modeltvector3f = NULL;
4804                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4805                         Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4806                 }
4807                 else
4808                 {
4809                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4810                         rsurface.modelsvector3f = NULL;
4811                         rsurface.modeltvector3f = NULL;
4812                         rsurface.modelnormal3f = NULL;
4813                         Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4814                 }
4815                 rsurface.modelvertex3f_bufferobject = 0;
4816                 rsurface.modelvertex3f_bufferoffset = 0;
4817                 rsurface.modelsvector3f_bufferobject = 0;
4818                 rsurface.modelsvector3f_bufferoffset = 0;
4819                 rsurface.modeltvector3f_bufferobject = 0;
4820                 rsurface.modeltvector3f_bufferoffset = 0;
4821                 rsurface.modelnormal3f_bufferobject = 0;
4822                 rsurface.modelnormal3f_bufferoffset = 0;
4823                 rsurface.generatedvertex = true;
4824         }
4825         else
4826         {
4827                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
4828                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4829                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4830                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4831                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4832                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4833                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4834                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4835                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4836                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
4837                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4838                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4839                 rsurface.generatedvertex = false;
4840         }
4841         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
4842         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4843         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4844         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
4845         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4846         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4847         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
4848         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4849         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4850         rsurface.modelelement3i = model->surfmesh.data_element3i;
4851         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4852         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4853         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4854         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4855         rsurface.modelsurfaces = model->data_surfaces;
4856         rsurface.vertex3f  = rsurface.modelvertex3f;
4857         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4858         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4859         rsurface.svector3f = rsurface.modelsvector3f;
4860         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4861         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4862         rsurface.tvector3f = rsurface.modeltvector3f;
4863         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4864         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4865         rsurface.normal3f  = rsurface.modelnormal3f;
4866         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4867         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4868         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4869 }
4870
4871 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4872 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4873 {
4874         int deformindex;
4875         int texturesurfaceindex;
4876         int i, j;
4877         float amplitude;
4878         float animpos;
4879         float scale;
4880         const float *v1, *in_tc;
4881         float *out_tc;
4882         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4883         float waveparms[4];
4884         q3shaderinfo_deform_t *deform;
4885         // if vertices are dynamic (animated models), generate them into the temporary rsurface.array_model* arrays and point rsurface.model* at them instead of the static data from the model itself
4886         if (rsurface.generatedvertex)
4887         {
4888                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4889                         generatenormals = true;
4890                 for (i = 0;i < Q3MAXDEFORMS;i++)
4891                 {
4892                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4893                         {
4894                                 generatetangents = true;
4895                                 generatenormals = true;
4896                         }
4897                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4898                                 generatenormals = true;
4899                 }
4900                 if (generatenormals && !rsurface.modelnormal3f)
4901                 {
4902                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4903                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4904                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4905                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4906                 }
4907                 if (generatetangents && !rsurface.modelsvector3f)
4908                 {
4909                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4910                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4911                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4912                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4913                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4914                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4915                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer);
4916                 }
4917         }
4918         rsurface.vertex3f  = rsurface.modelvertex3f;
4919         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4920         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4921         rsurface.svector3f = rsurface.modelsvector3f;
4922         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4923         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4924         rsurface.tvector3f = rsurface.modeltvector3f;
4925         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4926         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4927         rsurface.normal3f  = rsurface.modelnormal3f;
4928         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4929         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4930         // if vertices are deformed (sprite flares and things in maps, possibly
4931         // water waves, bulges and other deformations), generate them into
4932         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4933         // (may be static model data or generated data for an animated model, or
4934         //  the previous deform pass)
4935         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4936         {
4937                 switch (deform->deform)
4938                 {
4939                 default:
4940                 case Q3DEFORM_PROJECTIONSHADOW:
4941                 case Q3DEFORM_TEXT0:
4942                 case Q3DEFORM_TEXT1:
4943                 case Q3DEFORM_TEXT2:
4944                 case Q3DEFORM_TEXT3:
4945                 case Q3DEFORM_TEXT4:
4946                 case Q3DEFORM_TEXT5:
4947                 case Q3DEFORM_TEXT6:
4948                 case Q3DEFORM_TEXT7:
4949                 case Q3DEFORM_NONE:
4950                         break;
4951                 case Q3DEFORM_AUTOSPRITE:
4952                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
4953                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
4954                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
4955                         VectorNormalize(newforward);
4956                         VectorNormalize(newright);
4957                         VectorNormalize(newup);
4958                         // make deformed versions of only the model vertices used by the specified surfaces
4959                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4960                         {
4961                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4962                                 // a single autosprite surface can contain multiple sprites...
4963                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
4964                                 {
4965                                         VectorClear(center);
4966                                         for (i = 0;i < 4;i++)
4967                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4968                                         VectorScale(center, 0.25f, center);
4969                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
4970                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4971                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4972                                         for (i = 0;i < 4;i++)
4973                                         {
4974                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4975                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4976                                         }
4977                                 }
4978                                 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer);
4979                                 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer);
4980                         }
4981                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
4982                         rsurface.vertex3f_bufferobject = 0;
4983                         rsurface.vertex3f_bufferoffset = 0;
4984                         rsurface.svector3f = rsurface.array_deformedsvector3f;
4985                         rsurface.svector3f_bufferobject = 0;
4986                         rsurface.svector3f_bufferoffset = 0;
4987                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
4988                         rsurface.tvector3f_bufferobject = 0;
4989                         rsurface.tvector3f_bufferoffset = 0;
4990                         rsurface.normal3f = rsurface.array_deformednormal3f;
4991                         rsurface.normal3f_bufferobject = 0;
4992                         rsurface.normal3f_bufferoffset = 0;
4993                         break;
4994                 case Q3DEFORM_AUTOSPRITE2:
4995                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
4996                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
4997                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
4998                         VectorNormalize(newforward);
4999                         VectorNormalize(newright);
5000                         VectorNormalize(newup);
5001                         // make deformed versions of only the model vertices used by the specified surfaces
5002                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5003                         {
5004                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5005                                 const float *v1, *v2;
5006                                 vec3_t start, end;
5007                                 float f, l;
5008                                 struct
5009                                 {
5010                                         float length2;
5011                                         const float *v1;
5012                                         const float *v2;
5013                                 }
5014                                 shortest[2];
5015                                 memset(shortest, 0, sizeof(shortest));
5016                                 // a single autosprite surface can contain multiple sprites...
5017                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
5018                                 {
5019                                         VectorClear(center);
5020                                         for (i = 0;i < 4;i++)
5021                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5022                                         VectorScale(center, 0.25f, center);
5023                                         // find the two shortest edges, then use them to define the
5024                                         // axis vectors for rotating around the central axis
5025                                         for (i = 0;i < 6;i++)
5026                                         {
5027                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5028                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5029 #if 0
5030                                                 Debug_PolygonBegin(NULL, 0);
5031                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5032                                                 Debug_PolygonVertex((v1[0] + v2[0]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, (v1[1] + v2[1]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1], (v1[2] + v2[2]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2], 0, 0, 1, 1, 0, 1);
5033                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5034                                                 Debug_PolygonEnd();
5035 #endif
5036                                                 l = VectorDistance2(v1, v2);
5037                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5038                                                 if (v1[2] != v2[2])
5039                                                         l += (1.0f / 1024.0f);
5040                                                 if (shortest[0].length2 > l || i == 0)
5041                                                 {
5042                                                         shortest[1] = shortest[0];
5043                                                         shortest[0].length2 = l;
5044                                                         shortest[0].v1 = v1;
5045                                                         shortest[0].v2 = v2;
5046                                                 }
5047                                                 else if (shortest[1].length2 > l || i == 1)
5048                                                 {
5049                                                         shortest[1].length2 = l;
5050                                                         shortest[1].v1 = v1;
5051                                                         shortest[1].v2 = v2;
5052                                                 }
5053                                         }
5054                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5055                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5056 #if 0
5057                                         Debug_PolygonBegin(NULL, 0);
5058                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5059                                         Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 4, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 4, 0, 0, 0, 1, 0, 1);
5060                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5061                                         Debug_PolygonEnd();
5062 #endif
5063                                         // this calculates the right vector from the shortest edge
5064                                         // and the up vector from the edge midpoints
5065                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5066                                         VectorNormalize(right);
5067                                         VectorSubtract(end, start, up);
5068                                         VectorNormalize(up);
5069                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5070                                         //VectorSubtract(rsurface.modelorg, center, forward);
5071                                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5072                                         VectorNegate(forward, forward);
5073                                         VectorReflect(forward, 0, up, forward);
5074                                         VectorNormalize(forward);
5075                                         CrossProduct(up, forward, newright);
5076                                         VectorNormalize(newright);
5077 #if 0
5078                                         Debug_PolygonBegin(NULL, 0);
5079                                         Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 8, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 8, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 8, 0, 0, 1, 0, 0, 1);
5080                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5081                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
5082                                         Debug_PolygonEnd();
5083 #endif
5084 #if 0
5085                                         Debug_PolygonBegin(NULL, 0);
5086                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5087                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5088                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
5089                                         Debug_PolygonEnd();
5090 #endif
5091                                         // rotate the quad around the up axis vector, this is made
5092                                         // especially easy by the fact we know the quad is flat,
5093                                         // so we only have to subtract the center position and
5094                                         // measure distance along the right vector, and then
5095                                         // multiply that by the newright vector and add back the
5096                                         // center position
5097                                         // we also need to subtract the old position to undo the
5098                                         // displacement from the center, which we do with a
5099                                         // DotProduct, the subtraction/addition of center is also
5100                                         // optimized into DotProducts here
5101                                         l = DotProduct(right, center);
5102                                         for (i = 0;i < 4;i++)
5103                                         {
5104                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5105                                                 f = DotProduct(right, v1) - l;
5106                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5107                                         }
5108                                 }
5109                                 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer);
5110                                 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer);
5111                         }
5112                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5113                         rsurface.vertex3f_bufferobject = 0;
5114                         rsurface.vertex3f_bufferoffset = 0;
5115                         rsurface.svector3f = rsurface.array_deformedsvector3f;
5116                         rsurface.svector3f_bufferobject = 0;
5117                         rsurface.svector3f_bufferoffset = 0;
5118                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
5119                         rsurface.tvector3f_bufferobject = 0;
5120                         rsurface.tvector3f_bufferoffset = 0;
5121                         rsurface.normal3f = rsurface.array_deformednormal3f;
5122                         rsurface.normal3f_bufferobject = 0;
5123                         rsurface.normal3f_bufferoffset = 0;
5124                         break;
5125                 case Q3DEFORM_NORMAL:
5126                         // deform the normals to make reflections wavey
5127                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5128                         {
5129                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5130                                 for (j = 0;j < surface->num_vertices;j++)
5131                                 {
5132                                         float vertex[3];
5133                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
5134                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5135                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
5136                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5137                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5138                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5139                                         VectorNormalize(normal);
5140                                 }
5141                                 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer);
5142                         }
5143                         rsurface.svector3f = rsurface.array_deformedsvector3f;
5144                         rsurface.svector3f_bufferobject = 0;
5145                         rsurface.svector3f_bufferoffset = 0;
5146                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
5147                         rsurface.tvector3f_bufferobject = 0;
5148                         rsurface.tvector3f_bufferoffset = 0;
5149                         rsurface.normal3f = rsurface.array_deformednormal3f;
5150                         rsurface.normal3f_bufferobject = 0;
5151                         rsurface.normal3f_bufferoffset = 0;
5152                         break;
5153                 case Q3DEFORM_WAVE:
5154                         // deform vertex array to make wavey water and flags and such
5155                         waveparms[0] = deform->waveparms[0];
5156                         waveparms[1] = deform->waveparms[1];
5157                         waveparms[2] = deform->waveparms[2];
5158                         waveparms[3] = deform->waveparms[3];
5159                         // this is how a divisor of vertex influence on deformation
5160                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5161                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5162                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5163                         {
5164                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5165                                 for (j = 0;j < surface->num_vertices;j++)
5166                                 {
5167                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
5168                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
5169                                         // if the wavefunc depends on time, evaluate it per-vertex
5170                                         if (waveparms[3])
5171                                         {
5172                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5173                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5174                                         }
5175                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
5176                                 }
5177                         }
5178                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5179                         rsurface.vertex3f_bufferobject = 0;
5180                         rsurface.vertex3f_bufferoffset = 0;
5181                         break;
5182                 case Q3DEFORM_BULGE:
5183                         // deform vertex array to make the surface have moving bulges
5184                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5185                         {
5186                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5187                                 for (j = 0;j < surface->num_vertices;j++)
5188                                 {
5189                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
5190                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5191                                 }
5192                         }
5193                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5194                         rsurface.vertex3f_bufferobject = 0;
5195                         rsurface.vertex3f_bufferoffset = 0;
5196                         break;
5197                 case Q3DEFORM_MOVE:
5198                         // deform vertex array
5199                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
5200                         VectorScale(deform->parms, scale, waveparms);
5201                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5202                         {
5203                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5204                                 for (j = 0;j < surface->num_vertices;j++)
5205                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5206                         }
5207                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5208                         rsurface.vertex3f_bufferobject = 0;
5209                         rsurface.vertex3f_bufferoffset = 0;
5210                         break;
5211                 }
5212         }
5213         // generate texcoords based on the chosen texcoord source
5214         switch(rsurface.texture->tcgen.tcgen)
5215         {
5216         default:
5217         case Q3TCGEN_TEXTURE:
5218                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
5219                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
5220                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
5221                 break;
5222         case Q3TCGEN_LIGHTMAP:
5223                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
5224                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
5225                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
5226                 break;
5227         case Q3TCGEN_VECTOR:
5228                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5229                 {
5230                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5231                         for (j = 0, v1 = rsurface.modelvertex3f + 3 * surface->num_firstvertex, out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;j < surface->num_vertices;j++, v1 += 3, out_tc += 2)
5232                         {
5233                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
5234                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
5235                         }
5236                 }
5237                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
5238                 rsurface.texcoordtexture2f_bufferobject  = 0;
5239                 rsurface.texcoordtexture2f_bufferoffset  = 0;
5240                 break;
5241         case Q3TCGEN_ENVIRONMENT:
5242                 // make environment reflections using a spheremap
5243                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5244                 {
5245                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5246                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
5247                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
5248                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
5249                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
5250                         {
5251                                 float l, d, eyedir[3];
5252                                 VectorSubtract(rsurface.modelorg, vertex, eyedir);
5253                                 l = 0.5f / VectorLength(eyedir);
5254                                 d = DotProduct(normal, eyedir)*2;
5255                                 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
5256                                 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
5257                         }
5258                 }
5259                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
5260                 rsurface.texcoordtexture2f_bufferobject  = 0;
5261                 rsurface.texcoordtexture2f_bufferoffset  = 0;
5262                 break;
5263         }
5264         // the only tcmod that needs software vertex processing is turbulent, so
5265         // check for it here and apply the changes if needed
5266         // and we only support that as the first one
5267         // (handling a mixture of turbulent and other tcmods would be problematic
5268         //  without punting it entirely to a software path)
5269         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
5270         {
5271                 amplitude = rsurface.texture->tcmods[0].parms[1];
5272                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
5273                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5274                 {
5275                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5276                         for (j = 0, v1 = rsurface.modelvertex3f + 3 * surface->num_firstvertex, in_tc = rsurface.texcoordtexture2f + 2 * surface->num_firstvertex, out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;j < surface->num_vertices;j++, v1 += 3, in_tc += 2, out_tc += 2)
5277                         {
5278                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5279                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5280                         }
5281                 }
5282                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
5283                 rsurface.texcoordtexture2f_bufferobject  = 0;
5284                 rsurface.texcoordtexture2f_bufferoffset  = 0;
5285         }
5286         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
5287         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5288         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5289         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5290 }
5291
5292 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5293 {
5294         int i, j;
5295         const msurface_t *surface = texturesurfacelist[0];
5296         const msurface_t *surface2;
5297         int firstvertex;
5298         int endvertex;
5299         int numvertices;
5300         int numtriangles;
5301         // TODO: lock all array ranges before render, rather than on each surface
5302         if (texturenumsurfaces == 1)
5303         {
5304                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5305                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5306         }
5307         else if (r_batchmode.integer == 2)
5308         {
5309                 #define MAXBATCHTRIANGLES 4096
5310                 int batchtriangles = 0;
5311                 int batchelements[MAXBATCHTRIANGLES*3];
5312                 for (i = 0;i < texturenumsurfaces;i = j)
5313                 {
5314                         surface = texturesurfacelist[i];
5315                         j = i + 1;
5316                         if (surface->num_triangles > MAXBATCHTRIANGLES)
5317                         {
5318                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5319                                 continue;
5320                         }
5321                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5322                         batchtriangles = surface->num_triangles;
5323                         firstvertex = surface->num_firstvertex;
5324                         endvertex = surface->num_firstvertex + surface->num_vertices;
5325                         for (;j < texturenumsurfaces;j++)
5326                         {
5327                                 surface2 = texturesurfacelist[j];
5328                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5329                                         break;
5330                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5331                                 batchtriangles += surface2->num_triangles;
5332                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
5333                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5334                         }
5335                         surface2 = texturesurfacelist[j-1];
5336                         numvertices = endvertex - firstvertex;
5337                         R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5338                 }
5339         }
5340         else if (r_batchmode.integer == 1)
5341         {
5342                 for (i = 0;i < texturenumsurfaces;i = j)
5343                 {
5344                         surface = texturesurfacelist[i];
5345                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5346                                 if (texturesurfacelist[j] != surface2)
5347                                         break;
5348                         surface2 = texturesurfacelist[j-1];
5349                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5350                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5351                         GL_LockArrays(surface->num_firstvertex, numvertices);
5352                         R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5353                 }
5354         }
5355         else
5356         {
5357                 for (i = 0;i < texturenumsurfaces;i++)
5358                 {
5359                         surface = texturesurfacelist[i];
5360                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5361                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5362                 }
5363         }
5364 }
5365
5366 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5367 {
5368         int i, planeindex, vertexindex;
5369         float d, bestd;
5370         vec3_t vert;
5371         const float *v;
5372         r_waterstate_waterplane_t *p, *bestp;
5373         msurface_t *surface;
5374         if (r_waterstate.renderingscene)
5375                 return;
5376         for (i = 0;i < texturenumsurfaces;i++)
5377         {
5378                 surface = texturesurfacelist[i];
5379                 if (lightmaptexunit >= 0)
5380                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5381                 if (deluxemaptexunit >= 0)
5382                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5383                 // pick the closest matching water plane
5384                 bestd = 0;
5385                 bestp = NULL;
5386                 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5387                 {
5388                         d = 0;
5389                         for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5390                         {
5391                                 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5392                                 d += fabs(PlaneDiff(vert, &p->plane));
5393                         }
5394                         if (bestd > d || !bestp)
5395                         {
5396                                 bestd = d;
5397                                 bestp = p;
5398                         }
5399                 }
5400                 if (bestp)
5401                 {
5402                         if (refractiontexunit >= 0)
5403                                 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5404                         if (reflectiontexunit >= 0)
5405                                 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5406                 }
5407                 else
5408                 {
5409                         if (refractiontexunit >= 0)
5410                                 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5411                         if (reflectiontexunit >= 0)
5412                                 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5413                 }
5414                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5415                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5416         }
5417 }
5418
5419 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5420 {
5421         int i;
5422         int j;
5423         const msurface_t *surface = texturesurfacelist[0];
5424         const msurface_t *surface2;
5425         int firstvertex;
5426         int endvertex;
5427         int numvertices;
5428         int numtriangles;
5429         // TODO: lock all array ranges before render, rather than on each surface
5430         if (texturenumsurfaces == 1)
5431         {
5432                 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5433                 if (deluxemaptexunit >= 0)
5434                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5435                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5436                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5437         }
5438         else if (r_batchmode.integer == 2)
5439         {
5440                 #define MAXBATCHTRIANGLES 4096
5441                 int batchtriangles = 0;
5442                 int batchelements[MAXBATCHTRIANGLES*3];
5443                 for (i = 0;i < texturenumsurfaces;i = j)
5444                 {
5445                         surface = texturesurfacelist[i];
5446                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5447                         if (deluxemaptexunit >= 0)
5448                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5449                         j = i + 1;
5450                         if (surface->num_triangles > MAXBATCHTRIANGLES)
5451                         {
5452                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5453                                 continue;
5454                         }
5455                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5456                         batchtriangles = surface->num_triangles;
5457                         firstvertex = surface->num_firstvertex;
5458                         endvertex = surface->num_firstvertex + surface->num_vertices;
5459                         for (;j < texturenumsurfaces;j++)
5460                         {
5461                                 surface2 = texturesurfacelist[j];
5462                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5463                                         break;
5464                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5465                                 batchtriangles += surface2->num_triangles;
5466                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
5467                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5468                         }
5469                         surface2 = texturesurfacelist[j-1];
5470                         numvertices = endvertex - firstvertex;
5471                         R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5472                 }
5473         }
5474         else if (r_batchmode.integer == 1)
5475         {
5476 #if 0
5477                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5478                 for (i = 0;i < texturenumsurfaces;i = j)
5479                 {
5480                         surface = texturesurfacelist[i];
5481                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5482                                 if (texturesurfacelist[j] != surface2)
5483                                         break;
5484                         Con_Printf(" %i", j - i);
5485                 }
5486                 Con_Printf("\n");
5487                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5488 #endif
5489                 for (i = 0;i < texturenumsurfaces;i = j)
5490                 {
5491                         surface = texturesurfacelist[i];
5492                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5493                         if (deluxemaptexunit >= 0)
5494                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5495                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5496                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5497                                         break;
5498 #if 0
5499                         Con_Printf(" %i", j - i);
5500 #endif
5501                         surface2 = texturesurfacelist[j-1];
5502                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5503                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5504                         GL_LockArrays(surface->num_firstvertex, numvertices);
5505                         R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5506                 }
5507 #if 0
5508                 Con_Printf("\n");
5509 #endif
5510         }
5511         else
5512         {
5513                 for (i = 0;i < texturenumsurfaces;i++)
5514                 {
5515                         surface = texturesurfacelist[i];
5516                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5517                         if (deluxemaptexunit >= 0)
5518                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5519                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5520                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5521                 }
5522         }
5523 }
5524
5525 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5526 {
5527         int j;
5528         int texturesurfaceindex;
5529         if (r_showsurfaces.integer == 2)
5530         {
5531                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5532                 {
5533                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5534                         for (j = 0;j < surface->num_triangles;j++)
5535                         {
5536                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
5537                                 GL_Color(f, f, f, 1);
5538                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, 1, (rsurface.modelelement3i + 3 * (j + surface->num_firsttriangle)), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * (j + surface->num_firsttriangle)));
5539                         }
5540                 }
5541         }
5542         else
5543         {
5544                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5545                 {
5546                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5547                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
5548                         GL_Color((k & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, 1);
5549                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5550                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5551                 }
5552         }
5553 }
5554
5555 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5556 {
5557         int texturesurfaceindex;
5558         int i;
5559         float f;
5560         float *v, *c, *c2;
5561         if (rsurface.lightmapcolor4f)
5562         {
5563                 // generate color arrays for the surfaces in this list
5564                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5565                 {
5566                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5567                         for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
5568                         {
5569                                 f = FogPoint_Model(v);
5570                                 c2[0] = c[0] * f;
5571                                 c2[1] = c[1] * f;
5572                                 c2[2] = c[2] * f;
5573                                 c2[3] = c[3];
5574                         }
5575                 }
5576         }
5577         else
5578         {
5579                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5580                 {
5581                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5582                         for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
5583                         {
5584                                 f = FogPoint_Model(v);
5585                                 c2[0] = f;
5586                                 c2[1] = f;
5587                                 c2[2] = f;
5588                                 c2[3] = 1;
5589                         }
5590                 }
5591         }
5592         rsurface.lightmapcolor4f = rsurface.array_color4f;
5593         rsurface.lightmapcolor4f_bufferobject = 0;
5594         rsurface.lightmapcolor4f_bufferoffset = 0;
5595 }
5596
5597 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5598 {
5599         int texturesurfaceindex;
5600         int i;
5601         float *c, *c2;
5602         if (!rsurface.lightmapcolor4f)
5603                 return;
5604         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5605         {
5606                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5607                 for (i = 0, c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
5608                 {
5609                         c2[0] = c[0] * r;
5610                         c2[1] = c[1] * g;
5611                         c2[2] = c[2] * b;
5612                         c2[3] = c[3] * a;
5613                 }
5614         }
5615         rsurface.lightmapcolor4f = rsurface.array_color4f;
5616         rsurface.lightmapcolor4f_bufferobject = 0;
5617         rsurface.lightmapcolor4f_bufferoffset = 0;
5618 }
5619
5620 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5621 {
5622         // TODO: optimize
5623         rsurface.lightmapcolor4f = NULL;
5624         rsurface.lightmapcolor4f_bufferobject = 0;
5625         rsurface.lightmapcolor4f_bufferoffset = 0;
5626         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5627         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5628         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5629         GL_Color(r, g, b, a);
5630         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5631 }
5632
5633 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5634 {
5635         // TODO: optimize applyfog && applycolor case
5636         // just apply fog if necessary, and tint the fog color array if necessary
5637         rsurface.lightmapcolor4f = NULL;
5638         rsurface.lightmapcolor4f_bufferobject = 0;
5639         rsurface.lightmapcolor4f_bufferoffset = 0;
5640         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5641         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5642         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5643         GL_Color(r, g, b, a);
5644         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5645 }
5646
5647 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5648 {
5649         int texturesurfaceindex;
5650         int i;
5651         float *c;
5652         // TODO: optimize
5653         if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5654         {
5655                 // generate color arrays for the surfaces in this list
5656                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5657                 {
5658                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5659                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5660                         {
5661                                 if (surface->lightmapinfo->samples)
5662                                 {
5663                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5664                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5665                                         VectorScale(lm, scale, c);
5666                                         if (surface->lightmapinfo->styles[1] != 255)
5667                                         {
5668                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5669                                                 lm += size3;
5670                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5671                                                 VectorMA(c, scale, lm, c);
5672                                                 if (surface->lightmapinfo->styles[2] != 255)
5673                                                 {
5674                                                         lm += size3;
5675                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5676                                                         VectorMA(c, scale, lm, c);
5677                                                         if (surface->lightmapinfo->styles[3] != 255)
5678                                                         {
5679                                                                 lm += size3;
5680                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5681                                                                 VectorMA(c, scale, lm, c);
5682                                                         }
5683                                                 }
5684                                         }
5685                                 }
5686                                 else
5687                                         VectorClear(c);
5688                                 c[3] = 1;
5689                         }
5690                 }
5691                 rsurface.lightmapcolor4f = rsurface.array_color4f;
5692                 rsurface.lightmapcolor4f_bufferobject = 0;
5693                 rsurface.lightmapcolor4f_bufferoffset = 0;
5694         }
5695         else
5696         {
5697                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5698                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5699                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5700         }
5701         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5702         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5703         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5704         GL_Color(r, g, b, a);
5705         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5706 }
5707
5708 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5709 {
5710         int texturesurfaceindex;
5711         int i;
5712         float f;
5713         float *v, *c, *c2;
5714         vec3_t ambientcolor;
5715         vec3_t diffusecolor;
5716         vec3_t lightdir;
5717         // TODO: optimize
5718         // model lighting
5719         VectorCopy(rsurface.modellight_lightdir, lightdir);
5720         f = 0.5f * r_refdef.lightmapintensity;
5721         ambientcolor[0] = rsurface.modellight_ambient[0] * r * f;
5722         ambientcolor[1] = rsurface.modellight_ambient[1] * g * f;
5723         ambientcolor[2] = rsurface.modellight_ambient[2] * b * f;
5724         diffusecolor[0] = rsurface.modellight_diffuse[0] * r * f;
5725         diffusecolor[1] = rsurface.modellight_diffuse[1] * g * f;
5726         diffusecolor[2] = rsurface.modellight_diffuse[2] * b * f;
5727         if (VectorLength2(diffusecolor) > 0)
5728         {
5729                 // generate color arrays for the surfaces in this list
5730                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5731                 {
5732                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5733                         int numverts = surface->num_vertices;
5734                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5735                         c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5736                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5737                         // q3-style directional shading
5738                         for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5739                         {
5740                                 if ((f = DotProduct(c2, lightdir)) > 0)
5741                                         VectorMA(ambientcolor, f, diffusecolor, c);
5742                                 else
5743                                         VectorCopy(ambientcolor, c);
5744                                 c[3] = a;
5745                         }
5746                 }
5747                 r = 1;
5748                 g = 1;
5749                 b = 1;
5750                 a = 1;
5751                 applycolor = false;
5752                 rsurface.lightmapcolor4f = rsurface.array_color4f;
5753                 rsurface.lightmapcolor4f_bufferobject = 0;
5754                 rsurface.lightmapcolor4f_bufferoffset = 0;
5755         }
5756         else
5757         {
5758                 r = ambientcolor[0];
5759                 g = ambientcolor[1];
5760                 b = ambientcolor[2];
5761                 rsurface.lightmapcolor4f = NULL;
5762                 rsurface.lightmapcolor4f_bufferobject = 0;
5763                 rsurface.lightmapcolor4f_bufferoffset = 0;
5764         }
5765         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5766         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5767         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5768         GL_Color(r, g, b, a);
5769         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5770 }
5771
5772 void RSurf_SetupDepthAndCulling(void)
5773 {
5774         // submodels are biased to avoid z-fighting with world surfaces that they
5775         // may be exactly overlapping (avoids z-fighting artifacts on certain
5776         // doors and things in Quake maps)
5777         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5778         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
5779         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5780         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
5781 }
5782
5783 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5784 {
5785         // transparent sky would be ridiculous
5786         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5787                 return;
5788         R_SetupGenericShader(false);
5789         if (skyrendernow)
5790         {
5791                 skyrendernow = false;
5792                 // we have to force off the water clipping plane while rendering sky
5793                 R_SetupView(false);
5794                 R_Sky();
5795                 R_SetupView(true);
5796                 // restore entity matrix
5797                 R_Mesh_Matrix(&rsurface.matrix);
5798         }
5799         RSurf_SetupDepthAndCulling();
5800         GL_DepthMask(true);
5801         // LordHavoc: HalfLife maps have freaky skypolys so don't use
5802         // skymasking on them, and Quake3 never did sky masking (unlike
5803         // software Quake and software Quake2), so disable the sky masking
5804         // in Quake3 maps as it causes problems with q3map2 sky tricks,
5805         // and skymasking also looks very bad when noclipping outside the
5806         // level, so don't use it then either.
5807         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
5808         {
5809                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
5810                 R_Mesh_ColorPointer(NULL, 0, 0);
5811                 R_Mesh_ResetTextureState();
5812                 if (skyrendermasked)
5813                 {
5814                         R_SetupDepthOrShadowShader();
5815                         // depth-only (masking)
5816                         GL_ColorMask(0,0,0,0);
5817                         // just to make sure that braindead drivers don't draw
5818                         // anything despite that colormask...
5819                         GL_BlendFunc(GL_ZERO, GL_ONE);
5820                 }
5821                 else
5822                 {
5823                         R_SetupGenericShader(false);
5824                         // fog sky
5825                         GL_BlendFunc(GL_ONE, GL_ZERO);
5826                 }
5827                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5828                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5829                 if (skyrendermasked)
5830                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5831         }
5832         R_Mesh_ResetTextureState();
5833         GL_Color(1, 1, 1, 1);
5834 }
5835
5836 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
5837 {
5838         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5839                 return;
5840
5841         R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5842         R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5843         R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
5844         R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
5845         R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
5846         if (rsurface.texture->backgroundcurrentskinframe)
5847         {
5848                 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
5849                 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
5850                 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
5851                 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
5852         }
5853         R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
5854         R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5855         R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
5856         if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
5857                 R_Mesh_ColorPointer(NULL, 0, 0);
5858         else
5859                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5860
5861         if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5862         {
5863                 // render background
5864                 GL_BlendFunc(GL_ONE, GL_ZERO);
5865                 GL_DepthMask(true);
5866                 GL_AlphaTest(false);
5867
5868                 GL_Color(1, 1, 1, 1);
5869                 R_Mesh_ColorPointer(NULL, 0, 0);
5870
5871                 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5872                 if (r_glsl_permutation)
5873                 {
5874                         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5875                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5876                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5877                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5878                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5879                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5880                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
5881                 }
5882                 GL_LockArrays(0, 0);
5883
5884                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5885                 GL_DepthMask(false);
5886                 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
5887                         R_Mesh_ColorPointer(NULL, 0, 0);
5888                 else
5889                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5890                 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
5891                 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
5892         }
5893
5894         R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5895         if (!r_glsl_permutation)
5896                 return;
5897
5898         RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5899         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5900         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5901         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5902         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5903         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5904
5905         if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5906         {
5907                 GL_BlendFunc(GL_ONE, GL_ZERO);
5908                 GL_DepthMask(true);
5909                 GL_AlphaTest(false);
5910         }
5911         else
5912         {
5913                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5914                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5915                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5916         }
5917
5918         if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5919         {
5920                 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5921                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
5922                 else
5923                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
5924         }
5925         else
5926         {
5927                 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5928                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
5929                 else
5930                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5931         }
5932         GL_LockArrays(0, 0);
5933 }
5934
5935 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
5936 {
5937         // OpenGL 1.3 path - anything not completely ancient
5938         int texturesurfaceindex;
5939         qboolean applycolor;
5940         qboolean applyfog;
5941         rmeshstate_t m;
5942         int layerindex;
5943         const texturelayer_t *layer;
5944         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5945
5946         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5947         {
5948                 vec4_t layercolor;
5949                 int layertexrgbscale;
5950                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5951                 {
5952                         if (layerindex == 0)
5953                                 GL_AlphaTest(true);
5954                         else
5955                         {
5956                                 GL_AlphaTest(false);
5957                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5958                         }
5959                 }
5960                 GL_DepthMask(layer->depthmask && writedepth);
5961                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5962                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
5963                 {
5964                         layertexrgbscale = 4;
5965                         VectorScale(layer->color, 0.25f, layercolor);
5966                 }
5967                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
5968                 {
5969                         layertexrgbscale = 2;
5970                         VectorScale(layer->color, 0.5f, layercolor);
5971                 }
5972                 else
5973                 {
5974                         layertexrgbscale = 1;
5975                         VectorScale(layer->color, 1.0f, layercolor);
5976                 }
5977                 layercolor[3] = layer->color[3];
5978                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5979                 R_Mesh_ColorPointer(NULL, 0, 0);
5980                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5981                 switch (layer->type)
5982                 {
5983                 case TEXTURELAYERTYPE_LITTEXTURE:
5984                         memset(&m, 0, sizeof(m));
5985                         m.tex[0] = R_GetTexture(r_texture_white);
5986                         m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5987                         m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5988                         m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5989                         m.tex[1] = R_GetTexture(layer->texture);
5990                         m.texmatrix[1] = layer->texmatrix;
5991                         m.texrgbscale[1] = layertexrgbscale;
5992                         m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5993                         m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5994                         m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5995                         R_Mesh_TextureState(&m);
5996                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5997                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5998                         else if (rsurface.uselightmaptexture)
5999                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6000                         else
6001                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6002                         break;
6003                 case TEXTURELAYERTYPE_TEXTURE:
6004                         memset(&m, 0, sizeof(m));
6005                         m.tex[0] = R_GetTexture(layer->texture);
6006                         m.texmatrix[0] = layer->texmatrix;
6007                         m.texrgbscale[0] = layertexrgbscale;
6008                         m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6009                         m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6010                         m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6011                         R_Mesh_TextureState(&m);
6012                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6013                         break;
6014                 case TEXTURELAYERTYPE_FOG:
6015                         memset(&m, 0, sizeof(m));
6016                         m.texrgbscale[0] = layertexrgbscale;
6017                         if (layer->texture)
6018                         {
6019                                 m.tex[0] = R_GetTexture(layer->texture);
6020                                 m.texmatrix[0] = layer->texmatrix;
6021                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6022                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6023                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6024                         }
6025                         R_Mesh_TextureState(&m);
6026                         // generate a color array for the fog pass
6027                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6028                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6029                         {
6030                                 int i;
6031                                 float f, *v, *c;
6032                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6033                                 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
6034                                 {
6035                                         f = 1 - FogPoint_Model(v);
6036                                         c[0] = layercolor[0];
6037                                         c[1] = layercolor[1];
6038                                         c[2] = layercolor[2];
6039                                         c[3] = f * layercolor[3];
6040                                 }
6041                         }
6042                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6043                         break;
6044                 default:
6045                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6046                 }
6047                 GL_LockArrays(0, 0);
6048         }
6049         CHECKGLERROR
6050         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6051         {
6052                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6053                 GL_AlphaTest(false);
6054         }
6055 }
6056
6057 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6058 {
6059         // OpenGL 1.1 - crusty old voodoo path
6060         int texturesurfaceindex;
6061         qboolean applyfog;
6062         rmeshstate_t m;
6063         int layerindex;
6064         const texturelayer_t *layer;
6065         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6066
6067         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6068         {
6069                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6070                 {
6071                         if (layerindex == 0)
6072                                 GL_AlphaTest(true);
6073                         else
6074                         {
6075                                 GL_AlphaTest(false);
6076                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6077                         }
6078                 }
6079                 GL_DepthMask(layer->depthmask && writedepth);
6080                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6081                 R_Mesh_ColorPointer(NULL, 0, 0);
6082                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6083                 switch (layer->type)
6084                 {
6085                 case TEXTURELAYERTYPE_LITTEXTURE:
6086                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
6087                         {
6088                                 // two-pass lit texture with 2x rgbscale
6089                                 // first the lightmap pass
6090                                 memset(&m, 0, sizeof(m));
6091                                 m.tex[0] = R_GetTexture(r_texture_white);
6092                                 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6093                                 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6094                                 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6095                                 R_Mesh_TextureState(&m);
6096                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6097                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6098                                 else if (rsurface.uselightmaptexture)
6099                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6100                                 else
6101                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6102                                 GL_LockArrays(0, 0);
6103                                 // then apply the texture to it
6104                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6105                                 memset(&m, 0, sizeof(m));
6106                                 m.tex[0] = R_GetTexture(layer->texture);
6107                                 m.texmatrix[0] = layer->texmatrix;
6108                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6109                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6110                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6111                                 R_Mesh_TextureState(&m);
6112                                 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
6113                         }
6114                         else
6115                         {
6116                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6117                                 memset(&m, 0, sizeof(m));
6118                                 m.tex[0] = R_GetTexture(layer->texture);
6119                                 m.texmatrix[0] = layer->texmatrix;
6120                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6121                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6122                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6123                                 R_Mesh_TextureState(&m);
6124                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6125                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
6126                                 else
6127                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
6128                         }
6129                         break;
6130                 case TEXTURELAYERTYPE_TEXTURE:
6131                         // singletexture unlit texture with transparency support
6132                         memset(&m, 0, sizeof(m));
6133                         m.tex[0] = R_GetTexture(layer->texture);
6134                         m.texmatrix[0] = layer->texmatrix;
6135                         m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6136                         m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6137                         m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6138                         R_Mesh_TextureState(&m);
6139                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
6140                         break;
6141                 case TEXTURELAYERTYPE_FOG:
6142                         // singletexture fogging
6143                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6144                         if (layer->texture)
6145                         {
6146                                 memset(&m, 0, sizeof(m));
6147                                 m.tex[0] = R_GetTexture(layer->texture);
6148                                 m.texmatrix[0] = layer->texmatrix;
6149                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6150                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6151                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6152                                 R_Mesh_TextureState(&m);
6153                         }
6154                         else
6155                                 R_Mesh_ResetTextureState();
6156                         // generate a color array for the fog pass
6157                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6158                         {
6159                                 int i;
6160                                 float f, *v, *c;
6161                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6162                                 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
6163                                 {
6164                                         f = 1 - FogPoint_Model(v);
6165                                         c[0] = layer->color[0];
6166                                         c[1] = layer->color[1];
6167                                         c[2] = layer->color[2];
6168                                         c[3] = f * layer->color[3];
6169                                 }
6170                         }
6171                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6172                         break;
6173                 default:
6174                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6175                 }
6176                 GL_LockArrays(0, 0);
6177         }
6178         CHECKGLERROR
6179         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6180         {
6181                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6182                 GL_AlphaTest(false);
6183         }
6184 }
6185
6186 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6187 {
6188         CHECKGLERROR
6189         RSurf_SetupDepthAndCulling();
6190         if (r_glsl.integer && gl_support_fragment_shader)
6191                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6192         else if (gl_combine.integer && r_textureunits.integer >= 2)
6193                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6194         else
6195                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6196         CHECKGLERROR
6197 }
6198
6199 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6200 {
6201         int i, j;
6202         int texturenumsurfaces, endsurface;
6203         texture_t *texture;
6204         msurface_t *surface;
6205         msurface_t *texturesurfacelist[1024];
6206
6207         // if the model is static it doesn't matter what value we give for
6208         // wantnormals and wanttangents, so this logic uses only rules applicable
6209         // to a model, knowing that they are meaningless otherwise
6210         if (ent == r_refdef.scene.worldentity)
6211                 RSurf_ActiveWorldEntity();
6212         else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6213                 RSurf_ActiveModelEntity(ent, false, false);
6214         else
6215                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6216
6217         for (i = 0;i < numsurfaces;i = j)
6218         {
6219                 j = i + 1;
6220                 surface = rsurface.modelsurfaces + surfacelist[i];
6221                 texture = surface->texture;
6222                 R_UpdateTextureInfo(ent, texture);
6223                 rsurface.texture = texture->currentframe;
6224                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6225                 // scan ahead until we find a different texture
6226                 endsurface = min(i + 1024, numsurfaces);
6227                 texturenumsurfaces = 0;
6228                 texturesurfacelist[texturenumsurfaces++] = surface;
6229                 for (;j < endsurface;j++)
6230                 {
6231                         surface = rsurface.modelsurfaces + surfacelist[j];
6232                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6233                                 break;
6234                         texturesurfacelist[texturenumsurfaces++] = surface;
6235                 }
6236                 // render the range of surfaces
6237                 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6238         }
6239         GL_AlphaTest(false);
6240 }
6241
6242 static void R_ProcessTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
6243 {
6244         CHECKGLERROR
6245         if (depthonly)
6246         {
6247                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6248                         return;
6249                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6250                         return;
6251                 RSurf_SetupDepthAndCulling();
6252                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6253                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6254         }
6255         else if (r_showsurfaces.integer)
6256         {
6257                 RSurf_SetupDepthAndCulling();
6258                 GL_DepthTest(true);
6259                 GL_BlendFunc(GL_ONE, GL_ZERO);
6260                 GL_DepthMask(true);
6261                 GL_AlphaTest(false);
6262                 R_Mesh_ColorPointer(NULL, 0, 0);
6263                 R_Mesh_ResetTextureState();
6264                 R_SetupGenericShader(false);
6265                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6266                 if (!r_refdef.view.showdebug)
6267                 {
6268                         GL_Color(0, 0, 0, 1);
6269                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6270                 }
6271                 else
6272                         RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6273         }
6274         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6275                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6276         else if (!rsurface.texture->currentnumlayers)
6277                 return;
6278         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) && queueentity)
6279         {
6280                 // transparent surfaces get pushed off into the transparent queue
6281                 int surfacelistindex;
6282                 const msurface_t *surface;
6283                 vec3_t tempcenter, center;
6284                 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6285                 {
6286                         surface = texturesurfacelist[surfacelistindex];
6287                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6288                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6289                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6290                         Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6291                         R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6292                 }
6293         }
6294         else
6295         {
6296                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6297                 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6298         }
6299         CHECKGLERROR
6300 }
6301
6302 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
6303 {
6304         int i, j;
6305         texture_t *texture;
6306         // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
6307         if (addwaterplanes)
6308         {
6309                 for (i = 0;i < numsurfaces;i++)
6310                         if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
6311                                 R_Water_AddWaterPlane(surfacelist[i]);
6312                 return;
6313         }
6314         // break the surface list down into batches by texture and use of lightmapping
6315         for (i = 0;i < numsurfaces;i = j)
6316         {
6317                 j = i + 1;
6318                 // texture is the base texture pointer, rsurface.texture is the
6319                 // current frame/skin the texture is directing us to use (for example
6320                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6321                 // use skin 1 instead)
6322                 texture = surfacelist[i]->texture;
6323                 rsurface.texture = texture->currentframe;
6324                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6325                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6326                 {
6327                         // if this texture is not the kind we want, skip ahead to the next one
6328                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6329                                 ;
6330                         continue;
6331                 }
6332                 // simply scan ahead until we find a different texture or lightmap state
6333                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6334                         ;
6335                 // render the range of surfaces
6336                 R_ProcessTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
6337         }
6338 }
6339
6340 float locboxvertex3f[6*4*3] =
6341 {
6342         1,0,1, 1,0,0, 1,1,0, 1,1,1,
6343         0,1,1, 0,1,0, 0,0,0, 0,0,1,
6344         1,1,1, 1,1,0, 0,1,0, 0,1,1,
6345         0,0,1, 0,0,0, 1,0,0, 1,0,1,
6346         0,0,1, 1,0,1, 1,1,1, 0,1,1,
6347         1,0,0, 0,0,0, 0,1,0, 1,1,0
6348 };
6349
6350 int locboxelement3i[6*2*3] =
6351 {
6352          0, 1, 2, 0, 2, 3,
6353          4, 5, 6, 4, 6, 7,
6354          8, 9,10, 8,10,11,
6355         12,13,14, 12,14,15,
6356         16,17,18, 16,18,19,
6357         20,21,22, 20,22,23
6358 };
6359
6360 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6361 {
6362         int i, j;
6363         cl_locnode_t *loc = (cl_locnode_t *)ent;
6364         vec3_t mins, size;
6365         float vertex3f[6*4*3];
6366         CHECKGLERROR
6367         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6368         GL_DepthMask(false);
6369         GL_DepthRange(0, 1);
6370         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6371         GL_DepthTest(true);
6372         GL_CullFace(GL_NONE);
6373         R_Mesh_Matrix(&identitymatrix);
6374
6375         R_Mesh_VertexPointer(vertex3f, 0, 0);
6376         R_Mesh_ColorPointer(NULL, 0, 0);
6377         R_Mesh_ResetTextureState();
6378         R_SetupGenericShader(false);
6379
6380         i = surfacelist[0];
6381         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6382                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6383                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6384                         surfacelist[0] < 0 ? 0.5f : 0.125f);
6385
6386         if (VectorCompare(loc->mins, loc->maxs))
6387         {
6388                 VectorSet(size, 2, 2, 2);
6389                 VectorMA(loc->mins, -0.5f, size, mins);
6390         }
6391         else
6392         {
6393                 VectorCopy(loc->mins, mins);
6394                 VectorSubtract(loc->maxs, loc->mins, size);
6395         }
6396
6397         for (i = 0;i < 6*4*3;)
6398                 for (j = 0;j < 3;j++, i++)
6399                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6400
6401         R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6402 }
6403
6404 void R_DrawLocs(void)
6405 {
6406         int index;
6407         cl_locnode_t *loc, *nearestloc;
6408         vec3_t center;
6409         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6410         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6411         {
6412                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6413                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6414         }
6415 }
6416
6417 void R_DrawDebugModel(entity_render_t *ent)
6418 {
6419         int i, j, k, l, flagsmask;
6420         const int *elements;
6421         q3mbrush_t *brush;
6422         msurface_t *surface;
6423         model_t *model = ent->model;
6424         vec3_t v;
6425
6426         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
6427
6428         R_Mesh_ColorPointer(NULL, 0, 0);
6429         R_Mesh_ResetTextureState();
6430         R_SetupGenericShader(false);
6431         GL_DepthRange(0, 1);
6432         GL_DepthTest(!r_showdisabledepthtest.integer);
6433         GL_DepthMask(false);
6434         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6435
6436         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6437         {
6438                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6439                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6440                 {
6441                         if (brush->colbrushf && brush->colbrushf->numtriangles)
6442                         {
6443                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6444                                 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
6445                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6446                         }
6447                 }
6448                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6449                 {
6450                         if (surface->num_collisiontriangles)
6451                         {
6452                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6453                                 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
6454                                 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6455                         }
6456                 }
6457         }
6458
6459         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6460
6461         if (r_showtris.integer || r_shownormals.integer)
6462         {
6463                 if (r_showdisabledepthtest.integer)
6464                 {
6465                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6466                         GL_DepthMask(false);
6467                 }
6468                 else
6469                 {
6470                         GL_BlendFunc(GL_ONE, GL_ZERO);
6471                         GL_DepthMask(true);
6472                 }
6473                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6474                 {
6475                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
6476                                 continue;
6477                         rsurface.texture = surface->texture->currentframe;
6478                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6479                         {
6480                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6481                                 if (r_showtris.value > 0)
6482                                 {
6483                                         if (!rsurface.texture->currentlayers->depthmask)
6484                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
6485                                         else if (ent == r_refdef.scene.worldentity)
6486                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
6487                                         else
6488                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
6489                                         elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6490                                         CHECKGLERROR
6491                                         qglBegin(GL_LINES);
6492                                         for (k = 0;k < surface->num_triangles;k++, elements += 3)
6493                                         {
6494 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6495                                                 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6496                                                 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6497                                                 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6498                                         }
6499                                         qglEnd();
6500                                         CHECKGLERROR
6501                                 }
6502                                 if (r_shownormals.value > 0)
6503                                 {
6504                                         qglBegin(GL_LINES);
6505                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6506                                         {
6507                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
6508                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
6509                                                 qglVertex3f(v[0], v[1], v[2]);
6510                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
6511                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6512                                                 qglVertex3f(v[0], v[1], v[2]);
6513                                         }
6514                                         qglEnd();
6515                                         CHECKGLERROR
6516                                         qglBegin(GL_LINES);
6517                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6518                                         {
6519                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
6520                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
6521                                                 qglVertex3f(v[0], v[1], v[2]);
6522                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
6523                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6524                                                 qglVertex3f(v[0], v[1], v[2]);
6525                                         }
6526                                         qglEnd();
6527                                         CHECKGLERROR
6528                                         qglBegin(GL_LINES);
6529                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6530                                         {
6531                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
6532                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
6533                                                 qglVertex3f(v[0], v[1], v[2]);
6534                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
6535                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6536                                                 qglVertex3f(v[0], v[1], v[2]);
6537                                         }
6538                                         qglEnd();
6539                                         CHECKGLERROR
6540                                 }
6541                         }
6542                 }
6543                 rsurface.texture = NULL;
6544         }
6545 }
6546
6547 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6548 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6549 {
6550         int i, j, endj, f, flagsmask;
6551         msurface_t *surface;
6552         texture_t *t;
6553         model_t *model = r_refdef.scene.worldmodel;
6554         const int maxsurfacelist = 1024;
6555         int numsurfacelist = 0;
6556         msurface_t *surfacelist[1024];
6557         if (model == NULL)
6558                 return;
6559
6560         RSurf_ActiveWorldEntity();
6561
6562         // update light styles on this submodel
6563         if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6564         {
6565                 model_brush_lightstyleinfo_t *style;
6566                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6567                 {
6568                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
6569                         {
6570                                 msurface_t *surfaces = model->data_surfaces;
6571                                 int *list = style->surfacelist;
6572                                 style->value = r_refdef.scene.lightstylevalue[style->style];
6573                                 for (j = 0;j < style->numsurfaces;j++)
6574                                         surfaces[list[j]].cached_dlight = true;
6575                         }
6576                 }
6577         }
6578
6579         R_UpdateAllTextureInfo(r_refdef.scene.worldentity);
6580         flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL);
6581
6582         if (debug)
6583         {
6584                 R_DrawDebugModel(r_refdef.scene.worldentity);
6585                 return;
6586         }
6587
6588         f = 0;
6589         t = NULL;
6590         rsurface.uselightmaptexture = false;
6591         rsurface.texture = NULL;
6592         rsurface.rtlight = NULL;
6593         numsurfacelist = 0;
6594         j = model->firstmodelsurface;
6595         endj = j + model->nummodelsurfaces;
6596         while (j < endj)
6597         {
6598                 // quickly skip over non-visible surfaces
6599                 for (;j < endj && !r_refdef.viewcache.world_surfacevisible[j];j++)
6600                         ;
6601                 // quickly iterate over visible surfaces
6602                 for (;j < endj && r_refdef.viewcache.world_surfacevisible[j];j++)
6603                 {
6604                         // process this surface
6605                         surface = model->data_surfaces + j;
6606                         // if this surface fits the criteria, add it to the list
6607                         if (surface->num_triangles)
6608                         {
6609                                 // if lightmap parameters changed, rebuild lightmap texture
6610                                 if (surface->cached_dlight)
6611                                         R_BuildLightMap(r_refdef.scene.worldentity, surface);
6612                                 // add face to draw list
6613                                 surfacelist[numsurfacelist++] = surface;
6614                                 r_refdef.stats.world_triangles += surface->num_triangles;
6615                                 if (numsurfacelist >= maxsurfacelist)
6616                                 {
6617                                         r_refdef.stats.world_surfaces += numsurfacelist;
6618                                         R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6619                                         numsurfacelist = 0;
6620                                 }
6621                         }
6622                 }
6623         }
6624         r_refdef.stats.world_surfaces += numsurfacelist;
6625         if (numsurfacelist)
6626                 R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6627         GL_AlphaTest(false);
6628 }
6629
6630 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6631 {
6632         int i, j, f, flagsmask;
6633         msurface_t *surface, *endsurface;
6634         texture_t *t;
6635         model_t *model = ent->model;
6636         const int maxsurfacelist = 1024;
6637         int numsurfacelist = 0;
6638         msurface_t *surfacelist[1024];
6639         if (model == NULL)
6640                 return;
6641
6642         // if the model is static it doesn't matter what value we give for
6643         // wantnormals and wanttangents, so this logic uses only rules applicable
6644         // to a model, knowing that they are meaningless otherwise
6645         if (ent == r_refdef.scene.worldentity)
6646                 RSurf_ActiveWorldEntity();
6647         else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6648                 RSurf_ActiveModelEntity(ent, false, false);
6649         else
6650                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6651
6652         // update light styles
6653         if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6654         {
6655                 model_brush_lightstyleinfo_t *style;
6656                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6657                 {
6658                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
6659                         {
6660                                 msurface_t *surfaces = model->data_surfaces;
6661                                 int *list = style->surfacelist;
6662                                 style->value = r_refdef.scene.lightstylevalue[style->style];
6663                                 for (j = 0;j < style->numsurfaces;j++)
6664                                         surfaces[list[j]].cached_dlight = true;
6665                         }
6666                 }
6667         }
6668
6669         R_UpdateAllTextureInfo(ent);
6670         flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL);
6671
6672         if (debug)
6673         {
6674                 R_DrawDebugModel(ent);
6675                 return;
6676         }
6677
6678         f = 0;
6679         t = NULL;
6680         rsurface.uselightmaptexture = false;
6681         rsurface.texture = NULL;
6682         rsurface.rtlight = NULL;
6683         numsurfacelist = 0;
6684         surface = model->data_surfaces + model->firstmodelsurface;
6685         endsurface = surface + model->nummodelsurfaces;
6686         for (;surface < endsurface;surface++)
6687         {
6688                 // if this surface fits the criteria, add it to the list
6689                 if (surface->num_triangles)
6690                 {
6691                         // if lightmap parameters changed, rebuild lightmap texture
6692                         if (surface->cached_dlight)
6693                                 R_BuildLightMap(ent, surface);
6694                         // add face to draw list
6695                         surfacelist[numsurfacelist++] = surface;
6696                         r_refdef.stats.entities_triangles += surface->num_triangles;
6697                         if (numsurfacelist >= maxsurfacelist)
6698                         {
6699                                 r_refdef.stats.entities_surfaces += numsurfacelist;
6700                                 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6701                                 numsurfacelist = 0;
6702                         }
6703                 }
6704         }
6705         r_refdef.stats.entities_surfaces += numsurfacelist;
6706         if (numsurfacelist)
6707                 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6708         GL_AlphaTest(false);
6709 }