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