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