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