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