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