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