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