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