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