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