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