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