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