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