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