]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
removed some code scraps from previous patch
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "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 "#ifndef MODE_LIGHTSOURCE\n"
828 "# ifdef USEREFLECTION\n"
829 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
830 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
831 "       vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
832 "       color.rgb = mix(color.rgb, myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
833 "# endif\n"
834 "#endif\n"
835 "\n"
836 "#ifdef USEFOG\n"
837 "       // apply fog\n"
838 "       color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
839 "#endif\n"
840 "\n"
841 "#ifdef USECONTRASTBOOST\n"
842 "       color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n"
843 "#endif\n"
844 "\n"
845 "       color.rgb *= SceneBrightness;\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]] / ([[(ContrastBoost - 1) * SceneBrightness]] + 1 / color.rgb);
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                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1367         }
1368         if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1369         if (r_glsl_permutation->loc_Color_Pants >= 0)
1370         {
1371                 if (rsurface.texture->currentskinframe->pants)
1372                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1373                 else
1374                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1375         }
1376         if (r_glsl_permutation->loc_Color_Shirt >= 0)
1377         {
1378                 if (rsurface.texture->currentskinframe->shirt)
1379                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1380                 else
1381                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1382         }
1383         if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1384         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1385         if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1386         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);
1387         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]);
1388         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]);
1389         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1390         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1391         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1392         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1393         CHECKGLERROR
1394         return permutation;
1395 }
1396
1397 #define SKINFRAME_HASH 1024
1398
1399 struct
1400 {
1401         int loadsequence; // incremented each level change
1402         memexpandablearray_t array;
1403         skinframe_t *hash[SKINFRAME_HASH];
1404 }
1405 r_skinframe;
1406
1407 void R_SkinFrame_PrepareForPurge(void)
1408 {
1409         r_skinframe.loadsequence++;
1410         // wrap it without hitting zero
1411         if (r_skinframe.loadsequence >= 200)
1412                 r_skinframe.loadsequence = 1;
1413 }
1414
1415 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1416 {
1417         if (!skinframe)
1418                 return;
1419         // mark the skinframe as used for the purging code
1420         skinframe->loadsequence = r_skinframe.loadsequence;
1421 }
1422
1423 void R_SkinFrame_Purge(void)
1424 {
1425         int i;
1426         skinframe_t *s;
1427         for (i = 0;i < SKINFRAME_HASH;i++)
1428         {
1429                 for (s = r_skinframe.hash[i];s;s = s->next)
1430                 {
1431                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1432                         {
1433                                 if (s->base == r_texture_notexture)     s->base   = NULL;
1434                                 if (s->nmap == r_texture_blanknormalmap)s->nmap   = NULL;
1435                                 if (s->merged == s->base)               s->merged = NULL;
1436                                 if (s->stain ) R_FreeTexture(s->stain );s->stain  = NULL;
1437                                 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1438                                 if (s->base  ) R_FreeTexture(s->base  );s->base   = NULL;
1439                                 if (s->pants ) R_FreeTexture(s->pants );s->pants  = NULL;
1440                                 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt  = NULL;
1441                                 if (s->nmap  ) R_FreeTexture(s->nmap  );s->nmap   = NULL;
1442                                 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss  = NULL;
1443                                 if (s->glow  ) R_FreeTexture(s->glow  );s->glow   = NULL;
1444                                 if (s->fog   ) R_FreeTexture(s->fog   );s->fog    = NULL;
1445                                 s->loadsequence = 0;
1446                         }
1447                 }
1448         }
1449 }
1450
1451 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1452 {
1453         skinframe_t *item;
1454         int hashindex;
1455         char basename[MAX_QPATH];
1456
1457         Image_StripImageExtension(name, basename, sizeof(basename));
1458
1459         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1460         for (item = r_skinframe.hash[hashindex];item;item = item->next)
1461                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1462                         break;
1463         if (!item)
1464         {
1465                 if (!add)
1466                         return NULL;
1467                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1468                 memset(item, 0, sizeof(*item));
1469                 strlcpy(item->basename, basename, sizeof(item->basename));
1470                 item->textureflags = textureflags;
1471                 item->comparewidth = comparewidth;
1472                 item->compareheight = compareheight;
1473                 item->comparecrc = comparecrc;
1474                 item->next = r_skinframe.hash[hashindex];
1475                 r_skinframe.hash[hashindex] = item;
1476         }
1477         R_SkinFrame_MarkUsed(item);
1478         return item;
1479 }
1480
1481 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1482 {
1483         // FIXME: it should be possible to disable loading various layers using
1484         // cvars, to prevent wasted loading time and memory usage if the user does
1485         // not want them
1486         qboolean loadnormalmap = true;
1487         qboolean loadgloss = true;
1488         qboolean loadpantsandshirt = true;
1489         qboolean loadglow = true;
1490         int j;
1491         unsigned char *pixels;
1492         unsigned char *bumppixels;
1493         unsigned char *basepixels = NULL;
1494         int basepixels_width;
1495         int basepixels_height;
1496         skinframe_t *skinframe;
1497
1498         if (cls.state == ca_dedicated)
1499                 return NULL;
1500
1501         // return an existing skinframe if already loaded
1502         // if loading of the first image fails, don't make a new skinframe as it
1503         // would cause all future lookups of this to be missing
1504         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1505         if (skinframe && skinframe->base)
1506                 return skinframe;
1507
1508         basepixels = loadimagepixels(name, complain, 0, 0);
1509         if (basepixels == NULL)
1510                 return NULL;
1511
1512         // we've got some pixels to store, so really allocate this new texture now
1513         if (!skinframe)
1514                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1515         skinframe->stain = NULL;
1516         skinframe->merged = NULL;
1517         skinframe->base = r_texture_notexture;
1518         skinframe->pants = NULL;
1519         skinframe->shirt = NULL;
1520         skinframe->nmap = r_texture_blanknormalmap;
1521         skinframe->gloss = NULL;
1522         skinframe->glow = NULL;
1523         skinframe->fog = NULL;
1524
1525         basepixels_width = image_width;
1526         basepixels_height = image_height;
1527         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);
1528
1529         if (textureflags & TEXF_ALPHA)
1530         {
1531                 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1532                         if (basepixels[j] < 255)
1533                                 break;
1534                 if (j < basepixels_width * basepixels_height * 4)
1535                 {
1536                         // has transparent pixels
1537                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1538                         for (j = 0;j < image_width * image_height * 4;j += 4)
1539                         {
1540                                 pixels[j+0] = 255;
1541                                 pixels[j+1] = 255;
1542                                 pixels[j+2] = 255;
1543                                 pixels[j+3] = basepixels[j+3];
1544                         }
1545                         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);
1546                         Mem_Free(pixels);
1547                 }
1548         }
1549
1550         // _norm is the name used by tenebrae and has been adopted as standard
1551         if (loadnormalmap)
1552         {
1553                 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0)) != NULL)
1554                 {
1555                         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);
1556                         Mem_Free(pixels);
1557                         pixels = NULL;
1558                 }
1559                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0)) != NULL)
1560                 {
1561                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1562                         Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1563                         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);
1564                         Mem_Free(pixels);
1565                         Mem_Free(bumppixels);
1566                 }
1567                 else if (r_shadow_bumpscale_basetexture.value > 0)
1568                 {
1569                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1570                         Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1571                         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);
1572                         Mem_Free(pixels);
1573                 }
1574         }
1575         // _luma is supported for tenebrae compatibility
1576         // (I think it's a very stupid name, but oh well)
1577         // _glow is the preferred name
1578         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;}
1579         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;}
1580         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;}
1581         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;}
1582
1583         if (basepixels)
1584                 Mem_Free(basepixels);
1585
1586         return skinframe;
1587 }
1588
1589 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)
1590 {
1591         int i;
1592         if (!force)
1593         {
1594                 for (i = 0;i < width*height;i++)
1595                         if (((unsigned char *)&palette[in[i]])[3] > 0)
1596                                 break;
1597                 if (i == width*height)
1598                         return NULL;
1599         }
1600         return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1601 }
1602
1603 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)
1604 {
1605         int i;
1606         unsigned char *temp1, *temp2;
1607         skinframe_t *skinframe;
1608
1609         if (cls.state == ca_dedicated)
1610                 return NULL;
1611
1612         // if already loaded just return it, otherwise make a new skinframe
1613         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1614         if (skinframe && skinframe->base)
1615                 return skinframe;
1616
1617         skinframe->stain = NULL;
1618         skinframe->merged = NULL;
1619         skinframe->base = r_texture_notexture;
1620         skinframe->pants = NULL;
1621         skinframe->shirt = NULL;
1622         skinframe->nmap = r_texture_blanknormalmap;
1623         skinframe->gloss = NULL;
1624         skinframe->glow = NULL;
1625         skinframe->fog = NULL;
1626
1627         // if no data was provided, then clearly the caller wanted to get a blank skinframe
1628         if (!skindata)
1629                 return NULL;
1630
1631         if (bitsperpixel == 32)
1632         {
1633                 if (r_shadow_bumpscale_basetexture.value > 0)
1634                 {
1635                         temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1636                         temp2 = temp1 + width * height * 4;
1637                         Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1638                         skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1639                         Mem_Free(temp1);
1640                 }
1641                 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1642                 if (textureflags & TEXF_ALPHA)
1643                 {
1644                         for (i = 3;i < width * height * 4;i += 4)
1645                                 if (skindata[i] < 255)
1646                                         break;
1647                         if (i < width * height * 4)
1648                         {
1649                                 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1650                                 memcpy(fogpixels, skindata, width * height * 4);
1651                                 for (i = 0;i < width * height * 4;i += 4)
1652                                         fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1653                                 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1654                                 Mem_Free(fogpixels);
1655                         }
1656                 }
1657         }
1658         else if (bitsperpixel == 8)
1659         {
1660                 if (r_shadow_bumpscale_basetexture.value > 0)
1661                 {
1662                         temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1663                         temp2 = temp1 + width * height * 4;
1664                         if (bitsperpixel == 32)
1665                                 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1666                         else
1667                         {
1668                                 // use either a custom palette or the quake palette
1669                                 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1670                                 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1671                         }
1672                         skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1673                         Mem_Free(temp1);
1674                 }
1675                 // use either a custom palette, or the quake palette
1676                 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
1677                 if (!palette && loadglowtexture)
1678                         skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, skinframe->textureflags, false); // glow
1679                 if (!palette && loadpantsandshirt)
1680                 {
1681                         skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, skinframe->textureflags, false); // pants
1682                         skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, skinframe->textureflags, false); // shirt
1683                 }
1684                 if (skinframe->pants || skinframe->shirt)
1685                         skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, skinframe->textureflags, false); // no special colors
1686                 if (textureflags & TEXF_ALPHA)
1687                 {
1688                         // if not using a custom alphapalette, use the quake one
1689                         if (!alphapalette)
1690                                 alphapalette = palette_alpha;
1691                         for (i = 0;i < width * height;i++)
1692                                 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1693                                         break;
1694                         if (i < width * height)
1695                                 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask
1696                 }
1697         }
1698
1699         return skinframe;
1700 }
1701
1702 skinframe_t *R_SkinFrame_LoadMissing(void)
1703 {
1704         skinframe_t *skinframe;
1705
1706         if (cls.state == ca_dedicated)
1707                 return NULL;
1708
1709         skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1710         skinframe->stain = NULL;
1711         skinframe->merged = NULL;
1712         skinframe->base = r_texture_notexture;
1713         skinframe->pants = NULL;
1714         skinframe->shirt = NULL;
1715         skinframe->nmap = r_texture_blanknormalmap;
1716         skinframe->gloss = NULL;
1717         skinframe->glow = NULL;
1718         skinframe->fog = NULL;
1719
1720         return skinframe;
1721 }
1722
1723 void gl_main_start(void)
1724 {
1725         int x;
1726         double r, alpha;
1727
1728         r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1729         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1730         {
1731                 alpha = 1 - exp(r / ((double)x*(double)x));
1732                 if (x == FOGMASKTABLEWIDTH - 1)
1733                         alpha = 0;
1734                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1735         }
1736
1737         memset(r_qwskincache, 0, sizeof(r_qwskincache));
1738         memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1739
1740         // set up r_skinframe loading system for textures
1741         memset(&r_skinframe, 0, sizeof(r_skinframe));
1742         r_skinframe.loadsequence = 1;
1743         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1744
1745         r_main_texturepool = R_AllocTexturePool();
1746         R_BuildBlankTextures();
1747         R_BuildNoTexture();
1748         if (gl_texturecubemap)
1749         {
1750                 R_BuildWhiteCube();
1751                 R_BuildNormalizationCube();
1752         }
1753         R_BuildFogTexture();
1754         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1755         memset(&r_waterstate, 0, sizeof(r_waterstate));
1756         memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1757         memset(&r_svbsp, 0, sizeof (r_svbsp));
1758 }
1759
1760 void gl_main_shutdown(void)
1761 {
1762         memset(r_qwskincache, 0, sizeof(r_qwskincache));
1763         memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1764
1765         // clear out the r_skinframe state
1766         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1767         memset(&r_skinframe, 0, sizeof(r_skinframe));
1768
1769         if (r_svbsp.nodes)
1770                 Mem_Free(r_svbsp.nodes);
1771         memset(&r_svbsp, 0, sizeof (r_svbsp));
1772         R_FreeTexturePool(&r_main_texturepool);
1773         r_texture_blanknormalmap = NULL;
1774         r_texture_white = NULL;
1775         r_texture_grey128 = NULL;
1776         r_texture_black = NULL;
1777         r_texture_whitecube = NULL;
1778         r_texture_normalizationcube = NULL;
1779         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1780         memset(&r_waterstate, 0, sizeof(r_waterstate));
1781         R_GLSL_Restart_f();
1782 }
1783
1784 extern void CL_ParseEntityLump(char *entitystring);
1785 void gl_main_newmap(void)
1786 {
1787         // FIXME: move this code to client
1788         int l;
1789         char *entities, entname[MAX_QPATH];
1790         if (cl.worldmodel)
1791         {
1792                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1793                 l = (int)strlen(entname) - 4;
1794                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1795                 {
1796                         memcpy(entname + l, ".ent", 5);
1797                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1798                         {
1799                                 CL_ParseEntityLump(entities);
1800                                 Mem_Free(entities);
1801                                 return;
1802                         }
1803                 }
1804                 if (cl.worldmodel->brush.entities)
1805                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
1806         }
1807 }
1808
1809 void GL_Main_Init(void)
1810 {
1811         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1812
1813         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1814         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1815         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1816         if (gamemode == GAME_NEHAHRA)
1817         {
1818                 Cvar_RegisterVariable (&gl_fogenable);
1819                 Cvar_RegisterVariable (&gl_fogdensity);
1820                 Cvar_RegisterVariable (&gl_fogred);
1821                 Cvar_RegisterVariable (&gl_foggreen);
1822                 Cvar_RegisterVariable (&gl_fogblue);
1823                 Cvar_RegisterVariable (&gl_fogstart);
1824                 Cvar_RegisterVariable (&gl_fogend);
1825         }
1826         Cvar_RegisterVariable(&r_depthfirst);
1827         Cvar_RegisterVariable(&r_nearclip);
1828         Cvar_RegisterVariable(&r_showbboxes);
1829         Cvar_RegisterVariable(&r_showsurfaces);
1830         Cvar_RegisterVariable(&r_showtris);
1831         Cvar_RegisterVariable(&r_shownormals);
1832         Cvar_RegisterVariable(&r_showlighting);
1833         Cvar_RegisterVariable(&r_showshadowvolumes);
1834         Cvar_RegisterVariable(&r_showcollisionbrushes);
1835         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1836         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1837         Cvar_RegisterVariable(&r_showdisabledepthtest);
1838         Cvar_RegisterVariable(&r_drawportals);
1839         Cvar_RegisterVariable(&r_drawentities);
1840         Cvar_RegisterVariable(&r_cullentities_trace);
1841         Cvar_RegisterVariable(&r_cullentities_trace_samples);
1842         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1843         Cvar_RegisterVariable(&r_cullentities_trace_delay);
1844         Cvar_RegisterVariable(&r_drawviewmodel);
1845         Cvar_RegisterVariable(&r_speeds);
1846         Cvar_RegisterVariable(&r_fullbrights);
1847         Cvar_RegisterVariable(&r_wateralpha);
1848         Cvar_RegisterVariable(&r_dynamic);
1849         Cvar_RegisterVariable(&r_fullbright);
1850         Cvar_RegisterVariable(&r_shadows);
1851         Cvar_RegisterVariable(&r_shadows_throwdistance);
1852         Cvar_RegisterVariable(&r_q1bsp_skymasking);
1853         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
1854         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
1855         Cvar_RegisterVariable(&r_textureunits);
1856         Cvar_RegisterVariable(&r_glsl);
1857         Cvar_RegisterVariable(&r_glsl_offsetmapping);
1858         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1859         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1860         Cvar_RegisterVariable(&r_glsl_deluxemapping);
1861         Cvar_RegisterVariable(&r_water);
1862         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
1863         Cvar_RegisterVariable(&r_water_clippingplanebias);
1864         Cvar_RegisterVariable(&r_water_refractdistort);
1865         Cvar_RegisterVariable(&r_water_reflectdistort);
1866         Cvar_RegisterVariable(&r_lerpsprites);
1867         Cvar_RegisterVariable(&r_lerpmodels);
1868         Cvar_RegisterVariable(&r_waterscroll);
1869         Cvar_RegisterVariable(&r_bloom);
1870         Cvar_RegisterVariable(&r_bloom_colorscale);
1871         Cvar_RegisterVariable(&r_bloom_brighten);
1872         Cvar_RegisterVariable(&r_bloom_blur);
1873         Cvar_RegisterVariable(&r_bloom_resolution);
1874         Cvar_RegisterVariable(&r_bloom_colorexponent);
1875         Cvar_RegisterVariable(&r_bloom_colorsubtract);
1876         Cvar_RegisterVariable(&r_hdr);
1877         Cvar_RegisterVariable(&r_hdr_scenebrightness);
1878         Cvar_RegisterVariable(&r_glsl_contrastboost);
1879         Cvar_RegisterVariable(&r_hdr_glowintensity);
1880         Cvar_RegisterVariable(&r_hdr_range);
1881         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1882         Cvar_RegisterVariable(&developer_texturelogging);
1883         Cvar_RegisterVariable(&gl_lightmaps);
1884         Cvar_RegisterVariable(&r_test);
1885         Cvar_RegisterVariable(&r_batchmode);
1886         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1887                 Cvar_SetValue("r_fullbrights", 0);
1888         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1889 }
1890
1891 extern void R_Textures_Init(void);
1892 extern void GL_Draw_Init(void);
1893 extern void GL_Main_Init(void);
1894 extern void R_Shadow_Init(void);
1895 extern void R_Sky_Init(void);
1896 extern void GL_Surf_Init(void);
1897 extern void R_Light_Init(void);
1898 extern void R_Particles_Init(void);
1899 extern void R_Explosion_Init(void);
1900 extern void gl_backend_init(void);
1901 extern void Sbar_Init(void);
1902 extern void R_LightningBeams_Init(void);
1903 extern void Mod_RenderInit(void);
1904
1905 void Render_Init(void)
1906 {
1907         gl_backend_init();
1908         R_Textures_Init();
1909         GL_Main_Init();
1910         GL_Draw_Init();
1911         R_Shadow_Init();
1912         R_Sky_Init();
1913         GL_Surf_Init();
1914         Sbar_Init();
1915         R_Light_Init();
1916         R_Particles_Init();
1917         R_Explosion_Init();
1918         R_LightningBeams_Init();
1919         Mod_RenderInit();
1920 }
1921
1922 /*
1923 ===============
1924 GL_Init
1925 ===============
1926 */
1927 extern char *ENGINE_EXTENSIONS;
1928 void GL_Init (void)
1929 {
1930         VID_CheckExtensions();
1931
1932         // LordHavoc: report supported extensions
1933         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1934
1935         // clear to black (loading plaque will be seen over this)
1936         CHECKGLERROR
1937         qglClearColor(0,0,0,1);CHECKGLERROR
1938         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1939 }
1940
1941 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1942 {
1943         int i;
1944         mplane_t *p;
1945         for (i = 0;i < r_view.numfrustumplanes;i++)
1946         {
1947                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
1948                 if (i == 4)
1949                         continue;
1950                 p = r_view.frustum + i;
1951                 switch(p->signbits)
1952                 {
1953                 default:
1954                 case 0:
1955                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1956                                 return true;
1957                         break;
1958                 case 1:
1959                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1960                                 return true;
1961                         break;
1962                 case 2:
1963                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1964                                 return true;
1965                         break;
1966                 case 3:
1967                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1968                                 return true;
1969                         break;
1970                 case 4:
1971                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1972                                 return true;
1973                         break;
1974                 case 5:
1975                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1976                                 return true;
1977                         break;
1978                 case 6:
1979                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1980                                 return true;
1981                         break;
1982                 case 7:
1983                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1984                                 return true;
1985                         break;
1986                 }
1987         }
1988         return false;
1989 }
1990
1991 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1992 {
1993         int i;
1994         const mplane_t *p;
1995         for (i = 0;i < numplanes;i++)
1996         {
1997                 p = planes + i;
1998                 switch(p->signbits)
1999                 {
2000                 default:
2001                 case 0:
2002                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2003                                 return true;
2004                         break;
2005                 case 1:
2006                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2007                                 return true;
2008                         break;
2009                 case 2:
2010                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2011                                 return true;
2012                         break;
2013                 case 3:
2014                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2015                                 return true;
2016                         break;
2017                 case 4:
2018                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2019                                 return true;
2020                         break;
2021                 case 5:
2022                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2023                                 return true;
2024                         break;
2025                 case 6:
2026                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2027                                 return true;
2028                         break;
2029                 case 7:
2030                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2031                                 return true;
2032                         break;
2033                 }
2034         }
2035         return false;
2036 }
2037
2038 //==================================================================================
2039
2040 static void R_UpdateEntityLighting(entity_render_t *ent)
2041 {
2042         vec3_t tempdiffusenormal;
2043
2044         // fetch the lighting from the worldmodel data
2045         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));
2046         VectorClear(ent->modellight_diffuse);
2047         VectorClear(tempdiffusenormal);
2048         if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
2049         {
2050                 vec3_t org;
2051                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2052                 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
2053         }
2054         else // highly rare
2055                 VectorSet(ent->modellight_ambient, 1, 1, 1);
2056
2057         // move the light direction into modelspace coordinates for lighting code
2058         Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
2059         if(VectorLength2(ent->modellight_lightdir) > 0)
2060         {
2061                 VectorNormalize(ent->modellight_lightdir);
2062         }
2063         else
2064         {
2065                 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
2066         }
2067
2068         // scale ambient and directional light contributions according to rendering variables
2069         ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
2070         ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
2071         ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
2072         ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
2073         ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
2074         ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
2075 }
2076
2077 static void R_View_UpdateEntityVisible (void)
2078 {
2079         int i, renderimask;
2080         entity_render_t *ent;
2081
2082         if (!r_drawentities.integer)
2083                 return;
2084
2085         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2086         if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
2087         {
2088                 // worldmodel can check visibility
2089                 for (i = 0;i < r_refdef.numentities;i++)
2090                 {
2091                         ent = r_refdef.entities[i];
2092                         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));
2093                 }
2094                 if(r_cullentities_trace.integer)
2095                 {
2096                         for (i = 0;i < r_refdef.numentities;i++)
2097                         {
2098                                 ent = r_refdef.entities[i];
2099                                 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2100                                 {
2101                                         if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
2102                                                 ent->last_trace_visibility = realtime;
2103                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2104                                                 r_viewcache.entityvisible[i] = 0;
2105                                 }
2106                         }
2107                 }
2108         }
2109         else
2110         {
2111                 // no worldmodel or it can't check visibility
2112                 for (i = 0;i < r_refdef.numentities;i++)
2113                 {
2114                         ent = r_refdef.entities[i];
2115                         r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
2116                 }
2117         }
2118
2119         // update entity lighting (even on hidden entities for r_shadows)
2120         for (i = 0;i < r_refdef.numentities;i++)
2121                 R_UpdateEntityLighting(r_refdef.entities[i]);
2122 }
2123
2124 // only used if skyrendermasked, and normally returns false
2125 int R_DrawBrushModelsSky (void)
2126 {
2127         int i, sky;
2128         entity_render_t *ent;
2129
2130         if (!r_drawentities.integer)
2131                 return false;
2132
2133         sky = false;
2134         for (i = 0;i < r_refdef.numentities;i++)
2135         {
2136                 if (!r_viewcache.entityvisible[i])
2137                         continue;
2138                 ent = r_refdef.entities[i];
2139                 if (!ent->model || !ent->model->DrawSky)
2140                         continue;
2141                 ent->model->DrawSky(ent);
2142                 sky = true;
2143         }
2144         return sky;
2145 }
2146
2147 static void R_DrawNoModel(entity_render_t *ent);
2148 static void R_DrawModels(void)
2149 {
2150         int i;
2151         entity_render_t *ent;
2152
2153         if (!r_drawentities.integer)
2154                 return;
2155
2156         for (i = 0;i < r_refdef.numentities;i++)
2157         {
2158                 if (!r_viewcache.entityvisible[i])
2159                         continue;
2160                 ent = r_refdef.entities[i];
2161                 r_refdef.stats.entities++;
2162                 if (ent->model && ent->model->Draw != NULL)
2163                         ent->model->Draw(ent);
2164                 else
2165                         R_DrawNoModel(ent);
2166         }
2167 }
2168
2169 static void R_DrawModelsDepth(void)
2170 {
2171         int i;
2172         entity_render_t *ent;
2173
2174         if (!r_drawentities.integer)
2175                 return;
2176
2177         for (i = 0;i < r_refdef.numentities;i++)
2178         {
2179                 if (!r_viewcache.entityvisible[i])
2180                         continue;
2181                 ent = r_refdef.entities[i];
2182                 r_refdef.stats.entities++;
2183                 if (ent->model && ent->model->DrawDepth != NULL)
2184                         ent->model->DrawDepth(ent);
2185         }
2186 }
2187
2188 static void R_DrawModelsDebug(void)
2189 {
2190         int i;
2191         entity_render_t *ent;
2192
2193         if (!r_drawentities.integer)
2194                 return;
2195
2196         for (i = 0;i < r_refdef.numentities;i++)
2197         {
2198                 if (!r_viewcache.entityvisible[i])
2199                         continue;
2200                 ent = r_refdef.entities[i];
2201                 r_refdef.stats.entities++;
2202                 if (ent->model && ent->model->DrawDebug != NULL)
2203                         ent->model->DrawDebug(ent);
2204         }
2205 }
2206
2207 static void R_DrawModelsAddWaterPlanes(void)
2208 {
2209         int i;
2210         entity_render_t *ent;
2211
2212         if (!r_drawentities.integer)
2213                 return;
2214
2215         for (i = 0;i < r_refdef.numentities;i++)
2216         {
2217                 if (!r_viewcache.entityvisible[i])
2218                         continue;
2219                 ent = r_refdef.entities[i];
2220                 r_refdef.stats.entities++;
2221                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2222                         ent->model->DrawAddWaterPlanes(ent);
2223         }
2224 }
2225
2226 static void R_View_SetFrustum(void)
2227 {
2228         int i;
2229         double slopex, slopey;
2230
2231         // break apart the view matrix into vectors for various purposes
2232         Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
2233         VectorNegate(r_view.left, r_view.right);
2234
2235 #if 0
2236         r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
2237         r_view.frustum[0].normal[1] = 0 - 0;
2238         r_view.frustum[0].normal[2] = -1 - 0;
2239         r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
2240         r_view.frustum[1].normal[1] = 0 + 0;
2241         r_view.frustum[1].normal[2] = -1 + 0;
2242         r_view.frustum[2].normal[0] = 0 - 0;
2243         r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
2244         r_view.frustum[2].normal[2] = -1 - 0;
2245         r_view.frustum[3].normal[0] = 0 + 0;
2246         r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
2247         r_view.frustum[3].normal[2] = -1 + 0;
2248 #endif
2249
2250 #if 0
2251         zNear = r_refdef.nearclip;
2252         nudge = 1.0 - 1.0 / (1<<23);
2253         r_view.frustum[4].normal[0] = 0 - 0;
2254         r_view.frustum[4].normal[1] = 0 - 0;
2255         r_view.frustum[4].normal[2] = -1 - -nudge;
2256         r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
2257         r_view.frustum[5].normal[0] = 0 + 0;
2258         r_view.frustum[5].normal[1] = 0 + 0;
2259         r_view.frustum[5].normal[2] = -1 + -nudge;
2260         r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
2261 #endif
2262
2263
2264
2265 #if 0
2266         r_view.frustum[0].normal[0] = m[3] - m[0];
2267         r_view.frustum[0].normal[1] = m[7] - m[4];
2268         r_view.frustum[0].normal[2] = m[11] - m[8];
2269         r_view.frustum[0].dist = m[15] - m[12];
2270
2271         r_view.frustum[1].normal[0] = m[3] + m[0];
2272         r_view.frustum[1].normal[1] = m[7] + m[4];
2273         r_view.frustum[1].normal[2] = m[11] + m[8];
2274         r_view.frustum[1].dist = m[15] + m[12];
2275
2276         r_view.frustum[2].normal[0] = m[3] - m[1];
2277         r_view.frustum[2].normal[1] = m[7] - m[5];
2278         r_view.frustum[2].normal[2] = m[11] - m[9];
2279         r_view.frustum[2].dist = m[15] - m[13];
2280
2281         r_view.frustum[3].normal[0] = m[3] + m[1];
2282         r_view.frustum[3].normal[1] = m[7] + m[5];
2283         r_view.frustum[3].normal[2] = m[11] + m[9];
2284         r_view.frustum[3].dist = m[15] + m[13];
2285
2286         r_view.frustum[4].normal[0] = m[3] - m[2];
2287         r_view.frustum[4].normal[1] = m[7] - m[6];
2288         r_view.frustum[4].normal[2] = m[11] - m[10];
2289         r_view.frustum[4].dist = m[15] - m[14];
2290
2291         r_view.frustum[5].normal[0] = m[3] + m[2];
2292         r_view.frustum[5].normal[1] = m[7] + m[6];
2293         r_view.frustum[5].normal[2] = m[11] + m[10];
2294         r_view.frustum[5].dist = m[15] + m[14];
2295 #endif
2296
2297
2298
2299         if (r_view.useperspective)
2300         {
2301                 slopex = 1.0 / r_view.frustum_x;
2302                 slopey = 1.0 / r_view.frustum_y;
2303                 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
2304                 VectorMA(r_view.forward,  slopex, r_view.left, r_view.frustum[1].normal);
2305                 VectorMA(r_view.forward, -slopey, r_view.up  , r_view.frustum[2].normal);
2306                 VectorMA(r_view.forward,  slopey, r_view.up  , r_view.frustum[3].normal);
2307                 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2308
2309                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2310                 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
2311                 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward,  1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
2312                 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left,  1024 * slopey, r_view.up, r_view.frustumcorner[2]);
2313                 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward,  1024 * slopex, r_view.left,  1024 * slopey, r_view.up, r_view.frustumcorner[3]);
2314
2315                 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
2316                 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
2317                 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
2318                 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
2319                 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2320         }
2321         else
2322         {
2323                 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
2324                 VectorScale(r_view.left,  r_view.ortho_x, r_view.frustum[1].normal);
2325                 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
2326                 VectorScale(r_view.up,  r_view.ortho_y, r_view.frustum[3].normal);
2327                 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2328                 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
2329                 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
2330                 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
2331                 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
2332                 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2333         }
2334         r_view.numfrustumplanes = 5;
2335
2336         if (r_view.useclipplane)
2337         {
2338                 r_view.numfrustumplanes = 6;
2339                 r_view.frustum[5] = r_view.clipplane;
2340         }
2341
2342         for (i = 0;i < r_view.numfrustumplanes;i++)
2343                 PlaneClassify(r_view.frustum + i);
2344
2345         // LordHavoc: note to all quake engine coders, Quake had a special case
2346         // for 90 degrees which assumed a square view (wrong), so I removed it,
2347         // Quake2 has it disabled as well.
2348
2349         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2350         //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2351         //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2352         //PlaneClassify(&frustum[0]);
2353
2354         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2355         //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2356         //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2357         //PlaneClassify(&frustum[1]);
2358
2359         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2360         //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2361         //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2362         //PlaneClassify(&frustum[2]);
2363
2364         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2365         //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2366         //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2367         //PlaneClassify(&frustum[3]);
2368
2369         // nearclip plane
2370         //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2371         //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2372         //PlaneClassify(&frustum[4]);
2373 }
2374
2375 void R_View_Update(void)
2376 {
2377         R_View_SetFrustum();
2378         R_View_WorldVisibility(r_view.useclipplane);
2379         R_View_UpdateEntityVisible();
2380 }
2381
2382 void R_SetupView(void)
2383 {
2384         if (!r_view.useperspective)
2385                 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);
2386         else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2387                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2388         else
2389                 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2390
2391         GL_SetupView_Orientation_FromEntity(&r_view.matrix);
2392
2393         if (r_view.useclipplane)
2394         {
2395                 // LordHavoc: couldn't figure out how to make this approach the
2396                 vec_t dist = r_view.clipplane.dist - r_water_clippingplanebias.value;
2397                 vec_t viewdist = DotProduct(r_view.origin, r_view.clipplane.normal);
2398                 if (viewdist < r_view.clipplane.dist + r_water_clippingplanebias.value)
2399                         dist = r_view.clipplane.dist;
2400                 GL_SetupView_ApplyCustomNearClipPlane(r_view.clipplane.normal[0], r_view.clipplane.normal[1], r_view.clipplane.normal[2], dist);
2401         }
2402 }
2403
2404 void R_ResetViewRendering2D(void)
2405 {
2406         if (gl_support_fragment_shader)
2407         {
2408                 qglUseProgramObjectARB(0);CHECKGLERROR
2409         }
2410
2411         DrawQ_Finish();
2412
2413         // GL is weird because it's bottom to top, r_view.y is top to bottom
2414         qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2415         GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2416         GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2417         GL_Color(1, 1, 1, 1);
2418         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2419         GL_BlendFunc(GL_ONE, GL_ZERO);
2420         GL_AlphaTest(false);
2421         GL_ScissorTest(false);
2422         GL_DepthMask(false);
2423         GL_DepthRange(0, 1);
2424         GL_DepthTest(false);
2425         R_Mesh_Matrix(&identitymatrix);
2426         R_Mesh_ResetTextureState();
2427         GL_PolygonOffset(0, 0);
2428         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2429         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2430         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2431         qglStencilMask(~0);CHECKGLERROR
2432         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2433         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2434         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2435 }
2436
2437 void R_ResetViewRendering3D(void)
2438 {
2439         if (gl_support_fragment_shader)
2440         {
2441                 qglUseProgramObjectARB(0);CHECKGLERROR
2442         }
2443
2444         DrawQ_Finish();
2445
2446         // GL is weird because it's bottom to top, r_view.y is top to bottom
2447         qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2448         R_SetupView();
2449         GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2450         GL_Color(1, 1, 1, 1);
2451         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2452         GL_BlendFunc(GL_ONE, GL_ZERO);
2453         GL_AlphaTest(false);
2454         GL_ScissorTest(true);
2455         GL_DepthMask(true);
2456         GL_DepthRange(0, 1);
2457         GL_DepthTest(true);
2458         R_Mesh_Matrix(&identitymatrix);
2459         R_Mesh_ResetTextureState();
2460         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2461         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2462         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2463         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2464         qglStencilMask(~0);CHECKGLERROR
2465         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2466         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2467         GL_CullFace(r_view.cullface_back);
2468 }
2469
2470 /*
2471         R_Bloom_SetupShader(
2472 "// bloom shader\n"
2473 "// written by Forest 'LordHavoc' Hale\n"
2474 "\n"
2475 "// common definitions between vertex shader and fragment shader:\n"
2476 "\n"
2477 "#ifdef __GLSL_CG_DATA_TYPES\n"
2478 "#define myhalf half\n"
2479 "#define myhvec2 hvec2\n"
2480 "#define myhvec3 hvec3\n"
2481 "#define myhvec4 hvec4\n"
2482 "#else\n"
2483 "#define myhalf float\n"
2484 "#define myhvec2 vec2\n"
2485 "#define myhvec3 vec3\n"
2486 "#define myhvec4 vec4\n"
2487 "#endif\n"
2488 "\n"
2489 "varying vec2 ScreenTexCoord;\n"
2490 "varying vec2 BloomTexCoord;\n"
2491 "\n"
2492 "\n"
2493 "\n"
2494 "\n"
2495 "// vertex shader specific:\n"
2496 "#ifdef VERTEX_SHADER\n"
2497 "\n"
2498 "void main(void)\n"
2499 "{\n"
2500 "       ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2501 "       BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2502 "       // transform vertex to camera space, using ftransform to match non-VS\n"
2503 "       // rendering\n"
2504 "       gl_Position = ftransform();\n"
2505 "}\n"
2506 "\n"
2507 "#endif // VERTEX_SHADER\n"
2508 "\n"
2509 "\n"
2510 "\n"
2511 "\n"
2512 "// fragment shader specific:\n"
2513 "#ifdef FRAGMENT_SHADER\n"
2514 "\n"
2515 "void main(void)\n"
2516 "{\n"
2517 "       int x, y;
2518 "       myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2519 "       for (x = -BLUR_X;x <= BLUR_X;x++)
2520 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2521 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2522 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2523 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2524
2525 "       gl_FragColor = vec4(color);\n"
2526 "}\n"
2527 "\n"
2528 "#endif // FRAGMENT_SHADER\n"
2529 */
2530
2531 void R_RenderScene(qboolean addwaterplanes);
2532
2533 static void R_Water_StartFrame(void)
2534 {
2535         int i;
2536         int waterwidth, waterheight, texturewidth, textureheight;
2537         r_waterstate_waterplane_t *p;
2538
2539         // set waterwidth and waterheight to the water resolution that will be
2540         // used (often less than the screen resolution for faster rendering)
2541         waterwidth = (int)bound(1, r_view.width * r_water_resolutionmultiplier.value, r_view.width);
2542         waterheight = (int)bound(1, r_view.height * r_water_resolutionmultiplier.value, r_view.height);
2543
2544         // calculate desired texture sizes
2545         // can't use water if the card does not support the texture size
2546         if (!r_water.integer || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2547                 texturewidth = textureheight = waterwidth = waterheight = 0;
2548         else if (gl_support_arb_texture_non_power_of_two)
2549         {
2550                 texturewidth = waterwidth;
2551                 textureheight = waterheight;
2552         }
2553         else
2554         {
2555                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
2556                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
2557         }
2558
2559         // allocate textures as needed
2560         if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2561         {
2562                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2563                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2564                 {
2565                         if (p->texture_refraction)
2566                                 R_FreeTexture(p->texture_refraction);
2567                         p->texture_refraction = NULL;
2568                         if (p->texture_reflection)
2569                                 R_FreeTexture(p->texture_reflection);
2570                         p->texture_reflection = NULL;
2571                 }
2572                 memset(&r_waterstate, 0, sizeof(r_waterstate));
2573                 r_waterstate.waterwidth = waterwidth;
2574                 r_waterstate.waterheight = waterheight;
2575                 r_waterstate.texturewidth = texturewidth;
2576                 r_waterstate.textureheight = textureheight;
2577         }
2578
2579         if (r_waterstate.waterwidth)
2580         {
2581                 r_waterstate.enabled = true;
2582
2583                 // set up variables that will be used in shader setup
2584                 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2585                 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2586                 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2587                 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2588         }
2589
2590         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2591         r_waterstate.numwaterplanes = 0;
2592 }
2593
2594 static void R_Water_AddWaterPlane(msurface_t *surface)
2595 {
2596         int triangleindex, planeindex;
2597         const int *e;
2598         vec_t f;
2599         vec3_t vert[3];
2600         vec3_t normal;
2601         vec3_t center;
2602         r_waterstate_waterplane_t *p;
2603         // just use the first triangle with a valid normal for any decisions
2604         VectorClear(normal);
2605         VectorClear(center);
2606         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2607         {
2608                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2609                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2610                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2611                 TriangleNormal(vert[0], vert[1], vert[2], normal);
2612                 if (VectorLength2(normal) >= 0.001)
2613                         break;
2614         }
2615         // now find the center of this surface
2616         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles*3;triangleindex++, e++)
2617         {
2618                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2619                 VectorAdd(center, vert[0], center);
2620         }
2621         f = 1.0 / surface->num_triangles*3;
2622         VectorScale(center, f, center);
2623
2624         // find a matching plane if there is one
2625         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2626                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2627                         break;
2628         if (planeindex >= r_waterstate.maxwaterplanes)
2629                 return; // nothing we can do, out of planes
2630
2631         // if this triangle does not fit any known plane rendered this frame, add one
2632         if (planeindex >= r_waterstate.numwaterplanes)
2633         {
2634                 // store the new plane
2635                 r_waterstate.numwaterplanes++;
2636                 VectorCopy(normal, p->plane.normal);
2637                 VectorNormalize(p->plane.normal);
2638                 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2639                 PlaneClassify(&p->plane);
2640                 // flip the plane if it does not face the viewer
2641                 if (PlaneDiff(r_view.origin, &p->plane) < 0)
2642                 {
2643                         VectorNegate(p->plane.normal, p->plane.normal);
2644                         p->plane.dist *= -1;
2645                         PlaneClassify(&p->plane);
2646                 }
2647                 // clear materialflags and pvs
2648                 p->materialflags = 0;
2649                 p->pvsvalid = false;
2650         }
2651         // merge this surface's materialflags into the waterplane
2652         p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2653         // merge this surface's PVS into the waterplane
2654         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.worldmodel && r_refdef.worldmodel->brush.FatPVS)
2655         {
2656                 r_refdef.worldmodel->brush.FatPVS(r_refdef.worldmodel, r_view.origin, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2657                 p->pvsvalid = true;
2658         }
2659 }
2660
2661 static void R_Water_ProcessPlanes(void)
2662 {
2663         r_view_t originalview;
2664         int planeindex;
2665         r_waterstate_waterplane_t *p;
2666
2667         originalview = r_view;
2668
2669         // make sure enough textures are allocated
2670         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2671         {
2672                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2673                 {
2674                         if (!p->texture_refraction)
2675                                 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);
2676                         if (!p->texture_refraction)
2677                                 goto error;
2678                 }
2679
2680                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2681                 {
2682                         if (!p->texture_reflection)
2683                                 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);
2684                         if (!p->texture_reflection)
2685                                 goto error;
2686                 }
2687         }
2688
2689         // render views
2690         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2691         {
2692                 r_view.showdebug = false;
2693                 r_view.width = r_waterstate.waterwidth;
2694                 r_view.height = r_waterstate.waterheight;
2695                 r_view.useclipplane = true;
2696                 r_waterstate.renderingscene = true;
2697
2698                 // render the normal view scene and copy into texture
2699                 // (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)
2700                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2701                 {
2702                         r_view.clipplane = p->plane;
2703                         VectorNegate(r_view.clipplane.normal, r_view.clipplane.normal);
2704                         r_view.clipplane.dist = -r_view.clipplane.dist;
2705                         PlaneClassify(&r_view.clipplane);
2706
2707                         R_RenderScene(false);
2708
2709                         // copy view into the screen texture
2710                         R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
2711                         GL_ActiveTexture(0);
2712                         CHECKGLERROR
2713                         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
2714                 }
2715
2716                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2717                 {
2718                         // render reflected scene and copy into texture
2719                         Matrix4x4_Reflect(&r_view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2720                         r_view.clipplane = p->plane;
2721                         // reverse the cullface settings for this render
2722                         r_view.cullface_front = GL_FRONT;
2723                         r_view.cullface_back = GL_BACK;
2724                         if (r_refdef.worldmodel && r_refdef.worldmodel->brush.num_pvsclusterbytes)
2725                         {
2726                                 r_view.usecustompvs = true;
2727                                 if (p->pvsvalid)
2728                                         memcpy(r_viewcache.world_pvsbits, p->pvsbits, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2729                                 else
2730                                         memset(r_viewcache.world_pvsbits, 0xFF, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2731                         }
2732
2733                         R_ResetViewRendering3D();
2734                         R_ClearScreen();
2735
2736                         R_RenderScene(false);
2737
2738                         R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
2739                         GL_ActiveTexture(0);
2740                         CHECKGLERROR
2741                         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
2742
2743                         R_ResetViewRendering3D();
2744                         R_ClearScreen();
2745                 }
2746
2747                 r_view = originalview;
2748                 r_waterstate.renderingscene = false;
2749         }
2750         return;
2751 error:
2752         r_view = originalview;
2753         r_waterstate.renderingscene = false;
2754         Cvar_SetValueQuick(&r_water, 0);
2755         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
2756         return;
2757 }
2758
2759 void R_Bloom_StartFrame(void)
2760 {
2761         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2762
2763         // set bloomwidth and bloomheight to the bloom resolution that will be
2764         // used (often less than the screen resolution for faster rendering)
2765         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2766         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2767         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2768
2769         // calculate desired texture sizes
2770         if (gl_support_arb_texture_non_power_of_two)
2771         {
2772                 screentexturewidth = r_view.width;
2773                 screentextureheight = r_view.height;
2774                 bloomtexturewidth = r_bloomstate.bloomwidth;
2775                 bloomtextureheight = r_bloomstate.bloomheight;
2776         }
2777         else
2778         {
2779                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
2780                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
2781                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
2782                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
2783         }
2784
2785         if (r_hdr.integer)
2786         {
2787                 screentexturewidth = screentextureheight = 0;
2788         }
2789         else if (r_bloom.integer)
2790         {
2791         }
2792         else
2793         {
2794                 screentexturewidth = screentextureheight = 0;
2795                 bloomtexturewidth = bloomtextureheight = 0;
2796         }
2797
2798         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)
2799         {
2800                 // can't use bloom if the parameters are too weird
2801                 // can't use bloom if the card does not support the texture size
2802                 if (r_bloomstate.texture_screen)
2803                         R_FreeTexture(r_bloomstate.texture_screen);
2804                 if (r_bloomstate.texture_bloom)
2805                         R_FreeTexture(r_bloomstate.texture_bloom);
2806                 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2807                 return;
2808         }
2809
2810         r_bloomstate.enabled = true;
2811         r_bloomstate.hdr = r_hdr.integer != 0;
2812
2813         // allocate textures as needed
2814         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2815         {
2816                 if (r_bloomstate.texture_screen)
2817                         R_FreeTexture(r_bloomstate.texture_screen);
2818                 r_bloomstate.texture_screen = NULL;
2819                 r_bloomstate.screentexturewidth = screentexturewidth;
2820                 r_bloomstate.screentextureheight = screentextureheight;
2821                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2822                         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);
2823         }
2824         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2825         {
2826                 if (r_bloomstate.texture_bloom)
2827                         R_FreeTexture(r_bloomstate.texture_bloom);
2828                 r_bloomstate.texture_bloom = NULL;
2829                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2830                 r_bloomstate.bloomtextureheight = bloomtextureheight;
2831                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2832                         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);
2833         }
2834
2835         // set up a texcoord array for the full resolution screen image
2836         // (we have to keep this around to copy back during final render)
2837         r_bloomstate.screentexcoord2f[0] = 0;
2838         r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2839         r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2840         r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2841         r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2842         r_bloomstate.screentexcoord2f[5] = 0;
2843         r_bloomstate.screentexcoord2f[6] = 0;
2844         r_bloomstate.screentexcoord2f[7] = 0;
2845
2846         // set up a texcoord array for the reduced resolution bloom image
2847         // (which will be additive blended over the screen image)
2848         r_bloomstate.bloomtexcoord2f[0] = 0;
2849         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2850         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2851         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2852         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2853         r_bloomstate.bloomtexcoord2f[5] = 0;
2854         r_bloomstate.bloomtexcoord2f[6] = 0;
2855         r_bloomstate.bloomtexcoord2f[7] = 0;
2856 }
2857
2858 void R_Bloom_CopyScreenTexture(float colorscale)
2859 {
2860         r_refdef.stats.bloom++;
2861
2862         R_ResetViewRendering2D();
2863         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2864         R_Mesh_ColorPointer(NULL, 0, 0);
2865         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2866         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2867
2868         // copy view into the screen texture
2869         GL_ActiveTexture(0);
2870         CHECKGLERROR
2871         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
2872         r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2873
2874         // now scale it down to the bloom texture size
2875         CHECKGLERROR
2876         qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2877         GL_BlendFunc(GL_ONE, GL_ZERO);
2878         GL_Color(colorscale, colorscale, colorscale, 1);
2879         // TODO: optimize with multitexture or GLSL
2880         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2881         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2882
2883         // we now have a bloom image in the framebuffer
2884         // copy it into the bloom image texture for later processing
2885         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2886         GL_ActiveTexture(0);
2887         CHECKGLERROR
2888         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
2889         r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2890 }
2891
2892 void R_Bloom_CopyHDRTexture(void)
2893 {
2894         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2895         GL_ActiveTexture(0);
2896         CHECKGLERROR
2897         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
2898         r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2899 }
2900
2901 void R_Bloom_MakeTexture(void)
2902 {
2903         int x, range, dir;
2904         float xoffset, yoffset, r, brighten;
2905
2906         r_refdef.stats.bloom++;
2907
2908         R_ResetViewRendering2D();
2909         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2910         R_Mesh_ColorPointer(NULL, 0, 0);
2911
2912         // we have a bloom image in the framebuffer
2913         CHECKGLERROR
2914         qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2915
2916         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
2917         {
2918                 x *= 2;
2919                 r = bound(0, r_bloom_colorexponent.value / x, 1);
2920                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2921                 GL_Color(r, r, r, 1);
2922                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2923                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2924                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2925                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2926
2927                 // copy the vertically blurred bloom view to a texture
2928                 GL_ActiveTexture(0);
2929                 CHECKGLERROR
2930                 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
2931                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2932         }
2933
2934         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2935         brighten = r_bloom_brighten.value;
2936         if (r_hdr.integer)
2937                 brighten *= r_hdr_range.value;
2938         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2939         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2940
2941         for (dir = 0;dir < 2;dir++)
2942         {
2943                 // blend on at multiple vertical offsets to achieve a vertical blur
2944                 // TODO: do offset blends using GLSL
2945                 GL_BlendFunc(GL_ONE, GL_ZERO);
2946                 for (x = -range;x <= range;x++)
2947                 {
2948                         if (!dir){xoffset = 0;yoffset = x;}
2949                         else {xoffset = x;yoffset = 0;}
2950                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
2951                         yoffset /= (float)r_bloomstate.bloomtextureheight;
2952                         // compute a texcoord array with the specified x and y offset
2953                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2954                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2955                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2956                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2957                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2958                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2959                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2960                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2961                         // this r value looks like a 'dot' particle, fading sharply to
2962                         // black at the edges
2963                         // (probably not realistic but looks good enough)
2964                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2965                         //r = (dir ? 1.0f : brighten)/(range*2+1);
2966                         r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2967                         GL_Color(r, r, r, 1);
2968                         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2969                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2970                         GL_BlendFunc(GL_ONE, GL_ONE);
2971                 }
2972
2973                 // copy the vertically blurred bloom view to a texture
2974                 GL_ActiveTexture(0);
2975                 CHECKGLERROR
2976                 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
2977                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2978         }
2979
2980         // apply subtract last
2981         // (just like it would be in a GLSL shader)
2982         if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
2983         {
2984                 GL_BlendFunc(GL_ONE, GL_ZERO);
2985                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2986                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2987                 GL_Color(1, 1, 1, 1);
2988                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2989                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2990
2991                 GL_BlendFunc(GL_ONE, GL_ONE);
2992                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2993                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2994                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2995                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
2996                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2997                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2998                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2999
3000                 // copy the darkened bloom view to a texture
3001                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3002                 GL_ActiveTexture(0);
3003                 CHECKGLERROR
3004                 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
3005                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3006         }
3007 }
3008
3009 void R_HDR_RenderBloomTexture(void)
3010 {
3011         int oldwidth, oldheight;
3012
3013         oldwidth = r_view.width;
3014         oldheight = r_view.height;
3015         r_view.width = r_bloomstate.bloomwidth;
3016         r_view.height = r_bloomstate.bloomheight;
3017
3018         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
3019         // TODO: add exposure compensation features
3020         // TODO: add fp16 framebuffer support
3021
3022         r_view.showdebug = false;
3023         r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
3024         if (r_hdr.integer)
3025                 r_view.colorscale /= r_hdr_range.value;
3026         r_waterstate.numwaterplanes = 0;
3027         R_RenderScene(r_waterstate.enabled);
3028         r_view.showdebug = true;
3029
3030         R_ResetViewRendering2D();
3031
3032         R_Bloom_CopyHDRTexture();
3033         R_Bloom_MakeTexture();
3034
3035         R_ResetViewRendering3D();
3036
3037         R_ClearScreen();
3038         if (r_timereport_active)
3039                 R_TimeReport("clear");
3040
3041
3042         // restore the view settings
3043         r_view.width = oldwidth;
3044         r_view.height = oldheight;
3045 }
3046
3047 static void R_BlendView(void)
3048 {
3049         if (r_bloomstate.enabled && r_bloomstate.hdr)
3050         {
3051                 // render high dynamic range bloom effect
3052                 // the bloom texture was made earlier this render, so we just need to
3053                 // blend it onto the screen...
3054                 R_ResetViewRendering2D();
3055                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3056                 R_Mesh_ColorPointer(NULL, 0, 0);
3057                 GL_Color(1, 1, 1, 1);
3058                 GL_BlendFunc(GL_ONE, GL_ONE);
3059                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3060                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3061                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3062                 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3063         }
3064         else if (r_bloomstate.enabled)
3065         {
3066                 // render simple bloom effect
3067                 // copy the screen and shrink it and darken it for the bloom process
3068                 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
3069                 // make the bloom texture
3070                 R_Bloom_MakeTexture();
3071                 // put the original screen image back in place and blend the bloom
3072                 // texture on it
3073                 R_ResetViewRendering2D();
3074                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3075                 R_Mesh_ColorPointer(NULL, 0, 0);
3076                 GL_Color(1, 1, 1, 1);
3077                 GL_BlendFunc(GL_ONE, GL_ZERO);
3078                 // do both in one pass if possible
3079                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3080                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3081                 if (r_textureunits.integer >= 2 && gl_combine.integer)
3082                 {
3083                         R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
3084                         R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3085                         R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3086                 }
3087                 else
3088                 {
3089                         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3090                         r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3091                         // now blend on the bloom texture
3092                         GL_BlendFunc(GL_ONE, GL_ONE);
3093                         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3094                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3095                 }
3096                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3097                 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3098         }
3099         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3100         {
3101                 // apply a color tint to the whole view
3102                 R_ResetViewRendering2D();
3103                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3104                 R_Mesh_ColorPointer(NULL, 0, 0);
3105                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3106                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3107                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3108         }
3109 }
3110
3111 void R_RenderScene(qboolean addwaterplanes);
3112
3113 matrix4x4_t r_waterscrollmatrix;
3114
3115 void R_UpdateVariables(void)
3116 {
3117         R_Textures_Frame();
3118
3119         r_refdef.farclip = 4096;
3120         if (r_refdef.worldmodel)
3121                 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
3122         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3123
3124         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3125                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3126         r_refdef.polygonfactor = 0;
3127         r_refdef.polygonoffset = 0;
3128         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3129         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3130
3131         r_refdef.rtworld = r_shadow_realtime_world.integer;
3132         r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3133         r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3134         r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3135         r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3136         if (r_showsurfaces.integer)
3137         {
3138                 r_refdef.rtworld = false;
3139                 r_refdef.rtworldshadows = false;
3140                 r_refdef.rtdlight = false;
3141                 r_refdef.rtdlightshadows = false;
3142                 r_refdef.lightmapintensity = 0;
3143         }
3144
3145         if (gamemode == GAME_NEHAHRA)
3146         {
3147                 if (gl_fogenable.integer)
3148                 {
3149                         r_refdef.oldgl_fogenable = true;
3150                         r_refdef.fog_density = gl_fogdensity.value;
3151                         r_refdef.fog_red = gl_fogred.value;
3152                         r_refdef.fog_green = gl_foggreen.value;
3153                         r_refdef.fog_blue = gl_fogblue.value;
3154                 }
3155                 else if (r_refdef.oldgl_fogenable)
3156                 {
3157                         r_refdef.oldgl_fogenable = false;
3158                         r_refdef.fog_density = 0;
3159                         r_refdef.fog_red = 0;
3160                         r_refdef.fog_green = 0;
3161                         r_refdef.fog_blue = 0;
3162                 }
3163         }
3164         if (r_refdef.fog_density)
3165         {
3166                 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red  , 1.0f);
3167                 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
3168                 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
3169         }
3170         if (r_refdef.fog_density)
3171         {
3172                 r_refdef.fogenabled = true;
3173                 // this is the point where the fog reaches 0.9986 alpha, which we
3174                 // consider a good enough cutoff point for the texture
3175                 // (0.9986 * 256 == 255.6)
3176                 r_refdef.fogrange = 400 / r_refdef.fog_density;
3177                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3178                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3179                 // fog color was already set
3180         }
3181         else
3182                 r_refdef.fogenabled = false;
3183 }
3184
3185 /*
3186 ================
3187 R_RenderView
3188 ================
3189 */
3190 void R_RenderView(void)
3191 {
3192         if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
3193                 return; //Host_Error ("R_RenderView: NULL worldmodel");
3194
3195         R_Shadow_UpdateWorldLightSelection();
3196
3197         R_Bloom_StartFrame();
3198         R_Water_StartFrame();
3199
3200         CHECKGLERROR
3201         if (r_timereport_active)
3202                 R_TimeReport("setup");
3203
3204         R_ResetViewRendering3D();
3205
3206         R_ClearScreen();
3207         if (r_timereport_active)
3208                 R_TimeReport("clear");
3209
3210         r_view.showdebug = true;
3211
3212         // this produces a bloom texture to be used in R_BlendView() later
3213         if (r_hdr.integer)
3214                 R_HDR_RenderBloomTexture();
3215
3216         r_view.colorscale = r_hdr_scenebrightness.value;
3217         r_waterstate.numwaterplanes = 0;
3218         R_RenderScene(r_waterstate.enabled);
3219
3220         R_BlendView();
3221         if (r_timereport_active)
3222                 R_TimeReport("blendview");
3223
3224         GL_Scissor(0, 0, vid.width, vid.height);
3225         GL_ScissorTest(false);
3226         CHECKGLERROR
3227 }
3228
3229 extern void R_DrawLightningBeams (void);
3230 extern void VM_CL_AddPolygonsToMeshQueue (void);
3231 extern void R_DrawPortals (void);
3232 extern cvar_t cl_locs_show;
3233 static void R_DrawLocs(void);
3234 static void R_DrawEntityBBoxes(void);
3235 void R_RenderScene(qboolean addwaterplanes)
3236 {
3237         if (addwaterplanes)
3238         {
3239                 R_ResetViewRendering3D();
3240
3241                 R_View_Update();
3242                 if (r_timereport_active)
3243                         R_TimeReport("watervisibility");
3244
3245                 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawAddWaterPlanes)
3246                 {
3247                         r_refdef.worldmodel->DrawAddWaterPlanes(r_refdef.worldentity);
3248                         if (r_timereport_active)
3249                                 R_TimeReport("waterworld");
3250                 }
3251
3252                 // don't let sound skip if going slow
3253                 if (r_refdef.extraupdate)
3254                         S_ExtraUpdate ();
3255
3256                 R_DrawModelsAddWaterPlanes();
3257                 if (r_timereport_active)
3258                         R_TimeReport("watermodels");
3259
3260                 R_Water_ProcessPlanes();
3261                 if (r_timereport_active)
3262                         R_TimeReport("waterscenes");
3263         }
3264
3265         R_ResetViewRendering3D();
3266
3267         // don't let sound skip if going slow
3268         if (r_refdef.extraupdate)
3269                 S_ExtraUpdate ();
3270
3271         R_MeshQueue_BeginScene();
3272
3273         R_SkyStartFrame();
3274
3275         R_View_Update();
3276         if (r_timereport_active)
3277                 R_TimeReport("visibility");
3278
3279         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);
3280
3281         if (cl.csqc_vidvars.drawworld)
3282         {
3283                 // don't let sound skip if going slow
3284                 if (r_refdef.extraupdate)
3285                         S_ExtraUpdate ();
3286
3287                 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
3288                 {
3289                         r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
3290                         if (r_timereport_active)
3291                                 R_TimeReport("worldsky");
3292                 }
3293
3294                 if (R_DrawBrushModelsSky() && r_timereport_active)
3295                         R_TimeReport("bmodelsky");
3296         }
3297
3298         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
3299         {
3300                 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
3301                 if (r_timereport_active)
3302                         R_TimeReport("worlddepth");
3303         }
3304         if (r_depthfirst.integer >= 2)
3305         {
3306                 R_DrawModelsDepth();
3307                 if (r_timereport_active)
3308                         R_TimeReport("modeldepth");
3309         }
3310
3311         if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
3312         {
3313                 r_refdef.worldmodel->Draw(r_refdef.worldentity);
3314                 if (r_timereport_active)
3315                         R_TimeReport("world");
3316         }
3317
3318         // don't let sound skip if going slow
3319         if (r_refdef.extraupdate)
3320                 S_ExtraUpdate ();
3321
3322         R_DrawModels();
3323         if (r_timereport_active)
3324                 R_TimeReport("models");
3325
3326         // don't let sound skip if going slow
3327         if (r_refdef.extraupdate)
3328                 S_ExtraUpdate ();
3329
3330         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3331         {
3332                 R_DrawModelShadows();
3333
3334                 R_ResetViewRendering3D();
3335
3336                 // don't let sound skip if going slow
3337                 if (r_refdef.extraupdate)
3338                         S_ExtraUpdate ();
3339         }
3340
3341         R_ShadowVolumeLighting(false);
3342         if (r_timereport_active)
3343                 R_TimeReport("rtlights");
3344
3345         // don't let sound skip if going slow
3346         if (r_refdef.extraupdate)
3347                 S_ExtraUpdate ();
3348
3349         if (cl.csqc_vidvars.drawworld)
3350         {
3351                 R_DrawLightningBeams();
3352                 if (r_timereport_active)
3353                         R_TimeReport("lightning");
3354
3355                 R_DrawParticles();
3356                 if (r_timereport_active)
3357                         R_TimeReport("particles");
3358
3359                 R_DrawExplosions();
3360                 if (r_timereport_active)
3361                         R_TimeReport("explosions");
3362         }
3363
3364         if (gl_support_fragment_shader)
3365         {
3366                 qglUseProgramObjectARB(0);CHECKGLERROR
3367         }
3368         VM_CL_AddPolygonsToMeshQueue();
3369
3370         if (r_view.showdebug)
3371         {
3372                 if (cl_locs_show.integer)
3373                 {
3374                         R_DrawLocs();
3375                         if (r_timereport_active)
3376                                 R_TimeReport("showlocs");
3377                 }
3378
3379                 if (r_drawportals.integer)
3380                 {
3381                         R_DrawPortals();
3382                         if (r_timereport_active)
3383                                 R_TimeReport("portals");
3384                 }
3385
3386                 if (r_showbboxes.value > 0)
3387                 {
3388                         R_DrawEntityBBoxes();
3389                         if (r_timereport_active)
3390                                 R_TimeReport("bboxes");
3391                 }
3392         }
3393
3394         if (gl_support_fragment_shader)
3395         {
3396                 qglUseProgramObjectARB(0);CHECKGLERROR
3397         }
3398         R_MeshQueue_RenderTransparent();
3399         if (r_timereport_active)
3400                 R_TimeReport("drawtrans");
3401
3402         if (gl_support_fragment_shader)
3403         {
3404                 qglUseProgramObjectARB(0);CHECKGLERROR
3405         }
3406
3407         if (r_view.showdebug && r_refdef.worldmodel && r_refdef.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3408         {
3409                 r_refdef.worldmodel->DrawDebug(r_refdef.worldentity);
3410                 if (r_timereport_active)
3411                         R_TimeReport("worlddebug");
3412                 R_DrawModelsDebug();
3413                 if (r_timereport_active)
3414                         R_TimeReport("modeldebug");
3415         }
3416
3417         if (gl_support_fragment_shader)
3418         {
3419                 qglUseProgramObjectARB(0);CHECKGLERROR
3420         }
3421
3422         if (cl.csqc_vidvars.drawworld)
3423         {
3424                 R_DrawCoronas();
3425                 if (r_timereport_active)
3426                         R_TimeReport("coronas");
3427         }
3428
3429         // don't let sound skip if going slow
3430         if (r_refdef.extraupdate)
3431                 S_ExtraUpdate ();
3432
3433         R_ResetViewRendering2D();
3434 }
3435
3436 static const int bboxelements[36] =
3437 {
3438         5, 1, 3, 5, 3, 7,
3439         6, 2, 0, 6, 0, 4,
3440         7, 3, 2, 7, 2, 6,
3441         4, 0, 1, 4, 1, 5,
3442         4, 5, 7, 4, 7, 6,
3443         1, 0, 2, 1, 2, 3,
3444 };
3445
3446 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3447 {
3448         int i;
3449         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3450         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3451         GL_DepthMask(false);
3452         GL_DepthRange(0, 1);
3453         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3454         R_Mesh_Matrix(&identitymatrix);
3455         R_Mesh_ResetTextureState();
3456
3457         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3458         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3459         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3460         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3461         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3462         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3463         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3464         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3465         R_FillColors(color4f, 8, cr, cg, cb, ca);
3466         if (r_refdef.fogenabled)
3467         {
3468                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3469                 {
3470                         f1 = FogPoint_World(v);
3471                         f2 = 1 - f1;
3472                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3473                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3474                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3475                 }
3476         }
3477         R_Mesh_VertexPointer(vertex3f, 0, 0);
3478         R_Mesh_ColorPointer(color4f, 0, 0);
3479         R_Mesh_ResetTextureState();
3480         R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3481 }
3482
3483 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3484 {
3485         int i;
3486         float color[4];
3487         prvm_edict_t *edict;
3488         // this function draws bounding boxes of server entities
3489         if (!sv.active)
3490                 return;
3491         SV_VM_Begin();
3492         for (i = 0;i < numsurfaces;i++)
3493         {
3494                 edict = PRVM_EDICT_NUM(surfacelist[i]);
3495                 switch ((int)edict->fields.server->solid)
3496                 {
3497                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
3498                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
3499                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
3500                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3501                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
3502                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
3503                 }
3504                 color[3] *= r_showbboxes.value;
3505                 color[3] = bound(0, color[3], 1);
3506                 GL_DepthTest(!r_showdisabledepthtest.integer);
3507                 GL_CullFace(r_view.cullface_front);
3508                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3509         }
3510         SV_VM_End();
3511 }
3512
3513 static void R_DrawEntityBBoxes(void)
3514 {
3515         int i;
3516         prvm_edict_t *edict;
3517         vec3_t center;
3518         // this function draws bounding boxes of server entities
3519         if (!sv.active)
3520                 return;
3521         SV_VM_Begin();
3522         for (i = 0;i < prog->num_edicts;i++)
3523         {
3524                 edict = PRVM_EDICT_NUM(i);
3525                 if (edict->priv.server->free)
3526                         continue;
3527                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3528                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3529         }
3530         SV_VM_End();
3531 }
3532
3533 int nomodelelements[24] =
3534 {
3535         5, 2, 0,
3536         5, 1, 2,
3537         5, 0, 3,
3538         5, 3, 1,
3539         0, 2, 4,
3540         2, 1, 4,
3541         3, 0, 4,
3542         1, 3, 4
3543 };
3544
3545 float nomodelvertex3f[6*3] =
3546 {
3547         -16,   0,   0,
3548          16,   0,   0,
3549           0, -16,   0,
3550           0,  16,   0,
3551           0,   0, -16,
3552           0,   0,  16
3553 };
3554
3555 float nomodelcolor4f[6*4] =
3556 {
3557         0.0f, 0.0f, 0.5f, 1.0f,
3558         0.0f, 0.0f, 0.5f, 1.0f,
3559         0.0f, 0.5f, 0.0f, 1.0f,
3560         0.0f, 0.5f, 0.0f, 1.0f,
3561         0.5f, 0.0f, 0.0f, 1.0f,
3562         0.5f, 0.0f, 0.0f, 1.0f
3563 };
3564
3565 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3566 {
3567         int i;
3568         float f1, f2, *c;
3569         float color4f[6*4];
3570         // this is only called once per entity so numsurfaces is always 1, and
3571         // surfacelist is always {0}, so this code does not handle batches
3572         R_Mesh_Matrix(&ent->matrix);
3573
3574         if (ent->flags & EF_ADDITIVE)
3575         {
3576                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3577                 GL_DepthMask(false);
3578         }
3579         else if (ent->alpha < 1)
3580         {
3581                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3582                 GL_DepthMask(false);
3583         }
3584         else
3585         {
3586                 GL_BlendFunc(GL_ONE, GL_ZERO);
3587                 GL_DepthMask(true);
3588         }
3589         GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3590         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3591         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3592         GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_view.cullface_back);
3593         R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3594         if (r_refdef.fogenabled)
3595         {
3596                 vec3_t org;
3597                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3598                 R_Mesh_ColorPointer(color4f, 0, 0);
3599                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3600                 f1 = FogPoint_World(org);
3601                 f2 = 1 - f1;
3602                 for (i = 0, c = color4f;i < 6;i++, c += 4)
3603                 {
3604                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3605                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3606                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3607                         c[3] *= ent->alpha;
3608                 }
3609         }
3610         else if (ent->alpha != 1)
3611         {
3612                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3613                 R_Mesh_ColorPointer(color4f, 0, 0);
3614                 for (i = 0, c = color4f;i < 6;i++, c += 4)
3615                         c[3] *= ent->alpha;
3616         }
3617         else
3618                 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3619         R_Mesh_ResetTextureState();
3620         R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3621 }
3622
3623 void R_DrawNoModel(entity_render_t *ent)
3624 {
3625         vec3_t org;
3626         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3627         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3628                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3629         //else
3630         //      R_DrawNoModelCallback(ent, 0);
3631 }
3632
3633 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3634 {
3635         vec3_t right1, right2, diff, normal;
3636
3637         VectorSubtract (org2, org1, normal);
3638
3639         // calculate 'right' vector for start
3640         VectorSubtract (r_view.origin, org1, diff);
3641         CrossProduct (normal, diff, right1);
3642         VectorNormalize (right1);
3643
3644         // calculate 'right' vector for end
3645         VectorSubtract (r_view.origin, org2, diff);
3646         CrossProduct (normal, diff, right2);
3647         VectorNormalize (right2);
3648
3649         vert[ 0] = org1[0] + width * right1[0];
3650         vert[ 1] = org1[1] + width * right1[1];
3651         vert[ 2] = org1[2] + width * right1[2];
3652         vert[ 3] = org1[0] - width * right1[0];
3653         vert[ 4] = org1[1] - width * right1[1];
3654         vert[ 5] = org1[2] - width * right1[2];
3655         vert[ 6] = org2[0] - width * right2[0];
3656         vert[ 7] = org2[1] - width * right2[1];
3657         vert[ 8] = org2[2] - width * right2[2];
3658         vert[ 9] = org2[0] + width * right2[0];
3659         vert[10] = org2[1] + width * right2[1];
3660         vert[11] = org2[2] + width * right2[2];
3661 }
3662
3663 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3664
3665 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)
3666 {
3667         float fog = 1.0f;
3668         float vertex3f[12];
3669
3670         if (r_refdef.fogenabled)
3671                 fog = FogPoint_World(origin);
3672
3673         R_Mesh_Matrix(&identitymatrix);
3674         GL_BlendFunc(blendfunc1, blendfunc2);
3675
3676         if(v_flipped_state)
3677         {
3678                 scalex1 = -scalex1;
3679                 scalex2 = -scalex2;
3680                 GL_CullFace(r_view.cullface_front);
3681         }
3682         else
3683                 GL_CullFace(r_view.cullface_back);
3684
3685         GL_DepthMask(false);
3686         GL_DepthRange(0, depthshort ? 0.0625 : 1);
3687         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3688         GL_DepthTest(!depthdisable);
3689
3690         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3691         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3692         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3693         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3694         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3695         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3696         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3697         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3698         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3699         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3700         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3701         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3702
3703         R_Mesh_VertexPointer(vertex3f, 0, 0);
3704         R_Mesh_ColorPointer(NULL, 0, 0);
3705         R_Mesh_ResetTextureState();
3706         R_Mesh_TexBind(0, R_GetTexture(texture));
3707         R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3708         // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3709         GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3710         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3711
3712         if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3713         {
3714                 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3715                 GL_BlendFunc(blendfunc1, GL_ONE);
3716                 fog = 1 - fog;
3717                 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);
3718                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3719         }
3720 }
3721
3722 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3723 {
3724         int i;
3725         float *vertex3f;
3726         float v[3];
3727         VectorSet(v, x, y, z);
3728         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3729                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3730                         break;
3731         if (i == mesh->numvertices)
3732         {
3733                 if (mesh->numvertices < mesh->maxvertices)
3734                 {
3735                         VectorCopy(v, vertex3f);
3736                         mesh->numvertices++;
3737                 }
3738                 return mesh->numvertices;
3739         }
3740         else
3741                 return i;
3742 }
3743
3744 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3745 {
3746         int i;
3747         int *e, element[3];
3748         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3749         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3750         e = mesh->element3i + mesh->numtriangles * 3;
3751         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3752         {
3753                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3754                 if (mesh->numtriangles < mesh->maxtriangles)
3755                 {
3756                         *e++ = element[0];
3757                         *e++ = element[1];
3758                         *e++ = element[2];
3759                         mesh->numtriangles++;
3760                 }
3761                 element[1] = element[2];
3762         }
3763 }
3764
3765 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3766 {
3767         int i;
3768         int *e, element[3];
3769         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3770         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3771         e = mesh->element3i + mesh->numtriangles * 3;
3772         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3773         {
3774                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3775                 if (mesh->numtriangles < mesh->maxtriangles)
3776                 {
3777                         *e++ = element[0];
3778                         *e++ = element[1];
3779                         *e++ = element[2];
3780                         mesh->numtriangles++;
3781                 }
3782                 element[1] = element[2];
3783         }
3784 }
3785
3786 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3787 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3788 {
3789         int planenum, planenum2;
3790         int w;
3791         int tempnumpoints;
3792         mplane_t *plane, *plane2;
3793         double maxdist;
3794         double temppoints[2][256*3];
3795         // figure out how large a bounding box we need to properly compute this brush
3796         maxdist = 0;
3797         for (w = 0;w < numplanes;w++)
3798                 maxdist = max(maxdist, planes[w].dist);
3799         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3800         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3801         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3802         {
3803                 w = 0;
3804                 tempnumpoints = 4;
3805                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3806                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3807                 {
3808                         if (planenum2 == planenum)
3809                                 continue;
3810                         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);
3811                         w = !w;
3812                 }
3813                 if (tempnumpoints < 3)
3814                         continue;
3815                 // generate elements forming a triangle fan for this polygon
3816                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3817         }
3818 }
3819
3820 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)
3821 {
3822         texturelayer_t *layer;
3823         layer = t->currentlayers + t->currentnumlayers++;
3824         layer->type = type;
3825         layer->depthmask = depthmask;
3826         layer->blendfunc1 = blendfunc1;
3827         layer->blendfunc2 = blendfunc2;
3828         layer->texture = texture;
3829         layer->texmatrix = *matrix;
3830         layer->color[0] = r * r_view.colorscale;
3831         layer->color[1] = g * r_view.colorscale;
3832         layer->color[2] = b * r_view.colorscale;
3833         layer->color[3] = a;
3834 }
3835
3836 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3837 {
3838         double index, f;
3839         index = parms[2] + r_refdef.time * parms[3];
3840         index -= floor(index);
3841         switch (func)
3842         {
3843         default:
3844         case Q3WAVEFUNC_NONE:
3845         case Q3WAVEFUNC_NOISE:
3846         case Q3WAVEFUNC_COUNT:
3847                 f = 0;
3848                 break;
3849         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3850         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3851         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3852         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3853         case Q3WAVEFUNC_TRIANGLE:
3854                 index *= 4;
3855                 f = index - floor(index);
3856                 if (index < 1)
3857                         f = f;
3858                 else if (index < 2)
3859                         f = 1 - f;
3860                 else if (index < 3)
3861                         f = -f;
3862                 else
3863                         f = -(1 - f);
3864                 break;
3865         }
3866         return (float)(parms[0] + parms[1] * f);
3867 }
3868
3869 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3870 {
3871         int i;
3872         model_t *model = ent->model;
3873         float f;
3874         float tcmat[12];
3875         q3shaderinfo_layer_tcmod_t *tcmod;
3876
3877         // switch to an alternate material if this is a q1bsp animated material
3878         {
3879                 texture_t *texture = t;
3880                 int s = ent->skinnum;
3881                 if ((unsigned int)s >= (unsigned int)model->numskins)
3882                         s = 0;
3883                 if (model->skinscenes)
3884                 {
3885                         if (model->skinscenes[s].framecount > 1)
3886                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3887                         else
3888                                 s = model->skinscenes[s].firstframe;
3889                 }
3890                 if (s > 0)
3891                         t = t + s * model->num_surfaces;
3892                 if (t->animated)
3893                 {
3894                         // use an alternate animation if the entity's frame is not 0,
3895                         // and only if the texture has an alternate animation
3896                         if (ent->frame2 != 0 && t->anim_total[1])
3897                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3898                         else
3899                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3900                 }
3901                 texture->currentframe = t;
3902         }
3903
3904         // update currentskinframe to be a qw skin or animation frame
3905         if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
3906         {
3907                 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
3908                 {
3909                         strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
3910                         Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
3911                         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);
3912                 }
3913                 t->currentskinframe = r_qwskincache_skinframe[i];
3914                 if (t->currentskinframe == NULL)
3915                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3916         }
3917         else if (t->numskinframes >= 2)
3918                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3919         if (t->backgroundnumskinframes >= 2)
3920                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3921
3922         t->currentmaterialflags = t->basematerialflags;
3923         t->currentalpha = ent->alpha;
3924         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3925         {
3926                 t->currentalpha *= r_wateralpha.value;
3927                 /*
3928                  * FIXME what is this supposed to do?
3929                 // if rendering refraction/reflection, disable transparency
3930                 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
3931                         t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
3932                 */
3933         }
3934         if(!r_waterstate.enabled)
3935                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
3936         if (!(ent->flags & RENDER_LIGHT))
3937                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3938         if (ent->effects & EF_ADDITIVE)
3939                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3940         else if (t->currentalpha < 1)
3941                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3942         if (ent->effects & EF_DOUBLESIDED)
3943                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3944         if (ent->effects & EF_NODEPTHTEST)
3945                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3946         if (ent->flags & RENDER_VIEWMODEL)
3947                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3948         if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3949                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3950
3951         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
3952         {
3953                 matrix4x4_t matrix;
3954                 switch(tcmod->tcmod)
3955                 {
3956                 case Q3TCMOD_COUNT:
3957                 case Q3TCMOD_NONE:
3958                         if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3959                                 matrix = r_waterscrollmatrix;
3960                         else
3961                                 matrix = identitymatrix;
3962                         break;
3963                 case Q3TCMOD_ENTITYTRANSLATE:
3964                         // this is used in Q3 to allow the gamecode to control texcoord
3965                         // scrolling on the entity, which is not supported in darkplaces yet.
3966                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
3967                         break;
3968                 case Q3TCMOD_ROTATE:
3969                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
3970                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
3971                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
3972                         break;
3973                 case Q3TCMOD_SCALE:
3974                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
3975                         break;
3976                 case Q3TCMOD_SCROLL:
3977                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
3978                         break;
3979                 case Q3TCMOD_STRETCH:
3980                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
3981                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
3982                         break;
3983                 case Q3TCMOD_TRANSFORM:
3984                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
3985                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
3986                         VectorSet(tcmat +  6, 0                   , 0                , 1);
3987                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
3988                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
3989                         break;
3990                 case Q3TCMOD_TURBULENT:
3991                         // this is handled in the RSurf_PrepareVertices function
3992                         matrix = identitymatrix;
3993                         break;
3994                 }
3995                 // either replace or concatenate the transformation
3996                 if (i < 1)
3997                         t->currenttexmatrix = matrix;
3998                 else
3999                 {
4000                         matrix4x4_t temp = t->currenttexmatrix;
4001                         Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4002                 }
4003         }
4004
4005         t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4006         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4007         t->glosstexture = r_texture_black;
4008         t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4009         t->backgroundglosstexture = r_texture_black;
4010         t->specularpower = r_shadow_glossexponent.value;
4011         // TODO: store reference values for these in the texture?
4012         t->specularscale = 0;
4013         if (r_shadow_gloss.integer > 0)
4014         {
4015                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4016                 {
4017                         if (r_shadow_glossintensity.value > 0)
4018                         {
4019                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4020                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4021                                 t->specularscale = r_shadow_glossintensity.value;
4022                         }
4023                 }
4024                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4025                 {
4026                         t->glosstexture = r_texture_white;
4027                         t->backgroundglosstexture = r_texture_white;
4028                         t->specularscale = r_shadow_gloss2intensity.value;
4029                 }
4030         }
4031
4032         // lightmaps mode looks bad with dlights using actual texturing, so turn
4033         // off the colormap and glossmap, but leave the normalmap on as it still
4034         // accurately represents the shading involved
4035         if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
4036         {
4037                 t->basetexture = r_texture_white;
4038                 t->specularscale = 0;
4039         }
4040
4041         t->currentpolygonfactor = r_refdef.polygonfactor + t->basepolygonfactor;
4042         t->currentpolygonoffset = r_refdef.polygonoffset + t->basepolygonoffset;
4043         // submodels are biased to avoid z-fighting with world surfaces that they
4044         // may be exactly overlapping (avoids z-fighting artifacts on certain
4045         // doors and things in Quake maps)
4046         if (ent->model->brush.submodel)
4047         {
4048                 t->currentpolygonfactor += r_polygonoffset_submodel_factor.value;
4049                 t->currentpolygonoffset += r_polygonoffset_submodel_offset.value;
4050         }
4051
4052         VectorClear(t->dlightcolor);
4053         t->currentnumlayers = 0;
4054         if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
4055         {
4056                 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
4057                 {
4058                         int blendfunc1, blendfunc2, depthmask;
4059                         if (t->currentmaterialflags & MATERIALFLAG_ADD)
4060                         {
4061                                 blendfunc1 = GL_SRC_ALPHA;
4062                                 blendfunc2 = GL_ONE;
4063                         }
4064                         else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4065                         {
4066                                 blendfunc1 = GL_SRC_ALPHA;
4067                                 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4068                         }
4069                         else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4070                         {
4071                                 blendfunc1 = t->customblendfunc[0];
4072                                 blendfunc2 = t->customblendfunc[1];
4073                         }
4074                         else
4075                         {
4076                                 blendfunc1 = GL_ONE;
4077                                 blendfunc2 = GL_ZERO;
4078                         }
4079                         depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4080                         if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
4081                         {
4082                                 rtexture_t *currentbasetexture;
4083                                 int layerflags = 0;
4084                                 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4085                                         layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4086                                 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4087                                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4088                                 {
4089                                         // fullbright is not affected by r_refdef.lightmapintensity
4090                                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4091                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4092                                                 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);
4093                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4094                                                 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);
4095                                 }
4096                                 else
4097                                 {
4098                                         float colorscale;
4099                                         // set the color tint used for lights affecting this surface
4100                                         VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
4101                                         colorscale = 2;
4102                                         // q3bsp has no lightmap updates, so the lightstylevalue that
4103                                         // would normally be baked into the lightmap must be
4104                                         // applied to the color
4105                                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4106                                         if (ent->model->type == mod_brushq3)
4107                                                 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
4108                                         colorscale *= r_refdef.lightmapintensity;
4109                                         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);
4110                                         if (r_ambient.value >= (1.0f/64.0f))
4111                                                 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);
4112                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4113                                         {
4114                                                 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);
4115                                                 if (r_ambient.value >= (1.0f/64.0f))
4116                                                         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);
4117                                         }
4118                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4119                                         {
4120                                                 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);
4121                                                 if (r_ambient.value >= (1.0f/64.0f))
4122                                                         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);
4123                                         }
4124                                 }
4125                                 if (t->currentskinframe->glow != NULL)
4126                                         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);
4127                                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4128                                 {
4129                                         // if this is opaque use alpha blend which will darken the earlier
4130                                         // passes cheaply.
4131                                         //
4132                                         // if this is an alpha blended material, all the earlier passes
4133                                         // were darkened by fog already, so we only need to add the fog
4134                                         // color ontop through the fog mask texture
4135                                         //
4136                                         // if this is an additive blended material, all the earlier passes
4137                                         // were darkened by fog already, and we should not add fog color
4138                                         // (because the background was not darkened, there is no fog color
4139                                         // that was lost behind it).
4140                                         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);
4141                                 }
4142                         }
4143                 }
4144         }
4145 }
4146
4147 void R_UpdateAllTextureInfo(entity_render_t *ent)
4148 {
4149         int i;
4150         if (ent->model)
4151                 for (i = 0;i < ent->model->num_texturesperskin;i++)
4152                         R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4153 }
4154
4155 rsurfacestate_t rsurface;
4156
4157 void R_Mesh_ResizeArrays(int newvertices)
4158 {
4159         float *base;
4160         if (rsurface.array_size >= newvertices)
4161                 return;
4162         if (rsurface.array_modelvertex3f)
4163                 Mem_Free(rsurface.array_modelvertex3f);
4164         rsurface.array_size = (newvertices + 1023) & ~1023;
4165         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4166         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
4167         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
4168         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
4169         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
4170         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
4171         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4172         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4173         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
4174         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
4175         rsurface.array_color4f           = base + rsurface.array_size * 27;
4176         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4177 }
4178
4179 void RSurf_CleanUp(void)
4180 {
4181         CHECKGLERROR
4182         if (rsurface.mode == RSURFMODE_GLSL)
4183         {
4184                 qglUseProgramObjectARB(0);CHECKGLERROR
4185         }
4186         GL_AlphaTest(false);
4187         rsurface.mode = RSURFMODE_NONE;
4188         rsurface.uselightmaptexture = false;
4189         rsurface.texture = NULL;
4190 }
4191
4192 void RSurf_ActiveWorldEntity(void)
4193 {
4194         model_t *model = r_refdef.worldmodel;
4195         RSurf_CleanUp();
4196         if (rsurface.array_size < model->surfmesh.num_vertices)
4197                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4198         rsurface.matrix = identitymatrix;
4199         rsurface.inversematrix = identitymatrix;
4200         R_Mesh_Matrix(&identitymatrix);
4201         VectorCopy(r_view.origin, rsurface.modelorg);
4202         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4203         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4204         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4205         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4206         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4207         rsurface.frameblend[0].frame = 0;
4208         rsurface.frameblend[0].lerp = 1;
4209         rsurface.frameblend[1].frame = 0;
4210         rsurface.frameblend[1].lerp = 0;
4211         rsurface.frameblend[2].frame = 0;
4212         rsurface.frameblend[2].lerp = 0;
4213         rsurface.frameblend[3].frame = 0;
4214         rsurface.frameblend[3].lerp = 0;
4215         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
4216         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4217         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4218         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4219         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4220         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4221         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4222         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4223         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4224         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
4225         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4226         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4227         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
4228         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4229         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4230         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
4231         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4232         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4233         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
4234         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4235         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4236         rsurface.modelelement3i = model->surfmesh.data_element3i;
4237         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4238         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4239         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4240         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4241         rsurface.modelsurfaces = model->data_surfaces;
4242         rsurface.generatedvertex = false;
4243         rsurface.vertex3f  = rsurface.modelvertex3f;
4244         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4245         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4246         rsurface.svector3f = rsurface.modelsvector3f;
4247         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4248         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4249         rsurface.tvector3f = rsurface.modeltvector3f;
4250         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4251         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4252         rsurface.normal3f  = rsurface.modelnormal3f;
4253         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4254         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4255         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4256 }
4257
4258 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4259 {
4260         model_t *model = ent->model;
4261         RSurf_CleanUp();
4262         if (rsurface.array_size < model->surfmesh.num_vertices)
4263                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4264         rsurface.matrix = ent->matrix;
4265         rsurface.inversematrix = ent->inversematrix;
4266         R_Mesh_Matrix(&rsurface.matrix);
4267         Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
4268         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
4269         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4270         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4271         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4272         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4273         rsurface.frameblend[0] = ent->frameblend[0];
4274         rsurface.frameblend[1] = ent->frameblend[1];
4275         rsurface.frameblend[2] = ent->frameblend[2];
4276         rsurface.frameblend[3] = ent->frameblend[3];
4277         if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4278         {
4279                 if (wanttangents)
4280                 {
4281                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4282                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4283                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4284                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4285                         Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4286                 }
4287                 else if (wantnormals)
4288                 {
4289                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4290                         rsurface.modelsvector3f = NULL;
4291                         rsurface.modeltvector3f = NULL;
4292                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4293                         Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4294                 }
4295                 else
4296                 {
4297                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4298                         rsurface.modelsvector3f = NULL;
4299                         rsurface.modeltvector3f = NULL;
4300                         rsurface.modelnormal3f = NULL;
4301                         Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4302                 }
4303                 rsurface.modelvertex3f_bufferobject = 0;
4304                 rsurface.modelvertex3f_bufferoffset = 0;
4305                 rsurface.modelsvector3f_bufferobject = 0;
4306                 rsurface.modelsvector3f_bufferoffset = 0;
4307                 rsurface.modeltvector3f_bufferobject = 0;
4308                 rsurface.modeltvector3f_bufferoffset = 0;
4309                 rsurface.modelnormal3f_bufferobject = 0;
4310                 rsurface.modelnormal3f_bufferoffset = 0;
4311                 rsurface.generatedvertex = true;
4312         }
4313         else
4314         {
4315                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
4316                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4317                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4318                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4319                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4320                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4321                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4322                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4323                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4324                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
4325                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4326                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4327                 rsurface.generatedvertex = false;
4328         }
4329         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
4330         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4331         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4332         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
4333         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4334         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4335         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
4336         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4337         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4338         rsurface.modelelement3i = model->surfmesh.data_element3i;
4339         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4340         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4341         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4342         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4343         rsurface.modelsurfaces = model->data_surfaces;
4344         rsurface.vertex3f  = rsurface.modelvertex3f;
4345         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4346         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4347         rsurface.svector3f = rsurface.modelsvector3f;
4348         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4349         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4350         rsurface.tvector3f = rsurface.modeltvector3f;
4351         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4352         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4353         rsurface.normal3f  = rsurface.modelnormal3f;
4354         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4355         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4356         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4357 }
4358
4359 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4360 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4361 {
4362         int deformindex;
4363         int texturesurfaceindex;
4364         int i, j;
4365         float amplitude;
4366         float animpos;
4367         float scale;
4368         const float *v1, *in_tc;
4369         float *out_tc;
4370         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4371         float waveparms[4];
4372         q3shaderinfo_deform_t *deform;
4373         // 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
4374         if (rsurface.generatedvertex)
4375         {
4376                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4377                         generatenormals = true;
4378                 for (i = 0;i < Q3MAXDEFORMS;i++)
4379                 {
4380                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4381                         {
4382                                 generatetangents = true;
4383                                 generatenormals = true;
4384                         }
4385                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4386                                 generatenormals = true;
4387                 }
4388                 if (generatenormals && !rsurface.modelnormal3f)
4389                 {
4390                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4391                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4392                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4393                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4394                 }
4395                 if (generatetangents && !rsurface.modelsvector3f)
4396                 {
4397                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4398                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4399                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4400                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4401                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4402                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4403                         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);
4404                 }
4405         }
4406         rsurface.vertex3f  = rsurface.modelvertex3f;
4407         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4408         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4409         rsurface.svector3f = rsurface.modelsvector3f;
4410         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4411         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4412         rsurface.tvector3f = rsurface.modeltvector3f;
4413         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4414         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4415         rsurface.normal3f  = rsurface.modelnormal3f;
4416         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4417         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4418         // if vertices are deformed (sprite flares and things in maps, possibly
4419         // water waves, bulges and other deformations), generate them into
4420         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4421         // (may be static model data or generated data for an animated model, or
4422         //  the previous deform pass)
4423         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4424         {
4425                 switch (deform->deform)
4426                 {
4427                 default:
4428                 case Q3DEFORM_PROJECTIONSHADOW:
4429                 case Q3DEFORM_TEXT0:
4430                 case Q3DEFORM_TEXT1:
4431                 case Q3DEFORM_TEXT2:
4432                 case Q3DEFORM_TEXT3:
4433                 case Q3DEFORM_TEXT4:
4434                 case Q3DEFORM_TEXT5:
4435                 case Q3DEFORM_TEXT6:
4436                 case Q3DEFORM_TEXT7:
4437                 case Q3DEFORM_NONE:
4438                         break;
4439                 case Q3DEFORM_AUTOSPRITE:
4440                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4441                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4442                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4443                         VectorNormalize(newforward);
4444                         VectorNormalize(newright);
4445                         VectorNormalize(newup);
4446                         // make deformed versions of only the model vertices used by the specified surfaces
4447                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4448                         {
4449                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4450                                 // a single autosprite surface can contain multiple sprites...
4451                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
4452                                 {
4453                                         VectorClear(center);
4454                                         for (i = 0;i < 4;i++)
4455                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4456                                         VectorScale(center, 0.25f, center);
4457                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
4458                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4459                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4460                                         for (i = 0;i < 4;i++)
4461                                         {
4462                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4463                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4464                                         }
4465                                 }
4466                                 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);
4467                                 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);
4468                         }
4469                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
4470                         rsurface.vertex3f_bufferobject = 0;
4471                         rsurface.vertex3f_bufferoffset = 0;
4472                         rsurface.svector3f = rsurface.array_deformedsvector3f;
4473                         rsurface.svector3f_bufferobject = 0;
4474                         rsurface.svector3f_bufferoffset = 0;
4475                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
4476                         rsurface.tvector3f_bufferobject = 0;
4477                         rsurface.tvector3f_bufferoffset = 0;
4478                         rsurface.normal3f = rsurface.array_deformednormal3f;
4479                         rsurface.normal3f_bufferobject = 0;
4480                         rsurface.normal3f_bufferoffset = 0;
4481                         break;
4482                 case Q3DEFORM_AUTOSPRITE2:
4483                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4484                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4485                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4486                         VectorNormalize(newforward);
4487                         VectorNormalize(newright);
4488                         VectorNormalize(newup);
4489                         // make deformed versions of only the model vertices used by the specified surfaces
4490                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4491                         {
4492                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4493                                 const float *v1, *v2;
4494                                 vec3_t start, end;
4495                                 float f, l;
4496                                 struct
4497                                 {
4498                                         float length2;
4499                                         const float *v1;
4500                                         const float *v2;
4501                                 }
4502                                 shortest[2];
4503                                 memset(shortest, 0, sizeof(shortest));
4504                                 // a single autosprite surface can contain multiple sprites...
4505                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
4506                                 {
4507                                         VectorClear(center);
4508                                         for (i = 0;i < 4;i++)
4509                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4510                                         VectorScale(center, 0.25f, center);
4511                                         // find the two shortest edges, then use them to define the
4512                                         // axis vectors for rotating around the central axis
4513                                         for (i = 0;i < 6;i++)
4514                                         {
4515                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4516                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4517 #if 0
4518                                                 Debug_PolygonBegin(NULL, 0, false, 0);
4519                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4520                                                 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);
4521                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4522                                                 Debug_PolygonEnd();
4523 #endif
4524                                                 l = VectorDistance2(v1, v2);
4525                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4526                                                 if (v1[2] != v2[2])
4527                                                         l += (1.0f / 1024.0f);
4528                                                 if (shortest[0].length2 > l || i == 0)
4529                                                 {
4530                                                         shortest[1] = shortest[0];
4531                                                         shortest[0].length2 = l;
4532                                                         shortest[0].v1 = v1;
4533                                                         shortest[0].v2 = v2;
4534                                                 }
4535                                                 else if (shortest[1].length2 > l || i == 1)
4536                                                 {
4537                                                         shortest[1].length2 = l;
4538                                                         shortest[1].v1 = v1;
4539                                                         shortest[1].v2 = v2;
4540                                                 }
4541                                         }
4542                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4543                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4544 #if 0
4545                                         Debug_PolygonBegin(NULL, 0, false, 0);
4546                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4547                                         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);
4548                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4549                                         Debug_PolygonEnd();
4550 #endif
4551                                         // this calculates the right vector from the shortest edge
4552                                         // and the up vector from the edge midpoints
4553                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4554                                         VectorNormalize(right);
4555                                         VectorSubtract(end, start, up);
4556                                         VectorNormalize(up);
4557                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4558                                         //VectorSubtract(rsurface.modelorg, center, forward);
4559                                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
4560                                         VectorNegate(forward, forward);
4561                                         VectorReflect(forward, 0, up, forward);
4562                                         VectorNormalize(forward);
4563                                         CrossProduct(up, forward, newright);
4564                                         VectorNormalize(newright);
4565 #if 0
4566                                         Debug_PolygonBegin(NULL, 0, false, 0);
4567                                         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);
4568                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4569                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
4570                                         Debug_PolygonEnd();
4571 #endif
4572 #if 0
4573                                         Debug_PolygonBegin(NULL, 0, false, 0);
4574                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4575                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4576                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
4577                                         Debug_PolygonEnd();
4578 #endif
4579                                         // rotate the quad around the up axis vector, this is made
4580                                         // especially easy by the fact we know the quad is flat,
4581                                         // so we only have to subtract the center position and
4582                                         // measure distance along the right vector, and then
4583                                         // multiply that by the newright vector and add back the
4584                                         // center position
4585                                         // we also need to subtract the old position to undo the
4586                                         // displacement from the center, which we do with a
4587                                         // DotProduct, the subtraction/addition of center is also
4588                                         // optimized into DotProducts here
4589                                         l = DotProduct(right, center);
4590                                         for (i = 0;i < 4;i++)
4591                                         {
4592                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4593                                                 f = DotProduct(right, v1) - l;
4594                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4595                                         }
4596                                 }
4597                                 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);
4598                                 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);
4599                         }
4600                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
4601                         rsurface.vertex3f_bufferobject = 0;
4602                         rsurface.vertex3f_bufferoffset = 0;
4603                         rsurface.svector3f = rsurface.array_deformedsvector3f;
4604                         rsurface.svector3f_bufferobject = 0;
4605                         rsurface.svector3f_bufferoffset = 0;
4606                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
4607                         rsurface.tvector3f_bufferobject = 0;
4608                         rsurface.tvector3f_bufferoffset = 0;
4609                         rsurface.normal3f = rsurface.array_deformednormal3f;
4610                         rsurface.normal3f_bufferobject = 0;
4611                         rsurface.normal3f_bufferoffset = 0;
4612                         break;
4613                 case Q3DEFORM_NORMAL:
4614                         // deform the normals to make reflections wavey
4615                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4616                         {
4617                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4618                                 for (j = 0;j < surface->num_vertices;j++)
4619                                 {
4620                                         float vertex[3];
4621                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
4622                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4623                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
4624                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4625                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4626                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4627                                         VectorNormalize(normal);
4628                                 }
4629                                 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);
4630                         }
4631                         rsurface.svector3f = rsurface.array_deformedsvector3f;
4632                         rsurface.svector3f_bufferobject = 0;
4633                         rsurface.svector3f_bufferoffset = 0;
4634                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
4635                         rsurface.tvector3f_bufferobject = 0;
4636                         rsurface.tvector3f_bufferoffset = 0;
4637                         rsurface.normal3f = rsurface.array_deformednormal3f;
4638                         rsurface.normal3f_bufferobject = 0;
4639                         rsurface.normal3f_bufferoffset = 0;
4640                         break;
4641                 case Q3DEFORM_WAVE:
4642                         // deform vertex array to make wavey water and flags and such
4643                         waveparms[0] = deform->waveparms[0];
4644                         waveparms[1] = deform->waveparms[1];
4645                         waveparms[2] = deform->waveparms[2];
4646                         waveparms[3] = deform->waveparms[3];
4647                         // this is how a divisor of vertex influence on deformation
4648                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4649                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4650                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4651                         {
4652                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4653                                 for (j = 0;j < surface->num_vertices;j++)
4654                                 {
4655                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
4656                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
4657                                         // if the wavefunc depends on time, evaluate it per-vertex
4658                                         if (waveparms[3])
4659                                         {
4660                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4661                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4662                                         }
4663                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
4664                                 }
4665                         }
4666                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
4667                         rsurface.vertex3f_bufferobject = 0;
4668                         rsurface.vertex3f_bufferoffset = 0;
4669                         break;
4670                 case Q3DEFORM_BULGE:
4671                         // deform vertex array to make the surface have moving bulges
4672                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4673                         {
4674                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4675                                 for (j = 0;j < surface->num_vertices;j++)
4676                                 {
4677                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4678                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4679                                 }
4680                         }
4681                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
4682                         rsurface.vertex3f_bufferobject = 0;
4683                         rsurface.vertex3f_bufferoffset = 0;
4684                         break;
4685                 case Q3DEFORM_MOVE:
4686                         // deform vertex array
4687                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4688                         VectorScale(deform->parms, scale, waveparms);
4689                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4690                         {
4691                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4692                                 for (j = 0;j < surface->num_vertices;j++)
4693                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4694                         }
4695                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
4696                         rsurface.vertex3f_bufferobject = 0;
4697                         rsurface.vertex3f_bufferoffset = 0;
4698                         break;
4699                 }
4700         }
4701         // generate texcoords based on the chosen texcoord source
4702         switch(rsurface.texture->tcgen.tcgen)
4703         {
4704         default:
4705         case Q3TCGEN_TEXTURE:
4706                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
4707                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
4708                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
4709                 break;
4710         case Q3TCGEN_LIGHTMAP:
4711                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
4712                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
4713                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
4714                 break;
4715         case Q3TCGEN_VECTOR:
4716                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4717                 {
4718                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4719                         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)
4720                         {
4721                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4722                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4723                         }
4724                 }
4725                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
4726                 rsurface.texcoordtexture2f_bufferobject  = 0;
4727                 rsurface.texcoordtexture2f_bufferoffset  = 0;
4728                 break;
4729         case Q3TCGEN_ENVIRONMENT:
4730                 // make environment reflections using a spheremap
4731                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4732                 {
4733                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4734                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4735                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4736                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4737                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4738                         {
4739                                 float l, d, eyedir[3];
4740                                 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4741                                 l = 0.5f / VectorLength(eyedir);
4742                                 d = DotProduct(normal, eyedir)*2;
4743                                 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4744                                 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4745                         }
4746                 }
4747                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
4748                 rsurface.texcoordtexture2f_bufferobject  = 0;
4749                 rsurface.texcoordtexture2f_bufferoffset  = 0;
4750                 break;
4751         }
4752         // the only tcmod that needs software vertex processing is turbulent, so
4753         // check for it here and apply the changes if needed
4754         // and we only support that as the first one
4755         // (handling a mixture of turbulent and other tcmods would be problematic
4756         //  without punting it entirely to a software path)
4757         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4758         {
4759                 amplitude = rsurface.texture->tcmods[0].parms[1];
4760                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4761                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4762                 {
4763                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4764                         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)
4765                         {
4766                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4767                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4768                         }
4769                 }
4770                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
4771                 rsurface.texcoordtexture2f_bufferobject  = 0;
4772                 rsurface.texcoordtexture2f_bufferoffset  = 0;
4773         }
4774         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
4775         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4776         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4777         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4778 }
4779
4780 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4781 {
4782         int i, j;
4783         const msurface_t *surface = texturesurfacelist[0];
4784         const msurface_t *surface2;
4785         int firstvertex;
4786         int endvertex;
4787         int numvertices;
4788         int numtriangles;
4789         // TODO: lock all array ranges before render, rather than on each surface
4790         if (texturenumsurfaces == 1)
4791         {
4792                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4793                 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));
4794         }
4795         else if (r_batchmode.integer == 2)
4796         {
4797                 #define MAXBATCHTRIANGLES 4096
4798                 int batchtriangles = 0;
4799                 int batchelements[MAXBATCHTRIANGLES*3];
4800                 for (i = 0;i < texturenumsurfaces;i = j)
4801                 {
4802                         surface = texturesurfacelist[i];
4803                         j = i + 1;
4804                         if (surface->num_triangles > MAXBATCHTRIANGLES)
4805                         {
4806                                 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));
4807                                 continue;
4808                         }
4809                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4810                         batchtriangles = surface->num_triangles;
4811                         firstvertex = surface->num_firstvertex;
4812                         endvertex = surface->num_firstvertex + surface->num_vertices;
4813                         for (;j < texturenumsurfaces;j++)
4814                         {
4815                                 surface2 = texturesurfacelist[j];
4816                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4817                                         break;
4818                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4819                                 batchtriangles += surface2->num_triangles;
4820                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
4821                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4822                         }
4823                         surface2 = texturesurfacelist[j-1];
4824                         numvertices = endvertex - firstvertex;
4825                         R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4826                 }
4827         }
4828         else if (r_batchmode.integer == 1)
4829         {
4830                 for (i = 0;i < texturenumsurfaces;i = j)
4831                 {
4832                         surface = texturesurfacelist[i];
4833                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4834                                 if (texturesurfacelist[j] != surface2)
4835                                         break;
4836                         surface2 = texturesurfacelist[j-1];
4837                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4838                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4839                         GL_LockArrays(surface->num_firstvertex, numvertices);
4840                         R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4841                 }
4842         }
4843         else
4844         {
4845                 for (i = 0;i < texturenumsurfaces;i++)
4846                 {
4847                         surface = texturesurfacelist[i];
4848                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4849                         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));
4850                 }
4851         }
4852 }
4853
4854 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
4855 {
4856         int i, planeindex, vertexindex;
4857         float d, bestd;
4858         vec3_t vert;
4859         const float *v;
4860         r_waterstate_waterplane_t *p, *bestp;
4861         msurface_t *surface;
4862         if (r_waterstate.renderingscene)
4863                 return;
4864         for (i = 0;i < texturenumsurfaces;i++)
4865         {
4866                 surface = texturesurfacelist[i];
4867                 if (lightmaptexunit >= 0)
4868                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4869                 if (deluxemaptexunit >= 0)
4870                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4871                 // pick the closest matching water plane
4872                 bestd = 0;
4873                 bestp = NULL;
4874                 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4875                 {
4876                         d = 0;
4877                         for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
4878                         {
4879                                 Matrix4x4_Transform(&rsurface.matrix, v, vert);
4880                                 d += fabs(PlaneDiff(vert, &p->plane));
4881                         }
4882                         if (bestd > d || !bestp)
4883                         {
4884                                 bestd = d;
4885                                 bestp = p;
4886                         }
4887                 }
4888                 if (bestp)
4889                 {
4890                         if (refractiontexunit >= 0)
4891                                 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
4892                         if (reflectiontexunit >= 0)
4893                                 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
4894                 }
4895                 else
4896                 {
4897                         if (refractiontexunit >= 0)
4898                                 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
4899                         if (reflectiontexunit >= 0)
4900                                 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
4901                 }
4902                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4903                 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));
4904         }
4905 }
4906
4907 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
4908 {
4909         int i;
4910         int j;
4911         const msurface_t *surface = texturesurfacelist[0];
4912         const msurface_t *surface2;
4913         int firstvertex;
4914         int endvertex;
4915         int numvertices;
4916         int numtriangles;
4917         // TODO: lock all array ranges before render, rather than on each surface
4918         if (texturenumsurfaces == 1)
4919         {
4920                 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4921                 if (deluxemaptexunit >= 0)
4922                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4923                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4924                 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));
4925         }
4926         else if (r_batchmode.integer == 2)
4927         {
4928                 #define MAXBATCHTRIANGLES 4096
4929                 int batchtriangles = 0;
4930                 int batchelements[MAXBATCHTRIANGLES*3];
4931                 for (i = 0;i < texturenumsurfaces;i = j)
4932                 {
4933                         surface = texturesurfacelist[i];
4934                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4935                         if (deluxemaptexunit >= 0)
4936                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4937                         j = i + 1;
4938                         if (surface->num_triangles > MAXBATCHTRIANGLES)
4939                         {
4940                                 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));
4941                                 continue;
4942                         }
4943                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4944                         batchtriangles = surface->num_triangles;
4945                         firstvertex = surface->num_firstvertex;
4946                         endvertex = surface->num_firstvertex + surface->num_vertices;
4947                         for (;j < texturenumsurfaces;j++)
4948                         {
4949                                 surface2 = texturesurfacelist[j];
4950                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4951                                         break;
4952                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4953                                 batchtriangles += surface2->num_triangles;
4954                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
4955                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4956                         }
4957                         surface2 = texturesurfacelist[j-1];
4958                         numvertices = endvertex - firstvertex;
4959                         R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4960                 }
4961         }
4962         else if (r_batchmode.integer == 1)
4963         {
4964 #if 0
4965                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
4966                 for (i = 0;i < texturenumsurfaces;i = j)
4967                 {
4968                         surface = texturesurfacelist[i];
4969                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4970                                 if (texturesurfacelist[j] != surface2)
4971                                         break;
4972                         Con_Printf(" %i", j - i);
4973                 }
4974                 Con_Printf("\n");
4975                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
4976 #endif
4977                 for (i = 0;i < texturenumsurfaces;i = j)
4978                 {
4979                         surface = texturesurfacelist[i];
4980                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4981                         if (deluxemaptexunit >= 0)
4982                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4983                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4984                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
4985                                         break;
4986 #if 0
4987                         Con_Printf(" %i", j - i);
4988 #endif
4989                         surface2 = texturesurfacelist[j-1];
4990                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4991                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4992                         GL_LockArrays(surface->num_firstvertex, numvertices);
4993                         R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4994                 }
4995 #if 0
4996                 Con_Printf("\n");
4997 #endif
4998         }
4999         else
5000         {
5001                 for (i = 0;i < texturenumsurfaces;i++)
5002                 {
5003                         surface = texturesurfacelist[i];
5004                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5005                         if (deluxemaptexunit >= 0)
5006                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5007                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5008                         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));
5009                 }
5010         }
5011 }
5012
5013 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5014 {
5015         int j;
5016         int texturesurfaceindex;
5017         if (r_showsurfaces.integer == 2)
5018         {
5019                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5020                 {
5021                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5022                         for (j = 0;j < surface->num_triangles;j++)
5023                         {
5024                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
5025                                 GL_Color(f, f, f, 1);
5026                                 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)));
5027                         }
5028                 }
5029         }
5030         else
5031         {
5032                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5033                 {
5034                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5035                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
5036                         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);
5037                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5038                         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));
5039                 }
5040         }
5041 }
5042
5043 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5044 {
5045         int texturesurfaceindex;
5046         int i;
5047         float f;
5048         float *v, *c, *c2;
5049         if (rsurface.lightmapcolor4f)
5050         {
5051                 // generate color arrays for the surfaces in this list
5052                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5053                 {
5054                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5055                         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)
5056                         {
5057                                 f = FogPoint_Model(v);
5058                                 c2[0] = c[0] * f;
5059                                 c2[1] = c[1] * f;
5060                                 c2[2] = c[2] * f;
5061                                 c2[3] = c[3];
5062                         }
5063                 }
5064         }
5065         else
5066         {
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), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
5071                         {
5072                                 f = FogPoint_Model(v);
5073                                 c2[0] = f;
5074                                 c2[1] = f;
5075                                 c2[2] = f;
5076                                 c2[3] = 1;
5077                         }
5078                 }
5079         }
5080         rsurface.lightmapcolor4f = rsurface.array_color4f;
5081         rsurface.lightmapcolor4f_bufferobject = 0;
5082         rsurface.lightmapcolor4f_bufferoffset = 0;
5083 }
5084
5085 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5086 {
5087         int texturesurfaceindex;
5088         int i;
5089         float *c, *c2;
5090         if (!rsurface.lightmapcolor4f)
5091                 return;
5092         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5093         {
5094                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5095                 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)
5096                 {
5097                         c2[0] = c[0] * r;
5098                         c2[1] = c[1] * g;
5099                         c2[2] = c[2] * b;
5100                         c2[3] = c[3] * a;
5101                 }
5102         }
5103         rsurface.lightmapcolor4f = rsurface.array_color4f;
5104         rsurface.lightmapcolor4f_bufferobject = 0;
5105         rsurface.lightmapcolor4f_bufferoffset = 0;
5106 }
5107
5108 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5109 {
5110         // TODO: optimize
5111         rsurface.lightmapcolor4f = NULL;
5112         rsurface.lightmapcolor4f_bufferobject = 0;
5113         rsurface.lightmapcolor4f_bufferoffset = 0;
5114         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5115         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5116         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5117         GL_Color(r, g, b, a);
5118         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5119 }
5120
5121 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5122 {
5123         // TODO: optimize applyfog && applycolor case
5124         // just apply fog if necessary, and tint the fog color array if necessary
5125         rsurface.lightmapcolor4f = NULL;
5126         rsurface.lightmapcolor4f_bufferobject = 0;
5127         rsurface.lightmapcolor4f_bufferoffset = 0;
5128         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5129         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5130         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5131         GL_Color(r, g, b, a);
5132         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5133 }
5134
5135 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5136 {
5137         int texturesurfaceindex;
5138         int i;
5139         float *c;
5140         // TODO: optimize
5141         if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5142         {
5143                 // generate color arrays for the surfaces in this list
5144                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5145                 {
5146                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5147                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5148                         {
5149                                 if (surface->lightmapinfo->samples)
5150                                 {
5151                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5152                                         float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5153                                         VectorScale(lm, scale, c);
5154                                         if (surface->lightmapinfo->styles[1] != 255)
5155                                         {
5156                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5157                                                 lm += size3;
5158                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5159                                                 VectorMA(c, scale, lm, c);
5160                                                 if (surface->lightmapinfo->styles[2] != 255)
5161                                                 {
5162                                                         lm += size3;
5163                                                         scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5164                                                         VectorMA(c, scale, lm, c);
5165                                                         if (surface->lightmapinfo->styles[3] != 255)
5166                                                         {
5167                                                                 lm += size3;
5168                                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5169                                                                 VectorMA(c, scale, lm, c);
5170                                                         }
5171                                                 }
5172                                         }
5173                                 }
5174                                 else
5175                                         VectorClear(c);
5176                                 c[3] = 1;
5177                         }
5178                 }
5179                 rsurface.lightmapcolor4f = rsurface.array_color4f;
5180                 rsurface.lightmapcolor4f_bufferobject = 0;
5181                 rsurface.lightmapcolor4f_bufferoffset = 0;
5182         }
5183         else
5184         {
5185                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5186                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5187                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5188         }
5189         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5190         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5191         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5192         GL_Color(r, g, b, a);
5193         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5194 }
5195
5196 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5197 {
5198         int texturesurfaceindex;
5199         int i;
5200         float f;
5201         float *v, *c, *c2;
5202         vec3_t ambientcolor;
5203         vec3_t diffusecolor;
5204         vec3_t lightdir;
5205         // TODO: optimize
5206         // model lighting
5207         VectorCopy(rsurface.modellight_lightdir, lightdir);
5208         ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f;
5209         ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f;
5210         ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f;
5211         diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f;
5212         diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f;
5213         diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f;
5214         if (VectorLength2(diffusecolor) > 0)
5215         {
5216                 // generate color arrays for the surfaces in this list
5217                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5218                 {
5219                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5220                         int numverts = surface->num_vertices;
5221                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5222                         c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5223                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5224                         // q3-style directional shading
5225                         for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5226                         {
5227                                 if ((f = DotProduct(c2, lightdir)) > 0)
5228                                         VectorMA(ambientcolor, f, diffusecolor, c);
5229                                 else
5230                                         VectorCopy(ambientcolor, c);
5231                                 c[3] = a;
5232                         }
5233                 }
5234                 r = 1;
5235                 g = 1;
5236                 b = 1;
5237                 a = 1;
5238                 applycolor = false;
5239                 rsurface.lightmapcolor4f = rsurface.array_color4f;
5240                 rsurface.lightmapcolor4f_bufferobject = 0;
5241                 rsurface.lightmapcolor4f_bufferoffset = 0;
5242         }
5243         else
5244         {
5245                 r = ambientcolor[0];
5246                 g = ambientcolor[1];
5247                 b = ambientcolor[2];
5248                 rsurface.lightmapcolor4f = NULL;
5249                 rsurface.lightmapcolor4f_bufferobject = 0;
5250                 rsurface.lightmapcolor4f_bufferoffset = 0;
5251         }
5252         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5253         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5254         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5255         GL_Color(r, g, b, a);
5256         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5257 }
5258
5259 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5260 {
5261         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5262         GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5263         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5264         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5265         if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5266         {
5267                 rsurface.mode = RSURFMODE_SHOWSURFACES;
5268                 GL_DepthMask(true);
5269                 GL_BlendFunc(GL_ONE, GL_ZERO);
5270                 R_Mesh_ColorPointer(NULL, 0, 0);
5271                 R_Mesh_ResetTextureState();
5272         }
5273         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5274         RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5275 }
5276
5277 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5278 {
5279         // transparent sky would be ridiculous
5280         if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5281                 return;
5282         if (rsurface.mode != RSURFMODE_SKY)
5283         {
5284                 if (rsurface.mode == RSURFMODE_GLSL)
5285                 {
5286                         qglUseProgramObjectARB(0);CHECKGLERROR
5287                 }
5288                 rsurface.mode = RSURFMODE_SKY;
5289         }
5290         if (skyrendernow)
5291         {
5292                 skyrendernow = false;
5293                 R_Sky();
5294                 // restore entity matrix
5295                 R_Mesh_Matrix(&rsurface.matrix);
5296         }
5297         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5298         GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5299         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5300         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5301         GL_DepthMask(true);
5302         // LordHavoc: HalfLife maps have freaky skypolys so don't use
5303         // skymasking on them, and Quake3 never did sky masking (unlike
5304         // software Quake and software Quake2), so disable the sky masking
5305         // in Quake3 maps as it causes problems with q3map2 sky tricks,
5306         // and skymasking also looks very bad when noclipping outside the
5307         // level, so don't use it then either.
5308         if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
5309         {
5310                 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
5311                 R_Mesh_ColorPointer(NULL, 0, 0);
5312                 R_Mesh_ResetTextureState();
5313                 if (skyrendermasked)
5314                 {
5315                         // depth-only (masking)
5316                         GL_ColorMask(0,0,0,0);
5317                         // just to make sure that braindead drivers don't draw
5318                         // anything despite that colormask...
5319                         GL_BlendFunc(GL_ZERO, GL_ONE);
5320                 }
5321                 else
5322                 {
5323                         // fog sky
5324                         GL_BlendFunc(GL_ONE, GL_ZERO);
5325                 }
5326                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5327                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5328                 if (skyrendermasked)
5329                         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5330         }
5331 }
5332
5333 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5334 {
5335         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5336                 return;
5337
5338         if (rsurface.mode != RSURFMODE_GLSL)
5339         {
5340                 rsurface.mode = RSURFMODE_GLSL;
5341                 R_Mesh_ResetTextureState();
5342         }
5343
5344         R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5345         R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5346         R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
5347         R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
5348         R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
5349         R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
5350         R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5351         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5352         {
5353                 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5354                 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5355                 R_Mesh_ColorPointer(NULL, 0, 0);
5356         }
5357         else if (rsurface.uselightmaptexture)
5358         {
5359                 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5360                 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5361                 R_Mesh_ColorPointer(NULL, 0, 0);
5362         }
5363         else
5364         {
5365                 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5366                 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5367                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5368         }
5369         R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
5370         R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5371         R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5372
5373         if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5374         {
5375                 // render background
5376                 GL_BlendFunc(GL_ONE, GL_ZERO);
5377                 GL_DepthMask(true);
5378                 GL_AlphaTest(false);
5379
5380                 GL_Color(1, 1, 1, 1);
5381                 R_Mesh_ColorPointer(NULL, 0, 0);
5382
5383                 R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5384                 if (r_glsl_permutation)
5385                 {
5386                         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5387                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5388                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5389                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5390                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5391                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5392                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection ? 12 : -1);
5393                 }
5394
5395                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5396                 GL_DepthMask(false);
5397                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5398                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5399                 {
5400                         R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5401                         R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5402                         R_Mesh_ColorPointer(NULL, 0, 0);
5403                 }
5404                 else if (rsurface.uselightmaptexture)
5405                 {
5406                         R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5407                         R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5408                         R_Mesh_ColorPointer(NULL, 0, 0);
5409                 }
5410                 else
5411                 {
5412                         R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5413                         R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5414                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5415                 }
5416                 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5417                 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5418         }
5419
5420         R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5421         if (!r_glsl_permutation)
5422                 return;
5423
5424         if (rsurface.lightmode == 2)
5425                 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5426         else
5427                 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5428         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5429         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5430         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5431         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5432         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5433         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]);
5434
5435         if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5436         {
5437                 GL_BlendFunc(GL_ONE, GL_ZERO);
5438                 GL_DepthMask(true);
5439                 GL_AlphaTest(false);
5440         }
5441
5442         if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5443         {
5444                 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5445                         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);
5446                 else
5447                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5448         }
5449         else
5450         {
5451                 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5452                         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);
5453                 else
5454                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5455         }
5456         if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5457         {
5458         }
5459 }
5460
5461 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5462 {
5463         // OpenGL 1.3 path - anything not completely ancient
5464         int texturesurfaceindex;
5465         qboolean applycolor;
5466         qboolean applyfog;
5467         rmeshstate_t m;
5468         int layerindex;
5469         const texturelayer_t *layer;
5470         if (rsurface.mode != RSURFMODE_MULTIPASS)
5471                 rsurface.mode = RSURFMODE_MULTIPASS;
5472         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5473
5474         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5475         {
5476                 vec4_t layercolor;
5477                 int layertexrgbscale;
5478                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5479                 {
5480                         if (layerindex == 0)
5481                                 GL_AlphaTest(true);
5482                         else
5483                         {
5484                                 GL_AlphaTest(false);
5485                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5486                         }
5487                 }
5488                 GL_DepthMask(layer->depthmask);
5489                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5490                 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
5491                 {
5492                         layertexrgbscale = 4;
5493                         VectorScale(layer->color, 0.25f, layercolor);
5494                 }
5495                 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
5496                 {
5497                         layertexrgbscale = 2;
5498                         VectorScale(layer->color, 0.5f, layercolor);
5499                 }
5500                 else
5501                 {
5502                         layertexrgbscale = 1;
5503                         VectorScale(layer->color, 1.0f, layercolor);
5504                 }
5505                 layercolor[3] = layer->color[3];
5506                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5507                 R_Mesh_ColorPointer(NULL, 0, 0);
5508                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5509                 switch (layer->type)
5510                 {
5511                 case TEXTURELAYERTYPE_LITTEXTURE:
5512                         memset(&m, 0, sizeof(m));
5513                         m.tex[0] = R_GetTexture(r_texture_white);
5514                         m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5515                         m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5516                         m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5517                         m.tex[1] = R_GetTexture(layer->texture);
5518                         m.texmatrix[1] = layer->texmatrix;
5519                         m.texrgbscale[1] = layertexrgbscale;
5520                         m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5521                         m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5522                         m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5523                         R_Mesh_TextureState(&m);
5524                         if (rsurface.lightmode == 2)
5525                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5526                         else if (rsurface.uselightmaptexture)
5527                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5528                         else
5529                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5530                         break;
5531                 case TEXTURELAYERTYPE_TEXTURE:
5532                         memset(&m, 0, sizeof(m));
5533                         m.tex[0] = R_GetTexture(layer->texture);
5534                         m.texmatrix[0] = layer->texmatrix;
5535                         m.texrgbscale[0] = layertexrgbscale;
5536                         m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5537                         m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5538                         m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5539                         R_Mesh_TextureState(&m);
5540                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5541                         break;
5542                 case TEXTURELAYERTYPE_FOG:
5543                         memset(&m, 0, sizeof(m));
5544                         m.texrgbscale[0] = layertexrgbscale;
5545                         if (layer->texture)
5546                         {
5547                                 m.tex[0] = R_GetTexture(layer->texture);
5548                                 m.texmatrix[0] = layer->texmatrix;
5549                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5550                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5551                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5552                         }
5553                         R_Mesh_TextureState(&m);
5554                         // generate a color array for the fog pass
5555                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5556                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5557                         {
5558                                 int i;
5559                                 float f, *v, *c;
5560                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5561                                 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)
5562                                 {
5563                                         f = 1 - FogPoint_Model(v);
5564                                         c[0] = layercolor[0];
5565                                         c[1] = layercolor[1];
5566                                         c[2] = layercolor[2];
5567                                         c[3] = f * layercolor[3];
5568                                 }
5569                         }
5570                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5571                         break;
5572                 default:
5573                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5574                 }
5575                 GL_LockArrays(0, 0);
5576         }
5577         CHECKGLERROR
5578         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5579         {
5580                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5581                 GL_AlphaTest(false);
5582         }
5583 }
5584
5585 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5586 {
5587         // OpenGL 1.1 - crusty old voodoo path
5588         int texturesurfaceindex;
5589         qboolean applyfog;
5590         rmeshstate_t m;
5591         int layerindex;
5592         const texturelayer_t *layer;
5593         if (rsurface.mode != RSURFMODE_MULTIPASS)
5594                 rsurface.mode = RSURFMODE_MULTIPASS;
5595         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5596
5597         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5598         {
5599                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5600                 {
5601                         if (layerindex == 0)
5602                                 GL_AlphaTest(true);
5603                         else
5604                         {
5605                                 GL_AlphaTest(false);
5606                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5607                         }
5608                 }
5609                 GL_DepthMask(layer->depthmask);
5610                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5611                 R_Mesh_ColorPointer(NULL, 0, 0);
5612                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5613                 switch (layer->type)
5614                 {
5615                 case TEXTURELAYERTYPE_LITTEXTURE:
5616                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5617                         {
5618                                 // two-pass lit texture with 2x rgbscale
5619                                 // first the lightmap pass
5620                                 memset(&m, 0, sizeof(m));
5621                                 m.tex[0] = R_GetTexture(r_texture_white);
5622                                 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5623                                 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5624                                 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5625                                 R_Mesh_TextureState(&m);
5626                                 if (rsurface.lightmode == 2)
5627                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5628                                 else if (rsurface.uselightmaptexture)
5629                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5630                                 else
5631                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5632                                 GL_LockArrays(0, 0);
5633                                 // then apply the texture to it
5634                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5635                                 memset(&m, 0, sizeof(m));
5636                                 m.tex[0] = R_GetTexture(layer->texture);
5637                                 m.texmatrix[0] = layer->texmatrix;
5638                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5639                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5640                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5641                                 R_Mesh_TextureState(&m);
5642                                 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);
5643                         }
5644                         else
5645                         {
5646                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5647                                 memset(&m, 0, sizeof(m));
5648                                 m.tex[0] = R_GetTexture(layer->texture);
5649                                 m.texmatrix[0] = layer->texmatrix;
5650                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5651                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5652                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5653                                 R_Mesh_TextureState(&m);
5654                                 if (rsurface.lightmode == 2)
5655                                         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);
5656                                 else
5657                                         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);
5658                         }
5659                         break;
5660                 case TEXTURELAYERTYPE_TEXTURE:
5661                         // singletexture unlit texture with 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                         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);
5670                         break;
5671                 case TEXTURELAYERTYPE_FOG:
5672                         // singletexture fogging
5673                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5674                         if (layer->texture)
5675                         {
5676                                 memset(&m, 0, sizeof(m));
5677                                 m.tex[0] = R_GetTexture(layer->texture);
5678                                 m.texmatrix[0] = layer->texmatrix;
5679                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5680                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5681                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5682                                 R_Mesh_TextureState(&m);
5683                         }
5684                         else
5685                                 R_Mesh_ResetTextureState();
5686                         // generate a color array for the fog pass
5687                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5688                         {
5689                                 int i;
5690                                 float f, *v, *c;
5691                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5692                                 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)
5693                                 {
5694                                         f = 1 - FogPoint_Model(v);
5695                                         c[0] = layer->color[0];
5696                                         c[1] = layer->color[1];
5697                                         c[2] = layer->color[2];
5698                                         c[3] = f * layer->color[3];
5699                                 }
5700                         }
5701                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5702                         break;
5703                 default:
5704                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5705                 }
5706                 GL_LockArrays(0, 0);
5707         }
5708         CHECKGLERROR
5709         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5710         {
5711                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5712                 GL_AlphaTest(false);
5713         }
5714 }
5715
5716 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5717 {
5718         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5719                 return;
5720         rsurface.rtlight = NULL;
5721         CHECKGLERROR
5722         if (depthonly)
5723         {
5724                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5725                         return;
5726                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5727                         return;
5728                 if (rsurface.mode != RSURFMODE_MULTIPASS)
5729                         rsurface.mode = RSURFMODE_MULTIPASS;
5730                 if (r_depthfirst.integer == 3)
5731                 {
5732                         int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5733                         if (!r_view.showdebug)
5734                                 GL_Color(0, 0, 0, 1);
5735                         else
5736                                 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5737                 }
5738                 else
5739                 {
5740                         GL_ColorMask(0,0,0,0);
5741                         GL_Color(1,1,1,1);
5742                 }
5743                 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5744                 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5745                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5746                 GL_DepthTest(true);
5747                 GL_BlendFunc(GL_ONE, GL_ZERO);
5748                 GL_DepthMask(true);
5749                 GL_AlphaTest(false);
5750                 R_Mesh_ColorPointer(NULL, 0, 0);
5751                 R_Mesh_ResetTextureState();
5752                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5753                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5754                 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5755                 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5756         }
5757         else if (r_depthfirst.integer == 3)
5758                 return;
5759         else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5760         {
5761                 GL_Color(0, 0, 0, 1);
5762                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5763         }
5764         else if (r_showsurfaces.integer)
5765         {
5766                 if (rsurface.mode != RSURFMODE_MULTIPASS)
5767                         rsurface.mode = RSURFMODE_MULTIPASS;
5768                 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5769                 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5770                 GL_DepthTest(true);
5771                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5772                 GL_BlendFunc(GL_ONE, GL_ZERO);
5773                 GL_DepthMask(writedepth);
5774                 GL_Color(1,1,1,1);
5775                 GL_AlphaTest(false);
5776                 R_Mesh_ColorPointer(NULL, 0, 0);
5777                 R_Mesh_ResetTextureState();
5778                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5779                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5780                 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5781         }
5782         else if (gl_lightmaps.integer)
5783         {
5784                 rmeshstate_t m;
5785                 if (rsurface.mode != RSURFMODE_MULTIPASS)
5786                         rsurface.mode = RSURFMODE_MULTIPASS;
5787                 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5788                 GL_DepthTest(true);
5789                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5790                 GL_BlendFunc(GL_ONE, GL_ZERO);
5791                 GL_DepthMask(writedepth);
5792                 GL_Color(1,1,1,1);
5793                 GL_AlphaTest(false);
5794                 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5795                 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5796                 R_Mesh_ColorPointer(NULL, 0, 0);
5797                 memset(&m, 0, sizeof(m));
5798                 m.tex[0] = R_GetTexture(r_texture_white);
5799                 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5800                 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5801                 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5802                 R_Mesh_TextureState(&m);
5803                 RSurf_PrepareVerticesForBatch(rsurface.lightmode == 2, false, texturenumsurfaces, texturesurfacelist);
5804                 if (rsurface.lightmode == 2)
5805                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5806                 else if (rsurface.uselightmaptexture)
5807                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5808                 else
5809                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5810                 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5811         }
5812         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5813         {
5814                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5815                 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5816         }
5817         else if (rsurface.texture->currentnumlayers)
5818         {
5819                 // write depth for anything we skipped on the depth-only pass earlier
5820                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5821                         writedepth = true;
5822                 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5823                 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5824                 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5825                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5826                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5827                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5828                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5829                 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5830                 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5831                 if (r_glsl.integer && gl_support_fragment_shader)
5832                         R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
5833                 else if (gl_combine.integer && r_textureunits.integer >= 2)
5834                         R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
5835                 else
5836                         R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
5837                 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5838         }
5839         CHECKGLERROR
5840         GL_LockArrays(0, 0);
5841 }
5842
5843 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5844 {
5845         int i, j;
5846         int texturenumsurfaces, endsurface;
5847         texture_t *texture;
5848         msurface_t *surface;
5849         msurface_t *texturesurfacelist[1024];
5850
5851         // if the model is static it doesn't matter what value we give for
5852         // wantnormals and wanttangents, so this logic uses only rules applicable
5853         // to a model, knowing that they are meaningless otherwise
5854         if (ent == r_refdef.worldentity)
5855                 RSurf_ActiveWorldEntity();
5856         else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5857                 RSurf_ActiveModelEntity(ent, false, false);
5858         else
5859                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
5860
5861         for (i = 0;i < numsurfaces;i = j)
5862         {
5863                 j = i + 1;
5864                 surface = rsurface.modelsurfaces + surfacelist[i];
5865                 texture = surface->texture;
5866                 R_UpdateTextureInfo(ent, texture);
5867                 rsurface.texture = texture->currentframe;
5868                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
5869                 // scan ahead until we find a different texture
5870                 endsurface = min(i + 1024, numsurfaces);
5871                 texturenumsurfaces = 0;
5872                 texturesurfacelist[texturenumsurfaces++] = surface;
5873                 for (;j < endsurface;j++)
5874                 {
5875                         surface = rsurface.modelsurfaces + surfacelist[j];
5876                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
5877                                 break;
5878                         texturesurfacelist[texturenumsurfaces++] = surface;
5879                 }
5880                 // render the range of surfaces
5881                 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
5882         }
5883
5884         RSurf_CleanUp();
5885 }
5886
5887 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
5888 {
5889         int i, j;
5890         vec3_t tempcenter, center;
5891         texture_t *texture;
5892         // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
5893         if (addwaterplanes)
5894         {
5895                 for (i = 0;i < numsurfaces;i++)
5896                         if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
5897                                 R_Water_AddWaterPlane(surfacelist[i]);
5898                 return;
5899         }
5900         // break the surface list down into batches by texture and use of lightmapping
5901         for (i = 0;i < numsurfaces;i = j)
5902         {
5903                 j = i + 1;
5904                 // texture is the base texture pointer, rsurface.texture is the
5905                 // current frame/skin the texture is directing us to use (for example
5906                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
5907                 // use skin 1 instead)
5908                 texture = surfacelist[i]->texture;
5909                 rsurface.texture = texture->currentframe;
5910                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
5911                 if (!(rsurface.texture->currentmaterialflags & flagsmask))
5912                 {
5913                         // if this texture is not the kind we want, skip ahead to the next one
5914                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
5915                                 ;
5916                         continue;
5917                 }
5918                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5919                 {
5920                         // transparent surfaces get pushed off into the transparent queue
5921                         const msurface_t *surface = surfacelist[i];
5922                         if (depthonly)
5923                                 continue;
5924                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
5925                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
5926                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
5927                         Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
5928                         R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
5929                 }
5930                 else
5931                 {
5932                         // simply scan ahead until we find a different texture or lightmap state
5933                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
5934                                 ;
5935                         // render the range of surfaces
5936                         R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
5937                 }
5938         }
5939 }
5940
5941 float locboxvertex3f[6*4*3] =
5942 {
5943         1,0,1, 1,0,0, 1,1,0, 1,1,1,
5944         0,1,1, 0,1,0, 0,0,0, 0,0,1,
5945         1,1,1, 1,1,0, 0,1,0, 0,1,1,
5946         0,0,1, 0,0,0, 1,0,0, 1,0,1,
5947         0,0,1, 1,0,1, 1,1,1, 0,1,1,
5948         1,0,0, 0,0,0, 0,1,0, 1,1,0
5949 };
5950
5951 int locboxelement3i[6*2*3] =
5952 {
5953          0, 1, 2, 0, 2, 3,
5954          4, 5, 6, 4, 6, 7,
5955          8, 9,10, 8,10,11,
5956         12,13,14, 12,14,15,
5957         16,17,18, 16,18,19,
5958         20,21,22, 20,22,23
5959 };
5960
5961 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5962 {
5963         int i, j;
5964         cl_locnode_t *loc = (cl_locnode_t *)ent;
5965         vec3_t mins, size;
5966         float vertex3f[6*4*3];
5967         CHECKGLERROR
5968         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5969         GL_DepthMask(false);
5970         GL_DepthRange(0, 1);
5971         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5972         GL_DepthTest(true);
5973         GL_CullFace(GL_NONE);
5974         R_Mesh_Matrix(&identitymatrix);
5975
5976         R_Mesh_VertexPointer(vertex3f, 0, 0);
5977         R_Mesh_ColorPointer(NULL, 0, 0);
5978         R_Mesh_ResetTextureState();
5979
5980         i = surfacelist[0];
5981         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
5982                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
5983                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
5984                         surfacelist[0] < 0 ? 0.5f : 0.125f);
5985
5986         if (VectorCompare(loc->mins, loc->maxs))
5987         {
5988                 VectorSet(size, 2, 2, 2);
5989                 VectorMA(loc->mins, -0.5f, size, mins);
5990         }
5991         else
5992         {
5993                 VectorCopy(loc->mins, mins);
5994                 VectorSubtract(loc->maxs, loc->mins, size);
5995         }
5996
5997         for (i = 0;i < 6*4*3;)
5998                 for (j = 0;j < 3;j++, i++)
5999                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6000
6001         R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6002 }
6003
6004 void R_DrawLocs(void)
6005 {
6006         int index;
6007         cl_locnode_t *loc, *nearestloc;
6008         vec3_t center;
6009         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6010         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6011         {
6012                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6013                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6014         }
6015 }
6016
6017 void R_DrawDebugModel(entity_render_t *ent)
6018 {
6019         int i, j, k, l, flagsmask;
6020         const int *elements;
6021         q3mbrush_t *brush;
6022         msurface_t *surface;
6023         model_t *model = ent->model;
6024         vec3_t v;
6025
6026         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
6027
6028         R_Mesh_ColorPointer(NULL, 0, 0);
6029         R_Mesh_ResetTextureState();
6030         GL_DepthRange(0, 1);
6031         GL_DepthTest(!r_showdisabledepthtest.integer);
6032         GL_DepthMask(false);
6033         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6034
6035         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6036         {
6037                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6038                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6039                 {
6040                         if (brush->colbrushf && brush->colbrushf->numtriangles)
6041                         {
6042                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6043                                 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);
6044                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6045                         }
6046                 }
6047                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6048                 {
6049                         if (surface->num_collisiontriangles)
6050                         {
6051                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6052                                 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);
6053                                 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6054                         }
6055                 }
6056         }
6057
6058         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6059
6060         if (r_showtris.integer || r_shownormals.integer)
6061         {
6062                 if (r_showdisabledepthtest.integer)
6063                 {
6064                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6065                         GL_DepthMask(false);
6066                 }
6067                 else
6068                 {
6069                         GL_BlendFunc(GL_ONE, GL_ZERO);
6070                         GL_DepthMask(true);
6071                 }
6072                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6073                 {
6074                         if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
6075                                 continue;
6076                         rsurface.texture = surface->texture->currentframe;
6077                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6078                         {
6079                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6080                                 if (r_showtris.value > 0)
6081                                 {
6082                                         if (!rsurface.texture->currentlayers->depthmask)
6083                                                 GL_Color(r_view.colorscale, 0, 0, r_showtris.value);
6084                                         else if (ent == r_refdef.worldentity)
6085                                                 GL_Color(r_view.colorscale, r_view.colorscale, r_view.colorscale, r_showtris.value);
6086                                         else
6087                                                 GL_Color(0, r_view.colorscale, 0, r_showtris.value);
6088                                         elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6089                                         CHECKGLERROR
6090                                         qglBegin(GL_LINES);
6091                                         for (k = 0;k < surface->num_triangles;k++, elements += 3)
6092                                         {
6093 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6094                                                 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6095                                                 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6096                                                 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6097                                         }
6098                                         qglEnd();
6099                                         CHECKGLERROR
6100                                 }
6101                                 if (r_shownormals.value > 0)
6102                                 {
6103                                         GL_Color(r_view.colorscale, 0, 0, r_shownormals.value);
6104                                         qglBegin(GL_LINES);
6105                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6106                                         {
6107                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
6108                                                 qglVertex3f(v[0], v[1], v[2]);
6109                                                 VectorMA(v, 8, rsurface.svector3f + l * 3, v);
6110                                                 qglVertex3f(v[0], v[1], v[2]);
6111                                         }
6112                                         qglEnd();
6113                                         CHECKGLERROR
6114                                         GL_Color(0, 0, r_view.colorscale, r_shownormals.value);
6115                                         qglBegin(GL_LINES);
6116                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6117                                         {
6118                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
6119                                                 qglVertex3f(v[0], v[1], v[2]);
6120                                                 VectorMA(v, 8, rsurface.tvector3f + l * 3, v);
6121                                                 qglVertex3f(v[0], v[1], v[2]);
6122                                         }
6123                                         qglEnd();
6124                                         CHECKGLERROR
6125                                         GL_Color(0, r_view.colorscale, 0, r_shownormals.value);
6126                                         qglBegin(GL_LINES);
6127                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6128                                         {
6129                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
6130                                                 qglVertex3f(v[0], v[1], v[2]);
6131                                                 VectorMA(v, 8, rsurface.normal3f + l * 3, v);
6132                                                 qglVertex3f(v[0], v[1], v[2]);
6133                                         }
6134                                         qglEnd();
6135                                         CHECKGLERROR
6136                                 }
6137                         }
6138                 }
6139                 rsurface.texture = NULL;
6140         }
6141 }
6142
6143 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6144 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6145 {
6146         int i, j, endj, f, flagsmask;
6147         int counttriangles = 0;
6148         msurface_t *surface, **surfacechain;
6149         texture_t *t;
6150         model_t *model = r_refdef.worldmodel;
6151         const int maxsurfacelist = 1024;
6152         int numsurfacelist = 0;
6153         msurface_t *surfacelist[1024];
6154         if (model == NULL)
6155                 return;
6156
6157         RSurf_ActiveWorldEntity();
6158
6159         // update light styles
6160         if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6161         {
6162                 for (i = 0;i < model->brushq1.light_styles;i++)
6163                 {
6164                         if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6165                         {
6166                                 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6167                                 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6168                                         for (;(surface = *surfacechain);surfacechain++)
6169                                                 surface->cached_dlight = true;
6170                         }
6171                 }
6172         }
6173
6174         R_UpdateAllTextureInfo(r_refdef.worldentity);
6175         flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6176
6177         if (debug)
6178         {
6179                 R_DrawDebugModel(r_refdef.worldentity);
6180                 return;
6181         }
6182
6183         f = 0;
6184         t = NULL;
6185         rsurface.uselightmaptexture = false;
6186         rsurface.texture = NULL;
6187         numsurfacelist = 0;
6188         j = model->firstmodelsurface;
6189         endj = j + model->nummodelsurfaces;
6190         while (j < endj)
6191         {
6192                 // quickly skip over non-visible surfaces
6193                 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
6194                         ;
6195                 // quickly iterate over visible surfaces
6196                 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
6197                 {
6198                         // process this surface
6199                         surface = model->data_surfaces + j;
6200                         // if this surface fits the criteria, add it to the list
6201                         if (surface->num_triangles)
6202                         {
6203                                 // if lightmap parameters changed, rebuild lightmap texture
6204                                 if (surface->cached_dlight)
6205                                         R_BuildLightMap(r_refdef.worldentity, surface);
6206                                 // add face to draw list
6207                                 surfacelist[numsurfacelist++] = surface;
6208                                 counttriangles += surface->num_triangles;
6209                                 if (numsurfacelist >= maxsurfacelist)
6210                                 {
6211                                         R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6212                                         numsurfacelist = 0;
6213                                 }
6214                         }
6215                 }
6216         }
6217         if (numsurfacelist)
6218                 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6219         r_refdef.stats.entities_triangles += counttriangles;
6220         RSurf_CleanUp();
6221 }
6222
6223 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6224 {
6225         int i, f, flagsmask;
6226         int counttriangles = 0;
6227         msurface_t *surface, *endsurface, **surfacechain;
6228         texture_t *t;
6229         model_t *model = ent->model;
6230         const int maxsurfacelist = 1024;
6231         int numsurfacelist = 0;
6232         msurface_t *surfacelist[1024];
6233         if (model == NULL)
6234                 return;
6235
6236         // if the model is static it doesn't matter what value we give for
6237         // wantnormals and wanttangents, so this logic uses only rules applicable
6238         // to a model, knowing that they are meaningless otherwise
6239         if (ent == r_refdef.worldentity)
6240                 RSurf_ActiveWorldEntity();
6241         else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6242                 RSurf_ActiveModelEntity(ent, false, false);
6243         else
6244                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6245
6246         // update light styles
6247         if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6248         {
6249                 for (i = 0;i < model->brushq1.light_styles;i++)
6250                 {
6251                         if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6252                         {
6253                                 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6254                                 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6255                                         for (;(surface = *surfacechain);surfacechain++)
6256                                                 surface->cached_dlight = true;
6257                         }
6258                 }
6259         }
6260
6261         R_UpdateAllTextureInfo(ent);
6262         flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6263
6264         if (debug)
6265         {
6266                 R_DrawDebugModel(ent);
6267                 return;
6268         }
6269
6270         f = 0;
6271         t = NULL;
6272         rsurface.uselightmaptexture = false;
6273         rsurface.texture = NULL;
6274         numsurfacelist = 0;
6275         surface = model->data_surfaces + model->firstmodelsurface;
6276         endsurface = surface + model->nummodelsurfaces;
6277         for (;surface < endsurface;surface++)
6278         {
6279                 // if this surface fits the criteria, add it to the list
6280                 if (surface->num_triangles)
6281                 {
6282                         // if lightmap parameters changed, rebuild lightmap texture
6283                         if (surface->cached_dlight)
6284                                 R_BuildLightMap(ent, surface);
6285                         // add face to draw list
6286                         surfacelist[numsurfacelist++] = surface;
6287                         counttriangles += surface->num_triangles;
6288                         if (numsurfacelist >= maxsurfacelist)
6289                         {
6290                                 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6291                                 numsurfacelist = 0;
6292                         }
6293                 }
6294         }
6295         if (numsurfacelist)
6296                 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6297         r_refdef.stats.entities_triangles += counttriangles;
6298         RSurf_CleanUp();
6299 }