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