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