]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
factor out the pixel averaging code
[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 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 < 4; ++comp) \
1922                                 w += getpixel; \
1923                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
1924                         { \
1925                                 ++wsum; \
1926                                 for(comp = 0; comp < 4; ++comp) \
1927                                         avgcolor[comp] += (w = getpixel); \
1928                         } \
1929                         avgcolor[4] += w; \
1930                 } \
1931                 if(avgcolor[3] == 0) /* just fully transparent pixels seen? bad luck... */ \
1932                         avgcolor[3] = 255 * wsum; \
1933                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
1934                         avgcolor[3] = 1; \
1935                 skinframe->avgcolor[0] = avgcolor[2] / (1.0 * avgcolor[3]); \
1936                 skinframe->avgcolor[1] = avgcolor[1] / (1.0 * avgcolor[3]); \
1937                 skinframe->avgcolor[2] = avgcolor[0] / (1.0 * avgcolor[3]); \
1938                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
1939         }
1940
1941 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
1942 {
1943         // FIXME: it should be possible to disable loading various layers using
1944         // cvars, to prevent wasted loading time and memory usage if the user does
1945         // not want them
1946         qboolean loadnormalmap = true;
1947         qboolean loadgloss = true;
1948         qboolean loadpantsandshirt = true;
1949         qboolean loadglow = true;
1950         int j;
1951         unsigned char *pixels;
1952         unsigned char *bumppixels;
1953         unsigned char *basepixels = NULL;
1954         int basepixels_width;
1955         int basepixels_height;
1956         skinframe_t *skinframe;
1957
1958         *has_alpha = false;
1959
1960         if (cls.state == ca_dedicated)
1961                 return NULL;
1962
1963         // return an existing skinframe if already loaded
1964         // if loading of the first image fails, don't make a new skinframe as it
1965         // would cause all future lookups of this to be missing
1966         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1967         if (skinframe && skinframe->base)
1968                 return skinframe;
1969
1970         basepixels = loadimagepixelsbgra(name, complain, true);
1971         if (basepixels == NULL)
1972                 return NULL;
1973
1974         if (developer_loading.integer)
1975                 Con_Printf("loading skin \"%s\"\n", name);
1976
1977         // we've got some pixels to store, so really allocate this new texture now
1978         if (!skinframe)
1979                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1980         skinframe->stain = NULL;
1981         skinframe->merged = NULL;
1982         skinframe->base = r_texture_notexture;
1983         skinframe->pants = NULL;
1984         skinframe->shirt = NULL;
1985         skinframe->nmap = r_texture_blanknormalmap;
1986         skinframe->gloss = NULL;
1987         skinframe->glow = NULL;
1988         skinframe->fog = NULL;
1989
1990         basepixels_width = image_width;
1991         basepixels_height = image_height;
1992         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);
1993
1994         if (textureflags & TEXF_ALPHA)
1995         {
1996                 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1997                         if (basepixels[j] < 255)
1998                                 break;
1999                 if (j < basepixels_width * basepixels_height * 4)
2000                 {
2001                         // has transparent pixels
2002                         *has_alpha = true;
2003                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2004                         for (j = 0;j < image_width * image_height * 4;j += 4)
2005                         {
2006                                 pixels[j+0] = 255;
2007                                 pixels[j+1] = 255;
2008                                 pixels[j+2] = 255;
2009                                 pixels[j+3] = basepixels[j+3];
2010                         }
2011                         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);
2012                         Mem_Free(pixels);
2013                 }
2014         }
2015
2016         R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2017
2018         // _norm is the name used by tenebrae and has been adopted as standard
2019         if (loadnormalmap)
2020         {
2021                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2022                 {
2023                         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);
2024                         Mem_Free(pixels);
2025                         pixels = NULL;
2026                 }
2027                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2028                 {
2029                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2030                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2031                         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);
2032                         Mem_Free(pixels);
2033                         Mem_Free(bumppixels);
2034                 }
2035                 else if (r_shadow_bumpscale_basetexture.value > 0)
2036                 {
2037                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2038                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2039                         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);
2040                         Mem_Free(pixels);
2041                 }
2042         }
2043         // _luma is supported for tenebrae compatibility
2044         // (I think it's a very stupid name, but oh well)
2045         // _glow is the preferred name
2046         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;}
2047         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;}
2048         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;}
2049         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;}
2050
2051         if (basepixels)
2052                 Mem_Free(basepixels);
2053
2054         return skinframe;
2055 }
2056
2057 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2058 {
2059         qboolean has_alpha;
2060         return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha);
2061 }
2062
2063 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)
2064 {
2065         int i;
2066         if (!force)
2067         {
2068                 for (i = 0;i < width*height;i++)
2069                         if (((unsigned char *)&palette[in[i]])[3] > 0)
2070                                 break;
2071                 if (i == width*height)
2072                         return NULL;
2073         }
2074         return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2075 }
2076
2077 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2078 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2079 {
2080         int i;
2081         unsigned char *temp1, *temp2;
2082         skinframe_t *skinframe;
2083
2084         if (cls.state == ca_dedicated)
2085                 return NULL;
2086
2087         // if already loaded just return it, otherwise make a new skinframe
2088         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2089         if (skinframe && skinframe->base)
2090                 return skinframe;
2091
2092         skinframe->stain = NULL;
2093         skinframe->merged = NULL;
2094         skinframe->base = r_texture_notexture;
2095         skinframe->pants = NULL;
2096         skinframe->shirt = NULL;
2097         skinframe->nmap = r_texture_blanknormalmap;
2098         skinframe->gloss = NULL;
2099         skinframe->glow = NULL;
2100         skinframe->fog = NULL;
2101
2102         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2103         if (!skindata)
2104                 return NULL;
2105
2106         if (developer_loading.integer)
2107                 Con_Printf("loading 32bit skin \"%s\"\n", name);
2108
2109         if (r_shadow_bumpscale_basetexture.value > 0)
2110         {
2111                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2112                 temp2 = temp1 + width * height * 4;
2113                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2114                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2115                 Mem_Free(temp1);
2116         }
2117         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2118         if (textureflags & TEXF_ALPHA)
2119         {
2120                 for (i = 3;i < width * height * 4;i += 4)
2121                         if (skindata[i] < 255)
2122                                 break;
2123                 if (i < width * height * 4)
2124                 {
2125                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2126                         memcpy(fogpixels, skindata, width * height * 4);
2127                         for (i = 0;i < width * height * 4;i += 4)
2128                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2129                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2130                         Mem_Free(fogpixels);
2131                 }
2132         }
2133
2134         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2135
2136         return skinframe;
2137 }
2138
2139 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2140 {
2141         int i;
2142         unsigned char *temp1, *temp2;
2143         skinframe_t *skinframe;
2144
2145         if (cls.state == ca_dedicated)
2146                 return NULL;
2147
2148         // if already loaded just return it, otherwise make a new skinframe
2149         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2150         if (skinframe && skinframe->base)
2151                 return skinframe;
2152
2153         skinframe->stain = NULL;
2154         skinframe->merged = NULL;
2155         skinframe->base = r_texture_notexture;
2156         skinframe->pants = NULL;
2157         skinframe->shirt = NULL;
2158         skinframe->nmap = r_texture_blanknormalmap;
2159         skinframe->gloss = NULL;
2160         skinframe->glow = NULL;
2161         skinframe->fog = NULL;
2162
2163         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2164         if (!skindata)
2165                 return NULL;
2166
2167         if (developer_loading.integer)
2168                 Con_Printf("loading quake skin \"%s\"\n", name);
2169
2170         if (r_shadow_bumpscale_basetexture.value > 0)
2171         {
2172                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2173                 temp2 = temp1 + width * height * 4;
2174                 // use either a custom palette or the quake palette
2175                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2176                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2177                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2178                 Mem_Free(temp1);
2179         }
2180         // use either a custom palette, or the quake palette
2181         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
2182         if (loadglowtexture)
2183                 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2184         if (loadpantsandshirt)
2185         {
2186                 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2187                 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2188         }
2189         if (skinframe->pants || skinframe->shirt)
2190                 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
2191         if (textureflags & TEXF_ALPHA)
2192         {
2193                 for (i = 0;i < width * height;i++)
2194                         if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2195                                 break;
2196                 if (i < width * height)
2197                         skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2198         }
2199
2200         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_alpha)[skindata[pix]*4 + comp]);
2201
2202         return skinframe;
2203 }
2204
2205 skinframe_t *R_SkinFrame_LoadMissing(void)
2206 {
2207         skinframe_t *skinframe;
2208
2209         if (cls.state == ca_dedicated)
2210                 return NULL;
2211
2212         skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
2213         skinframe->stain = NULL;
2214         skinframe->merged = NULL;
2215         skinframe->base = r_texture_notexture;
2216         skinframe->pants = NULL;
2217         skinframe->shirt = NULL;
2218         skinframe->nmap = r_texture_blanknormalmap;
2219         skinframe->gloss = NULL;
2220         skinframe->glow = NULL;
2221         skinframe->fog = NULL;
2222
2223         skinframe->avgcolor[0] = rand() / RAND_MAX;
2224         skinframe->avgcolor[1] = rand() / RAND_MAX;
2225         skinframe->avgcolor[2] = rand() / RAND_MAX;
2226         skinframe->avgcolor[3] = 1;
2227
2228         return skinframe;
2229 }
2230
2231 void gl_main_start(void)
2232 {
2233         memset(r_qwskincache, 0, sizeof(r_qwskincache));
2234         memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2235
2236         // set up r_skinframe loading system for textures
2237         memset(&r_skinframe, 0, sizeof(r_skinframe));
2238         r_skinframe.loadsequence = 1;
2239         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2240
2241         r_main_texturepool = R_AllocTexturePool();
2242         R_BuildBlankTextures();
2243         R_BuildNoTexture();
2244         if (gl_texturecubemap)
2245         {
2246                 R_BuildWhiteCube();
2247                 R_BuildNormalizationCube();
2248         }
2249         r_texture_fogattenuation = NULL;
2250         r_texture_gammaramps = NULL;
2251         //r_texture_fogintensity = NULL;
2252         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2253         memset(&r_waterstate, 0, sizeof(r_waterstate));
2254         memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2255         memset(&r_svbsp, 0, sizeof (r_svbsp));
2256
2257         r_refdef.fogmasktable_density = 0;
2258 }
2259
2260 void gl_main_shutdown(void)
2261 {
2262         memset(r_qwskincache, 0, sizeof(r_qwskincache));
2263         memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2264
2265         // clear out the r_skinframe state
2266         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2267         memset(&r_skinframe, 0, sizeof(r_skinframe));
2268
2269         if (r_svbsp.nodes)
2270                 Mem_Free(r_svbsp.nodes);
2271         memset(&r_svbsp, 0, sizeof (r_svbsp));
2272         R_FreeTexturePool(&r_main_texturepool);
2273         r_texture_blanknormalmap = NULL;
2274         r_texture_white = NULL;
2275         r_texture_grey128 = NULL;
2276         r_texture_black = NULL;
2277         r_texture_whitecube = NULL;
2278         r_texture_normalizationcube = NULL;
2279         r_texture_fogattenuation = NULL;
2280         r_texture_gammaramps = NULL;
2281         //r_texture_fogintensity = NULL;
2282         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2283         memset(&r_waterstate, 0, sizeof(r_waterstate));
2284         R_GLSL_Restart_f();
2285 }
2286
2287 extern void CL_ParseEntityLump(char *entitystring);
2288 void gl_main_newmap(void)
2289 {
2290         // FIXME: move this code to client
2291         int l;
2292         char *entities, entname[MAX_QPATH];
2293         if (cl.worldmodel)
2294         {
2295                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2296                 l = (int)strlen(entname) - 4;
2297                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2298                 {
2299                         memcpy(entname + l, ".ent", 5);
2300                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2301                         {
2302                                 CL_ParseEntityLump(entities);
2303                                 Mem_Free(entities);
2304                                 return;
2305                         }
2306                 }
2307                 if (cl.worldmodel->brush.entities)
2308                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
2309         }
2310 }
2311
2312 void GL_Main_Init(void)
2313 {
2314         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2315
2316         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2317         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2318         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2319         if (gamemode == GAME_NEHAHRA)
2320         {
2321                 Cvar_RegisterVariable (&gl_fogenable);
2322                 Cvar_RegisterVariable (&gl_fogdensity);
2323                 Cvar_RegisterVariable (&gl_fogred);
2324                 Cvar_RegisterVariable (&gl_foggreen);
2325                 Cvar_RegisterVariable (&gl_fogblue);
2326                 Cvar_RegisterVariable (&gl_fogstart);
2327                 Cvar_RegisterVariable (&gl_fogend);
2328                 Cvar_RegisterVariable (&gl_skyclip);
2329         }
2330         Cvar_RegisterVariable(&r_depthfirst);
2331         Cvar_RegisterVariable(&r_useinfinitefarclip);
2332         Cvar_RegisterVariable(&r_nearclip);
2333         Cvar_RegisterVariable(&r_showbboxes);
2334         Cvar_RegisterVariable(&r_showsurfaces);
2335         Cvar_RegisterVariable(&r_showtris);
2336         Cvar_RegisterVariable(&r_shownormals);
2337         Cvar_RegisterVariable(&r_showlighting);
2338         Cvar_RegisterVariable(&r_showshadowvolumes);
2339         Cvar_RegisterVariable(&r_showcollisionbrushes);
2340         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2341         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2342         Cvar_RegisterVariable(&r_showdisabledepthtest);
2343         Cvar_RegisterVariable(&r_drawportals);
2344         Cvar_RegisterVariable(&r_drawentities);
2345         Cvar_RegisterVariable(&r_cullentities_trace);
2346         Cvar_RegisterVariable(&r_cullentities_trace_samples);
2347         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2348         Cvar_RegisterVariable(&r_cullentities_trace_delay);
2349         Cvar_RegisterVariable(&r_drawviewmodel);
2350         Cvar_RegisterVariable(&r_speeds);
2351         Cvar_RegisterVariable(&r_fullbrights);
2352         Cvar_RegisterVariable(&r_wateralpha);
2353         Cvar_RegisterVariable(&r_dynamic);
2354         Cvar_RegisterVariable(&r_fullbright);
2355         Cvar_RegisterVariable(&r_shadows);
2356         Cvar_RegisterVariable(&r_shadows_throwdistance);
2357         Cvar_RegisterVariable(&r_q1bsp_skymasking);
2358         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2359         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2360         Cvar_RegisterVariable(&r_fog_exp2);
2361         Cvar_RegisterVariable(&r_drawfog);
2362         Cvar_RegisterVariable(&r_textureunits);
2363         Cvar_RegisterVariable(&r_glsl);
2364         Cvar_RegisterVariable(&r_glsl_contrastboost);
2365         Cvar_RegisterVariable(&r_glsl_deluxemapping);
2366         Cvar_RegisterVariable(&r_glsl_offsetmapping);
2367         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2368         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2369         Cvar_RegisterVariable(&r_glsl_postprocess);
2370         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2371         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2372         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2373         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2374         Cvar_RegisterVariable(&r_glsl_usegeneric);
2375         Cvar_RegisterVariable(&r_water);
2376         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2377         Cvar_RegisterVariable(&r_water_clippingplanebias);
2378         Cvar_RegisterVariable(&r_water_refractdistort);
2379         Cvar_RegisterVariable(&r_water_reflectdistort);
2380         Cvar_RegisterVariable(&r_lerpsprites);
2381         Cvar_RegisterVariable(&r_lerpmodels);
2382         Cvar_RegisterVariable(&r_lerplightstyles);
2383         Cvar_RegisterVariable(&r_waterscroll);
2384         Cvar_RegisterVariable(&r_bloom);
2385         Cvar_RegisterVariable(&r_bloom_colorscale);
2386         Cvar_RegisterVariable(&r_bloom_brighten);
2387         Cvar_RegisterVariable(&r_bloom_blur);
2388         Cvar_RegisterVariable(&r_bloom_resolution);
2389         Cvar_RegisterVariable(&r_bloom_colorexponent);
2390         Cvar_RegisterVariable(&r_bloom_colorsubtract);
2391         Cvar_RegisterVariable(&r_hdr);
2392         Cvar_RegisterVariable(&r_hdr_scenebrightness);
2393         Cvar_RegisterVariable(&r_hdr_glowintensity);
2394         Cvar_RegisterVariable(&r_hdr_range);
2395         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2396         Cvar_RegisterVariable(&developer_texturelogging);
2397         Cvar_RegisterVariable(&gl_lightmaps);
2398         Cvar_RegisterVariable(&r_test);
2399         Cvar_RegisterVariable(&r_batchmode);
2400         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2401                 Cvar_SetValue("r_fullbrights", 0);
2402         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2403
2404         Cvar_RegisterVariable(&r_track_sprites);
2405         Cvar_RegisterVariable(&r_track_sprites_flags);
2406         Cvar_RegisterVariable(&r_track_sprites_scalew);
2407         Cvar_RegisterVariable(&r_track_sprites_scaleh);
2408 }
2409
2410 extern void R_Textures_Init(void);
2411 extern void GL_Draw_Init(void);
2412 extern void GL_Main_Init(void);
2413 extern void R_Shadow_Init(void);
2414 extern void R_Sky_Init(void);
2415 extern void GL_Surf_Init(void);
2416 extern void R_Particles_Init(void);
2417 extern void R_Explosion_Init(void);
2418 extern void gl_backend_init(void);
2419 extern void Sbar_Init(void);
2420 extern void R_LightningBeams_Init(void);
2421 extern void Mod_RenderInit(void);
2422
2423 void Render_Init(void)
2424 {
2425         gl_backend_init();
2426         R_Textures_Init();
2427         GL_Main_Init();
2428         GL_Draw_Init();
2429         R_Shadow_Init();
2430         R_Sky_Init();
2431         GL_Surf_Init();
2432         Sbar_Init();
2433         R_Particles_Init();
2434         R_Explosion_Init();
2435         R_LightningBeams_Init();
2436         Mod_RenderInit();
2437 }
2438
2439 /*
2440 ===============
2441 GL_Init
2442 ===============
2443 */
2444 extern char *ENGINE_EXTENSIONS;
2445 void GL_Init (void)
2446 {
2447         gl_renderer = (const char *)qglGetString(GL_RENDERER);
2448         gl_vendor = (const char *)qglGetString(GL_VENDOR);
2449         gl_version = (const char *)qglGetString(GL_VERSION);
2450         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2451
2452         if (!gl_extensions)
2453                 gl_extensions = "";
2454         if (!gl_platformextensions)
2455                 gl_platformextensions = "";
2456
2457         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2458         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2459         Con_Printf("GL_VERSION: %s\n", gl_version);
2460         Con_Printf("GL_EXTENSIONS: %s\n", gl_extensions);
2461         Con_Printf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2462
2463         VID_CheckExtensions();
2464
2465         // LordHavoc: report supported extensions
2466         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2467
2468         // clear to black (loading plaque will be seen over this)
2469         CHECKGLERROR
2470         qglClearColor(0,0,0,1);CHECKGLERROR
2471         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2472 }
2473
2474 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2475 {
2476         int i;
2477         mplane_t *p;
2478         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2479         {
2480                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2481                 if (i == 4)
2482                         continue;
2483                 p = r_refdef.view.frustum + i;
2484                 switch(p->signbits)
2485                 {
2486                 default:
2487                 case 0:
2488                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2489                                 return true;
2490                         break;
2491                 case 1:
2492                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2493                                 return true;
2494                         break;
2495                 case 2:
2496                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2497                                 return true;
2498                         break;
2499                 case 3:
2500                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2501                                 return true;
2502                         break;
2503                 case 4:
2504                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2505                                 return true;
2506                         break;
2507                 case 5:
2508                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2509                                 return true;
2510                         break;
2511                 case 6:
2512                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2513                                 return true;
2514                         break;
2515                 case 7:
2516                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2517                                 return true;
2518                         break;
2519                 }
2520         }
2521         return false;
2522 }
2523
2524 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2525 {
2526         int i;
2527         const mplane_t *p;
2528         for (i = 0;i < numplanes;i++)
2529         {
2530                 p = planes + i;
2531                 switch(p->signbits)
2532                 {
2533                 default:
2534                 case 0:
2535                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2536                                 return true;
2537                         break;
2538                 case 1:
2539                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2540                                 return true;
2541                         break;
2542                 case 2:
2543                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2544                                 return true;
2545                         break;
2546                 case 3:
2547                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2548                                 return true;
2549                         break;
2550                 case 4:
2551                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2552                                 return true;
2553                         break;
2554                 case 5:
2555                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2556                                 return true;
2557                         break;
2558                 case 6:
2559                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2560                                 return true;
2561                         break;
2562                 case 7:
2563                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2564                                 return true;
2565                         break;
2566                 }
2567         }
2568         return false;
2569 }
2570
2571 //==================================================================================
2572
2573 static void R_View_UpdateEntityVisible (void)
2574 {
2575         int i, renderimask;
2576         entity_render_t *ent;
2577
2578         if (!r_drawentities.integer)
2579                 return;
2580
2581         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2582         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2583         {
2584                 // worldmodel can check visibility
2585                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
2586                 for (i = 0;i < r_refdef.scene.numentities;i++)
2587                 {
2588                         ent = r_refdef.scene.entities[i];
2589                         if (!(ent->flags & renderimask))
2590                         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)))
2591                         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))
2592                                 r_refdef.viewcache.entityvisible[i] = true;
2593                 }
2594                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2595                 {
2596                         for (i = 0;i < r_refdef.scene.numentities;i++)
2597                         {
2598                                 ent = r_refdef.scene.entities[i];
2599                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2600                                 {
2601                                         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))
2602                                                 ent->last_trace_visibility = realtime;
2603                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2604                                                 r_refdef.viewcache.entityvisible[i] = 0;
2605                                 }
2606                         }
2607                 }
2608         }
2609         else
2610         {
2611                 // no worldmodel or it can't check visibility
2612                 for (i = 0;i < r_refdef.scene.numentities;i++)
2613                 {
2614                         ent = r_refdef.scene.entities[i];
2615                         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));
2616                 }
2617         }
2618 }
2619
2620 // only used if skyrendermasked, and normally returns false
2621 int R_DrawBrushModelsSky (void)
2622 {
2623         int i, sky;
2624         entity_render_t *ent;
2625
2626         if (!r_drawentities.integer)
2627                 return false;
2628
2629         sky = false;
2630         for (i = 0;i < r_refdef.scene.numentities;i++)
2631         {
2632                 if (!r_refdef.viewcache.entityvisible[i])
2633                         continue;
2634                 ent = r_refdef.scene.entities[i];
2635                 if (!ent->model || !ent->model->DrawSky)
2636                         continue;
2637                 ent->model->DrawSky(ent);
2638                 sky = true;
2639         }
2640         return sky;
2641 }
2642
2643 static void R_DrawNoModel(entity_render_t *ent);
2644 static void R_DrawModels(void)
2645 {
2646         int i;
2647         entity_render_t *ent;
2648
2649         if (!r_drawentities.integer)
2650                 return;
2651
2652         for (i = 0;i < r_refdef.scene.numentities;i++)
2653         {
2654                 if (!r_refdef.viewcache.entityvisible[i])
2655                         continue;
2656                 ent = r_refdef.scene.entities[i];
2657                 r_refdef.stats.entities++;
2658                 if (ent->model && ent->model->Draw != NULL)
2659                         ent->model->Draw(ent);
2660                 else
2661                         R_DrawNoModel(ent);
2662         }
2663 }
2664
2665 static void R_DrawModelsDepth(void)
2666 {
2667         int i;
2668         entity_render_t *ent;
2669
2670         if (!r_drawentities.integer)
2671                 return;
2672
2673         for (i = 0;i < r_refdef.scene.numentities;i++)
2674         {
2675                 if (!r_refdef.viewcache.entityvisible[i])
2676                         continue;
2677                 ent = r_refdef.scene.entities[i];
2678                 if (ent->model && ent->model->DrawDepth != NULL)
2679                         ent->model->DrawDepth(ent);
2680         }
2681 }
2682
2683 static void R_DrawModelsDebug(void)
2684 {
2685         int i;
2686         entity_render_t *ent;
2687
2688         if (!r_drawentities.integer)
2689                 return;
2690
2691         for (i = 0;i < r_refdef.scene.numentities;i++)
2692         {
2693                 if (!r_refdef.viewcache.entityvisible[i])
2694                         continue;
2695                 ent = r_refdef.scene.entities[i];
2696                 if (ent->model && ent->model->DrawDebug != NULL)
2697                         ent->model->DrawDebug(ent);
2698         }
2699 }
2700
2701 static void R_DrawModelsAddWaterPlanes(void)
2702 {
2703         int i;
2704         entity_render_t *ent;
2705
2706         if (!r_drawentities.integer)
2707                 return;
2708
2709         for (i = 0;i < r_refdef.scene.numentities;i++)
2710         {
2711                 if (!r_refdef.viewcache.entityvisible[i])
2712                         continue;
2713                 ent = r_refdef.scene.entities[i];
2714                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2715                         ent->model->DrawAddWaterPlanes(ent);
2716         }
2717 }
2718
2719 static void R_View_SetFrustum(void)
2720 {
2721         int i;
2722         double slopex, slopey;
2723         vec3_t forward, left, up, origin;
2724
2725         // we can't trust r_refdef.view.forward and friends in reflected scenes
2726         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
2727
2728 #if 0
2729         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2730         r_refdef.view.frustum[0].normal[1] = 0 - 0;
2731         r_refdef.view.frustum[0].normal[2] = -1 - 0;
2732         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2733         r_refdef.view.frustum[1].normal[1] = 0 + 0;
2734         r_refdef.view.frustum[1].normal[2] = -1 + 0;
2735         r_refdef.view.frustum[2].normal[0] = 0 - 0;
2736         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2737         r_refdef.view.frustum[2].normal[2] = -1 - 0;
2738         r_refdef.view.frustum[3].normal[0] = 0 + 0;
2739         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2740         r_refdef.view.frustum[3].normal[2] = -1 + 0;
2741 #endif
2742
2743 #if 0
2744         zNear = r_refdef.nearclip;
2745         nudge = 1.0 - 1.0 / (1<<23);
2746         r_refdef.view.frustum[4].normal[0] = 0 - 0;
2747         r_refdef.view.frustum[4].normal[1] = 0 - 0;
2748         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
2749         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
2750         r_refdef.view.frustum[5].normal[0] = 0 + 0;
2751         r_refdef.view.frustum[5].normal[1] = 0 + 0;
2752         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
2753         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
2754 #endif
2755
2756
2757
2758 #if 0
2759         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
2760         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
2761         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
2762         r_refdef.view.frustum[0].dist = m[15] - m[12];
2763
2764         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
2765         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
2766         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
2767         r_refdef.view.frustum[1].dist = m[15] + m[12];
2768
2769         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
2770         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
2771         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
2772         r_refdef.view.frustum[2].dist = m[15] - m[13];
2773
2774         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
2775         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
2776         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
2777         r_refdef.view.frustum[3].dist = m[15] + m[13];
2778
2779         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
2780         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
2781         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
2782         r_refdef.view.frustum[4].dist = m[15] - m[14];
2783
2784         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
2785         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
2786         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
2787         r_refdef.view.frustum[5].dist = m[15] + m[14];
2788 #endif
2789
2790         if (r_refdef.view.useperspective)
2791         {
2792                 slopex = 1.0 / r_refdef.view.frustum_x;
2793                 slopey = 1.0 / r_refdef.view.frustum_y;
2794                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
2795                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
2796                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
2797                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
2798                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2799
2800                 // Leaving those out was a mistake, those were in the old code, and they
2801                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2802                 // I couldn't reproduce it after adding those normalizations. --blub
2803                 VectorNormalize(r_refdef.view.frustum[0].normal);
2804                 VectorNormalize(r_refdef.view.frustum[1].normal);
2805                 VectorNormalize(r_refdef.view.frustum[2].normal);
2806                 VectorNormalize(r_refdef.view.frustum[3].normal);
2807
2808                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2809                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
2810                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
2811                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left,  1024 * slopey, up, r_refdef.view.frustumcorner[2]);
2812                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * slopex, left,  1024 * slopey, up, r_refdef.view.frustumcorner[3]);
2813
2814                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
2815                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
2816                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
2817                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
2818                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2819         }
2820         else
2821         {
2822                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
2823                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
2824                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
2825                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
2826                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2827                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
2828                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
2829                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
2830                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
2831                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2832         }
2833         r_refdef.view.numfrustumplanes = 5;
2834
2835         if (r_refdef.view.useclipplane)
2836         {
2837                 r_refdef.view.numfrustumplanes = 6;
2838                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
2839         }
2840
2841         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2842                 PlaneClassify(r_refdef.view.frustum + i);
2843
2844         // LordHavoc: note to all quake engine coders, Quake had a special case
2845         // for 90 degrees which assumed a square view (wrong), so I removed it,
2846         // Quake2 has it disabled as well.
2847
2848         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2849         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
2850         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
2851         //PlaneClassify(&frustum[0]);
2852
2853         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2854         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
2855         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
2856         //PlaneClassify(&frustum[1]);
2857
2858         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2859         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
2860         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
2861         //PlaneClassify(&frustum[2]);
2862
2863         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2864         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
2865         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
2866         //PlaneClassify(&frustum[3]);
2867
2868         // nearclip plane
2869         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
2870         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
2871         //PlaneClassify(&frustum[4]);
2872 }
2873
2874 void R_View_Update(void)
2875 {
2876         R_View_SetFrustum();
2877         R_View_WorldVisibility(r_refdef.view.useclipplane);
2878         R_View_UpdateEntityVisible();
2879 }
2880
2881 void R_SetupView(qboolean allowwaterclippingplane)
2882 {
2883         if (!r_refdef.view.useperspective)
2884                 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);
2885         else if (gl_stencil && r_useinfinitefarclip.integer)
2886                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
2887         else
2888                 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2889
2890         GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
2891
2892         if (r_refdef.view.useclipplane && allowwaterclippingplane)
2893         {
2894                 // LordHavoc: couldn't figure out how to make this approach the
2895                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
2896                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
2897                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
2898                         dist = r_refdef.view.clipplane.dist;
2899                 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
2900         }
2901 }
2902
2903 void R_ResetViewRendering2D(void)
2904 {
2905         DrawQ_Finish();
2906
2907         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2908         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2909         GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2910         GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2911         GL_Color(1, 1, 1, 1);
2912         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2913         GL_BlendFunc(GL_ONE, GL_ZERO);
2914         GL_AlphaTest(false);
2915         GL_ScissorTest(false);
2916         GL_DepthMask(false);
2917         GL_DepthRange(0, 1);
2918         GL_DepthTest(false);
2919         R_Mesh_Matrix(&identitymatrix);
2920         R_Mesh_ResetTextureState();
2921         GL_PolygonOffset(0, 0);
2922         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2923         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2924         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2925         qglStencilMask(~0);CHECKGLERROR
2926         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2927         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2928         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2929         R_SetupGenericShader(true);
2930 }
2931
2932 void R_ResetViewRendering3D(void)
2933 {
2934         DrawQ_Finish();
2935
2936         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2937         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2938         R_SetupView(true);
2939         GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2940         GL_Color(1, 1, 1, 1);
2941         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2942         GL_BlendFunc(GL_ONE, GL_ZERO);
2943         GL_AlphaTest(false);
2944         GL_ScissorTest(true);
2945         GL_DepthMask(true);
2946         GL_DepthRange(0, 1);
2947         GL_DepthTest(true);
2948         R_Mesh_Matrix(&identitymatrix);
2949         R_Mesh_ResetTextureState();
2950         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2951         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2952         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2953         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2954         qglStencilMask(~0);CHECKGLERROR
2955         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2956         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2957         GL_CullFace(r_refdef.view.cullface_back);
2958         R_SetupGenericShader(true);
2959 }
2960
2961 void R_RenderScene(qboolean addwaterplanes);
2962
2963 static void R_Water_StartFrame(void)
2964 {
2965         int i;
2966         int waterwidth, waterheight, texturewidth, textureheight;
2967         r_waterstate_waterplane_t *p;
2968
2969         // set waterwidth and waterheight to the water resolution that will be
2970         // used (often less than the screen resolution for faster rendering)
2971         waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
2972         waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
2973
2974         // calculate desired texture sizes
2975         // can't use water if the card does not support the texture size
2976         if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
2977                 texturewidth = textureheight = waterwidth = waterheight = 0;
2978         else if (gl_support_arb_texture_non_power_of_two)
2979         {
2980                 texturewidth = waterwidth;
2981                 textureheight = waterheight;
2982         }
2983         else
2984         {
2985                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
2986                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
2987         }
2988
2989         // allocate textures as needed
2990         if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2991         {
2992                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2993                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2994                 {
2995                         if (p->texture_refraction)
2996                                 R_FreeTexture(p->texture_refraction);
2997                         p->texture_refraction = NULL;
2998                         if (p->texture_reflection)
2999                                 R_FreeTexture(p->texture_reflection);
3000                         p->texture_reflection = NULL;
3001                 }
3002                 memset(&r_waterstate, 0, sizeof(r_waterstate));
3003                 r_waterstate.waterwidth = waterwidth;
3004                 r_waterstate.waterheight = waterheight;
3005                 r_waterstate.texturewidth = texturewidth;
3006                 r_waterstate.textureheight = textureheight;
3007         }
3008
3009         if (r_waterstate.waterwidth)
3010         {
3011                 r_waterstate.enabled = true;
3012
3013                 // set up variables that will be used in shader setup
3014                 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3015                 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
3016                 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3017                 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
3018         }
3019
3020         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3021         r_waterstate.numwaterplanes = 0;
3022 }
3023
3024 static void R_Water_AddWaterPlane(msurface_t *surface)
3025 {
3026         int triangleindex, planeindex;
3027         const int *e;
3028         vec3_t vert[3];
3029         vec3_t normal;
3030         vec3_t center;
3031         mplane_t plane;
3032         r_waterstate_waterplane_t *p;
3033         // just use the first triangle with a valid normal for any decisions
3034         VectorClear(normal);
3035         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3036         {
3037                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3038                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3039                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3040                 TriangleNormal(vert[0], vert[1], vert[2], normal);
3041                 if (VectorLength2(normal) >= 0.001)
3042                         break;
3043         }
3044
3045         VectorCopy(normal, plane.normal);
3046         VectorNormalize(plane.normal);
3047         plane.dist = DotProduct(vert[0], plane.normal);
3048         PlaneClassify(&plane);
3049         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3050         {
3051                 // skip backfaces (except if nocullface is set)
3052                 if (!(surface->texture->currentframe->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3053                         return;
3054                 VectorNegate(plane.normal, plane.normal);
3055                 plane.dist *= -1;
3056                 PlaneClassify(&plane);
3057         }
3058
3059
3060         // find a matching plane if there is one
3061         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3062                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3063                         break;
3064         if (planeindex >= r_waterstate.maxwaterplanes)
3065                 return; // nothing we can do, out of planes
3066
3067         // if this triangle does not fit any known plane rendered this frame, add one
3068         if (planeindex >= r_waterstate.numwaterplanes)
3069         {
3070                 // store the new plane
3071                 r_waterstate.numwaterplanes++;
3072                 p->plane = plane;
3073                 // clear materialflags and pvs
3074                 p->materialflags = 0;
3075                 p->pvsvalid = false;
3076         }
3077         // merge this surface's materialflags into the waterplane
3078         p->materialflags |= surface->texture->currentframe->currentmaterialflags;
3079         // merge this surface's PVS into the waterplane
3080         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3081         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3082          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3083         {
3084                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3085                 p->pvsvalid = true;
3086         }
3087 }
3088
3089 static void R_Water_ProcessPlanes(void)
3090 {
3091         r_refdef_view_t originalview;
3092         int planeindex;
3093         r_waterstate_waterplane_t *p;
3094
3095         originalview = r_refdef.view;
3096
3097         // make sure enough textures are allocated
3098         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3099         {
3100                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3101                 {
3102                         if (!p->texture_refraction)
3103                                 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);
3104                         if (!p->texture_refraction)
3105                                 goto error;
3106                 }
3107
3108                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3109                 {
3110                         if (!p->texture_reflection)
3111                                 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);
3112                         if (!p->texture_reflection)
3113                                 goto error;
3114                 }
3115         }
3116
3117         // render views
3118         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3119         {
3120                 r_refdef.view.showdebug = false;
3121                 r_refdef.view.width = r_waterstate.waterwidth;
3122                 r_refdef.view.height = r_waterstate.waterheight;
3123                 r_refdef.view.useclipplane = true;
3124                 r_waterstate.renderingscene = true;
3125
3126                 // render the normal view scene and copy into texture
3127                 // (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)
3128                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3129                 {
3130                         r_refdef.view.clipplane = p->plane;
3131                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3132                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3133                         PlaneClassify(&r_refdef.view.clipplane);
3134
3135                         R_RenderScene(false);
3136
3137                         // copy view into the screen texture
3138                         R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3139                         GL_ActiveTexture(0);
3140                         CHECKGLERROR
3141                         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
3142                 }
3143
3144                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3145                 {
3146                         // render reflected scene and copy into texture
3147                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3148                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3149                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3150                         r_refdef.view.clipplane = p->plane;
3151                         // reverse the cullface settings for this render
3152                         r_refdef.view.cullface_front = GL_FRONT;
3153                         r_refdef.view.cullface_back = GL_BACK;
3154                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3155                         {
3156                                 r_refdef.view.usecustompvs = true;
3157                                 if (p->pvsvalid)
3158                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3159                                 else
3160                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3161                         }
3162
3163                         R_ResetViewRendering3D();
3164                         R_ClearScreen(r_refdef.fogenabled);
3165                         if (r_timereport_active)
3166                                 R_TimeReport("viewclear");
3167
3168                         R_RenderScene(false);
3169
3170                         R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3171                         GL_ActiveTexture(0);
3172                         CHECKGLERROR
3173                         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
3174
3175                         R_ResetViewRendering3D();
3176                         R_ClearScreen(r_refdef.fogenabled);
3177                         if (r_timereport_active)
3178                                 R_TimeReport("viewclear");
3179                 }
3180
3181                 r_refdef.view = originalview;
3182                 r_refdef.view.clear = true;
3183                 r_waterstate.renderingscene = false;
3184         }
3185         return;
3186 error:
3187         r_refdef.view = originalview;
3188         r_waterstate.renderingscene = false;
3189         Cvar_SetValueQuick(&r_water, 0);
3190         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
3191         return;
3192 }
3193
3194 void R_Bloom_StartFrame(void)
3195 {
3196         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3197
3198         // set bloomwidth and bloomheight to the bloom resolution that will be
3199         // used (often less than the screen resolution for faster rendering)
3200         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3201         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3202         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3203         r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3204         r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3205
3206         // calculate desired texture sizes
3207         if (gl_support_arb_texture_non_power_of_two)
3208         {
3209                 screentexturewidth = r_refdef.view.width;
3210                 screentextureheight = r_refdef.view.height;
3211                 bloomtexturewidth = r_bloomstate.bloomwidth;
3212                 bloomtextureheight = r_bloomstate.bloomheight;
3213         }
3214         else
3215         {
3216                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
3217                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
3218                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
3219                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
3220         }
3221
3222         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))
3223         {
3224                 Cvar_SetValueQuick(&r_hdr, 0);
3225                 Cvar_SetValueQuick(&r_bloom, 0);
3226         }
3227
3228         if (!(r_glsl.integer && (r_glsl_postprocess.integer || (v_glslgamma.integer && !vid_gammatables_trivial) || r_bloom.integer || r_hdr.integer)) && !r_bloom.integer)
3229                 screentexturewidth = screentextureheight = 0;
3230         if (!r_hdr.integer && !r_bloom.integer)
3231                 bloomtexturewidth = bloomtextureheight = 0;
3232
3233         // allocate textures as needed
3234         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3235         {
3236                 if (r_bloomstate.texture_screen)
3237                         R_FreeTexture(r_bloomstate.texture_screen);
3238                 r_bloomstate.texture_screen = NULL;
3239                 r_bloomstate.screentexturewidth = screentexturewidth;
3240                 r_bloomstate.screentextureheight = screentextureheight;
3241                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3242                         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);
3243         }
3244         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3245         {
3246                 if (r_bloomstate.texture_bloom)
3247                         R_FreeTexture(r_bloomstate.texture_bloom);
3248                 r_bloomstate.texture_bloom = NULL;
3249                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3250                 r_bloomstate.bloomtextureheight = bloomtextureheight;
3251                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3252                         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);
3253         }
3254
3255         // set up a texcoord array for the full resolution screen image
3256         // (we have to keep this around to copy back during final render)
3257         r_bloomstate.screentexcoord2f[0] = 0;
3258         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
3259         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
3260         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
3261         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
3262         r_bloomstate.screentexcoord2f[5] = 0;
3263         r_bloomstate.screentexcoord2f[6] = 0;
3264         r_bloomstate.screentexcoord2f[7] = 0;
3265
3266         // set up a texcoord array for the reduced resolution bloom image
3267         // (which will be additive blended over the screen image)
3268         r_bloomstate.bloomtexcoord2f[0] = 0;
3269         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3270         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
3271         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3272         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
3273         r_bloomstate.bloomtexcoord2f[5] = 0;
3274         r_bloomstate.bloomtexcoord2f[6] = 0;
3275         r_bloomstate.bloomtexcoord2f[7] = 0;
3276
3277         if (r_hdr.integer || r_bloom.integer)
3278         {
3279                 r_bloomstate.enabled = true;
3280                 r_bloomstate.hdr = r_hdr.integer != 0;
3281         }
3282 }
3283
3284 void R_Bloom_CopyBloomTexture(float colorscale)
3285 {
3286         r_refdef.stats.bloom++;
3287
3288         // scale down screen texture to the bloom texture size
3289         CHECKGLERROR
3290         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3291         GL_BlendFunc(GL_ONE, GL_ZERO);
3292         GL_Color(colorscale, colorscale, colorscale, 1);
3293         // TODO: optimize with multitexture or GLSL
3294         R_SetupGenericShader(true);
3295         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3296         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3297         R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3298         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3299
3300         // we now have a bloom image in the framebuffer
3301         // copy it into the bloom image texture for later processing
3302         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3303         GL_ActiveTexture(0);
3304         CHECKGLERROR
3305         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
3306         r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3307 }
3308
3309 void R_Bloom_CopyHDRTexture(void)
3310 {
3311         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3312         GL_ActiveTexture(0);
3313         CHECKGLERROR
3314         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
3315         r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3316 }
3317
3318 void R_Bloom_MakeTexture(void)
3319 {
3320         int x, range, dir;
3321         float xoffset, yoffset, r, brighten;
3322
3323         r_refdef.stats.bloom++;
3324
3325         R_ResetViewRendering2D();
3326         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3327         R_Mesh_ColorPointer(NULL, 0, 0);
3328         R_SetupGenericShader(true);
3329
3330         // we have a bloom image in the framebuffer
3331         CHECKGLERROR
3332         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3333
3334         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3335         {
3336                 x *= 2;
3337                 r = bound(0, r_bloom_colorexponent.value / x, 1);
3338                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3339                 GL_Color(r, r, r, 1);
3340                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3341                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3342                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3343                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3344
3345                 // copy the vertically blurred bloom view to a texture
3346                 GL_ActiveTexture(0);
3347                 CHECKGLERROR
3348                 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
3349                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3350         }
3351
3352         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3353         brighten = r_bloom_brighten.value;
3354         if (r_hdr.integer)
3355                 brighten *= r_hdr_range.value;
3356         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3357         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3358
3359         for (dir = 0;dir < 2;dir++)
3360         {
3361                 // blend on at multiple vertical offsets to achieve a vertical blur
3362                 // TODO: do offset blends using GLSL
3363                 GL_BlendFunc(GL_ONE, GL_ZERO);
3364                 for (x = -range;x <= range;x++)
3365                 {
3366                         if (!dir){xoffset = 0;yoffset = x;}
3367                         else {xoffset = x;yoffset = 0;}
3368                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
3369                         yoffset /= (float)r_bloomstate.bloomtextureheight;
3370                         // compute a texcoord array with the specified x and y offset
3371                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3372                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3373                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3374                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3375                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3376                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3377                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3378                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3379                         // this r value looks like a 'dot' particle, fading sharply to
3380                         // black at the edges
3381                         // (probably not realistic but looks good enough)
3382                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3383                         //r = (dir ? 1.0f : brighten)/(range*2+1);
3384                         r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3385                         GL_Color(r, r, r, 1);
3386                         R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3387                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3388                         GL_BlendFunc(GL_ONE, GL_ONE);
3389                 }
3390
3391                 // copy the vertically blurred bloom view to a texture
3392                 GL_ActiveTexture(0);
3393                 CHECKGLERROR
3394                 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
3395                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3396         }
3397
3398         // apply subtract last
3399         // (just like it would be in a GLSL shader)
3400         if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3401         {
3402                 GL_BlendFunc(GL_ONE, GL_ZERO);
3403                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3404                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3405                 GL_Color(1, 1, 1, 1);
3406                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3407                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3408
3409                 GL_BlendFunc(GL_ONE, GL_ONE);
3410                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3411                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3412                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3413                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3414                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3415                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3416                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3417
3418                 // copy the darkened bloom view to a texture
3419                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3420                 GL_ActiveTexture(0);
3421                 CHECKGLERROR
3422                 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
3423                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3424         }
3425 }
3426
3427 void R_HDR_RenderBloomTexture(void)
3428 {
3429         int oldwidth, oldheight;
3430         float oldcolorscale;
3431
3432         oldcolorscale = r_refdef.view.colorscale;
3433         oldwidth = r_refdef.view.width;
3434         oldheight = r_refdef.view.height;
3435         r_refdef.view.width = r_bloomstate.bloomwidth;
3436         r_refdef.view.height = r_bloomstate.bloomheight;
3437
3438         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
3439         // TODO: add exposure compensation features
3440         // TODO: add fp16 framebuffer support
3441
3442         r_refdef.view.showdebug = false;
3443         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3444
3445         R_ClearScreen(r_refdef.fogenabled);
3446         if (r_timereport_active)
3447                 R_TimeReport("HDRclear");
3448
3449         r_waterstate.numwaterplanes = 0;
3450         R_RenderScene(r_waterstate.enabled);
3451         r_refdef.view.showdebug = true;
3452
3453         R_ResetViewRendering2D();
3454
3455         R_Bloom_CopyHDRTexture();
3456         R_Bloom_MakeTexture();
3457
3458         // restore the view settings
3459         r_refdef.view.width = oldwidth;
3460         r_refdef.view.height = oldheight;
3461         r_refdef.view.colorscale = oldcolorscale;
3462
3463         R_ResetViewRendering3D();
3464
3465         R_ClearScreen(r_refdef.fogenabled);
3466         if (r_timereport_active)
3467                 R_TimeReport("viewclear");
3468 }
3469
3470 static void R_BlendView(void)
3471 {
3472         if (r_bloomstate.texture_screen)
3473         {
3474                 // copy view into the screen texture
3475                 R_ResetViewRendering2D();
3476                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3477                 R_Mesh_ColorPointer(NULL, 0, 0);
3478                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3479                 GL_ActiveTexture(0);CHECKGLERROR
3480                 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
3481                 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3482         }
3483
3484         if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
3485         {
3486                 unsigned int permutation =
3487                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
3488                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)
3489                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
3490                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0);
3491
3492                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
3493                 {
3494                         // render simple bloom effect
3495                         // copy the screen and shrink it and darken it for the bloom process
3496                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3497                         // make the bloom texture
3498                         R_Bloom_MakeTexture();
3499                 }
3500
3501                 R_ResetViewRendering2D();
3502                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3503                 R_Mesh_ColorPointer(NULL, 0, 0);
3504                 GL_Color(1, 1, 1, 1);
3505                 GL_BlendFunc(GL_ONE, GL_ZERO);
3506                 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
3507                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3508                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3509                 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
3510                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3511                 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
3512                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
3513                 if (r_glsl_permutation->loc_TintColor >= 0)
3514                         qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3515                 if (r_glsl_permutation->loc_ClientTime >= 0)
3516                         qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3517                 if (r_glsl_permutation->loc_PixelSize >= 0)
3518                         qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
3519                 if (r_glsl_permutation->loc_UserVec1 >= 0)
3520                 {
3521                         float a=0, b=0, c=0, d=0;
3522 #if _MSC_VER >= 1400
3523 #define sscanf sscanf_s
3524 #endif
3525                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
3526                         qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
3527                 }
3528                 if (r_glsl_permutation->loc_UserVec2 >= 0)
3529                 {
3530                         float a=0, b=0, c=0, d=0;
3531                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
3532                         qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
3533                 }
3534                 if (r_glsl_permutation->loc_UserVec3 >= 0)
3535                 {
3536                         float a=0, b=0, c=0, d=0;
3537                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
3538                         qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
3539                 }
3540                 if (r_glsl_permutation->loc_UserVec4 >= 0)
3541                 {
3542                         float a=0, b=0, c=0, d=0;
3543                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
3544                         qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
3545                 }
3546                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3547                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3548                 return;
3549         }
3550
3551
3552
3553         if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
3554         {
3555                 // render high dynamic range bloom effect
3556                 // the bloom texture was made earlier this render, so we just need to
3557                 // blend it onto the screen...
3558                 R_ResetViewRendering2D();
3559                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3560                 R_Mesh_ColorPointer(NULL, 0, 0);
3561                 R_SetupGenericShader(true);
3562                 GL_Color(1, 1, 1, 1);
3563                 GL_BlendFunc(GL_ONE, GL_ONE);
3564                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3565                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3566                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3567                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3568         }
3569         else if (r_bloomstate.texture_bloom)
3570         {
3571                 // render simple bloom effect
3572                 // copy the screen and shrink it and darken it for the bloom process
3573                 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3574                 // make the bloom texture
3575                 R_Bloom_MakeTexture();
3576                 // put the original screen image back in place and blend the bloom
3577                 // texture on it
3578                 R_ResetViewRendering2D();
3579                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3580                 R_Mesh_ColorPointer(NULL, 0, 0);
3581                 GL_Color(1, 1, 1, 1);
3582                 GL_BlendFunc(GL_ONE, GL_ZERO);
3583                 // do both in one pass if possible
3584                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3585                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3586                 if (r_textureunits.integer >= 2 && gl_combine.integer)
3587                 {
3588                         R_SetupGenericTwoTextureShader(GL_ADD);
3589                         R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3590                         R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3591                 }
3592                 else
3593                 {
3594                         R_SetupGenericShader(true);
3595                         R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3596                         r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3597                         // now blend on the bloom texture
3598                         GL_BlendFunc(GL_ONE, GL_ONE);
3599                         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3600                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3601                 }
3602                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3603                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3604         }
3605         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3606         {
3607                 // apply a color tint to the whole view
3608                 R_ResetViewRendering2D();
3609                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3610                 R_Mesh_ColorPointer(NULL, 0, 0);
3611                 R_SetupGenericShader(false);
3612                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3613                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3614                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3615         }
3616 }
3617
3618 void R_RenderScene(qboolean addwaterplanes);
3619
3620 matrix4x4_t r_waterscrollmatrix;
3621
3622 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3623 {
3624         if (r_refdef.fog_density)
3625         {
3626                 r_refdef.fogcolor[0] = r_refdef.fog_red;
3627                 r_refdef.fogcolor[1] = r_refdef.fog_green;
3628                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3629
3630                 {
3631                         vec3_t fogvec;
3632                         VectorCopy(r_refdef.fogcolor, fogvec);
3633                         if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3634                         {
3635                                 //   color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3636                                 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3637                                 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3638                                 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3639                         }
3640                         //   color.rgb *= ContrastBoost * SceneBrightness;
3641                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3642                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3643                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3644                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3645                 }
3646         }
3647 }
3648
3649 void R_UpdateVariables(void)
3650 {
3651         R_Textures_Frame();
3652
3653         r_refdef.scene.ambient = r_ambient.value;
3654
3655         r_refdef.farclip = 4096;
3656         if (r_refdef.scene.worldmodel)
3657                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
3658         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3659
3660         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3661                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3662         r_refdef.polygonfactor = 0;
3663         r_refdef.polygonoffset = 0;
3664         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3665         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3666
3667         r_refdef.scene.rtworld = r_shadow_realtime_world.integer;
3668         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3669         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3670         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3671         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3672         if (r_showsurfaces.integer)
3673         {
3674                 r_refdef.scene.rtworld = false;
3675                 r_refdef.scene.rtworldshadows = false;
3676                 r_refdef.scene.rtdlight = false;
3677                 r_refdef.scene.rtdlightshadows = false;
3678                 r_refdef.lightmapintensity = 0;
3679         }
3680
3681         if (gamemode == GAME_NEHAHRA)
3682         {
3683                 if (gl_fogenable.integer)
3684                 {
3685                         r_refdef.oldgl_fogenable = true;
3686                         r_refdef.fog_density = gl_fogdensity.value;
3687                         r_refdef.fog_red = gl_fogred.value;
3688                         r_refdef.fog_green = gl_foggreen.value;
3689                         r_refdef.fog_blue = gl_fogblue.value;
3690                         r_refdef.fog_alpha = 1;
3691                         r_refdef.fog_start = 0;
3692                         r_refdef.fog_end = gl_skyclip.value;
3693                 }
3694                 else if (r_refdef.oldgl_fogenable)
3695                 {
3696                         r_refdef.oldgl_fogenable = false;
3697                         r_refdef.fog_density = 0;
3698                         r_refdef.fog_red = 0;
3699                         r_refdef.fog_green = 0;
3700                         r_refdef.fog_blue = 0;
3701                         r_refdef.fog_alpha = 0;
3702                         r_refdef.fog_start = 0;
3703                         r_refdef.fog_end = 0;
3704                 }
3705         }
3706
3707         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
3708         r_refdef.fog_start = max(0, r_refdef.fog_start);
3709         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
3710
3711         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
3712
3713         if (r_refdef.fog_density && r_drawfog.integer)
3714         {
3715                 r_refdef.fogenabled = true;
3716                 // this is the point where the fog reaches 0.9986 alpha, which we
3717                 // consider a good enough cutoff point for the texture
3718                 // (0.9986 * 256 == 255.6)
3719                 if (r_fog_exp2.integer)
3720                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
3721                 else
3722                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
3723                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
3724                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3725                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3726                 // fog color was already set
3727                 // update the fog texture
3728                 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)
3729                         R_BuildFogTexture();
3730         }
3731         else
3732                 r_refdef.fogenabled = false;
3733
3734         if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
3735         {
3736                 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
3737                 {
3738                         // build GLSL gamma texture
3739 #define RAMPWIDTH 256
3740                         unsigned short ramp[RAMPWIDTH * 3];
3741                         unsigned char ramprgb[RAMPWIDTH][4];
3742                         int i;
3743
3744                         r_texture_gammaramps_serial = vid_gammatables_serial;
3745
3746                         VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
3747                         for(i = 0; i < RAMPWIDTH; ++i)
3748                         {
3749                                 ramprgb[i][0] = ramp[i] >> 8;
3750                                 ramprgb[i][1] = ramp[i + RAMPWIDTH] >> 8;
3751                                 ramprgb[i][2] = ramp[i + 2 * RAMPWIDTH] >> 8;
3752                                 ramprgb[i][3] = 0;
3753                         }
3754                         if (r_texture_gammaramps)
3755                         {
3756                                 R_UpdateTexture(r_texture_gammaramps, &ramprgb[0][0], 0, 0, RAMPWIDTH, 1);
3757                         }
3758                         else
3759                         {
3760                                 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);
3761                         }
3762                 }
3763         }
3764         else
3765         {
3766                 // remove GLSL gamma texture
3767         }
3768 }
3769
3770 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
3771 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
3772 /*
3773 ================
3774 R_SelectScene
3775 ================
3776 */
3777 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
3778         if( scenetype != r_currentscenetype ) {
3779                 // store the old scenetype
3780                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
3781                 r_currentscenetype = scenetype;
3782                 // move in the new scene
3783                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
3784         }
3785 }
3786
3787 /*
3788 ================
3789 R_GetScenePointer
3790 ================
3791 */
3792 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
3793 {
3794         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
3795         if( scenetype == r_currentscenetype ) {
3796                 return &r_refdef.scene;
3797         } else {
3798                 return &r_scenes_store[ scenetype ];
3799         }
3800 }
3801
3802 /*
3803 ================
3804 R_RenderView
3805 ================
3806 */
3807 void R_RenderView(void)
3808 {
3809         if (r_refdef.view.isoverlay)
3810         {
3811                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
3812                 GL_Clear( GL_DEPTH_BUFFER_BIT );
3813                 R_TimeReport("depthclear");
3814
3815                 r_refdef.view.showdebug = false;
3816
3817                 r_waterstate.enabled = false;
3818                 r_waterstate.numwaterplanes = 0;
3819
3820                 R_RenderScene(false);
3821
3822                 CHECKGLERROR
3823                 return;
3824         }
3825
3826         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
3827                 return; //Host_Error ("R_RenderView: NULL worldmodel");
3828
3829         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
3830
3831         // break apart the view matrix into vectors for various purposes
3832         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
3833         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
3834         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
3835         VectorNegate(r_refdef.view.left, r_refdef.view.right);
3836         // make an inverted copy of the view matrix for tracking sprites
3837         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
3838
3839         R_Shadow_UpdateWorldLightSelection();
3840
3841         R_Bloom_StartFrame();
3842         R_Water_StartFrame();
3843
3844         CHECKGLERROR
3845         if (r_timereport_active)
3846                 R_TimeReport("viewsetup");
3847
3848         R_ResetViewRendering3D();
3849
3850         if (r_refdef.view.clear || r_refdef.fogenabled)
3851         {
3852                 R_ClearScreen(r_refdef.fogenabled);
3853                 if (r_timereport_active)
3854                         R_TimeReport("viewclear");
3855         }
3856         r_refdef.view.clear = true;
3857
3858         r_refdef.view.showdebug = true;
3859
3860         // this produces a bloom texture to be used in R_BlendView() later
3861         if (r_hdr.integer)
3862                 R_HDR_RenderBloomTexture();
3863
3864         r_waterstate.numwaterplanes = 0;
3865         R_RenderScene(r_waterstate.enabled);
3866
3867         R_BlendView();
3868         if (r_timereport_active)
3869                 R_TimeReport("blendview");
3870
3871         GL_Scissor(0, 0, vid.width, vid.height);
3872         GL_ScissorTest(false);
3873         CHECKGLERROR
3874 }
3875
3876 extern void R_DrawLightningBeams (void);
3877 extern void VM_CL_AddPolygonsToMeshQueue (void);
3878 extern void R_DrawPortals (void);
3879 extern cvar_t cl_locs_show;
3880 static void R_DrawLocs(void);
3881 static void R_DrawEntityBBoxes(void);
3882 void R_RenderScene(qboolean addwaterplanes)
3883 {
3884         r_refdef.stats.renders++;
3885
3886         R_UpdateFogColor();
3887
3888         if (addwaterplanes)
3889         {
3890                 R_ResetViewRendering3D();
3891
3892                 R_View_Update();
3893                 if (r_timereport_active)
3894                         R_TimeReport("watervis");
3895
3896                 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
3897                 {
3898                         r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
3899                         if (r_timereport_active)
3900                                 R_TimeReport("waterworld");
3901                 }
3902
3903                 // don't let sound skip if going slow
3904                 if (r_refdef.scene.extraupdate)
3905                         S_ExtraUpdate ();
3906
3907                 R_DrawModelsAddWaterPlanes();
3908                 if (r_timereport_active)
3909                         R_TimeReport("watermodels");
3910
3911                 R_Water_ProcessPlanes();
3912                 if (r_timereport_active)
3913                         R_TimeReport("waterscenes");
3914         }
3915
3916         R_ResetViewRendering3D();
3917
3918         // don't let sound skip if going slow
3919         if (r_refdef.scene.extraupdate)
3920                 S_ExtraUpdate ();
3921
3922         R_MeshQueue_BeginScene();
3923
3924         R_SkyStartFrame();
3925
3926         R_View_Update();
3927         if (r_timereport_active)
3928                 R_TimeReport("visibility");
3929
3930         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);
3931
3932         if (cl.csqc_vidvars.drawworld)
3933         {
3934                 // don't let sound skip if going slow
3935                 if (r_refdef.scene.extraupdate)
3936                         S_ExtraUpdate ();
3937
3938                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
3939                 {
3940                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
3941                         if (r_timereport_active)
3942                                 R_TimeReport("worldsky");
3943                 }
3944
3945                 if (R_DrawBrushModelsSky() && r_timereport_active)
3946                         R_TimeReport("bmodelsky");
3947         }
3948
3949         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
3950         {
3951                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
3952                 if (r_timereport_active)
3953                         R_TimeReport("worlddepth");
3954         }
3955         if (r_depthfirst.integer >= 2)
3956         {
3957                 R_DrawModelsDepth();
3958                 if (r_timereport_active)
3959                         R_TimeReport("modeldepth");
3960         }
3961
3962         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
3963         {
3964                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
3965                 if (r_timereport_active)
3966                         R_TimeReport("world");
3967         }
3968
3969         // don't let sound skip if going slow
3970         if (r_refdef.scene.extraupdate)
3971                 S_ExtraUpdate ();
3972
3973         R_DrawModels();
3974         if (r_timereport_active)
3975                 R_TimeReport("models");
3976
3977         // don't let sound skip if going slow
3978         if (r_refdef.scene.extraupdate)
3979                 S_ExtraUpdate ();
3980
3981         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3982         {
3983                 R_DrawModelShadows();
3984
3985                 R_ResetViewRendering3D();
3986
3987                 // don't let sound skip if going slow
3988                 if (r_refdef.scene.extraupdate)
3989                         S_ExtraUpdate ();
3990         }
3991
3992         R_ShadowVolumeLighting(false);
3993         if (r_timereport_active)
3994                 R_TimeReport("rtlights");
3995
3996         // don't let sound skip if going slow
3997         if (r_refdef.scene.extraupdate)
3998                 S_ExtraUpdate ();
3999
4000         if (cl.csqc_vidvars.drawworld)
4001         {
4002                 R_DrawLightningBeams();
4003                 if (r_timereport_active)
4004                         R_TimeReport("lightning");
4005
4006                 R_DrawDecals();
4007                 if (r_timereport_active)
4008                         R_TimeReport("decals");
4009
4010                 R_DrawParticles();
4011                 if (r_timereport_active)
4012                         R_TimeReport("particles");
4013
4014                 R_DrawExplosions();
4015                 if (r_timereport_active)
4016                         R_TimeReport("explosions");
4017         }
4018
4019         R_SetupGenericShader(true);
4020         VM_CL_AddPolygonsToMeshQueue();
4021
4022         if (r_refdef.view.showdebug)
4023         {
4024                 if (cl_locs_show.integer)
4025                 {
4026                         R_DrawLocs();
4027                         if (r_timereport_active)
4028                                 R_TimeReport("showlocs");
4029                 }
4030
4031                 if (r_drawportals.integer)
4032                 {
4033                         R_DrawPortals();
4034                         if (r_timereport_active)
4035                                 R_TimeReport("portals");
4036                 }
4037
4038                 if (r_showbboxes.value > 0)
4039                 {
4040                         R_DrawEntityBBoxes();
4041                         if (r_timereport_active)
4042                                 R_TimeReport("bboxes");
4043                 }
4044         }
4045
4046         R_SetupGenericShader(true);
4047         R_MeshQueue_RenderTransparent();
4048         if (r_timereport_active)
4049                 R_TimeReport("drawtrans");
4050
4051         R_SetupGenericShader(true);
4052
4053         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))
4054         {
4055                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4056                 if (r_timereport_active)
4057                         R_TimeReport("worlddebug");
4058                 R_DrawModelsDebug();
4059                 if (r_timereport_active)
4060                         R_TimeReport("modeldebug");
4061         }
4062
4063         R_SetupGenericShader(true);
4064
4065         if (cl.csqc_vidvars.drawworld)
4066         {
4067                 R_DrawCoronas();
4068                 if (r_timereport_active)
4069                         R_TimeReport("coronas");
4070         }
4071
4072         // don't let sound skip if going slow
4073         if (r_refdef.scene.extraupdate)
4074                 S_ExtraUpdate ();
4075
4076         R_ResetViewRendering2D();
4077 }
4078
4079 static const unsigned short bboxelements[36] =
4080 {
4081         5, 1, 3, 5, 3, 7,
4082         6, 2, 0, 6, 0, 4,
4083         7, 3, 2, 7, 2, 6,
4084         4, 0, 1, 4, 1, 5,
4085         4, 5, 7, 4, 7, 6,
4086         1, 0, 2, 1, 2, 3,
4087 };
4088
4089 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4090 {
4091         int i;
4092         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4093         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4094         GL_DepthMask(false);
4095         GL_DepthRange(0, 1);
4096         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4097         R_Mesh_Matrix(&identitymatrix);
4098         R_Mesh_ResetTextureState();
4099
4100         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4101         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4102         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4103         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4104         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4105         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4106         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4107         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4108         R_FillColors(color4f, 8, cr, cg, cb, ca);
4109         if (r_refdef.fogenabled)
4110         {
4111                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4112                 {
4113                         f1 = FogPoint_World(v);
4114                         f2 = 1 - f1;
4115                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4116                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4117                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4118                 }
4119         }
4120         R_Mesh_VertexPointer(vertex3f, 0, 0);
4121         R_Mesh_ColorPointer(color4f, 0, 0);
4122         R_Mesh_ResetTextureState();
4123         R_SetupGenericShader(false);
4124         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4125 }
4126
4127 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4128 {
4129         int i;
4130         float color[4];
4131         prvm_edict_t *edict;
4132         prvm_prog_t *prog_save = prog;
4133
4134         // this function draws bounding boxes of server entities
4135         if (!sv.active)
4136                 return;
4137
4138         GL_CullFace(GL_NONE);
4139         R_SetupGenericShader(false);
4140
4141         prog = 0;
4142         SV_VM_Begin();
4143         for (i = 0;i < numsurfaces;i++)
4144         {
4145                 edict = PRVM_EDICT_NUM(surfacelist[i]);
4146                 switch ((int)edict->fields.server->solid)
4147                 {
4148                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
4149                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
4150                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
4151                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4152                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
4153                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
4154                 }
4155                 color[3] *= r_showbboxes.value;
4156                 color[3] = bound(0, color[3], 1);
4157                 GL_DepthTest(!r_showdisabledepthtest.integer);
4158                 GL_CullFace(r_refdef.view.cullface_front);
4159                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4160         }
4161         SV_VM_End();
4162         prog = prog_save;
4163 }
4164
4165 static void R_DrawEntityBBoxes(void)
4166 {
4167         int i;
4168         prvm_edict_t *edict;
4169         vec3_t center;
4170         prvm_prog_t *prog_save = prog;
4171
4172         // this function draws bounding boxes of server entities
4173         if (!sv.active)
4174                 return;
4175
4176         prog = 0;
4177         SV_VM_Begin();
4178         for (i = 0;i < prog->num_edicts;i++)
4179         {
4180                 edict = PRVM_EDICT_NUM(i);
4181                 if (edict->priv.server->free)
4182                         continue;
4183                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
4184                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
4185                         continue;
4186                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
4187                         continue;
4188                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4189                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4190         }
4191         SV_VM_End();
4192         prog = prog_save;
4193 }
4194
4195 unsigned short nomodelelements[24] =
4196 {
4197         5, 2, 0,
4198         5, 1, 2,
4199         5, 0, 3,
4200         5, 3, 1,
4201         0, 2, 4,
4202         2, 1, 4,
4203         3, 0, 4,
4204         1, 3, 4
4205 };
4206
4207 float nomodelvertex3f[6*3] =
4208 {
4209         -16,   0,   0,
4210          16,   0,   0,
4211           0, -16,   0,
4212           0,  16,   0,
4213           0,   0, -16,
4214           0,   0,  16
4215 };
4216
4217 float nomodelcolor4f[6*4] =
4218 {
4219         0.0f, 0.0f, 0.5f, 1.0f,
4220         0.0f, 0.0f, 0.5f, 1.0f,
4221         0.0f, 0.5f, 0.0f, 1.0f,
4222         0.0f, 0.5f, 0.0f, 1.0f,
4223         0.5f, 0.0f, 0.0f, 1.0f,
4224         0.5f, 0.0f, 0.0f, 1.0f
4225 };
4226
4227 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4228 {
4229         int i;
4230         float f1, f2, *c;
4231         float color4f[6*4];
4232         // this is only called once per entity so numsurfaces is always 1, and
4233         // surfacelist is always {0}, so this code does not handle batches
4234         R_Mesh_Matrix(&ent->matrix);
4235
4236         if (ent->flags & EF_ADDITIVE)
4237         {
4238                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4239                 GL_DepthMask(false);
4240         }
4241         else if (ent->alpha < 1)
4242         {
4243                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4244                 GL_DepthMask(false);
4245         }
4246         else
4247         {
4248                 GL_BlendFunc(GL_ONE, GL_ZERO);
4249                 GL_DepthMask(true);
4250         }
4251         GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4252         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4253         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4254         GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4255         R_SetupGenericShader(false);
4256         R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4257         if (r_refdef.fogenabled)
4258         {
4259                 vec3_t org;
4260                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4261                 R_Mesh_ColorPointer(color4f, 0, 0);
4262                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4263                 f1 = FogPoint_World(org);
4264                 f2 = 1 - f1;
4265                 for (i = 0, c = color4f;i < 6;i++, c += 4)
4266                 {
4267                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4268                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4269                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4270                         c[3] *= ent->alpha;
4271                 }
4272         }
4273         else if (ent->alpha != 1)
4274         {
4275                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4276                 R_Mesh_ColorPointer(color4f, 0, 0);
4277                 for (i = 0, c = color4f;i < 6;i++, c += 4)
4278                         c[3] *= ent->alpha;
4279         }
4280         else
4281                 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4282         R_Mesh_ResetTextureState();
4283         R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
4284 }
4285
4286 void R_DrawNoModel(entity_render_t *ent)
4287 {
4288         vec3_t org;
4289         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4290         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4291                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4292         //else
4293         //      R_DrawNoModelCallback(ent, 0);
4294 }
4295
4296 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4297 {
4298         vec3_t right1, right2, diff, normal;
4299
4300         VectorSubtract (org2, org1, normal);
4301
4302         // calculate 'right' vector for start
4303         VectorSubtract (r_refdef.view.origin, org1, diff);
4304         CrossProduct (normal, diff, right1);
4305         VectorNormalize (right1);
4306
4307         // calculate 'right' vector for end
4308         VectorSubtract (r_refdef.view.origin, org2, diff);
4309         CrossProduct (normal, diff, right2);
4310         VectorNormalize (right2);
4311
4312         vert[ 0] = org1[0] + width * right1[0];
4313         vert[ 1] = org1[1] + width * right1[1];
4314         vert[ 2] = org1[2] + width * right1[2];
4315         vert[ 3] = org1[0] - width * right1[0];
4316         vert[ 4] = org1[1] - width * right1[1];
4317         vert[ 5] = org1[2] - width * right1[2];
4318         vert[ 6] = org2[0] - width * right2[0];
4319         vert[ 7] = org2[1] - width * right2[1];
4320         vert[ 8] = org2[2] - width * right2[2];
4321         vert[ 9] = org2[0] + width * right2[0];
4322         vert[10] = org2[1] + width * right2[1];
4323         vert[11] = org2[2] + width * right2[2];
4324 }
4325
4326 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4327
4328 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)
4329 {
4330         float fog = 1.0f;
4331         float vertex3f[12];
4332
4333         if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4334                 fog = FogPoint_World(origin);
4335
4336         R_Mesh_Matrix(&identitymatrix);
4337         GL_BlendFunc(blendfunc1, blendfunc2);
4338
4339         if(v_flipped_state)
4340         {
4341                 scalex1 = -scalex1;
4342                 scalex2 = -scalex2;
4343                 GL_CullFace(r_refdef.view.cullface_front);
4344         }
4345         else
4346                 GL_CullFace(r_refdef.view.cullface_back);
4347         GL_CullFace(GL_NONE);
4348
4349         GL_DepthMask(false);
4350         GL_DepthRange(0, depthshort ? 0.0625 : 1);
4351         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4352         GL_DepthTest(!depthdisable);
4353
4354         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4355         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4356         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4357         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
4358         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
4359         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
4360         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
4361         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
4362         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
4363         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
4364         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
4365         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
4366
4367         R_Mesh_VertexPointer(vertex3f, 0, 0);
4368         R_Mesh_ColorPointer(NULL, 0, 0);
4369         R_Mesh_ResetTextureState();
4370         R_SetupGenericShader(true);
4371         R_Mesh_TexBind(0, R_GetTexture(texture));
4372         R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
4373         // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
4374         GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
4375         R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4376
4377         if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
4378         {
4379                 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
4380                 GL_BlendFunc(blendfunc1, GL_ONE);
4381                 fog = 1 - fog;
4382                 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
4383                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4384         }
4385 }
4386
4387 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
4388 {
4389         int i;
4390         float *vertex3f;
4391         float v[3];
4392         VectorSet(v, x, y, z);
4393         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
4394                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
4395                         break;
4396         if (i == mesh->numvertices)
4397         {
4398                 if (mesh->numvertices < mesh->maxvertices)
4399                 {
4400                         VectorCopy(v, vertex3f);
4401                         mesh->numvertices++;
4402                 }
4403                 return mesh->numvertices;
4404         }
4405         else
4406                 return i;
4407 }
4408
4409 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
4410 {
4411         int i;
4412         int *e, element[3];
4413         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4414         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4415         e = mesh->element3i + mesh->numtriangles * 3;
4416         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
4417         {
4418                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
4419                 if (mesh->numtriangles < mesh->maxtriangles)
4420                 {
4421                         *e++ = element[0];
4422                         *e++ = element[1];
4423                         *e++ = element[2];
4424                         mesh->numtriangles++;
4425                 }
4426                 element[1] = element[2];
4427         }
4428 }
4429
4430 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
4431 {
4432         int i;
4433         int *e, element[3];
4434         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4435         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4436         e = mesh->element3i + mesh->numtriangles * 3;
4437         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
4438         {
4439                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
4440                 if (mesh->numtriangles < mesh->maxtriangles)
4441                 {
4442                         *e++ = element[0];
4443                         *e++ = element[1];
4444                         *e++ = element[2];
4445                         mesh->numtriangles++;
4446                 }
4447                 element[1] = element[2];
4448         }
4449 }
4450
4451 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
4452 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
4453 {
4454         int planenum, planenum2;
4455         int w;
4456         int tempnumpoints;
4457         mplane_t *plane, *plane2;
4458         double maxdist;
4459         double temppoints[2][256*3];
4460         // figure out how large a bounding box we need to properly compute this brush
4461         maxdist = 0;
4462         for (w = 0;w < numplanes;w++)
4463                 maxdist = max(maxdist, planes[w].dist);
4464         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4465         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4466         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4467         {
4468                 w = 0;
4469                 tempnumpoints = 4;
4470                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4471                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4472                 {
4473                         if (planenum2 == planenum)
4474                                 continue;
4475                         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);
4476                         w = !w;
4477                 }
4478                 if (tempnumpoints < 3)
4479                         continue;
4480                 // generate elements forming a triangle fan for this polygon
4481                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4482         }
4483 }
4484
4485 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)
4486 {
4487         texturelayer_t *layer;
4488         layer = t->currentlayers + t->currentnumlayers++;
4489         layer->type = type;
4490         layer->depthmask = depthmask;
4491         layer->blendfunc1 = blendfunc1;
4492         layer->blendfunc2 = blendfunc2;
4493         layer->texture = texture;
4494         layer->texmatrix = *matrix;
4495         layer->color[0] = r * r_refdef.view.colorscale;
4496         layer->color[1] = g * r_refdef.view.colorscale;
4497         layer->color[2] = b * r_refdef.view.colorscale;
4498         layer->color[3] = a;
4499 }
4500
4501 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4502 {
4503         double index, f;
4504         index = parms[2] + r_refdef.scene.time * parms[3];
4505         index -= floor(index);
4506         switch (func)
4507         {
4508         default:
4509         case Q3WAVEFUNC_NONE:
4510         case Q3WAVEFUNC_NOISE:
4511         case Q3WAVEFUNC_COUNT:
4512                 f = 0;
4513                 break;
4514         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4515         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4516         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4517         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4518         case Q3WAVEFUNC_TRIANGLE:
4519                 index *= 4;
4520                 f = index - floor(index);
4521                 if (index < 1)
4522                         f = f;
4523                 else if (index < 2)
4524                         f = 1 - f;
4525                 else if (index < 3)
4526                         f = -f;
4527                 else
4528                         f = -(1 - f);
4529                 break;
4530         }
4531         return (float)(parms[0] + parms[1] * f);
4532 }
4533
4534 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
4535 {
4536         int w, h, idx;
4537         int i;
4538         dp_model_t *model = ent->model;
4539         float f;
4540         float tcmat[12];
4541         q3shaderinfo_layer_tcmod_t *tcmod;
4542
4543         if (t->basematerialflags & MATERIALFLAG_NODRAW)
4544         {
4545                 t->currentmaterialflags = MATERIALFLAG_NODRAW;
4546                 return;
4547         }
4548
4549         // switch to an alternate material if this is a q1bsp animated material
4550         {
4551                 texture_t *texture = t;
4552                 int s = ent->skinnum;
4553                 if ((unsigned int)s >= (unsigned int)model->numskins)
4554                         s = 0;
4555                 if (model->skinscenes)
4556                 {
4557                         if (model->skinscenes[s].framecount > 1)
4558                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4559                         else
4560                                 s = model->skinscenes[s].firstframe;
4561                 }
4562                 if (s > 0)
4563                         t = t + s * model->num_surfaces;
4564                 if (t->animated)
4565                 {
4566                         // use an alternate animation if the entity's frame is not 0,
4567                         // and only if the texture has an alternate animation
4568                         if (ent->frame2 != 0 && t->anim_total[1])
4569                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4570                         else
4571                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4572                 }
4573                 texture->currentframe = t;
4574         }
4575
4576         // update currentskinframe to be a qw skin or animation frame
4577         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"))
4578         {
4579                 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4580                 {
4581                         strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4582                         if (developer_loading.integer)
4583                                 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
4584                         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);
4585                 }
4586                 t->currentskinframe = r_qwskincache_skinframe[i];
4587                 if (t->currentskinframe == NULL)
4588                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4589         }
4590         else if (t->numskinframes >= 2)
4591                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4592         if (t->backgroundnumskinframes >= 2)
4593                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
4594
4595         t->currentmaterialflags = t->basematerialflags;
4596         t->currentalpha = ent->alpha;
4597         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4598                 t->currentalpha *= r_wateralpha.value;
4599         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
4600                 t->currentalpha *= t->r_water_wateralpha;
4601         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
4602                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4603         if (!(ent->flags & RENDER_LIGHT))
4604                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4605         else if (rsurface.modeltexcoordlightmap2f == NULL)
4606         {
4607                 // pick a model lighting mode
4608                 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4609                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4610                 else
4611                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4612         }
4613         if (ent->effects & EF_ADDITIVE)
4614                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4615         else if (t->currentalpha < 1)
4616                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4617         if (ent->effects & EF_DOUBLESIDED)
4618                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4619         if (ent->effects & EF_NODEPTHTEST)
4620                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4621         if (ent->flags & RENDER_VIEWMODEL)
4622                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4623         if (t->backgroundnumskinframes)
4624                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4625         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
4626         {
4627                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
4628                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
4629         }
4630         else
4631                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
4632
4633         // there is no tcmod
4634         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4635                 t->currenttexmatrix = r_waterscrollmatrix;
4636
4637         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4638         {
4639                 matrix4x4_t matrix;
4640                 switch(tcmod->tcmod)
4641                 {
4642                 case Q3TCMOD_COUNT:
4643                 case Q3TCMOD_NONE:
4644                         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4645                                 matrix = r_waterscrollmatrix;
4646                         else
4647                                 matrix = identitymatrix;
4648                         break;
4649                 case Q3TCMOD_ENTITYTRANSLATE:
4650                         // this is used in Q3 to allow the gamecode to control texcoord
4651                         // scrolling on the entity, which is not supported in darkplaces yet.
4652                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4653                         break;
4654                 case Q3TCMOD_ROTATE:
4655                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4656                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4657                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4658                         break;
4659                 case Q3TCMOD_SCALE:
4660                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4661                         break;
4662                 case Q3TCMOD_SCROLL:
4663                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4664                         break;
4665                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
4666                         w = tcmod->parms[0];
4667                         h = tcmod->parms[1];
4668                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
4669                         f = f - floor(f);
4670                         idx = floor(f * w * h);
4671                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
4672                         break;
4673                 case Q3TCMOD_STRETCH:
4674                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4675                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4676                         break;
4677                 case Q3TCMOD_TRANSFORM:
4678                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
4679                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
4680                         VectorSet(tcmat +  6, 0                   , 0                , 1);
4681                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
4682                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4683                         break;
4684                 case Q3TCMOD_TURBULENT:
4685                         // this is handled in the RSurf_PrepareVertices function
4686                         matrix = identitymatrix;
4687                         break;
4688                 }
4689                 // either replace or concatenate the transformation
4690                 if (i < 1)
4691                         t->currenttexmatrix = matrix;
4692                 else
4693                 {
4694                         matrix4x4_t temp = t->currenttexmatrix;
4695                         Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4696                 }
4697         }
4698
4699         t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4700         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4701         t->glosstexture = r_texture_black;
4702         t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4703         t->backgroundglosstexture = r_texture_black;
4704         t->specularpower = r_shadow_glossexponent.value;
4705         // TODO: store reference values for these in the texture?
4706         t->specularscale = 0;
4707         if (r_shadow_gloss.integer > 0)
4708         {
4709                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4710                 {
4711                         if (r_shadow_glossintensity.value > 0)
4712                         {
4713                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4714                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4715                                 t->specularscale = r_shadow_glossintensity.value;
4716                         }
4717                 }
4718                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4719                 {
4720                         t->glosstexture = r_texture_white;
4721                         t->backgroundglosstexture = r_texture_white;
4722                         t->specularscale = r_shadow_gloss2intensity.value;
4723                 }
4724         }
4725
4726         // lightmaps mode looks bad with dlights using actual texturing, so turn
4727         // off the colormap and glossmap, but leave the normalmap on as it still
4728         // accurately represents the shading involved
4729         if (gl_lightmaps.integer)
4730         {
4731                 t->basetexture = r_texture_grey128;
4732                 t->backgroundbasetexture = NULL;
4733                 t->specularscale = 0;
4734                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
4735         }
4736
4737         Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4738         VectorClear(t->dlightcolor);
4739         t->currentnumlayers = 0;
4740         if (t->currentmaterialflags & MATERIALFLAG_WALL)
4741         {
4742                 int layerflags = 0;
4743                 int blendfunc1, blendfunc2, depthmask;
4744                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4745                 {
4746                         blendfunc1 = GL_SRC_ALPHA;
4747                         blendfunc2 = GL_ONE;
4748                 }
4749                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4750                 {
4751                         blendfunc1 = GL_SRC_ALPHA;
4752                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4753                 }
4754                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4755                 {
4756                         blendfunc1 = t->customblendfunc[0];
4757                         blendfunc2 = t->customblendfunc[1];
4758                 }
4759                 else
4760                 {
4761                         blendfunc1 = GL_ONE;
4762                         blendfunc2 = GL_ZERO;
4763                 }
4764                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4765                 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4766                         layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4767                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4768                 {
4769                         // fullbright is not affected by r_refdef.lightmapintensity
4770                         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]);
4771                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4772                                 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]);
4773                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4774                                 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]);
4775                 }
4776                 else
4777                 {
4778                         vec3_t ambientcolor;
4779                         float colorscale;
4780                         // set the color tint used for lights affecting this surface
4781                         VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
4782                         colorscale = 2;
4783                         // q3bsp has no lightmap updates, so the lightstylevalue that
4784                         // would normally be baked into the lightmap must be
4785                         // applied to the color
4786                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4787                         if (ent->model->type == mod_brushq3)
4788                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
4789                         colorscale *= r_refdef.lightmapintensity;
4790                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
4791                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4792                         // basic lit geometry
4793                         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]);
4794                         // add pants/shirt if needed
4795                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4796                                 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]);
4797                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4798                                 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]);
4799                         // now add ambient passes if needed
4800                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
4801                         {
4802                                 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]);
4803                                 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4804                                         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]);
4805                                 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4806                                         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]);
4807                         }
4808                 }
4809                 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
4810                         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]);
4811                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4812                 {
4813                         // if this is opaque use alpha blend which will darken the earlier
4814                         // passes cheaply.
4815                         //
4816                         // if this is an alpha blended material, all the earlier passes
4817                         // were darkened by fog already, so we only need to add the fog
4818                         // color ontop through the fog mask texture
4819                         //
4820                         // if this is an additive blended material, all the earlier passes
4821                         // were darkened by fog already, and we should not add fog color
4822                         // (because the background was not darkened, there is no fog color
4823                         // that was lost behind it).
4824                         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]);
4825                 }
4826         }
4827 }
4828
4829 void R_UpdateAllTextureInfo(entity_render_t *ent)
4830 {
4831         int i;
4832         if (ent->model)
4833                 for (i = 0;i < ent->model->num_texturesperskin;i++)
4834                         R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4835 }
4836
4837 rsurfacestate_t rsurface;
4838
4839 void R_Mesh_ResizeArrays(int newvertices)
4840 {
4841         float *base;
4842         if (rsurface.array_size >= newvertices)
4843                 return;
4844         if (rsurface.array_modelvertex3f)
4845                 Mem_Free(rsurface.array_modelvertex3f);
4846         rsurface.array_size = (newvertices + 1023) & ~1023;
4847         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4848         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
4849         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
4850         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
4851         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
4852         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
4853         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4854         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4855         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
4856         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
4857         rsurface.array_color4f           = base + rsurface.array_size * 27;
4858         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4859 }
4860
4861 void RSurf_ActiveWorldEntity(void)
4862 {
4863         dp_model_t *model = r_refdef.scene.worldmodel;
4864         if (rsurface.array_size < model->surfmesh.num_vertices)
4865                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4866         rsurface.matrix = identitymatrix;
4867         rsurface.inversematrix = identitymatrix;
4868         R_Mesh_Matrix(&identitymatrix);
4869         VectorCopy(r_refdef.view.origin, rsurface.modelorg);
4870         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4871         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4872         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4873         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4874         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4875         rsurface.frameblend[0].frame = 0;
4876         rsurface.frameblend[0].lerp = 1;
4877         rsurface.frameblend[1].frame = 0;
4878         rsurface.frameblend[1].lerp = 0;
4879         rsurface.frameblend[2].frame = 0;
4880         rsurface.frameblend[2].lerp = 0;
4881         rsurface.frameblend[3].frame = 0;
4882         rsurface.frameblend[3].lerp = 0;
4883         rsurface.basepolygonfactor = r_refdef.polygonfactor;
4884         rsurface.basepolygonoffset = r_refdef.polygonoffset;
4885         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
4886         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4887         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4888         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4889         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4890         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4891         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4892         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4893         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4894         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
4895         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4896         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4897         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
4898         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4899         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4900         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
4901         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4902         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4903         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
4904         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4905         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4906         rsurface.modelelement3i = model->surfmesh.data_element3i;
4907         rsurface.modelelement3s = model->surfmesh.data_element3s;
4908         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
4909         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
4910         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4911         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4912         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4913         rsurface.modelsurfaces = model->data_surfaces;
4914         rsurface.generatedvertex = false;
4915         rsurface.vertex3f  = rsurface.modelvertex3f;
4916         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4917         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4918         rsurface.svector3f = rsurface.modelsvector3f;
4919         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4920         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4921         rsurface.tvector3f = rsurface.modeltvector3f;
4922         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4923         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4924         rsurface.normal3f  = rsurface.modelnormal3f;
4925         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4926         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4927         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4928 }
4929
4930 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4931 {
4932         dp_model_t *model = ent->model;
4933         if (rsurface.array_size < model->surfmesh.num_vertices)
4934                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4935         rsurface.matrix = ent->matrix;
4936         rsurface.inversematrix = ent->inversematrix;
4937         R_Mesh_Matrix(&rsurface.matrix);
4938         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
4939         rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
4940         rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
4941         rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
4942         rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
4943         rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
4944         rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
4945         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4946         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4947         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4948         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4949         rsurface.frameblend[0] = ent->frameblend[0];
4950         rsurface.frameblend[1] = ent->frameblend[1];
4951         rsurface.frameblend[2] = ent->frameblend[2];
4952         rsurface.frameblend[3] = ent->frameblend[3];
4953         rsurface.basepolygonfactor = r_refdef.polygonfactor;
4954         rsurface.basepolygonoffset = r_refdef.polygonoffset;
4955         if (ent->model->brush.submodel)
4956         {
4957                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
4958                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
4959         }
4960         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4961         {
4962                 if (wanttangents)
4963                 {
4964                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4965                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4966                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4967                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4968                         model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4969                 }
4970                 else if (wantnormals)
4971                 {
4972                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4973                         rsurface.modelsvector3f = NULL;
4974                         rsurface.modeltvector3f = NULL;
4975                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4976                         model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4977                 }
4978                 else
4979                 {
4980                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4981                         rsurface.modelsvector3f = NULL;
4982                         rsurface.modeltvector3f = NULL;
4983                         rsurface.modelnormal3f = NULL;
4984                         model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4985                 }
4986                 rsurface.modelvertex3f_bufferobject = 0;
4987                 rsurface.modelvertex3f_bufferoffset = 0;
4988                 rsurface.modelsvector3f_bufferobject = 0;
4989                 rsurface.modelsvector3f_bufferoffset = 0;
4990                 rsurface.modeltvector3f_bufferobject = 0;
4991                 rsurface.modeltvector3f_bufferoffset = 0;
4992                 rsurface.modelnormal3f_bufferobject = 0;
4993                 rsurface.modelnormal3f_bufferoffset = 0;
4994                 rsurface.generatedvertex = true;
4995         }
4996         else
4997         {
4998                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
4999                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5000                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5001                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5002                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5003                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5004                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5005                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5006                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5007                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
5008                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5009                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5010                 rsurface.generatedvertex = false;
5011         }
5012         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
5013         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5014         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5015         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
5016         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5017         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5018         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
5019         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5020         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5021         rsurface.modelelement3i = model->surfmesh.data_element3i;
5022         rsurface.modelelement3s = model->surfmesh.data_element3s;
5023         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5024         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5025         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5026         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5027         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5028         rsurface.modelsurfaces = model->data_surfaces;
5029         rsurface.vertex3f  = rsurface.modelvertex3f;
5030         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5031         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5032         rsurface.svector3f = rsurface.modelsvector3f;
5033         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5034         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5035         rsurface.tvector3f = rsurface.modeltvector3f;
5036         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5037         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5038         rsurface.normal3f  = rsurface.modelnormal3f;
5039         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5040         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5041         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5042 }
5043
5044 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5045 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5046 {
5047         int deformindex;
5048         int texturesurfaceindex;
5049         int i, j;
5050         float amplitude;
5051         float animpos;
5052         float scale;
5053         const float *v1, *in_tc;
5054         float *out_tc;
5055         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5056         float waveparms[4];
5057         q3shaderinfo_deform_t *deform;
5058         // 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
5059         if (rsurface.generatedvertex)
5060         {
5061                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5062                         generatenormals = true;
5063                 for (i = 0;i < Q3MAXDEFORMS;i++)
5064                 {
5065                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5066                         {
5067                                 generatetangents = true;
5068                                 generatenormals = true;
5069                         }
5070                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5071                                 generatenormals = true;
5072                 }
5073                 if (generatenormals && !rsurface.modelnormal3f)
5074                 {
5075                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5076                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5077                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5078                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
5079                 }
5080                 if (generatetangents && !rsurface.modelsvector3f)
5081                 {
5082                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5083                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5084                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5085                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5086                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5087                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5088                         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);
5089                 }
5090         }
5091         rsurface.vertex3f  = rsurface.modelvertex3f;
5092         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5093         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5094         rsurface.svector3f = rsurface.modelsvector3f;
5095         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5096         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5097         rsurface.tvector3f = rsurface.modeltvector3f;
5098         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5099         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5100         rsurface.normal3f  = rsurface.modelnormal3f;
5101         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5102         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5103         // if vertices are deformed (sprite flares and things in maps, possibly
5104         // water waves, bulges and other deformations), generate them into
5105         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5106         // (may be static model data or generated data for an animated model, or
5107         //  the previous deform pass)
5108         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5109         {
5110                 switch (deform->deform)
5111                 {
5112                 default:
5113                 case Q3DEFORM_PROJECTIONSHADOW:
5114                 case Q3DEFORM_TEXT0:
5115                 case Q3DEFORM_TEXT1:
5116                 case Q3DEFORM_TEXT2:
5117                 case Q3DEFORM_TEXT3:
5118                 case Q3DEFORM_TEXT4:
5119                 case Q3DEFORM_TEXT5:
5120                 case Q3DEFORM_TEXT6:
5121                 case Q3DEFORM_TEXT7:
5122                 case Q3DEFORM_NONE:
5123                         break;
5124                 case Q3DEFORM_AUTOSPRITE:
5125                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5126                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5127                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5128                         VectorNormalize(newforward);
5129                         VectorNormalize(newright);
5130                         VectorNormalize(newup);
5131                         // make deformed versions of only the model vertices used by the specified surfaces
5132                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5133                         {
5134                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5135                                 // a single autosprite surface can contain multiple sprites...
5136                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
5137                                 {
5138                                         VectorClear(center);
5139                                         for (i = 0;i < 4;i++)
5140                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5141                                         VectorScale(center, 0.25f, center);
5142                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
5143                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5144                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5145                                         for (i = 0;i < 4;i++)
5146                                         {
5147                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5148                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5149                                         }
5150                                 }
5151                                 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);
5152                                 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);
5153                         }
5154                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5155                         rsurface.vertex3f_bufferobject = 0;
5156                         rsurface.vertex3f_bufferoffset = 0;
5157                         rsurface.svector3f = rsurface.array_deformedsvector3f;
5158                         rsurface.svector3f_bufferobject = 0;
5159                         rsurface.svector3f_bufferoffset = 0;
5160                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
5161                         rsurface.tvector3f_bufferobject = 0;
5162                         rsurface.tvector3f_bufferoffset = 0;
5163                         rsurface.normal3f = rsurface.array_deformednormal3f;
5164                         rsurface.normal3f_bufferobject = 0;
5165                         rsurface.normal3f_bufferoffset = 0;
5166                         break;
5167                 case Q3DEFORM_AUTOSPRITE2:
5168                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5169                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5170                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5171                         VectorNormalize(newforward);
5172                         VectorNormalize(newright);
5173                         VectorNormalize(newup);
5174                         // make deformed versions of only the model vertices used by the specified surfaces
5175                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5176                         {
5177                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5178                                 const float *v1, *v2;
5179                                 vec3_t start, end;
5180                                 float f, l;
5181                                 struct
5182                                 {
5183                                         float length2;
5184                                         const float *v1;
5185                                         const float *v2;
5186                                 }
5187                                 shortest[2];
5188                                 memset(shortest, 0, sizeof(shortest));
5189                                 // a single autosprite surface can contain multiple sprites...
5190                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
5191                                 {
5192                                         VectorClear(center);
5193                                         for (i = 0;i < 4;i++)
5194                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5195                                         VectorScale(center, 0.25f, center);
5196                                         // find the two shortest edges, then use them to define the
5197                                         // axis vectors for rotating around the central axis
5198                                         for (i = 0;i < 6;i++)
5199                                         {
5200                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5201                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5202 #if 0
5203                                                 Debug_PolygonBegin(NULL, 0);
5204                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5205                                                 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);
5206                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5207                                                 Debug_PolygonEnd();
5208 #endif
5209                                                 l = VectorDistance2(v1, v2);
5210                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5211                                                 if (v1[2] != v2[2])
5212                                                         l += (1.0f / 1024.0f);
5213                                                 if (shortest[0].length2 > l || i == 0)
5214                                                 {
5215                                                         shortest[1] = shortest[0];
5216                                                         shortest[0].length2 = l;
5217                                                         shortest[0].v1 = v1;
5218                                                         shortest[0].v2 = v2;
5219                                                 }
5220                                                 else if (shortest[1].length2 > l || i == 1)
5221                                                 {
5222                                                         shortest[1].length2 = l;
5223                                                         shortest[1].v1 = v1;
5224                                                         shortest[1].v2 = v2;
5225                                                 }
5226                                         }
5227                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5228                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5229 #if 0
5230                                         Debug_PolygonBegin(NULL, 0);
5231                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5232                                         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);
5233                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5234                                         Debug_PolygonEnd();
5235 #endif
5236                                         // this calculates the right vector from the shortest edge
5237                                         // and the up vector from the edge midpoints
5238                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5239                                         VectorNormalize(right);
5240                                         VectorSubtract(end, start, up);
5241                                         VectorNormalize(up);
5242                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5243                                         //VectorSubtract(rsurface.modelorg, center, forward);
5244                                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5245                                         VectorNegate(forward, forward);
5246                                         VectorReflect(forward, 0, up, forward);
5247                                         VectorNormalize(forward);
5248                                         CrossProduct(up, forward, newright);
5249                                         VectorNormalize(newright);
5250 #if 0
5251                                         Debug_PolygonBegin(NULL, 0);
5252                                         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);
5253                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5254                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
5255                                         Debug_PolygonEnd();
5256 #endif
5257 #if 0
5258                                         Debug_PolygonBegin(NULL, 0);
5259                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5260                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5261                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
5262                                         Debug_PolygonEnd();
5263 #endif
5264                                         // rotate the quad around the up axis vector, this is made
5265                                         // especially easy by the fact we know the quad is flat,
5266                                         // so we only have to subtract the center position and
5267                                         // measure distance along the right vector, and then
5268                                         // multiply that by the newright vector and add back the
5269                                         // center position
5270                                         // we also need to subtract the old position to undo the
5271                                         // displacement from the center, which we do with a
5272                                         // DotProduct, the subtraction/addition of center is also
5273                                         // optimized into DotProducts here
5274                                         l = DotProduct(right, center);
5275                                         for (i = 0;i < 4;i++)
5276                                         {
5277                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5278                                                 f = DotProduct(right, v1) - l;
5279                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5280                                         }
5281                                 }
5282                                 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);
5283                                 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);
5284                         }
5285                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5286                         rsurface.vertex3f_bufferobject = 0;
5287                         rsurface.vertex3f_bufferoffset = 0;
5288                         rsurface.svector3f = rsurface.array_deformedsvector3f;
5289                         rsurface.svector3f_bufferobject = 0;
5290                         rsurface.svector3f_bufferoffset = 0;
5291                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
5292                         rsurface.tvector3f_bufferobject = 0;
5293                         rsurface.tvector3f_bufferoffset = 0;
5294                         rsurface.normal3f = rsurface.array_deformednormal3f;
5295                         rsurface.normal3f_bufferobject = 0;
5296                         rsurface.normal3f_bufferoffset = 0;
5297                         break;
5298                 case Q3DEFORM_NORMAL:
5299                         // deform the normals to make reflections wavey
5300                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5301                         {
5302                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5303                                 for (j = 0;j < surface->num_vertices;j++)
5304                                 {
5305                                         float vertex[3];
5306                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
5307                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5308                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
5309                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5310                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5311                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5312                                         VectorNormalize(normal);
5313                                 }
5314                                 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);
5315                         }
5316                         rsurface.svector3f = rsurface.array_deformedsvector3f;
5317                         rsurface.svector3f_bufferobject = 0;
5318                         rsurface.svector3f_bufferoffset = 0;
5319                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
5320                         rsurface.tvector3f_bufferobject = 0;
5321                         rsurface.tvector3f_bufferoffset = 0;
5322                         rsurface.normal3f = rsurface.array_deformednormal3f;
5323                         rsurface.normal3f_bufferobject = 0;
5324                         rsurface.normal3f_bufferoffset = 0;
5325                         break;
5326                 case Q3DEFORM_WAVE:
5327                         // deform vertex array to make wavey water and flags and such
5328                         waveparms[0] = deform->waveparms[0];
5329                         waveparms[1] = deform->waveparms[1];
5330                         waveparms[2] = deform->waveparms[2];
5331                         waveparms[3] = deform->waveparms[3];
5332                         // this is how a divisor of vertex influence on deformation
5333                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5334                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5335                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5336                         {
5337                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5338                                 for (j = 0;j < surface->num_vertices;j++)
5339                                 {
5340                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
5341                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
5342                                         // if the wavefunc depends on time, evaluate it per-vertex
5343                                         if (waveparms[3])
5344                                         {
5345                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5346                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5347                                         }
5348                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
5349                                 }
5350                         }
5351                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5352                         rsurface.vertex3f_bufferobject = 0;
5353                         rsurface.vertex3f_bufferoffset = 0;
5354                         break;
5355                 case Q3DEFORM_BULGE:
5356                         // deform vertex array to make the surface have moving bulges
5357                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5358                         {
5359                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5360                                 for (j = 0;j < surface->num_vertices;j++)
5361                                 {
5362                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
5363                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5364                                 }
5365                         }
5366                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5367                         rsurface.vertex3f_bufferobject = 0;
5368                         rsurface.vertex3f_bufferoffset = 0;
5369                         break;
5370                 case Q3DEFORM_MOVE:
5371                         // deform vertex array
5372                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
5373                         VectorScale(deform->parms, scale, waveparms);
5374                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5375                         {
5376                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5377                                 for (j = 0;j < surface->num_vertices;j++)
5378                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5379                         }
5380                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5381                         rsurface.vertex3f_bufferobject = 0;
5382                         rsurface.vertex3f_bufferoffset = 0;
5383                         break;
5384                 }
5385         }
5386         // generate texcoords based on the chosen texcoord source
5387         switch(rsurface.texture->tcgen.tcgen)
5388         {
5389         default:
5390         case Q3TCGEN_TEXTURE:
5391                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
5392                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
5393                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
5394                 break;
5395         case Q3TCGEN_LIGHTMAP:
5396                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
5397                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
5398                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
5399                 break;
5400         case Q3TCGEN_VECTOR:
5401                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5402                 {
5403                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5404                         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)
5405                         {
5406                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
5407                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
5408                         }
5409                 }
5410                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
5411                 rsurface.texcoordtexture2f_bufferobject  = 0;
5412                 rsurface.texcoordtexture2f_bufferoffset  = 0;
5413                 break;
5414         case Q3TCGEN_ENVIRONMENT:
5415                 // make environment reflections using a spheremap
5416                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5417                 {
5418                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5419                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
5420                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
5421                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
5422                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
5423                         {
5424                                 float l, d, eyedir[3];
5425                                 VectorSubtract(rsurface.modelorg, vertex, eyedir);
5426                                 l = 0.5f / VectorLength(eyedir);
5427                                 d = DotProduct(normal, eyedir)*2;
5428                                 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
5429                                 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
5430                         }
5431                 }
5432                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
5433                 rsurface.texcoordtexture2f_bufferobject  = 0;
5434                 rsurface.texcoordtexture2f_bufferoffset  = 0;
5435                 break;
5436         }
5437         // the only tcmod that needs software vertex processing is turbulent, so
5438         // check for it here and apply the changes if needed
5439         // and we only support that as the first one
5440         // (handling a mixture of turbulent and other tcmods would be problematic
5441         //  without punting it entirely to a software path)
5442         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
5443         {
5444                 amplitude = rsurface.texture->tcmods[0].parms[1];
5445                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
5446                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5447                 {
5448                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5449                         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)
5450                         {
5451                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5452                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5453                         }
5454                 }
5455                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
5456                 rsurface.texcoordtexture2f_bufferobject  = 0;
5457                 rsurface.texcoordtexture2f_bufferoffset  = 0;
5458         }
5459         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
5460         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5461         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5462         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5463 }
5464
5465 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5466 {
5467         int i, j;
5468         const msurface_t *surface = texturesurfacelist[0];
5469         const msurface_t *surface2;
5470         int firstvertex;
5471         int endvertex;
5472         int numvertices;
5473         int numtriangles;
5474         // TODO: lock all array ranges before render, rather than on each surface
5475         if (texturenumsurfaces == 1)
5476         {
5477                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5478                 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);
5479         }
5480         else if (r_batchmode.integer == 2)
5481         {
5482                 #define MAXBATCHTRIANGLES 4096
5483                 int batchtriangles = 0;
5484                 int batchelements[MAXBATCHTRIANGLES*3];
5485                 for (i = 0;i < texturenumsurfaces;i = j)
5486                 {
5487                         surface = texturesurfacelist[i];
5488                         j = i + 1;
5489                         if (surface->num_triangles > MAXBATCHTRIANGLES)
5490                         {
5491                                 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);
5492                                 continue;
5493                         }
5494                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5495                         batchtriangles = surface->num_triangles;
5496                         firstvertex = surface->num_firstvertex;
5497                         endvertex = surface->num_firstvertex + surface->num_vertices;
5498                         for (;j < texturenumsurfaces;j++)
5499                         {
5500                                 surface2 = texturesurfacelist[j];
5501                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5502                                         break;
5503                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5504                                 batchtriangles += surface2->num_triangles;
5505                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
5506                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5507                         }
5508                         surface2 = texturesurfacelist[j-1];
5509                         numvertices = endvertex - firstvertex;
5510                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5511                 }
5512         }
5513         else if (r_batchmode.integer == 1)
5514         {
5515                 for (i = 0;i < texturenumsurfaces;i = j)
5516                 {
5517                         surface = texturesurfacelist[i];
5518                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5519                                 if (texturesurfacelist[j] != surface2)
5520                                         break;
5521                         surface2 = texturesurfacelist[j-1];
5522                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5523                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5524                         GL_LockArrays(surface->num_firstvertex, numvertices);
5525                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5526                 }
5527         }
5528         else
5529         {
5530                 for (i = 0;i < texturenumsurfaces;i++)
5531                 {
5532                         surface = texturesurfacelist[i];
5533                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5534                         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);
5535                 }
5536         }
5537 }
5538
5539 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5540 {
5541         int i, planeindex, vertexindex;
5542         float d, bestd;
5543         vec3_t vert;
5544         const float *v;
5545         r_waterstate_waterplane_t *p, *bestp;
5546         msurface_t *surface;
5547         if (r_waterstate.renderingscene)
5548                 return;
5549         for (i = 0;i < texturenumsurfaces;i++)
5550         {
5551                 surface = texturesurfacelist[i];
5552                 if (lightmaptexunit >= 0)
5553                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5554                 if (deluxemaptexunit >= 0)
5555                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5556                 // pick the closest matching water plane
5557                 bestd = 0;
5558                 bestp = NULL;
5559                 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5560                 {
5561                         d = 0;
5562                         for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5563                         {
5564                                 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5565                                 d += fabs(PlaneDiff(vert, &p->plane));
5566                         }
5567                         if (bestd > d || !bestp)
5568                         {
5569                                 bestd = d;
5570                                 bestp = p;
5571                         }
5572                 }
5573                 if (bestp)
5574                 {
5575                         if (refractiontexunit >= 0)
5576                                 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5577                         if (reflectiontexunit >= 0)
5578                                 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5579                 }
5580                 else
5581                 {
5582                         if (refractiontexunit >= 0)
5583                                 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5584                         if (reflectiontexunit >= 0)
5585                                 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5586                 }
5587                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5588                 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);
5589         }
5590 }
5591
5592 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5593 {
5594         int i;
5595         int j;
5596         const msurface_t *surface = texturesurfacelist[0];
5597         const msurface_t *surface2;
5598         int firstvertex;
5599         int endvertex;
5600         int numvertices;
5601         int numtriangles;
5602         // TODO: lock all array ranges before render, rather than on each surface
5603         if (texturenumsurfaces == 1)
5604         {
5605                 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5606                 if (deluxemaptexunit >= 0)
5607                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5608                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5609                 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);
5610         }
5611         else if (r_batchmode.integer == 2)
5612         {
5613                 #define MAXBATCHTRIANGLES 4096
5614                 int batchtriangles = 0;
5615                 int batchelements[MAXBATCHTRIANGLES*3];
5616                 for (i = 0;i < texturenumsurfaces;i = j)
5617                 {
5618                         surface = texturesurfacelist[i];
5619                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5620                         if (deluxemaptexunit >= 0)
5621                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5622                         j = i + 1;
5623                         if (surface->num_triangles > MAXBATCHTRIANGLES)
5624                         {
5625                                 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);
5626                                 continue;
5627                         }
5628                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5629                         batchtriangles = surface->num_triangles;
5630                         firstvertex = surface->num_firstvertex;
5631                         endvertex = surface->num_firstvertex + surface->num_vertices;
5632                         for (;j < texturenumsurfaces;j++)
5633                         {
5634                                 surface2 = texturesurfacelist[j];
5635                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5636                                         break;
5637                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5638                                 batchtriangles += surface2->num_triangles;
5639                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
5640                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5641                         }
5642                         surface2 = texturesurfacelist[j-1];
5643                         numvertices = endvertex - firstvertex;
5644                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5645                 }
5646         }
5647         else if (r_batchmode.integer == 1)
5648         {
5649 #if 0
5650                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5651                 for (i = 0;i < texturenumsurfaces;i = j)
5652                 {
5653                         surface = texturesurfacelist[i];
5654                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5655                                 if (texturesurfacelist[j] != surface2)
5656                                         break;
5657                         Con_Printf(" %i", j - i);
5658                 }
5659                 Con_Printf("\n");
5660                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5661 #endif
5662                 for (i = 0;i < texturenumsurfaces;i = j)
5663                 {
5664                         surface = texturesurfacelist[i];
5665                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5666                         if (deluxemaptexunit >= 0)
5667                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5668                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5669                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5670                                         break;
5671 #if 0
5672                         Con_Printf(" %i", j - i);
5673 #endif
5674                         surface2 = texturesurfacelist[j-1];
5675                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5676                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5677                         GL_LockArrays(surface->num_firstvertex, numvertices);
5678                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5679                 }
5680 #if 0
5681                 Con_Printf("\n");
5682 #endif
5683         }
5684         else
5685         {
5686                 for (i = 0;i < texturenumsurfaces;i++)
5687                 {
5688                         surface = texturesurfacelist[i];
5689                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5690                         if (deluxemaptexunit >= 0)
5691                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5692                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5693                         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);
5694                 }
5695         }
5696 }
5697
5698 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5699 {
5700         int j;
5701         int texturesurfaceindex;
5702         if (r_showsurfaces.integer == 2)
5703         {
5704                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5705                 {
5706                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5707                         for (j = 0;j < surface->num_triangles;j++)
5708                         {
5709                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
5710                                 GL_Color(f, f, f, 1);
5711                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5712                         }
5713                 }
5714         }
5715         else
5716         {
5717                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5718                 {
5719                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5720                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
5721                         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);
5722                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5723                         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);
5724                 }
5725         }
5726 }
5727
5728 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
5729 {
5730         int texturesurfaceindex;
5731         int i;
5732         float f;
5733         float *v, *c2;
5734         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5735         {
5736                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5737                 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)
5738                 {
5739                         f = FogPoint_Model(v);
5740                         c2[0] = 1;
5741                         c2[1] = 1;
5742                         c2[2] = 1;
5743                         c2[3] = 1;
5744                 }
5745         }
5746         rsurface.lightmapcolor4f = rsurface.array_color4f;
5747         rsurface.lightmapcolor4f_bufferobject = 0;
5748         rsurface.lightmapcolor4f_bufferoffset = 0;
5749 }
5750
5751 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5752 {
5753         int texturesurfaceindex;
5754         int i;
5755         float f;
5756         float *v, *c, *c2;
5757         if (rsurface.lightmapcolor4f)
5758         {
5759                 // generate color arrays for the surfaces in this list
5760                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5761                 {
5762                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5763                         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)
5764                         {
5765                                 f = FogPoint_Model(v);
5766                                 c2[0] = c[0] * f;
5767                                 c2[1] = c[1] * f;
5768                                 c2[2] = c[2] * f;
5769                                 c2[3] = c[3];
5770                         }
5771                 }
5772         }
5773         else
5774         {
5775                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5776                 {
5777                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5778                         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)
5779                         {
5780                                 f = FogPoint_Model(v);
5781                                 c2[0] = f;
5782                                 c2[1] = f;
5783                                 c2[2] = f;
5784                                 c2[3] = 1;
5785                         }
5786                 }
5787         }
5788         rsurface.lightmapcolor4f = rsurface.array_color4f;
5789         rsurface.lightmapcolor4f_bufferobject = 0;
5790         rsurface.lightmapcolor4f_bufferoffset = 0;
5791 }
5792
5793 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
5794 {
5795         int texturesurfaceindex;
5796         int i;
5797         float f;
5798         float *v, *c, *c2;
5799         if (!rsurface.lightmapcolor4f)
5800                 return;
5801         // generate color arrays for the surfaces in this list
5802         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5803         {
5804                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5805                 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)
5806                 {
5807                         f = FogPoint_Model(v);
5808                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
5809                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
5810                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
5811                         c2[3] = c[3];
5812                 }
5813         }
5814         rsurface.lightmapcolor4f = rsurface.array_color4f;
5815         rsurface.lightmapcolor4f_bufferobject = 0;
5816         rsurface.lightmapcolor4f_bufferoffset = 0;
5817 }
5818
5819 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5820 {
5821         int texturesurfaceindex;
5822         int i;
5823         float *c, *c2;
5824         if (!rsurface.lightmapcolor4f)
5825                 return;
5826         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5827         {
5828                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5829                 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)
5830                 {
5831                         c2[0] = c[0] * r;
5832                         c2[1] = c[1] * g;
5833                         c2[2] = c[2] * b;
5834                         c2[3] = c[3] * a;
5835                 }
5836         }
5837         rsurface.lightmapcolor4f = rsurface.array_color4f;
5838         rsurface.lightmapcolor4f_bufferobject = 0;
5839         rsurface.lightmapcolor4f_bufferoffset = 0;
5840 }
5841
5842 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
5843 {
5844         int texturesurfaceindex;
5845         int i;
5846         float *c, *c2;
5847         if (!rsurface.lightmapcolor4f)
5848                 return;
5849         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5850         {
5851                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5852                 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)
5853                 {
5854                         c2[0] = c[0] + r_refdef.scene.ambient / 64.0;
5855                         c2[1] = c[1] + r_refdef.scene.ambient / 64.0;
5856                         c2[2] = c[2] + r_refdef.scene.ambient / 64.0;
5857                         c2[3] = c[3];
5858                 }
5859         }
5860         rsurface.lightmapcolor4f = rsurface.array_color4f;
5861         rsurface.lightmapcolor4f_bufferobject = 0;
5862         rsurface.lightmapcolor4f_bufferoffset = 0;
5863 }
5864
5865 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5866 {
5867         // TODO: optimize
5868         rsurface.lightmapcolor4f = NULL;
5869         rsurface.lightmapcolor4f_bufferobject = 0;
5870         rsurface.lightmapcolor4f_bufferoffset = 0;
5871         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5872         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5873         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5874         GL_Color(r, g, b, a);
5875         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5876 }
5877
5878 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5879 {
5880         // TODO: optimize applyfog && applycolor case
5881         // just apply fog if necessary, and tint the fog color array if necessary
5882         rsurface.lightmapcolor4f = NULL;
5883         rsurface.lightmapcolor4f_bufferobject = 0;
5884         rsurface.lightmapcolor4f_bufferoffset = 0;
5885         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5886         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5887         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5888         GL_Color(r, g, b, a);
5889         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5890 }
5891
5892 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5893 {
5894         int texturesurfaceindex;
5895         int i;
5896         float *c;
5897         // TODO: optimize
5898         if (texturesurfacelist[0]->lightmapinfo)
5899         {
5900                 // generate color arrays for the surfaces in this list
5901                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5902                 {
5903                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5904                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5905                         {
5906                                 if (surface->lightmapinfo->samples)
5907                                 {
5908                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5909                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5910                                         VectorScale(lm, scale, c);
5911                                         if (surface->lightmapinfo->styles[1] != 255)
5912                                         {
5913                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5914                                                 lm += size3;
5915                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5916                                                 VectorMA(c, scale, lm, c);
5917                                                 if (surface->lightmapinfo->styles[2] != 255)
5918                                                 {
5919                                                         lm += size3;
5920                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5921                                                         VectorMA(c, scale, lm, c);
5922                                                         if (surface->lightmapinfo->styles[3] != 255)
5923                                                         {
5924                                                                 lm += size3;
5925                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5926                                                                 VectorMA(c, scale, lm, c);
5927                                                         }
5928                                                 }
5929                                         }
5930                                 }
5931                                 else
5932                                         VectorClear(c);
5933                                 c[3] = 1;
5934                         }
5935                 }
5936                 rsurface.lightmapcolor4f = rsurface.array_color4f;
5937                 rsurface.lightmapcolor4f_bufferobject = 0;
5938                 rsurface.lightmapcolor4f_bufferoffset = 0;
5939         }
5940         else
5941         {
5942                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5943                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5944                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5945         }
5946         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5947         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5948         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5949         GL_Color(r, g, b, a);
5950         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5951 }
5952
5953 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
5954 {
5955         int texturesurfaceindex;
5956         int i;
5957         float f;
5958         float *v, *c, *c2, alpha;
5959         vec3_t ambientcolor;
5960         vec3_t diffusecolor;
5961         vec3_t lightdir;
5962         // TODO: optimize
5963         // model lighting
5964         VectorCopy(rsurface.modellight_lightdir, lightdir);
5965         f = 0.5f * r_refdef.lightmapintensity;
5966         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
5967         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
5968         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
5969         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
5970         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
5971         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
5972         alpha = *a;
5973         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
5974         {
5975                 // generate color arrays for the surfaces in this list
5976                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5977                 {
5978                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5979                         int numverts = surface->num_vertices;
5980                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5981                         c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5982                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5983                         // q3-style directional shading
5984                         for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5985                         {
5986                                 if ((f = DotProduct(c2, lightdir)) > 0)
5987                                         VectorMA(ambientcolor, f, diffusecolor, c);
5988                                 else
5989                                         VectorCopy(ambientcolor, c);
5990                                 c[3] = alpha;
5991                         }
5992                 }
5993                 *r = 1;
5994                 *g = 1;
5995                 *b = 1;
5996                 *a = 1;
5997                 rsurface.lightmapcolor4f = rsurface.array_color4f;
5998                 rsurface.lightmapcolor4f_bufferobject = 0;
5999                 rsurface.lightmapcolor4f_bufferoffset = 0;
6000                 *applycolor = false;
6001         }
6002         else
6003         {
6004                 *r = ambientcolor[0];
6005                 *g = ambientcolor[1];
6006                 *b = ambientcolor[2];
6007                 rsurface.lightmapcolor4f = NULL;
6008                 rsurface.lightmapcolor4f_bufferobject = 0;
6009                 rsurface.lightmapcolor4f_bufferoffset = 0;
6010         }
6011 }
6012
6013 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6014 {
6015         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6016         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6017         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6018         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6019         GL_Color(r, g, b, a);
6020         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6021 }
6022
6023 void RSurf_SetupDepthAndCulling(void)
6024 {
6025         // submodels are biased to avoid z-fighting with world surfaces that they
6026         // may be exactly overlapping (avoids z-fighting artifacts on certain
6027         // doors and things in Quake maps)
6028         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6029         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6030         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6031         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6032 }
6033
6034 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6035 {
6036         // transparent sky would be ridiculous
6037         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6038                 return;
6039         R_SetupGenericShader(false);
6040         if (skyrendernow)
6041         {
6042                 skyrendernow = false;
6043                 // we have to force off the water clipping plane while rendering sky
6044                 R_SetupView(false);
6045                 R_Sky();
6046                 R_SetupView(true);
6047                 // restore entity matrix
6048                 R_Mesh_Matrix(&rsurface.matrix);
6049         }
6050         RSurf_SetupDepthAndCulling();
6051         GL_DepthMask(true);
6052         // LordHavoc: HalfLife maps have freaky skypolys so don't use
6053         // skymasking on them, and Quake3 never did sky masking (unlike
6054         // software Quake and software Quake2), so disable the sky masking
6055         // in Quake3 maps as it causes problems with q3map2 sky tricks,
6056         // and skymasking also looks very bad when noclipping outside the
6057         // level, so don't use it then either.
6058         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6059         {
6060                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6061                 R_Mesh_ColorPointer(NULL, 0, 0);
6062                 R_Mesh_ResetTextureState();
6063                 if (skyrendermasked)
6064                 {
6065                         R_SetupDepthOrShadowShader();
6066                         // depth-only (masking)
6067                         GL_ColorMask(0,0,0,0);
6068                         // just to make sure that braindead drivers don't draw
6069                         // anything despite that colormask...
6070                         GL_BlendFunc(GL_ZERO, GL_ONE);
6071                 }
6072                 else
6073                 {
6074                         R_SetupGenericShader(false);
6075                         // fog sky
6076                         GL_BlendFunc(GL_ONE, GL_ZERO);
6077                 }
6078                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6079                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6080                 if (skyrendermasked)
6081                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6082         }
6083         R_Mesh_ResetTextureState();
6084         GL_Color(1, 1, 1, 1);
6085 }
6086
6087 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6088 {
6089         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6090                 return;
6091
6092         R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6093         R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6094         R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6095         R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6096         R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6097         if (rsurface.texture->backgroundcurrentskinframe)
6098         {
6099                 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6100                 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6101                 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6102                 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6103         }
6104         if(rsurface.texture->colormapping)
6105         {
6106                 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6107                 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6108         }
6109         R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6110         if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6111                 R_Mesh_ColorPointer(NULL, 0, 0);
6112         else
6113                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6114
6115         if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6116         {
6117                 // render background
6118                 GL_BlendFunc(GL_ONE, GL_ZERO);
6119                 GL_DepthMask(true);
6120                 GL_AlphaTest(false);
6121
6122                 GL_Color(1, 1, 1, 1);
6123                 R_Mesh_ColorPointer(NULL, 0, 0);
6124
6125                 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6126                 if (r_glsl_permutation)
6127                 {
6128                         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6129                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6130                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6131                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6132                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6133                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6134                         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);
6135                 }
6136                 GL_LockArrays(0, 0);
6137
6138                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6139                 GL_DepthMask(false);
6140                 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6141                         R_Mesh_ColorPointer(NULL, 0, 0);
6142                 else
6143                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6144                 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6145                 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6146         }
6147
6148         R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6149         if (!r_glsl_permutation)
6150                 return;
6151
6152         RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
6153         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6154         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6155         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6156         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6157         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6158
6159         if (r_glsl_permutation->loc_Texture_Refraction >= 0)
6160         {
6161                 GL_BlendFunc(GL_ONE, GL_ZERO);
6162                 GL_DepthMask(true);
6163                 GL_AlphaTest(false);
6164         }
6165         else
6166         {
6167                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6168                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6169                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6170         }
6171
6172         if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6173         {
6174                 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6175                         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);
6176                 else
6177                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
6178         }
6179         else
6180         {
6181                 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6182                         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);
6183                 else
6184                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6185         }
6186         GL_LockArrays(0, 0);
6187 }
6188
6189 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6190 {
6191         // OpenGL 1.3 path - anything not completely ancient
6192         int texturesurfaceindex;
6193         qboolean applycolor;
6194         qboolean applyfog;
6195         rmeshstate_t m;
6196         int layerindex;
6197         const texturelayer_t *layer;
6198         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6199
6200         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6201         {
6202                 vec4_t layercolor;
6203                 int layertexrgbscale;
6204                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6205                 {
6206                         if (layerindex == 0)
6207                                 GL_AlphaTest(true);
6208                         else
6209                         {
6210                                 GL_AlphaTest(false);
6211                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6212                         }
6213                 }
6214                 GL_DepthMask(layer->depthmask && writedepth);
6215                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6216                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
6217                 {
6218                         layertexrgbscale = 4;
6219                         VectorScale(layer->color, 0.25f, layercolor);
6220                 }
6221                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
6222                 {
6223                         layertexrgbscale = 2;
6224                         VectorScale(layer->color, 0.5f, layercolor);
6225                 }
6226                 else
6227                 {
6228                         layertexrgbscale = 1;
6229                         VectorScale(layer->color, 1.0f, layercolor);
6230                 }
6231                 layercolor[3] = layer->color[3];
6232                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6233                 R_Mesh_ColorPointer(NULL, 0, 0);
6234                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6235                 switch (layer->type)
6236                 {
6237                 case TEXTURELAYERTYPE_LITTEXTURE:
6238                         memset(&m, 0, sizeof(m));
6239                         m.tex[0] = R_GetTexture(r_texture_white);
6240                         m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6241                         m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6242                         m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6243                         m.tex[1] = R_GetTexture(layer->texture);
6244                         m.texmatrix[1] = layer->texmatrix;
6245                         m.texrgbscale[1] = layertexrgbscale;
6246                         m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
6247                         m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
6248                         m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
6249                         R_Mesh_TextureState(&m);
6250                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6251                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6252                         else if (rsurface.uselightmaptexture)
6253                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6254                         else
6255                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6256                         break;
6257                 case TEXTURELAYERTYPE_TEXTURE:
6258                         memset(&m, 0, sizeof(m));
6259                         m.tex[0] = R_GetTexture(layer->texture);
6260                         m.texmatrix[0] = layer->texmatrix;
6261                         m.texrgbscale[0] = layertexrgbscale;
6262                         m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6263                         m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6264                         m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6265                         R_Mesh_TextureState(&m);
6266                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6267                         break;
6268                 case TEXTURELAYERTYPE_FOG:
6269                         memset(&m, 0, sizeof(m));
6270                         m.texrgbscale[0] = layertexrgbscale;
6271                         if (layer->texture)
6272                         {
6273                                 m.tex[0] = R_GetTexture(layer->texture);
6274                                 m.texmatrix[0] = layer->texmatrix;
6275                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6276                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6277                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6278                         }
6279                         R_Mesh_TextureState(&m);
6280                         // generate a color array for the fog pass
6281                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6282                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6283                         {
6284                                 int i;
6285                                 float f, *v, *c;
6286                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6287                                 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)
6288                                 {
6289                                         f = 1 - FogPoint_Model(v);
6290                                         c[0] = layercolor[0];
6291                                         c[1] = layercolor[1];
6292                                         c[2] = layercolor[2];
6293                                         c[3] = f * layercolor[3];
6294                                 }
6295                         }
6296                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6297                         break;
6298                 default:
6299                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6300                 }
6301                 GL_LockArrays(0, 0);
6302         }
6303         CHECKGLERROR
6304         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6305         {
6306                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6307                 GL_AlphaTest(false);
6308         }
6309 }
6310
6311 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6312 {
6313         // OpenGL 1.1 - crusty old voodoo path
6314         int texturesurfaceindex;
6315         qboolean applyfog;
6316         rmeshstate_t m;
6317         int layerindex;
6318         const texturelayer_t *layer;
6319         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6320
6321         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6322         {
6323                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6324                 {
6325                         if (layerindex == 0)
6326                                 GL_AlphaTest(true);
6327                         else
6328                         {
6329                                 GL_AlphaTest(false);
6330                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6331                         }
6332                 }
6333                 GL_DepthMask(layer->depthmask && writedepth);
6334                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6335                 R_Mesh_ColorPointer(NULL, 0, 0);
6336                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6337                 switch (layer->type)
6338                 {
6339                 case TEXTURELAYERTYPE_LITTEXTURE:
6340                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
6341                         {
6342                                 // two-pass lit texture with 2x rgbscale
6343                                 // first the lightmap pass
6344                                 memset(&m, 0, sizeof(m));
6345                                 m.tex[0] = R_GetTexture(r_texture_white);
6346                                 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6347                                 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6348                                 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6349                                 R_Mesh_TextureState(&m);
6350                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6351                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6352                                 else if (rsurface.uselightmaptexture)
6353                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6354                                 else
6355                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6356                                 GL_LockArrays(0, 0);
6357                                 // then apply the texture to it
6358                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6359                                 memset(&m, 0, sizeof(m));
6360                                 m.tex[0] = R_GetTexture(layer->texture);
6361                                 m.texmatrix[0] = layer->texmatrix;
6362                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6363                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6364                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6365                                 R_Mesh_TextureState(&m);
6366                                 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);
6367                         }
6368                         else
6369                         {
6370                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6371                                 memset(&m, 0, sizeof(m));
6372                                 m.tex[0] = R_GetTexture(layer->texture);
6373                                 m.texmatrix[0] = layer->texmatrix;
6374                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6375                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6376                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6377                                 R_Mesh_TextureState(&m);
6378                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6379                                         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);
6380                                 else
6381                                         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);
6382                         }
6383                         break;
6384                 case TEXTURELAYERTYPE_TEXTURE:
6385                         // singletexture unlit texture with transparency support
6386                         memset(&m, 0, sizeof(m));
6387                         m.tex[0] = R_GetTexture(layer->texture);
6388                         m.texmatrix[0] = layer->texmatrix;
6389                         m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6390                         m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6391                         m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6392                         R_Mesh_TextureState(&m);
6393                         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);
6394                         break;
6395                 case TEXTURELAYERTYPE_FOG:
6396                         // singletexture fogging
6397                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6398                         if (layer->texture)
6399                         {
6400                                 memset(&m, 0, sizeof(m));
6401                                 m.tex[0] = R_GetTexture(layer->texture);
6402                                 m.texmatrix[0] = layer->texmatrix;
6403                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6404                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6405                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6406                                 R_Mesh_TextureState(&m);
6407                         }
6408                         else
6409                                 R_Mesh_ResetTextureState();
6410                         // generate a color array for the fog pass
6411                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6412                         {
6413                                 int i;
6414                                 float f, *v, *c;
6415                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6416                                 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)
6417                                 {
6418                                         f = 1 - FogPoint_Model(v);
6419                                         c[0] = layer->color[0];
6420                                         c[1] = layer->color[1];
6421                                         c[2] = layer->color[2];
6422                                         c[3] = f * layer->color[3];
6423                                 }
6424                         }
6425                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6426                         break;
6427                 default:
6428                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6429                 }
6430                 GL_LockArrays(0, 0);
6431         }
6432         CHECKGLERROR
6433         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6434         {
6435                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6436                 GL_AlphaTest(false);
6437         }
6438 }
6439
6440 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6441 {
6442         float c[4];
6443
6444         GL_AlphaTest(false);
6445         R_Mesh_ColorPointer(NULL, 0, 0);
6446         R_Mesh_ResetTextureState();
6447         R_SetupGenericShader(false);
6448
6449         if(rsurface.texture && rsurface.texture->currentskinframe)
6450                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
6451         else
6452         {
6453                 c[0] = 1;
6454                 c[1] = 0;
6455                 c[2] = 1;
6456                 c[3] = 1;
6457         }
6458
6459         if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
6460         {
6461                 c[0] = rsurface.colormap_pantscolor[0] * 0.2 + rsurface.colormap_shirtcolor[0] * 0.3;
6462                 c[1] = rsurface.colormap_pantscolor[1] * 0.2 + rsurface.colormap_shirtcolor[1] * 0.3;
6463                 c[2] = rsurface.colormap_pantscolor[2] * 0.2 + rsurface.colormap_shirtcolor[2] * 0.3;
6464         }
6465
6466         // brighten it up (as texture value 127 means "unlit")
6467         c[0] *= 2 * r_refdef.view.colorscale;
6468         c[1] *= 2 * r_refdef.view.colorscale;
6469         c[2] *= 2 * r_refdef.view.colorscale;
6470
6471         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
6472                 c[3] *= r_wateralpha.value;
6473
6474         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
6475         {
6476                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6477                 GL_DepthMask(false);
6478         }
6479         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6480         {
6481                 GL_BlendFunc(GL_ONE, GL_ONE);
6482                 GL_DepthMask(false);
6483         }
6484         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6485         {
6486                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
6487                 GL_DepthMask(false);
6488         }
6489         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6490         {
6491                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
6492                 GL_DepthMask(false);
6493         }
6494         else
6495         {
6496                 GL_BlendFunc(GL_ONE, GL_ZERO);
6497                 GL_DepthMask(writedepth);
6498         }
6499
6500         rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6501         rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6502         rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6503
6504         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6505         {
6506                 qboolean applycolor = true;
6507                 float one = 1.0;
6508
6509                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6510                 r_refdef.lightmapintensity = 1;
6511                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
6512                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
6513         }
6514         else
6515                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6516
6517         if(!rsurface.lightmapcolor4f)
6518                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
6519
6520         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
6521         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
6522         if(r_refdef.fogenabled)
6523                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
6524
6525         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6526         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6527 }
6528
6529 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6530 {
6531         CHECKGLERROR
6532         RSurf_SetupDepthAndCulling();
6533         if (r_showsurfaces.integer == 3)
6534                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6535         else if (r_glsl.integer && gl_support_fragment_shader)
6536                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6537         else if (gl_combine.integer && r_textureunits.integer >= 2)
6538                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6539         else
6540                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6541         CHECKGLERROR
6542 }
6543
6544 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6545 {
6546         int i, j;
6547         int texturenumsurfaces, endsurface;
6548         texture_t *texture;
6549         msurface_t *surface;
6550         msurface_t *texturesurfacelist[1024];
6551
6552         // if the model is static it doesn't matter what value we give for
6553         // wantnormals and wanttangents, so this logic uses only rules applicable
6554         // to a model, knowing that they are meaningless otherwise
6555         if (ent == r_refdef.scene.worldentity)
6556                 RSurf_ActiveWorldEntity();
6557         else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6558                 RSurf_ActiveModelEntity(ent, false, false);
6559         else
6560                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6561
6562         for (i = 0;i < numsurfaces;i = j)
6563         {
6564                 j = i + 1;
6565                 surface = rsurface.modelsurfaces + surfacelist[i];
6566                 texture = surface->texture;
6567                 R_UpdateTextureInfo(ent, texture);
6568                 rsurface.texture = texture->currentframe;
6569                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6570                 // scan ahead until we find a different texture
6571                 endsurface = min(i + 1024, numsurfaces);
6572                 texturenumsurfaces = 0;
6573                 texturesurfacelist[texturenumsurfaces++] = surface;
6574                 for (;j < endsurface;j++)
6575                 {
6576                         surface = rsurface.modelsurfaces + surfacelist[j];
6577                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6578                                 break;
6579                         texturesurfacelist[texturenumsurfaces++] = surface;
6580                 }
6581                 // render the range of surfaces
6582                 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6583         }
6584         GL_AlphaTest(false);
6585 }
6586
6587 static void R_ProcessTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
6588 {
6589         CHECKGLERROR
6590         if (depthonly)
6591         {
6592                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6593                         return;
6594                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6595                         return;
6596                 RSurf_SetupDepthAndCulling();
6597                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6598                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6599         }
6600         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
6601         {
6602                 RSurf_SetupDepthAndCulling();
6603                 GL_AlphaTest(false);
6604                 R_Mesh_ColorPointer(NULL, 0, 0);
6605                 R_Mesh_ResetTextureState();
6606                 R_SetupGenericShader(false);
6607                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6608                 GL_DepthMask(true);
6609                 GL_BlendFunc(GL_ONE, GL_ZERO);
6610                 GL_Color(0, 0, 0, 1);
6611                 GL_DepthTest(writedepth);
6612                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6613         }
6614         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
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_DepthTest(true);
6625                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6626         }
6627         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6628                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6629         else if (!rsurface.texture->currentnumlayers)
6630                 return;
6631         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
6632         {
6633                 // transparent surfaces get pushed off into the transparent queue
6634                 int surfacelistindex;
6635                 const msurface_t *surface;
6636                 vec3_t tempcenter, center;
6637                 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6638                 {
6639                         surface = texturesurfacelist[surfacelistindex];
6640                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6641                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6642                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6643                         Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6644                         R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6645                 }
6646         }
6647         else
6648         {
6649                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6650                 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6651         }
6652         CHECKGLERROR
6653 }
6654
6655 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
6656 {
6657         int i, j;
6658         texture_t *texture;
6659         // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
6660         if (addwaterplanes)
6661         {
6662                 for (i = 0;i < numsurfaces;i++)
6663                         if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
6664                                 R_Water_AddWaterPlane(surfacelist[i]);
6665                 return;
6666         }
6667         // break the surface list down into batches by texture and use of lightmapping
6668         for (i = 0;i < numsurfaces;i = j)
6669         {
6670                 j = i + 1;
6671                 // texture is the base texture pointer, rsurface.texture is the
6672                 // current frame/skin the texture is directing us to use (for example
6673                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6674                 // use skin 1 instead)
6675                 texture = surfacelist[i]->texture;
6676                 rsurface.texture = texture->currentframe;
6677                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6678                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6679                 {
6680                         // if this texture is not the kind we want, skip ahead to the next one
6681                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6682                                 ;
6683                         continue;
6684                 }
6685                 // simply scan ahead until we find a different texture or lightmap state
6686                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6687                         ;
6688                 // render the range of surfaces
6689                 R_ProcessTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
6690         }
6691 }
6692
6693 float locboxvertex3f[6*4*3] =
6694 {
6695         1,0,1, 1,0,0, 1,1,0, 1,1,1,
6696         0,1,1, 0,1,0, 0,0,0, 0,0,1,
6697         1,1,1, 1,1,0, 0,1,0, 0,1,1,
6698         0,0,1, 0,0,0, 1,0,0, 1,0,1,
6699         0,0,1, 1,0,1, 1,1,1, 0,1,1,
6700         1,0,0, 0,0,0, 0,1,0, 1,1,0
6701 };
6702
6703 unsigned short locboxelements[6*2*3] =
6704 {
6705          0, 1, 2, 0, 2, 3,
6706          4, 5, 6, 4, 6, 7,
6707          8, 9,10, 8,10,11,
6708         12,13,14, 12,14,15,
6709         16,17,18, 16,18,19,
6710         20,21,22, 20,22,23
6711 };
6712
6713 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6714 {
6715         int i, j;
6716         cl_locnode_t *loc = (cl_locnode_t *)ent;
6717         vec3_t mins, size;
6718         float vertex3f[6*4*3];
6719         CHECKGLERROR
6720         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6721         GL_DepthMask(false);
6722         GL_DepthRange(0, 1);
6723         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6724         GL_DepthTest(true);
6725         GL_CullFace(GL_NONE);
6726         R_Mesh_Matrix(&identitymatrix);
6727
6728         R_Mesh_VertexPointer(vertex3f, 0, 0);
6729         R_Mesh_ColorPointer(NULL, 0, 0);
6730         R_Mesh_ResetTextureState();
6731         R_SetupGenericShader(false);
6732
6733         i = surfacelist[0];
6734         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6735                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6736                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6737                         surfacelist[0] < 0 ? 0.5f : 0.125f);
6738
6739         if (VectorCompare(loc->mins, loc->maxs))
6740         {
6741                 VectorSet(size, 2, 2, 2);
6742                 VectorMA(loc->mins, -0.5f, size, mins);
6743         }
6744         else
6745         {
6746                 VectorCopy(loc->mins, mins);
6747                 VectorSubtract(loc->maxs, loc->mins, size);
6748         }
6749
6750         for (i = 0;i < 6*4*3;)
6751                 for (j = 0;j < 3;j++, i++)
6752                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6753
6754         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
6755 }
6756
6757 void R_DrawLocs(void)
6758 {
6759         int index;
6760         cl_locnode_t *loc, *nearestloc;
6761         vec3_t center;
6762         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6763         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6764         {
6765                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6766                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6767         }
6768 }
6769
6770 void R_DrawDebugModel(entity_render_t *ent)
6771 {
6772         int i, j, k, l, flagsmask;
6773         const int *elements;
6774         q3mbrush_t *brush;
6775         msurface_t *surface;
6776         dp_model_t *model = ent->model;
6777         vec3_t v;
6778
6779         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
6780
6781         R_Mesh_ColorPointer(NULL, 0, 0);
6782         R_Mesh_ResetTextureState();
6783         R_SetupGenericShader(false);
6784         GL_DepthRange(0, 1);
6785         GL_DepthTest(!r_showdisabledepthtest.integer);
6786         GL_DepthMask(false);
6787         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6788
6789         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6790         {
6791                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6792                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6793                 {
6794                         if (brush->colbrushf && brush->colbrushf->numtriangles)
6795                         {
6796                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6797                                 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);
6798                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
6799                         }
6800                 }
6801                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6802                 {
6803                         if (surface->num_collisiontriangles)
6804                         {
6805                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6806                                 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);
6807                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
6808                         }
6809                 }
6810         }
6811
6812         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6813
6814         if (r_showtris.integer || r_shownormals.integer)
6815         {
6816                 if (r_showdisabledepthtest.integer)
6817                 {
6818                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6819                         GL_DepthMask(false);
6820                 }
6821                 else
6822                 {
6823                         GL_BlendFunc(GL_ONE, GL_ZERO);
6824                         GL_DepthMask(true);
6825                 }
6826                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6827                 {
6828                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
6829                                 continue;
6830                         rsurface.texture = surface->texture->currentframe;
6831                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6832                         {
6833                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6834                                 if (r_showtris.value > 0)
6835                                 {
6836                                         if (!rsurface.texture->currentlayers->depthmask)
6837                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
6838                                         else if (ent == r_refdef.scene.worldentity)
6839                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
6840                                         else
6841                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
6842                                         elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6843                                         CHECKGLERROR
6844                                         qglBegin(GL_LINES);
6845                                         for (k = 0;k < surface->num_triangles;k++, elements += 3)
6846                                         {
6847 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6848                                                 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6849                                                 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6850                                                 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6851                                         }
6852                                         qglEnd();
6853                                         CHECKGLERROR
6854                                 }
6855                                 if (r_shownormals.value > 0)
6856                                 {
6857                                         qglBegin(GL_LINES);
6858                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6859                                         {
6860                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
6861                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
6862                                                 qglVertex3f(v[0], v[1], v[2]);
6863                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
6864                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6865                                                 qglVertex3f(v[0], v[1], v[2]);
6866                                         }
6867                                         qglEnd();
6868                                         CHECKGLERROR
6869                                         qglBegin(GL_LINES);
6870                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6871                                         {
6872                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
6873                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
6874                                                 qglVertex3f(v[0], v[1], v[2]);
6875                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
6876                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6877                                                 qglVertex3f(v[0], v[1], v[2]);
6878                                         }
6879                                         qglEnd();
6880                                         CHECKGLERROR
6881                                         qglBegin(GL_LINES);
6882                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6883                                         {
6884                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
6885                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
6886                                                 qglVertex3f(v[0], v[1], v[2]);
6887                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
6888                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6889                                                 qglVertex3f(v[0], v[1], v[2]);
6890                                         }
6891                                         qglEnd();
6892                                         CHECKGLERROR
6893                                 }
6894                         }
6895                 }
6896                 rsurface.texture = NULL;
6897         }
6898 }
6899
6900 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6901 int r_maxsurfacelist = 0;
6902 msurface_t **r_surfacelist = NULL;
6903 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6904 {
6905         int i, j, endj, f, flagsmask;
6906         texture_t *t;
6907         dp_model_t *model = r_refdef.scene.worldmodel;
6908         msurface_t *surfaces;
6909         unsigned char *update;
6910         int numsurfacelist = 0;
6911         if (model == NULL)
6912                 return;
6913
6914         if (r_maxsurfacelist < model->num_surfaces)
6915         {
6916                 r_maxsurfacelist = model->num_surfaces;
6917                 if (r_surfacelist)
6918                         Mem_Free(r_surfacelist);
6919                 r_surfacelist = Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
6920         }
6921
6922         RSurf_ActiveWorldEntity();
6923
6924         surfaces = model->data_surfaces;
6925         update = model->brushq1.lightmapupdateflags;
6926
6927         // update light styles on this submodel
6928         if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6929         {
6930                 model_brush_lightstyleinfo_t *style;
6931                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6932                 {
6933                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
6934                         {
6935                                 int *list = style->surfacelist;
6936                                 style->value = r_refdef.scene.lightstylevalue[style->style];
6937                                 for (j = 0;j < style->numsurfaces;j++)
6938                                         update[list[j]] = true;
6939                         }
6940                 }
6941         }
6942
6943         R_UpdateAllTextureInfo(r_refdef.scene.worldentity);
6944         flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL);
6945
6946         if (debug)
6947         {
6948                 R_DrawDebugModel(r_refdef.scene.worldentity);
6949                 return;
6950         }
6951
6952         f = 0;
6953         t = NULL;
6954         rsurface.uselightmaptexture = false;
6955         rsurface.texture = NULL;
6956         rsurface.rtlight = NULL;
6957         numsurfacelist = 0;
6958         // add visible surfaces to draw list
6959         j = model->firstmodelsurface;
6960         endj = j + model->nummodelsurfaces;
6961         if (update)
6962         {
6963                 for (;j < endj;j++)
6964                 {
6965                         if (r_refdef.viewcache.world_surfacevisible[j])
6966                         {
6967                                 r_surfacelist[numsurfacelist++] = surfaces + j;
6968                                 // update lightmap if needed
6969                                 if (update[j])
6970                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
6971                         }
6972                 }
6973         }
6974         else
6975                 for (;j < endj;j++)
6976                         if (r_refdef.viewcache.world_surfacevisible[j])
6977                                 r_surfacelist[numsurfacelist++] = surfaces + j;
6978         // don't do anything if there were no surfaces
6979         if (!numsurfacelist)
6980                 return;
6981         R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6982         GL_AlphaTest(false);
6983
6984         // add to stats if desired
6985         if (r_speeds.integer && !skysurfaces && !depthonly && !addwaterplanes)
6986         {
6987                 r_refdef.stats.world_surfaces += numsurfacelist;
6988                 for (j = 0;j < numsurfacelist;j++)
6989                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
6990         }
6991 }
6992
6993 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6994 {
6995         int i, j, endj, f, flagsmask;
6996         texture_t *t;
6997         dp_model_t *model = ent->model;
6998         msurface_t *surfaces;
6999         unsigned char *update;
7000         int numsurfacelist = 0;
7001         if (model == NULL)
7002                 return;
7003
7004         if (r_maxsurfacelist < model->num_surfaces)
7005         {
7006                 r_maxsurfacelist = model->num_surfaces;
7007                 if (r_surfacelist)
7008                         Mem_Free(r_surfacelist);
7009                 r_surfacelist = Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7010         }
7011
7012         // if the model is static it doesn't matter what value we give for
7013         // wantnormals and wanttangents, so this logic uses only rules applicable
7014         // to a model, knowing that they are meaningless otherwise
7015         if (ent == r_refdef.scene.worldentity)
7016                 RSurf_ActiveWorldEntity();
7017         else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
7018                 RSurf_ActiveModelEntity(ent, false, false);
7019         else
7020                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
7021
7022         surfaces = model->data_surfaces;
7023         update = model->brushq1.lightmapupdateflags;
7024
7025         // update light styles
7026         if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7027         {
7028                 model_brush_lightstyleinfo_t *style;
7029                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7030                 {
7031                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
7032                         {
7033                                 int *list = style->surfacelist;
7034                                 style->value = r_refdef.scene.lightstylevalue[style->style];
7035                                 for (j = 0;j < style->numsurfaces;j++)
7036                                         update[list[j]] = true;
7037                         }
7038                 }
7039         }
7040
7041         R_UpdateAllTextureInfo(ent);
7042         flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL);
7043
7044         if (debug)
7045         {
7046                 R_DrawDebugModel(ent);
7047                 return;
7048         }
7049
7050         f = 0;
7051         t = NULL;
7052         rsurface.uselightmaptexture = false;
7053         rsurface.texture = NULL;
7054         rsurface.rtlight = NULL;
7055         numsurfacelist = 0;
7056         // add visible surfaces to draw list
7057         j = model->firstmodelsurface;
7058         endj = j + model->nummodelsurfaces;
7059         for (;j < endj;j++)
7060                 r_surfacelist[numsurfacelist++] = surfaces + j;
7061         // don't do anything if there were no surfaces
7062         if (!numsurfacelist)
7063                 return;
7064         // update lightmaps if needed
7065         if (update)
7066                 for (j = model->firstmodelsurface;j < endj;j++)
7067                         if (update[j])
7068                                 R_BuildLightMap(ent, surfaces + j);
7069         R_QueueSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
7070         GL_AlphaTest(false);
7071
7072         // add to stats if desired
7073         if (r_speeds.integer && !skysurfaces && !depthonly && !addwaterplanes)
7074         {
7075                 r_refdef.stats.entities++;
7076                 r_refdef.stats.entities_surfaces += numsurfacelist;
7077                 for (j = 0;j < numsurfacelist;j++)
7078                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
7079         }
7080 }