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