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