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