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