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