]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
experimental new mode "r_showsurfaces 3": shows faces in average texture color
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
30
31 //
32 // screen size info
33 //
34 r_refdef_t r_refdef;
35
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];
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         for(j = 0; j < basepixels_width * basepixels_height * 4; j += 4)
1989         {
1990                 avgcolor[2] += basepixels[j + 0];
1991                 avgcolor[1] += basepixels[j + 1];
1992                 avgcolor[0] += basepixels[j + 2];
1993                 avgcolor[3] += basepixels[j + 3];
1994         }
1995         if(avgcolor[3] == 0) // just fully transparent pixels seen? bad luck...
1996                 avgcolor[3] = 255.0 * basepixels_width * basepixels_height;
1997         if(avgcolor[3] == 0) // no pixels seen? even worse
1998                 avgcolor[3] = 1;
1999         avgcolor[0] /= avgcolor[3];
2000         avgcolor[1] /= avgcolor[3];
2001         avgcolor[2] /= avgcolor[3];
2002         avgcolor[3] /= basepixels_width * 255.0 * basepixels_height; // to 0..1 range
2003         skinframe->avgcolor[0] = avgcolor[0];
2004         skinframe->avgcolor[1] = avgcolor[1];
2005         skinframe->avgcolor[2] = avgcolor[2];
2006         skinframe->avgcolor[3] = avgcolor[3];
2007
2008         // _norm is the name used by tenebrae and has been adopted as standard
2009         if (loadnormalmap)
2010         {
2011                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2012                 {
2013                         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);
2014                         Mem_Free(pixels);
2015                         pixels = NULL;
2016                 }
2017                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2018                 {
2019                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2020                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2021                         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);
2022                         Mem_Free(pixels);
2023                         Mem_Free(bumppixels);
2024                 }
2025                 else if (r_shadow_bumpscale_basetexture.value > 0)
2026                 {
2027                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2028                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2029                         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);
2030                         Mem_Free(pixels);
2031                 }
2032         }
2033         // _luma is supported for tenebrae compatibility
2034         // (I think it's a very stupid name, but oh well)
2035         // _glow is the preferred name
2036         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;}
2037         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;}
2038         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;}
2039         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;}
2040
2041         if (basepixels)
2042                 Mem_Free(basepixels);
2043
2044         return skinframe;
2045 }
2046
2047 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2048 {
2049         qboolean has_alpha;
2050         return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha);
2051 }
2052
2053 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)
2054 {
2055         int i;
2056         if (!force)
2057         {
2058                 for (i = 0;i < width*height;i++)
2059                         if (((unsigned char *)&palette[in[i]])[3] > 0)
2060                                 break;
2061                 if (i == width*height)
2062                         return NULL;
2063         }
2064         return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2065 }
2066
2067 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2068 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2069 {
2070         int i;
2071         unsigned char *temp1, *temp2;
2072         skinframe_t *skinframe;
2073         double avgcolor[4];
2074         int j;
2075
2076         if (cls.state == ca_dedicated)
2077                 return NULL;
2078
2079         // if already loaded just return it, otherwise make a new skinframe
2080         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2081         if (skinframe && skinframe->base)
2082                 return skinframe;
2083
2084         skinframe->stain = NULL;
2085         skinframe->merged = NULL;
2086         skinframe->base = r_texture_notexture;
2087         skinframe->pants = NULL;
2088         skinframe->shirt = NULL;
2089         skinframe->nmap = r_texture_blanknormalmap;
2090         skinframe->gloss = NULL;
2091         skinframe->glow = NULL;
2092         skinframe->fog = NULL;
2093
2094         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2095         if (!skindata)
2096                 return NULL;
2097
2098         if (developer_loading.integer)
2099                 Con_Printf("loading 32bit skin \"%s\"\n", name);
2100
2101         if (r_shadow_bumpscale_basetexture.value > 0)
2102         {
2103                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2104                 temp2 = temp1 + width * height * 4;
2105                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2106                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2107                 Mem_Free(temp1);
2108         }
2109         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2110         if (textureflags & TEXF_ALPHA)
2111         {
2112                 for (i = 3;i < width * height * 4;i += 4)
2113                         if (skindata[i] < 255)
2114                                 break;
2115                 if (i < width * height * 4)
2116                 {
2117                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2118                         memcpy(fogpixels, skindata, width * height * 4);
2119                         for (i = 0;i < width * height * 4;i += 4)
2120                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2121                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2122                         Mem_Free(fogpixels);
2123                 }
2124         }
2125
2126         avgcolor[0] = 0;
2127         avgcolor[1] = 0;
2128         avgcolor[2] = 0;
2129         avgcolor[3] = 0;
2130         for(j = 0; j < width * height * 4; j += 4)
2131         {
2132                 avgcolor[2] += skindata[j + 0];
2133                 avgcolor[1] += skindata[j + 1];
2134                 avgcolor[0] += skindata[j + 2];
2135                 avgcolor[3] += skindata[j + 3];
2136         }
2137         if(avgcolor[3] == 0) // just fully transparent pixels seen? bad luck...
2138                 avgcolor[3] = 255.0 * width * height;
2139         if(avgcolor[3] == 0) // no pixels seen? even worse
2140                 avgcolor[3] = 1;
2141         avgcolor[0] /= avgcolor[3];
2142         avgcolor[1] /= avgcolor[3];
2143         avgcolor[2] /= avgcolor[3];
2144         avgcolor[3] /= width * 255.0 * height; // to 0..1 range
2145         skinframe->avgcolor[0] = avgcolor[0];
2146         skinframe->avgcolor[1] = avgcolor[1];
2147         skinframe->avgcolor[2] = avgcolor[2];
2148         skinframe->avgcolor[3] = avgcolor[3];
2149
2150         return skinframe;
2151 }
2152
2153 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2154 {
2155         int i;
2156         unsigned char *temp1, *temp2;
2157         skinframe_t *skinframe;
2158         double avgcolor[4];
2159         int j;
2160
2161         if (cls.state == ca_dedicated)
2162                 return NULL;
2163
2164         // if already loaded just return it, otherwise make a new skinframe
2165         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2166         if (skinframe && skinframe->base)
2167                 return skinframe;
2168
2169         skinframe->stain = NULL;
2170         skinframe->merged = NULL;
2171         skinframe->base = r_texture_notexture;
2172         skinframe->pants = NULL;
2173         skinframe->shirt = NULL;
2174         skinframe->nmap = r_texture_blanknormalmap;
2175         skinframe->gloss = NULL;
2176         skinframe->glow = NULL;
2177         skinframe->fog = NULL;
2178
2179         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2180         if (!skindata)
2181                 return NULL;
2182
2183         if (developer_loading.integer)
2184                 Con_Printf("loading quake skin \"%s\"\n", name);
2185
2186         if (r_shadow_bumpscale_basetexture.value > 0)
2187         {
2188                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2189                 temp2 = temp1 + width * height * 4;
2190                 // use either a custom palette or the quake palette
2191                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2192                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2193                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2194                 Mem_Free(temp1);
2195         }
2196         // use either a custom palette, or the quake palette
2197         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
2198         if (loadglowtexture)
2199                 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2200         if (loadpantsandshirt)
2201         {
2202                 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2203                 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2204         }
2205         if (skinframe->pants || skinframe->shirt)
2206                 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
2207         if (textureflags & TEXF_ALPHA)
2208         {
2209                 for (i = 0;i < width * height;i++)
2210                         if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2211                                 break;
2212                 if (i < width * height)
2213                         skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2214         }
2215
2216         avgcolor[0] = 0;
2217         avgcolor[1] = 0;
2218         avgcolor[2] = 0;
2219         avgcolor[3] = 0;
2220         for(j = 0; j < width * height; ++j)
2221         {
2222                 temp1 = ((unsigned char *)palette_bgra_alpha) + (skindata[j]*4);
2223                 avgcolor[2] += temp1[0];
2224                 avgcolor[1] += temp1[1];
2225                 avgcolor[0] += temp1[2];
2226                 avgcolor[3] += temp1[3];
2227         }
2228         if(avgcolor[3] == 0) // just fully transparent pixels seen? bad luck...
2229                 avgcolor[3] = 255.0 * width * height;
2230         if(avgcolor[3] == 0) // no pixels seen? even worse
2231                 avgcolor[3] = 1;
2232         avgcolor[0] /= avgcolor[3];
2233         avgcolor[1] /= avgcolor[3];
2234         avgcolor[2] /= avgcolor[3];
2235         avgcolor[3] /= width * 255.0 * height; // to 0..1 range
2236         skinframe->avgcolor[0] = avgcolor[0];
2237         skinframe->avgcolor[1] = avgcolor[1];
2238         skinframe->avgcolor[2] = avgcolor[2];
2239         skinframe->avgcolor[3] = avgcolor[3];
2240
2241         return skinframe;
2242 }
2243
2244 skinframe_t *R_SkinFrame_LoadMissing(void)
2245 {
2246         skinframe_t *skinframe;
2247
2248         if (cls.state == ca_dedicated)
2249                 return NULL;
2250
2251         skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
2252         skinframe->stain = NULL;
2253         skinframe->merged = NULL;
2254         skinframe->base = r_texture_notexture;
2255         skinframe->pants = NULL;
2256         skinframe->shirt = NULL;
2257         skinframe->nmap = r_texture_blanknormalmap;
2258         skinframe->gloss = NULL;
2259         skinframe->glow = NULL;
2260         skinframe->fog = NULL;
2261
2262         skinframe->avgcolor[0] = rand() / RAND_MAX;
2263         skinframe->avgcolor[1] = rand() / RAND_MAX;
2264         skinframe->avgcolor[2] = rand() / RAND_MAX;
2265         skinframe->avgcolor[3] = 1;
2266
2267         return skinframe;
2268 }
2269
2270 void gl_main_start(void)
2271 {
2272         memset(r_qwskincache, 0, sizeof(r_qwskincache));
2273         memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2274
2275         // set up r_skinframe loading system for textures
2276         memset(&r_skinframe, 0, sizeof(r_skinframe));
2277         r_skinframe.loadsequence = 1;
2278         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2279
2280         r_main_texturepool = R_AllocTexturePool();
2281         R_BuildBlankTextures();
2282         R_BuildNoTexture();
2283         if (gl_texturecubemap)
2284         {
2285                 R_BuildWhiteCube();
2286                 R_BuildNormalizationCube();
2287         }
2288         r_texture_fogattenuation = NULL;
2289         r_texture_gammaramps = NULL;
2290         //r_texture_fogintensity = NULL;
2291         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2292         memset(&r_waterstate, 0, sizeof(r_waterstate));
2293         memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2294         memset(&r_svbsp, 0, sizeof (r_svbsp));
2295
2296         r_refdef.fogmasktable_density = 0;
2297 }
2298
2299 void gl_main_shutdown(void)
2300 {
2301         memset(r_qwskincache, 0, sizeof(r_qwskincache));
2302         memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2303
2304         // clear out the r_skinframe state
2305         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2306         memset(&r_skinframe, 0, sizeof(r_skinframe));
2307
2308         if (r_svbsp.nodes)
2309                 Mem_Free(r_svbsp.nodes);
2310         memset(&r_svbsp, 0, sizeof (r_svbsp));
2311         R_FreeTexturePool(&r_main_texturepool);
2312         r_texture_blanknormalmap = NULL;
2313         r_texture_white = NULL;
2314         r_texture_grey128 = NULL;
2315         r_texture_black = NULL;
2316         r_texture_whitecube = NULL;
2317         r_texture_normalizationcube = NULL;
2318         r_texture_fogattenuation = NULL;
2319         r_texture_gammaramps = NULL;
2320         //r_texture_fogintensity = NULL;
2321         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2322         memset(&r_waterstate, 0, sizeof(r_waterstate));
2323         R_GLSL_Restart_f();
2324 }
2325
2326 extern void CL_ParseEntityLump(char *entitystring);
2327 void gl_main_newmap(void)
2328 {
2329         // FIXME: move this code to client
2330         int l;
2331         char *entities, entname[MAX_QPATH];
2332         if (cl.worldmodel)
2333         {
2334                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2335                 l = (int)strlen(entname) - 4;
2336                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2337                 {
2338                         memcpy(entname + l, ".ent", 5);
2339                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2340                         {
2341                                 CL_ParseEntityLump(entities);
2342                                 Mem_Free(entities);
2343                                 return;
2344                         }
2345                 }
2346                 if (cl.worldmodel->brush.entities)
2347                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
2348         }
2349 }
2350
2351 void GL_Main_Init(void)
2352 {
2353         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2354
2355         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2356         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2357         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2358         if (gamemode == GAME_NEHAHRA)
2359         {
2360                 Cvar_RegisterVariable (&gl_fogenable);
2361                 Cvar_RegisterVariable (&gl_fogdensity);
2362                 Cvar_RegisterVariable (&gl_fogred);
2363                 Cvar_RegisterVariable (&gl_foggreen);
2364                 Cvar_RegisterVariable (&gl_fogblue);
2365                 Cvar_RegisterVariable (&gl_fogstart);
2366                 Cvar_RegisterVariable (&gl_fogend);
2367                 Cvar_RegisterVariable (&gl_skyclip);
2368         }
2369         Cvar_RegisterVariable(&r_depthfirst);
2370         Cvar_RegisterVariable(&r_useinfinitefarclip);
2371         Cvar_RegisterVariable(&r_nearclip);
2372         Cvar_RegisterVariable(&r_showbboxes);
2373         Cvar_RegisterVariable(&r_showsurfaces);
2374         Cvar_RegisterVariable(&r_showtris);
2375         Cvar_RegisterVariable(&r_shownormals);
2376         Cvar_RegisterVariable(&r_showlighting);
2377         Cvar_RegisterVariable(&r_showshadowvolumes);
2378         Cvar_RegisterVariable(&r_showcollisionbrushes);
2379         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2380         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2381         Cvar_RegisterVariable(&r_showdisabledepthtest);
2382         Cvar_RegisterVariable(&r_drawportals);
2383         Cvar_RegisterVariable(&r_drawentities);
2384         Cvar_RegisterVariable(&r_cullentities_trace);
2385         Cvar_RegisterVariable(&r_cullentities_trace_samples);
2386         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2387         Cvar_RegisterVariable(&r_cullentities_trace_delay);
2388         Cvar_RegisterVariable(&r_drawviewmodel);
2389         Cvar_RegisterVariable(&r_speeds);
2390         Cvar_RegisterVariable(&r_fullbrights);
2391         Cvar_RegisterVariable(&r_wateralpha);
2392         Cvar_RegisterVariable(&r_dynamic);
2393         Cvar_RegisterVariable(&r_fullbright);
2394         Cvar_RegisterVariable(&r_shadows);
2395         Cvar_RegisterVariable(&r_shadows_throwdistance);
2396         Cvar_RegisterVariable(&r_q1bsp_skymasking);
2397         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2398         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2399         Cvar_RegisterVariable(&r_fog_exp2);
2400         Cvar_RegisterVariable(&r_drawfog);
2401         Cvar_RegisterVariable(&r_textureunits);
2402         Cvar_RegisterVariable(&r_glsl);
2403         Cvar_RegisterVariable(&r_glsl_contrastboost);
2404         Cvar_RegisterVariable(&r_glsl_deluxemapping);
2405         Cvar_RegisterVariable(&r_glsl_offsetmapping);
2406         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2407         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2408         Cvar_RegisterVariable(&r_glsl_postprocess);
2409         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2410         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2411         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2412         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2413         Cvar_RegisterVariable(&r_glsl_usegeneric);
2414         Cvar_RegisterVariable(&r_water);
2415         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2416         Cvar_RegisterVariable(&r_water_clippingplanebias);
2417         Cvar_RegisterVariable(&r_water_refractdistort);
2418         Cvar_RegisterVariable(&r_water_reflectdistort);
2419         Cvar_RegisterVariable(&r_lerpsprites);
2420         Cvar_RegisterVariable(&r_lerpmodels);
2421         Cvar_RegisterVariable(&r_lerplightstyles);
2422         Cvar_RegisterVariable(&r_waterscroll);
2423         Cvar_RegisterVariable(&r_bloom);
2424         Cvar_RegisterVariable(&r_bloom_colorscale);
2425         Cvar_RegisterVariable(&r_bloom_brighten);
2426         Cvar_RegisterVariable(&r_bloom_blur);
2427         Cvar_RegisterVariable(&r_bloom_resolution);
2428         Cvar_RegisterVariable(&r_bloom_colorexponent);
2429         Cvar_RegisterVariable(&r_bloom_colorsubtract);
2430         Cvar_RegisterVariable(&r_hdr);
2431         Cvar_RegisterVariable(&r_hdr_scenebrightness);
2432         Cvar_RegisterVariable(&r_hdr_glowintensity);
2433         Cvar_RegisterVariable(&r_hdr_range);
2434         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2435         Cvar_RegisterVariable(&developer_texturelogging);
2436         Cvar_RegisterVariable(&gl_lightmaps);
2437         Cvar_RegisterVariable(&r_test);
2438         Cvar_RegisterVariable(&r_batchmode);
2439         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2440                 Cvar_SetValue("r_fullbrights", 0);
2441         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2442
2443         Cvar_RegisterVariable(&r_track_sprites);
2444         Cvar_RegisterVariable(&r_track_sprites_flags);
2445         Cvar_RegisterVariable(&r_track_sprites_scalew);
2446         Cvar_RegisterVariable(&r_track_sprites_scaleh);
2447 }
2448
2449 extern void R_Textures_Init(void);
2450 extern void GL_Draw_Init(void);
2451 extern void GL_Main_Init(void);
2452 extern void R_Shadow_Init(void);
2453 extern void R_Sky_Init(void);
2454 extern void GL_Surf_Init(void);
2455 extern void R_Particles_Init(void);
2456 extern void R_Explosion_Init(void);
2457 extern void gl_backend_init(void);
2458 extern void Sbar_Init(void);
2459 extern void R_LightningBeams_Init(void);
2460 extern void Mod_RenderInit(void);
2461
2462 void Render_Init(void)
2463 {
2464         gl_backend_init();
2465         R_Textures_Init();
2466         GL_Main_Init();
2467         GL_Draw_Init();
2468         R_Shadow_Init();
2469         R_Sky_Init();
2470         GL_Surf_Init();
2471         Sbar_Init();
2472         R_Particles_Init();
2473         R_Explosion_Init();
2474         R_LightningBeams_Init();
2475         Mod_RenderInit();
2476 }
2477
2478 /*
2479 ===============
2480 GL_Init
2481 ===============
2482 */
2483 extern char *ENGINE_EXTENSIONS;
2484 void GL_Init (void)
2485 {
2486         gl_renderer = (const char *)qglGetString(GL_RENDERER);
2487         gl_vendor = (const char *)qglGetString(GL_VENDOR);
2488         gl_version = (const char *)qglGetString(GL_VERSION);
2489         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2490
2491         if (!gl_extensions)
2492                 gl_extensions = "";
2493         if (!gl_platformextensions)
2494                 gl_platformextensions = "";
2495
2496         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2497         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2498         Con_Printf("GL_VERSION: %s\n", gl_version);
2499         Con_Printf("GL_EXTENSIONS: %s\n", gl_extensions);
2500         Con_Printf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2501
2502         VID_CheckExtensions();
2503
2504         // LordHavoc: report supported extensions
2505         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2506
2507         // clear to black (loading plaque will be seen over this)
2508         CHECKGLERROR
2509         qglClearColor(0,0,0,1);CHECKGLERROR
2510         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2511 }
2512
2513 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2514 {
2515         int i;
2516         mplane_t *p;
2517         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2518         {
2519                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2520                 if (i == 4)
2521                         continue;
2522                 p = r_refdef.view.frustum + i;
2523                 switch(p->signbits)
2524                 {
2525                 default:
2526                 case 0:
2527                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2528                                 return true;
2529                         break;
2530                 case 1:
2531                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2532                                 return true;
2533                         break;
2534                 case 2:
2535                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2536                                 return true;
2537                         break;
2538                 case 3:
2539                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2540                                 return true;
2541                         break;
2542                 case 4:
2543                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2544                                 return true;
2545                         break;
2546                 case 5:
2547                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2548                                 return true;
2549                         break;
2550                 case 6:
2551                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2552                                 return true;
2553                         break;
2554                 case 7:
2555                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2556                                 return true;
2557                         break;
2558                 }
2559         }
2560         return false;
2561 }
2562
2563 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2564 {
2565         int i;
2566         const mplane_t *p;
2567         for (i = 0;i < numplanes;i++)
2568         {
2569                 p = planes + i;
2570                 switch(p->signbits)
2571                 {
2572                 default:
2573                 case 0:
2574                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2575                                 return true;
2576                         break;
2577                 case 1:
2578                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2579                                 return true;
2580                         break;
2581                 case 2:
2582                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2583                                 return true;
2584                         break;
2585                 case 3:
2586                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2587                                 return true;
2588                         break;
2589                 case 4:
2590                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2591                                 return true;
2592                         break;
2593                 case 5:
2594                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2595                                 return true;
2596                         break;
2597                 case 6:
2598                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2599                                 return true;
2600                         break;
2601                 case 7:
2602                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2603                                 return true;
2604                         break;
2605                 }
2606         }
2607         return false;
2608 }
2609
2610 //==================================================================================
2611
2612 static void R_View_UpdateEntityVisible (void)
2613 {
2614         int i, renderimask;
2615         entity_render_t *ent;
2616
2617         if (!r_drawentities.integer)
2618                 return;
2619
2620         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2621         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2622         {
2623                 // worldmodel can check visibility
2624                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
2625                 for (i = 0;i < r_refdef.scene.numentities;i++)
2626                 {
2627                         ent = r_refdef.scene.entities[i];
2628                         if (!(ent->flags & renderimask))
2629                         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)))
2630                         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))
2631                                 r_refdef.viewcache.entityvisible[i] = true;
2632                 }
2633                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2634                 {
2635                         for (i = 0;i < r_refdef.scene.numentities;i++)
2636                         {
2637                                 ent = r_refdef.scene.entities[i];
2638                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2639                                 {
2640                                         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))
2641                                                 ent->last_trace_visibility = realtime;
2642                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2643                                                 r_refdef.viewcache.entityvisible[i] = 0;
2644                                 }
2645                         }
2646                 }
2647         }
2648         else
2649         {
2650                 // no worldmodel or it can't check visibility
2651                 for (i = 0;i < r_refdef.scene.numentities;i++)
2652                 {
2653                         ent = r_refdef.scene.entities[i];
2654                         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));
2655                 }
2656         }
2657 }
2658
2659 // only used if skyrendermasked, and normally returns false
2660 int R_DrawBrushModelsSky (void)
2661 {
2662         int i, sky;
2663         entity_render_t *ent;
2664
2665         if (!r_drawentities.integer)
2666                 return false;
2667
2668         sky = false;
2669         for (i = 0;i < r_refdef.scene.numentities;i++)
2670         {
2671                 if (!r_refdef.viewcache.entityvisible[i])
2672                         continue;
2673                 ent = r_refdef.scene.entities[i];
2674                 if (!ent->model || !ent->model->DrawSky)
2675                         continue;
2676                 ent->model->DrawSky(ent);
2677                 sky = true;
2678         }
2679         return sky;
2680 }
2681
2682 static void R_DrawNoModel(entity_render_t *ent);
2683 static void R_DrawModels(void)
2684 {
2685         int i;
2686         entity_render_t *ent;
2687
2688         if (!r_drawentities.integer)
2689                 return;
2690
2691         for (i = 0;i < r_refdef.scene.numentities;i++)
2692         {
2693                 if (!r_refdef.viewcache.entityvisible[i])
2694                         continue;
2695                 ent = r_refdef.scene.entities[i];
2696                 r_refdef.stats.entities++;
2697                 if (ent->model && ent->model->Draw != NULL)
2698                         ent->model->Draw(ent);
2699                 else
2700                         R_DrawNoModel(ent);
2701         }
2702 }
2703
2704 static void R_DrawModelsDepth(void)
2705 {
2706         int i;
2707         entity_render_t *ent;
2708
2709         if (!r_drawentities.integer)
2710                 return;
2711
2712         for (i = 0;i < r_refdef.scene.numentities;i++)
2713         {
2714                 if (!r_refdef.viewcache.entityvisible[i])
2715                         continue;
2716                 ent = r_refdef.scene.entities[i];
2717                 if (ent->model && ent->model->DrawDepth != NULL)
2718                         ent->model->DrawDepth(ent);
2719         }
2720 }
2721
2722 static void R_DrawModelsDebug(void)
2723 {
2724         int i;
2725         entity_render_t *ent;
2726
2727         if (!r_drawentities.integer)
2728                 return;
2729
2730         for (i = 0;i < r_refdef.scene.numentities;i++)
2731         {
2732                 if (!r_refdef.viewcache.entityvisible[i])
2733                         continue;
2734                 ent = r_refdef.scene.entities[i];
2735                 if (ent->model && ent->model->DrawDebug != NULL)
2736                         ent->model->DrawDebug(ent);
2737         }
2738 }
2739
2740 static void R_DrawModelsAddWaterPlanes(void)
2741 {
2742         int i;
2743         entity_render_t *ent;
2744
2745         if (!r_drawentities.integer)
2746                 return;
2747
2748         for (i = 0;i < r_refdef.scene.numentities;i++)
2749         {
2750                 if (!r_refdef.viewcache.entityvisible[i])
2751                         continue;
2752                 ent = r_refdef.scene.entities[i];
2753                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2754                         ent->model->DrawAddWaterPlanes(ent);
2755         }
2756 }
2757
2758 static void R_View_SetFrustum(void)
2759 {
2760         int i;
2761         double slopex, slopey;
2762         vec3_t forward, left, up, origin;
2763
2764         // we can't trust r_refdef.view.forward and friends in reflected scenes
2765         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
2766
2767 #if 0
2768         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2769         r_refdef.view.frustum[0].normal[1] = 0 - 0;
2770         r_refdef.view.frustum[0].normal[2] = -1 - 0;
2771         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2772         r_refdef.view.frustum[1].normal[1] = 0 + 0;
2773         r_refdef.view.frustum[1].normal[2] = -1 + 0;
2774         r_refdef.view.frustum[2].normal[0] = 0 - 0;
2775         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2776         r_refdef.view.frustum[2].normal[2] = -1 - 0;
2777         r_refdef.view.frustum[3].normal[0] = 0 + 0;
2778         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2779         r_refdef.view.frustum[3].normal[2] = -1 + 0;
2780 #endif
2781
2782 #if 0
2783         zNear = r_refdef.nearclip;
2784         nudge = 1.0 - 1.0 / (1<<23);
2785         r_refdef.view.frustum[4].normal[0] = 0 - 0;
2786         r_refdef.view.frustum[4].normal[1] = 0 - 0;
2787         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
2788         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
2789         r_refdef.view.frustum[5].normal[0] = 0 + 0;
2790         r_refdef.view.frustum[5].normal[1] = 0 + 0;
2791         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
2792         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
2793 #endif
2794
2795
2796
2797 #if 0
2798         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
2799         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
2800         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
2801         r_refdef.view.frustum[0].dist = m[15] - m[12];
2802
2803         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
2804         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
2805         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
2806         r_refdef.view.frustum[1].dist = m[15] + m[12];
2807
2808         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
2809         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
2810         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
2811         r_refdef.view.frustum[2].dist = m[15] - m[13];
2812
2813         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
2814         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
2815         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
2816         r_refdef.view.frustum[3].dist = m[15] + m[13];
2817
2818         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
2819         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
2820         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
2821         r_refdef.view.frustum[4].dist = m[15] - m[14];
2822
2823         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
2824         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
2825         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
2826         r_refdef.view.frustum[5].dist = m[15] + m[14];
2827 #endif
2828
2829         if (r_refdef.view.useperspective)
2830         {
2831                 slopex = 1.0 / r_refdef.view.frustum_x;
2832                 slopey = 1.0 / r_refdef.view.frustum_y;
2833                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
2834                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
2835                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
2836                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
2837                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2838
2839                 // Leaving those out was a mistake, those were in the old code, and they
2840                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2841                 // I couldn't reproduce it after adding those normalizations. --blub
2842                 VectorNormalize(r_refdef.view.frustum[0].normal);
2843                 VectorNormalize(r_refdef.view.frustum[1].normal);
2844                 VectorNormalize(r_refdef.view.frustum[2].normal);
2845                 VectorNormalize(r_refdef.view.frustum[3].normal);
2846
2847                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2848                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
2849                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
2850                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left,  1024 * slopey, up, r_refdef.view.frustumcorner[2]);
2851                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * slopex, left,  1024 * slopey, up, r_refdef.view.frustumcorner[3]);
2852
2853                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
2854                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
2855                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
2856                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
2857                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2858         }
2859         else
2860         {
2861                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
2862                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
2863                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
2864                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
2865                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2866                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
2867                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
2868                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
2869                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
2870                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2871         }
2872         r_refdef.view.numfrustumplanes = 5;
2873
2874         if (r_refdef.view.useclipplane)
2875         {
2876                 r_refdef.view.numfrustumplanes = 6;
2877                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
2878         }
2879
2880         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2881                 PlaneClassify(r_refdef.view.frustum + i);
2882
2883         // LordHavoc: note to all quake engine coders, Quake had a special case
2884         // for 90 degrees which assumed a square view (wrong), so I removed it,
2885         // Quake2 has it disabled as well.
2886
2887         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2888         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
2889         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
2890         //PlaneClassify(&frustum[0]);
2891
2892         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2893         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
2894         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
2895         //PlaneClassify(&frustum[1]);
2896
2897         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2898         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
2899         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
2900         //PlaneClassify(&frustum[2]);
2901
2902         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2903         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
2904         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
2905         //PlaneClassify(&frustum[3]);
2906
2907         // nearclip plane
2908         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
2909         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
2910         //PlaneClassify(&frustum[4]);
2911 }
2912
2913 void R_View_Update(void)
2914 {
2915         R_View_SetFrustum();
2916         R_View_WorldVisibility(r_refdef.view.useclipplane);
2917         R_View_UpdateEntityVisible();
2918 }
2919
2920 void R_SetupView(qboolean allowwaterclippingplane)
2921 {
2922         if (!r_refdef.view.useperspective)
2923                 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);
2924         else if (gl_stencil && r_useinfinitefarclip.integer)
2925                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
2926         else
2927                 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2928
2929         GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
2930
2931         if (r_refdef.view.useclipplane && allowwaterclippingplane)
2932         {
2933                 // LordHavoc: couldn't figure out how to make this approach the
2934                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
2935                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
2936                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
2937                         dist = r_refdef.view.clipplane.dist;
2938                 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
2939         }
2940 }
2941
2942 void R_ResetViewRendering2D(void)
2943 {
2944         DrawQ_Finish();
2945
2946         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2947         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2948         GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2949         GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2950         GL_Color(1, 1, 1, 1);
2951         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2952         GL_BlendFunc(GL_ONE, GL_ZERO);
2953         GL_AlphaTest(false);
2954         GL_ScissorTest(false);
2955         GL_DepthMask(false);
2956         GL_DepthRange(0, 1);
2957         GL_DepthTest(false);
2958         R_Mesh_Matrix(&identitymatrix);
2959         R_Mesh_ResetTextureState();
2960         GL_PolygonOffset(0, 0);
2961         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2962         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2963         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2964         qglStencilMask(~0);CHECKGLERROR
2965         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2966         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2967         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2968         R_SetupGenericShader(true);
2969 }
2970
2971 void R_ResetViewRendering3D(void)
2972 {
2973         DrawQ_Finish();
2974
2975         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2976         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2977         R_SetupView(true);
2978         GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2979         GL_Color(1, 1, 1, 1);
2980         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2981         GL_BlendFunc(GL_ONE, GL_ZERO);
2982         GL_AlphaTest(false);
2983         GL_ScissorTest(true);
2984         GL_DepthMask(true);
2985         GL_DepthRange(0, 1);
2986         GL_DepthTest(true);
2987         R_Mesh_Matrix(&identitymatrix);
2988         R_Mesh_ResetTextureState();
2989         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2990         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2991         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2992         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2993         qglStencilMask(~0);CHECKGLERROR
2994         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2995         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2996         GL_CullFace(r_refdef.view.cullface_back);
2997         R_SetupGenericShader(true);
2998 }
2999
3000 void R_RenderScene(qboolean addwaterplanes);
3001
3002 static void R_Water_StartFrame(void)
3003 {
3004         int i;
3005         int waterwidth, waterheight, texturewidth, textureheight;
3006         r_waterstate_waterplane_t *p;
3007
3008         // set waterwidth and waterheight to the water resolution that will be
3009         // used (often less than the screen resolution for faster rendering)
3010         waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3011         waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3012
3013         // calculate desired texture sizes
3014         // can't use water if the card does not support the texture size
3015         if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
3016                 texturewidth = textureheight = waterwidth = waterheight = 0;
3017         else if (gl_support_arb_texture_non_power_of_two)
3018         {
3019                 texturewidth = waterwidth;
3020                 textureheight = waterheight;
3021         }
3022         else
3023         {
3024                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
3025                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
3026         }
3027
3028         // allocate textures as needed
3029         if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3030         {
3031                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3032                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3033                 {
3034                         if (p->texture_refraction)
3035                                 R_FreeTexture(p->texture_refraction);
3036                         p->texture_refraction = NULL;
3037                         if (p->texture_reflection)
3038                                 R_FreeTexture(p->texture_reflection);
3039                         p->texture_reflection = NULL;
3040                 }
3041                 memset(&r_waterstate, 0, sizeof(r_waterstate));
3042                 r_waterstate.waterwidth = waterwidth;
3043                 r_waterstate.waterheight = waterheight;
3044                 r_waterstate.texturewidth = texturewidth;
3045                 r_waterstate.textureheight = textureheight;
3046         }
3047
3048         if (r_waterstate.waterwidth)
3049         {
3050                 r_waterstate.enabled = true;
3051
3052                 // set up variables that will be used in shader setup
3053                 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3054                 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
3055                 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3056                 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
3057         }
3058
3059         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3060         r_waterstate.numwaterplanes = 0;
3061 }
3062
3063 static void R_Water_AddWaterPlane(msurface_t *surface)
3064 {
3065         int triangleindex, planeindex;
3066         const int *e;
3067         vec3_t vert[3];
3068         vec3_t normal;
3069         vec3_t center;
3070         mplane_t plane;
3071         r_waterstate_waterplane_t *p;
3072         // just use the first triangle with a valid normal for any decisions
3073         VectorClear(normal);
3074         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3075         {
3076                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3077                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3078                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3079                 TriangleNormal(vert[0], vert[1], vert[2], normal);
3080                 if (VectorLength2(normal) >= 0.001)
3081                         break;
3082         }
3083
3084         VectorCopy(normal, plane.normal);
3085         VectorNormalize(plane.normal);
3086         plane.dist = DotProduct(vert[0], plane.normal);
3087         PlaneClassify(&plane);
3088         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3089         {
3090                 // skip backfaces (except if nocullface is set)
3091                 if (!(surface->texture->currentframe->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3092                         return;
3093                 VectorNegate(plane.normal, plane.normal);
3094                 plane.dist *= -1;
3095                 PlaneClassify(&plane);
3096         }
3097
3098
3099         // find a matching plane if there is one
3100         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3101                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3102                         break;
3103         if (planeindex >= r_waterstate.maxwaterplanes)
3104                 return; // nothing we can do, out of planes
3105
3106         // if this triangle does not fit any known plane rendered this frame, add one
3107         if (planeindex >= r_waterstate.numwaterplanes)
3108         {
3109                 // store the new plane
3110                 r_waterstate.numwaterplanes++;
3111                 p->plane = plane;
3112                 // clear materialflags and pvs
3113                 p->materialflags = 0;
3114                 p->pvsvalid = false;
3115         }
3116         // merge this surface's materialflags into the waterplane
3117         p->materialflags |= surface->texture->currentframe->currentmaterialflags;
3118         // merge this surface's PVS into the waterplane
3119         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3120         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3121          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3122         {
3123                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3124                 p->pvsvalid = true;
3125         }
3126 }
3127
3128 static void R_Water_ProcessPlanes(void)
3129 {
3130         r_refdef_view_t originalview;
3131         int planeindex;
3132         r_waterstate_waterplane_t *p;
3133
3134         originalview = r_refdef.view;
3135
3136         // make sure enough textures are allocated
3137         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3138         {
3139                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3140                 {
3141                         if (!p->texture_refraction)
3142                                 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);
3143                         if (!p->texture_refraction)
3144                                 goto error;
3145                 }
3146
3147                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3148                 {
3149                         if (!p->texture_reflection)
3150                                 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);
3151                         if (!p->texture_reflection)
3152                                 goto error;
3153                 }
3154         }
3155
3156         // render views
3157         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3158         {
3159                 r_refdef.view.showdebug = false;
3160                 r_refdef.view.width = r_waterstate.waterwidth;
3161                 r_refdef.view.height = r_waterstate.waterheight;
3162                 r_refdef.view.useclipplane = true;
3163                 r_waterstate.renderingscene = true;
3164
3165                 // render the normal view scene and copy into texture
3166                 // (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)
3167                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3168                 {
3169                         r_refdef.view.clipplane = p->plane;
3170                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3171                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3172                         PlaneClassify(&r_refdef.view.clipplane);
3173
3174                         R_RenderScene(false);
3175
3176                         // copy view into the screen texture
3177                         R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3178                         GL_ActiveTexture(0);
3179                         CHECKGLERROR
3180                         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
3181                 }
3182
3183                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3184                 {
3185                         // render reflected scene and copy into texture
3186                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3187                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3188                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3189                         r_refdef.view.clipplane = p->plane;
3190                         // reverse the cullface settings for this render
3191                         r_refdef.view.cullface_front = GL_FRONT;
3192                         r_refdef.view.cullface_back = GL_BACK;
3193                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3194                         {
3195                                 r_refdef.view.usecustompvs = true;
3196                                 if (p->pvsvalid)
3197                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3198                                 else
3199                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3200                         }
3201
3202                         R_ResetViewRendering3D();
3203                         R_ClearScreen(r_refdef.fogenabled);
3204                         if (r_timereport_active)
3205                                 R_TimeReport("viewclear");
3206
3207                         R_RenderScene(false);
3208
3209                         R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3210                         GL_ActiveTexture(0);
3211                         CHECKGLERROR
3212                         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
3213
3214                         R_ResetViewRendering3D();
3215                         R_ClearScreen(r_refdef.fogenabled);
3216                         if (r_timereport_active)
3217                                 R_TimeReport("viewclear");
3218                 }
3219
3220                 r_refdef.view = originalview;
3221                 r_refdef.view.clear = true;
3222                 r_waterstate.renderingscene = false;
3223         }
3224         return;
3225 error:
3226         r_refdef.view = originalview;
3227         r_waterstate.renderingscene = false;
3228         Cvar_SetValueQuick(&r_water, 0);
3229         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
3230         return;
3231 }
3232
3233 void R_Bloom_StartFrame(void)
3234 {
3235         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3236
3237         // set bloomwidth and bloomheight to the bloom resolution that will be
3238         // used (often less than the screen resolution for faster rendering)
3239         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3240         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3241         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3242         r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3243         r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3244
3245         // calculate desired texture sizes
3246         if (gl_support_arb_texture_non_power_of_two)
3247         {
3248                 screentexturewidth = r_refdef.view.width;
3249                 screentextureheight = r_refdef.view.height;
3250                 bloomtexturewidth = r_bloomstate.bloomwidth;
3251                 bloomtextureheight = r_bloomstate.bloomheight;
3252         }
3253         else
3254         {
3255                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
3256                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
3257                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
3258                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
3259         }
3260
3261         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))
3262         {
3263                 Cvar_SetValueQuick(&r_hdr, 0);
3264                 Cvar_SetValueQuick(&r_bloom, 0);
3265         }
3266
3267         if (!(r_glsl.integer && (r_glsl_postprocess.integer || (v_glslgamma.integer && !vid_gammatables_trivial) || r_bloom.integer || r_hdr.integer)) && !r_bloom.integer)
3268                 screentexturewidth = screentextureheight = 0;
3269         if (!r_hdr.integer && !r_bloom.integer)
3270                 bloomtexturewidth = bloomtextureheight = 0;
3271
3272         // allocate textures as needed
3273         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3274         {
3275                 if (r_bloomstate.texture_screen)
3276                         R_FreeTexture(r_bloomstate.texture_screen);
3277                 r_bloomstate.texture_screen = NULL;
3278                 r_bloomstate.screentexturewidth = screentexturewidth;
3279                 r_bloomstate.screentextureheight = screentextureheight;
3280                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3281                         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);
3282         }
3283         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3284         {
3285                 if (r_bloomstate.texture_bloom)
3286                         R_FreeTexture(r_bloomstate.texture_bloom);
3287                 r_bloomstate.texture_bloom = NULL;
3288                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3289                 r_bloomstate.bloomtextureheight = bloomtextureheight;
3290                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3291                         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);
3292         }
3293
3294         // set up a texcoord array for the full resolution screen image
3295         // (we have to keep this around to copy back during final render)
3296         r_bloomstate.screentexcoord2f[0] = 0;
3297         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
3298         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
3299         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
3300         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
3301         r_bloomstate.screentexcoord2f[5] = 0;
3302         r_bloomstate.screentexcoord2f[6] = 0;
3303         r_bloomstate.screentexcoord2f[7] = 0;
3304
3305         // set up a texcoord array for the reduced resolution bloom image
3306         // (which will be additive blended over the screen image)
3307         r_bloomstate.bloomtexcoord2f[0] = 0;
3308         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3309         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
3310         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3311         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
3312         r_bloomstate.bloomtexcoord2f[5] = 0;
3313         r_bloomstate.bloomtexcoord2f[6] = 0;
3314         r_bloomstate.bloomtexcoord2f[7] = 0;
3315
3316         if (r_hdr.integer || r_bloom.integer)
3317         {
3318                 r_bloomstate.enabled = true;
3319                 r_bloomstate.hdr = r_hdr.integer != 0;
3320         }
3321 }
3322
3323 void R_Bloom_CopyBloomTexture(float colorscale)
3324 {
3325         r_refdef.stats.bloom++;
3326
3327         // scale down screen texture to the bloom texture size
3328         CHECKGLERROR
3329         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3330         GL_BlendFunc(GL_ONE, GL_ZERO);
3331         GL_Color(colorscale, colorscale, colorscale, 1);
3332         // TODO: optimize with multitexture or GLSL
3333         R_SetupGenericShader(true);
3334         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3335         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3336         R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3337         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3338
3339         // we now have a bloom image in the framebuffer
3340         // copy it into the bloom image texture for later processing
3341         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3342         GL_ActiveTexture(0);
3343         CHECKGLERROR
3344         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
3345         r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3346 }
3347
3348 void R_Bloom_CopyHDRTexture(void)
3349 {
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_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3354         r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3355 }
3356
3357 void R_Bloom_MakeTexture(void)
3358 {
3359         int x, range, dir;
3360         float xoffset, yoffset, r, brighten;
3361
3362         r_refdef.stats.bloom++;
3363
3364         R_ResetViewRendering2D();
3365         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3366         R_Mesh_ColorPointer(NULL, 0, 0);
3367         R_SetupGenericShader(true);
3368
3369         // we have a bloom image in the framebuffer
3370         CHECKGLERROR
3371         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3372
3373         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3374         {
3375                 x *= 2;
3376                 r = bound(0, r_bloom_colorexponent.value / x, 1);
3377                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3378                 GL_Color(r, r, r, 1);
3379                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3380                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3381                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3382                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3383
3384                 // copy the vertically blurred bloom view to a texture
3385                 GL_ActiveTexture(0);
3386                 CHECKGLERROR
3387                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3388                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3389         }
3390
3391         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3392         brighten = r_bloom_brighten.value;
3393         if (r_hdr.integer)
3394                 brighten *= r_hdr_range.value;
3395         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3396         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3397
3398         for (dir = 0;dir < 2;dir++)
3399         {
3400                 // blend on at multiple vertical offsets to achieve a vertical blur
3401                 // TODO: do offset blends using GLSL
3402                 GL_BlendFunc(GL_ONE, GL_ZERO);
3403                 for (x = -range;x <= range;x++)
3404                 {
3405                         if (!dir){xoffset = 0;yoffset = x;}
3406                         else {xoffset = x;yoffset = 0;}
3407                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
3408                         yoffset /= (float)r_bloomstate.bloomtextureheight;
3409                         // compute a texcoord array with the specified x and y offset
3410                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3411                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3412                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3413                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3414                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3415                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3416                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3417                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3418                         // this r value looks like a 'dot' particle, fading sharply to
3419                         // black at the edges
3420                         // (probably not realistic but looks good enough)
3421                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3422                         //r = (dir ? 1.0f : brighten)/(range*2+1);
3423                         r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3424                         GL_Color(r, r, r, 1);
3425                         R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3426                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3427                         GL_BlendFunc(GL_ONE, GL_ONE);
3428                 }
3429
3430                 // copy the vertically blurred bloom view to a texture
3431                 GL_ActiveTexture(0);
3432                 CHECKGLERROR
3433                 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
3434                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3435         }
3436
3437         // apply subtract last
3438         // (just like it would be in a GLSL shader)
3439         if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3440         {
3441                 GL_BlendFunc(GL_ONE, GL_ZERO);
3442                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3443                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3444                 GL_Color(1, 1, 1, 1);
3445                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3446                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3447
3448                 GL_BlendFunc(GL_ONE, GL_ONE);
3449                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3450                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3451                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3452                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3453                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3454                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3455                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3456
3457                 // copy the darkened bloom view to a texture
3458                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3459                 GL_ActiveTexture(0);
3460                 CHECKGLERROR
3461                 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
3462                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3463         }
3464 }
3465
3466 void R_HDR_RenderBloomTexture(void)
3467 {
3468         int oldwidth, oldheight;
3469         float oldcolorscale;
3470
3471         oldcolorscale = r_refdef.view.colorscale;
3472         oldwidth = r_refdef.view.width;
3473         oldheight = r_refdef.view.height;
3474         r_refdef.view.width = r_bloomstate.bloomwidth;
3475         r_refdef.view.height = r_bloomstate.bloomheight;
3476
3477         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
3478         // TODO: add exposure compensation features
3479         // TODO: add fp16 framebuffer support
3480
3481         r_refdef.view.showdebug = false;
3482         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3483
3484         R_ClearScreen(r_refdef.fogenabled);
3485         if (r_timereport_active)
3486                 R_TimeReport("HDRclear");
3487
3488         r_waterstate.numwaterplanes = 0;
3489         R_RenderScene(r_waterstate.enabled);
3490         r_refdef.view.showdebug = true;
3491
3492         R_ResetViewRendering2D();
3493
3494         R_Bloom_CopyHDRTexture();
3495         R_Bloom_MakeTexture();
3496
3497         // restore the view settings
3498         r_refdef.view.width = oldwidth;
3499         r_refdef.view.height = oldheight;
3500         r_refdef.view.colorscale = oldcolorscale;
3501
3502         R_ResetViewRendering3D();
3503
3504         R_ClearScreen(r_refdef.fogenabled);
3505         if (r_timereport_active)
3506                 R_TimeReport("viewclear");
3507 }
3508
3509 static void R_BlendView(void)
3510 {
3511         if (r_bloomstate.texture_screen)
3512         {
3513                 // copy view into the screen texture
3514                 R_ResetViewRendering2D();
3515                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3516                 R_Mesh_ColorPointer(NULL, 0, 0);
3517                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3518                 GL_ActiveTexture(0);CHECKGLERROR
3519                 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
3520                 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3521         }
3522
3523         if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
3524         {
3525                 unsigned int permutation =
3526                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
3527                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)
3528                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
3529                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0);
3530
3531                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
3532                 {
3533                         // render simple bloom effect
3534                         // copy the screen and shrink it and darken it for the bloom process
3535                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3536                         // make the bloom texture
3537                         R_Bloom_MakeTexture();
3538                 }
3539
3540                 R_ResetViewRendering2D();
3541                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3542                 R_Mesh_ColorPointer(NULL, 0, 0);
3543                 GL_Color(1, 1, 1, 1);
3544                 GL_BlendFunc(GL_ONE, GL_ZERO);
3545                 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
3546                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3547                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3548                 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
3549                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3550                 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
3551                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
3552                 if (r_glsl_permutation->loc_TintColor >= 0)
3553                         qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3554                 if (r_glsl_permutation->loc_ClientTime >= 0)
3555                         qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3556                 if (r_glsl_permutation->loc_PixelSize >= 0)
3557                         qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
3558                 if (r_glsl_permutation->loc_UserVec1 >= 0)
3559                 {
3560                         float a=0, b=0, c=0, d=0;
3561 #if _MSC_VER >= 1400
3562 #define sscanf sscanf_s
3563 #endif
3564                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
3565                         qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
3566                 }
3567                 if (r_glsl_permutation->loc_UserVec2 >= 0)
3568                 {
3569                         float a=0, b=0, c=0, d=0;
3570                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
3571                         qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
3572                 }
3573                 if (r_glsl_permutation->loc_UserVec3 >= 0)
3574                 {
3575                         float a=0, b=0, c=0, d=0;
3576                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
3577                         qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
3578                 }
3579                 if (r_glsl_permutation->loc_UserVec4 >= 0)
3580                 {
3581                         float a=0, b=0, c=0, d=0;
3582                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
3583                         qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
3584                 }
3585                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3586                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3587                 return;
3588         }
3589
3590
3591
3592         if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
3593         {
3594                 // render high dynamic range bloom effect
3595                 // the bloom texture was made earlier this render, so we just need to
3596                 // blend it onto the screen...
3597                 R_ResetViewRendering2D();
3598                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3599                 R_Mesh_ColorPointer(NULL, 0, 0);
3600                 R_SetupGenericShader(true);
3601                 GL_Color(1, 1, 1, 1);
3602                 GL_BlendFunc(GL_ONE, GL_ONE);
3603                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3604                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3605                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3606                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3607         }
3608         else if (r_bloomstate.texture_bloom)
3609         {
3610                 // render simple bloom effect
3611                 // copy the screen and shrink it and darken it for the bloom process
3612                 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3613                 // make the bloom texture
3614                 R_Bloom_MakeTexture();
3615                 // put the original screen image back in place and blend the bloom
3616                 // texture on it
3617                 R_ResetViewRendering2D();
3618                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3619                 R_Mesh_ColorPointer(NULL, 0, 0);
3620                 GL_Color(1, 1, 1, 1);
3621                 GL_BlendFunc(GL_ONE, GL_ZERO);
3622                 // do both in one pass if possible
3623                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3624                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3625                 if (r_textureunits.integer >= 2 && gl_combine.integer)
3626                 {
3627                         R_SetupGenericTwoTextureShader(GL_ADD);
3628                         R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3629                         R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3630                 }
3631                 else
3632                 {
3633                         R_SetupGenericShader(true);
3634                         R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3635                         r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3636                         // now blend on the bloom texture
3637                         GL_BlendFunc(GL_ONE, GL_ONE);
3638                         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3639                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3640                 }
3641                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3642                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3643         }
3644         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3645         {
3646                 // apply a color tint to the whole view
3647                 R_ResetViewRendering2D();
3648                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3649                 R_Mesh_ColorPointer(NULL, 0, 0);
3650                 R_SetupGenericShader(false);
3651                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3652                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3653                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3654         }
3655 }
3656
3657 void R_RenderScene(qboolean addwaterplanes);
3658
3659 matrix4x4_t r_waterscrollmatrix;
3660
3661 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3662 {
3663         if (r_refdef.fog_density)
3664         {
3665                 r_refdef.fogcolor[0] = r_refdef.fog_red;
3666                 r_refdef.fogcolor[1] = r_refdef.fog_green;
3667                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3668
3669                 {
3670                         vec3_t fogvec;
3671                         VectorCopy(r_refdef.fogcolor, fogvec);
3672                         if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3673                         {
3674                                 //   color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3675                                 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3676                                 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3677                                 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3678                         }
3679                         //   color.rgb *= ContrastBoost * SceneBrightness;
3680                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3681                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3682                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3683                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3684                 }
3685         }
3686 }
3687
3688 void R_UpdateVariables(void)
3689 {
3690         R_Textures_Frame();
3691
3692         r_refdef.scene.ambient = r_ambient.value;
3693
3694         r_refdef.farclip = 4096;
3695         if (r_refdef.scene.worldmodel)
3696                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
3697         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3698
3699         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3700                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3701         r_refdef.polygonfactor = 0;
3702         r_refdef.polygonoffset = 0;
3703         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3704         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3705
3706         r_refdef.scene.rtworld = r_shadow_realtime_world.integer;
3707         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3708         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3709         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3710         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3711         if (r_showsurfaces.integer)
3712         {
3713                 r_refdef.scene.rtworld = false;
3714                 r_refdef.scene.rtworldshadows = false;
3715                 r_refdef.scene.rtdlight = false;
3716                 r_refdef.scene.rtdlightshadows = false;
3717                 r_refdef.lightmapintensity = 0;
3718         }
3719
3720         if (gamemode == GAME_NEHAHRA)
3721         {
3722                 if (gl_fogenable.integer)
3723                 {
3724                         r_refdef.oldgl_fogenable = true;
3725                         r_refdef.fog_density = gl_fogdensity.value;
3726                         r_refdef.fog_red = gl_fogred.value;
3727                         r_refdef.fog_green = gl_foggreen.value;
3728                         r_refdef.fog_blue = gl_fogblue.value;
3729                         r_refdef.fog_alpha = 1;
3730                         r_refdef.fog_start = 0;
3731                         r_refdef.fog_end = gl_skyclip.value;
3732                 }
3733                 else if (r_refdef.oldgl_fogenable)
3734                 {
3735                         r_refdef.oldgl_fogenable = false;
3736                         r_refdef.fog_density = 0;
3737                         r_refdef.fog_red = 0;
3738                         r_refdef.fog_green = 0;
3739                         r_refdef.fog_blue = 0;
3740                         r_refdef.fog_alpha = 0;
3741                         r_refdef.fog_start = 0;
3742                         r_refdef.fog_end = 0;
3743                 }
3744         }
3745
3746         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
3747         r_refdef.fog_start = max(0, r_refdef.fog_start);
3748         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
3749
3750         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
3751
3752         if (r_refdef.fog_density && r_drawfog.integer)
3753         {
3754                 r_refdef.fogenabled = true;
3755                 // this is the point where the fog reaches 0.9986 alpha, which we
3756                 // consider a good enough cutoff point for the texture
3757                 // (0.9986 * 256 == 255.6)
3758                 if (r_fog_exp2.integer)
3759                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
3760                 else
3761                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
3762                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
3763                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3764                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3765                 // fog color was already set
3766                 // update the fog texture
3767                 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)
3768                         R_BuildFogTexture();
3769         }
3770         else
3771                 r_refdef.fogenabled = false;
3772
3773         if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
3774         {
3775                 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
3776                 {
3777                         // build GLSL gamma texture
3778 #define RAMPWIDTH 256
3779                         unsigned short ramp[RAMPWIDTH * 3];
3780                         unsigned char ramprgb[RAMPWIDTH][4];
3781                         int i;
3782
3783                         r_texture_gammaramps_serial = vid_gammatables_serial;
3784
3785                         VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
3786                         for(i = 0; i < RAMPWIDTH; ++i)
3787                         {
3788                                 ramprgb[i][0] = ramp[i] >> 8;
3789                                 ramprgb[i][1] = ramp[i + RAMPWIDTH] >> 8;
3790                                 ramprgb[i][2] = ramp[i + 2 * RAMPWIDTH] >> 8;
3791                                 ramprgb[i][3] = 0;
3792                         }
3793                         if (r_texture_gammaramps)
3794                         {
3795                                 R_UpdateTexture(r_texture_gammaramps, &ramprgb[0][0], 0, 0, RAMPWIDTH, 1);
3796                         }
3797                         else
3798                         {
3799                                 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);
3800                         }
3801                 }
3802         }
3803         else
3804         {
3805                 // remove GLSL gamma texture
3806         }
3807 }
3808
3809 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
3810 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
3811 /*
3812 ================
3813 R_SelectScene
3814 ================
3815 */
3816 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
3817         if( scenetype != r_currentscenetype ) {
3818                 // store the old scenetype
3819                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
3820                 r_currentscenetype = scenetype;
3821                 // move in the new scene
3822                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
3823         }
3824 }
3825
3826 /*
3827 ================
3828 R_GetScenePointer
3829 ================
3830 */
3831 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
3832 {
3833         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
3834         if( scenetype == r_currentscenetype ) {
3835                 return &r_refdef.scene;
3836         } else {
3837                 return &r_scenes_store[ scenetype ];
3838         }
3839 }
3840
3841 /*
3842 ================
3843 R_RenderView
3844 ================
3845 */
3846 void R_RenderView(void)
3847 {
3848         if (r_refdef.view.isoverlay)
3849         {
3850                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
3851                 GL_Clear( GL_DEPTH_BUFFER_BIT );
3852                 R_TimeReport("depthclear");
3853
3854                 r_refdef.view.showdebug = false;
3855
3856                 r_waterstate.enabled = false;
3857                 r_waterstate.numwaterplanes = 0;
3858
3859                 R_RenderScene(false);
3860
3861                 CHECKGLERROR
3862                 return;
3863         }
3864
3865         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
3866                 return; //Host_Error ("R_RenderView: NULL worldmodel");
3867
3868         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
3869
3870         // break apart the view matrix into vectors for various purposes
3871         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
3872         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
3873         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
3874         VectorNegate(r_refdef.view.left, r_refdef.view.right);
3875         // make an inverted copy of the view matrix for tracking sprites
3876         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
3877
3878         R_Shadow_UpdateWorldLightSelection();
3879
3880         R_Bloom_StartFrame();
3881         R_Water_StartFrame();
3882
3883         CHECKGLERROR
3884         if (r_timereport_active)
3885                 R_TimeReport("viewsetup");
3886
3887         R_ResetViewRendering3D();
3888
3889         if (r_refdef.view.clear || r_refdef.fogenabled)
3890         {
3891                 R_ClearScreen(r_refdef.fogenabled);
3892                 if (r_timereport_active)
3893                         R_TimeReport("viewclear");
3894         }
3895         r_refdef.view.clear = true;
3896
3897         r_refdef.view.showdebug = true;
3898
3899         // this produces a bloom texture to be used in R_BlendView() later
3900         if (r_hdr.integer)
3901                 R_HDR_RenderBloomTexture();
3902
3903         r_waterstate.numwaterplanes = 0;
3904         R_RenderScene(r_waterstate.enabled);
3905
3906         R_BlendView();
3907         if (r_timereport_active)
3908                 R_TimeReport("blendview");
3909
3910         GL_Scissor(0, 0, vid.width, vid.height);
3911         GL_ScissorTest(false);
3912         CHECKGLERROR
3913 }
3914
3915 extern void R_DrawLightningBeams (void);
3916 extern void VM_CL_AddPolygonsToMeshQueue (void);
3917 extern void R_DrawPortals (void);
3918 extern cvar_t cl_locs_show;
3919 static void R_DrawLocs(void);
3920 static void R_DrawEntityBBoxes(void);
3921 void R_RenderScene(qboolean addwaterplanes)
3922 {
3923         r_refdef.stats.renders++;
3924
3925         R_UpdateFogColor();
3926
3927         if (addwaterplanes)
3928         {
3929                 R_ResetViewRendering3D();
3930
3931                 R_View_Update();
3932                 if (r_timereport_active)
3933                         R_TimeReport("watervis");
3934
3935                 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
3936                 {
3937                         r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
3938                         if (r_timereport_active)
3939                                 R_TimeReport("waterworld");
3940                 }
3941
3942                 // don't let sound skip if going slow
3943                 if (r_refdef.scene.extraupdate)
3944                         S_ExtraUpdate ();
3945
3946                 R_DrawModelsAddWaterPlanes();
3947                 if (r_timereport_active)
3948                         R_TimeReport("watermodels");
3949
3950                 R_Water_ProcessPlanes();
3951                 if (r_timereport_active)
3952                         R_TimeReport("waterscenes");
3953         }
3954
3955         R_ResetViewRendering3D();
3956
3957         // don't let sound skip if going slow
3958         if (r_refdef.scene.extraupdate)
3959                 S_ExtraUpdate ();
3960
3961         R_MeshQueue_BeginScene();
3962
3963         R_SkyStartFrame();
3964
3965         R_View_Update();
3966         if (r_timereport_active)
3967                 R_TimeReport("visibility");
3968
3969         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);
3970
3971         if (cl.csqc_vidvars.drawworld)
3972         {
3973                 // don't let sound skip if going slow
3974                 if (r_refdef.scene.extraupdate)
3975                         S_ExtraUpdate ();
3976
3977                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
3978                 {
3979                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
3980                         if (r_timereport_active)
3981                                 R_TimeReport("worldsky");
3982                 }
3983
3984                 if (R_DrawBrushModelsSky() && r_timereport_active)
3985                         R_TimeReport("bmodelsky");
3986         }
3987
3988         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
3989         {
3990                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
3991                 if (r_timereport_active)
3992                         R_TimeReport("worlddepth");
3993         }
3994         if (r_depthfirst.integer >= 2)
3995         {
3996                 R_DrawModelsDepth();
3997                 if (r_timereport_active)
3998                         R_TimeReport("modeldepth");
3999         }
4000
4001         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4002         {
4003                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4004                 if (r_timereport_active)
4005                         R_TimeReport("world");
4006         }
4007
4008         // don't let sound skip if going slow
4009         if (r_refdef.scene.extraupdate)
4010                 S_ExtraUpdate ();
4011
4012         R_DrawModels();
4013         if (r_timereport_active)
4014                 R_TimeReport("models");
4015
4016         // don't let sound skip if going slow
4017         if (r_refdef.scene.extraupdate)
4018                 S_ExtraUpdate ();
4019
4020         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
4021         {
4022                 R_DrawModelShadows();
4023
4024                 R_ResetViewRendering3D();
4025
4026                 // don't let sound skip if going slow
4027                 if (r_refdef.scene.extraupdate)
4028                         S_ExtraUpdate ();
4029         }
4030
4031         R_ShadowVolumeLighting(false);
4032         if (r_timereport_active)
4033                 R_TimeReport("rtlights");
4034
4035         // don't let sound skip if going slow
4036         if (r_refdef.scene.extraupdate)
4037                 S_ExtraUpdate ();
4038
4039         if (cl.csqc_vidvars.drawworld)
4040         {
4041                 R_DrawLightningBeams();
4042                 if (r_timereport_active)
4043                         R_TimeReport("lightning");
4044
4045                 R_DrawDecals();
4046                 if (r_timereport_active)
4047                         R_TimeReport("decals");
4048
4049                 R_DrawParticles();
4050                 if (r_timereport_active)
4051                         R_TimeReport("particles");
4052
4053                 R_DrawExplosions();
4054                 if (r_timereport_active)
4055                         R_TimeReport("explosions");
4056         }
4057
4058         R_SetupGenericShader(true);
4059         VM_CL_AddPolygonsToMeshQueue();
4060
4061         if (r_refdef.view.showdebug)
4062         {
4063                 if (cl_locs_show.integer)
4064                 {
4065                         R_DrawLocs();
4066                         if (r_timereport_active)
4067                                 R_TimeReport("showlocs");
4068                 }
4069
4070                 if (r_drawportals.integer)
4071                 {
4072                         R_DrawPortals();
4073                         if (r_timereport_active)
4074                                 R_TimeReport("portals");
4075                 }
4076
4077                 if (r_showbboxes.value > 0)
4078                 {
4079                         R_DrawEntityBBoxes();
4080                         if (r_timereport_active)
4081                                 R_TimeReport("bboxes");
4082                 }
4083         }
4084
4085         R_SetupGenericShader(true);
4086         R_MeshQueue_RenderTransparent();
4087         if (r_timereport_active)
4088                 R_TimeReport("drawtrans");
4089
4090         R_SetupGenericShader(true);
4091
4092         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))
4093         {
4094                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4095                 if (r_timereport_active)
4096                         R_TimeReport("worlddebug");
4097                 R_DrawModelsDebug();
4098                 if (r_timereport_active)
4099                         R_TimeReport("modeldebug");
4100         }
4101
4102         R_SetupGenericShader(true);
4103
4104         if (cl.csqc_vidvars.drawworld)
4105         {
4106                 R_DrawCoronas();
4107                 if (r_timereport_active)
4108                         R_TimeReport("coronas");
4109         }
4110
4111         // don't let sound skip if going slow
4112         if (r_refdef.scene.extraupdate)
4113                 S_ExtraUpdate ();
4114
4115         R_ResetViewRendering2D();
4116 }
4117
4118 static const unsigned short bboxelements[36] =
4119 {
4120         5, 1, 3, 5, 3, 7,
4121         6, 2, 0, 6, 0, 4,
4122         7, 3, 2, 7, 2, 6,
4123         4, 0, 1, 4, 1, 5,
4124         4, 5, 7, 4, 7, 6,
4125         1, 0, 2, 1, 2, 3,
4126 };
4127
4128 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4129 {
4130         int i;
4131         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4132         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4133         GL_DepthMask(false);
4134         GL_DepthRange(0, 1);
4135         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4136         R_Mesh_Matrix(&identitymatrix);
4137         R_Mesh_ResetTextureState();
4138
4139         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4140         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4141         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4142         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4143         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4144         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4145         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4146         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4147         R_FillColors(color4f, 8, cr, cg, cb, ca);
4148         if (r_refdef.fogenabled)
4149         {
4150                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4151                 {
4152                         f1 = FogPoint_World(v);
4153                         f2 = 1 - f1;
4154                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4155                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4156                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4157                 }
4158         }
4159         R_Mesh_VertexPointer(vertex3f, 0, 0);
4160         R_Mesh_ColorPointer(color4f, 0, 0);
4161         R_Mesh_ResetTextureState();
4162         R_SetupGenericShader(false);
4163         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4164 }
4165
4166 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4167 {
4168         int i;
4169         float color[4];
4170         prvm_edict_t *edict;
4171         prvm_prog_t *prog_save = prog;
4172
4173         // this function draws bounding boxes of server entities
4174         if (!sv.active)
4175                 return;
4176
4177         GL_CullFace(GL_NONE);
4178         R_SetupGenericShader(false);
4179
4180         prog = 0;
4181         SV_VM_Begin();
4182         for (i = 0;i < numsurfaces;i++)
4183         {
4184                 edict = PRVM_EDICT_NUM(surfacelist[i]);
4185                 switch ((int)edict->fields.server->solid)
4186                 {
4187                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
4188                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
4189                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
4190                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4191                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
4192                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
4193                 }
4194                 color[3] *= r_showbboxes.value;
4195                 color[3] = bound(0, color[3], 1);
4196                 GL_DepthTest(!r_showdisabledepthtest.integer);
4197                 GL_CullFace(r_refdef.view.cullface_front);
4198                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4199         }
4200         SV_VM_End();
4201         prog = prog_save;
4202 }
4203
4204 static void R_DrawEntityBBoxes(void)
4205 {
4206         int i;
4207         prvm_edict_t *edict;
4208         vec3_t center;
4209         prvm_prog_t *prog_save = prog;
4210
4211         // this function draws bounding boxes of server entities
4212         if (!sv.active)
4213                 return;
4214
4215         prog = 0;
4216         SV_VM_Begin();
4217         for (i = 0;i < prog->num_edicts;i++)
4218         {
4219                 edict = PRVM_EDICT_NUM(i);
4220                 if (edict->priv.server->free)
4221                         continue;
4222                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
4223                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
4224                         continue;
4225                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
4226                         continue;
4227                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4228                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4229         }
4230         SV_VM_End();
4231         prog = prog_save;
4232 }
4233
4234 unsigned short nomodelelements[24] =
4235 {
4236         5, 2, 0,
4237         5, 1, 2,
4238         5, 0, 3,
4239         5, 3, 1,
4240         0, 2, 4,
4241         2, 1, 4,
4242         3, 0, 4,
4243         1, 3, 4
4244 };
4245
4246 float nomodelvertex3f[6*3] =
4247 {
4248         -16,   0,   0,
4249          16,   0,   0,
4250           0, -16,   0,
4251           0,  16,   0,
4252           0,   0, -16,
4253           0,   0,  16
4254 };
4255
4256 float nomodelcolor4f[6*4] =
4257 {
4258         0.0f, 0.0f, 0.5f, 1.0f,
4259         0.0f, 0.0f, 0.5f, 1.0f,
4260         0.0f, 0.5f, 0.0f, 1.0f,
4261         0.0f, 0.5f, 0.0f, 1.0f,
4262         0.5f, 0.0f, 0.0f, 1.0f,
4263         0.5f, 0.0f, 0.0f, 1.0f
4264 };
4265
4266 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4267 {
4268         int i;
4269         float f1, f2, *c;
4270         float color4f[6*4];
4271         // this is only called once per entity so numsurfaces is always 1, and
4272         // surfacelist is always {0}, so this code does not handle batches
4273         R_Mesh_Matrix(&ent->matrix);
4274
4275         if (ent->flags & EF_ADDITIVE)
4276         {
4277                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4278                 GL_DepthMask(false);
4279         }
4280         else if (ent->alpha < 1)
4281         {
4282                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4283                 GL_DepthMask(false);
4284         }
4285         else
4286         {
4287                 GL_BlendFunc(GL_ONE, GL_ZERO);
4288                 GL_DepthMask(true);
4289         }
4290         GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4291         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4292         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4293         GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4294         R_SetupGenericShader(false);
4295         R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4296         if (r_refdef.fogenabled)
4297         {
4298                 vec3_t org;
4299                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4300                 R_Mesh_ColorPointer(color4f, 0, 0);
4301                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4302                 f1 = FogPoint_World(org);
4303                 f2 = 1 - f1;
4304                 for (i = 0, c = color4f;i < 6;i++, c += 4)
4305                 {
4306                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4307                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4308                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4309                         c[3] *= ent->alpha;
4310                 }
4311         }
4312         else if (ent->alpha != 1)
4313         {
4314                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4315                 R_Mesh_ColorPointer(color4f, 0, 0);
4316                 for (i = 0, c = color4f;i < 6;i++, c += 4)
4317                         c[3] *= ent->alpha;
4318         }
4319         else
4320                 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4321         R_Mesh_ResetTextureState();
4322         R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
4323 }
4324
4325 void R_DrawNoModel(entity_render_t *ent)
4326 {
4327         vec3_t org;
4328         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4329         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4330                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4331         //else
4332         //      R_DrawNoModelCallback(ent, 0);
4333 }
4334
4335 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4336 {
4337         vec3_t right1, right2, diff, normal;
4338
4339         VectorSubtract (org2, org1, normal);
4340
4341         // calculate 'right' vector for start
4342         VectorSubtract (r_refdef.view.origin, org1, diff);
4343         CrossProduct (normal, diff, right1);
4344         VectorNormalize (right1);
4345
4346         // calculate 'right' vector for end
4347         VectorSubtract (r_refdef.view.origin, org2, diff);
4348         CrossProduct (normal, diff, right2);
4349         VectorNormalize (right2);
4350
4351         vert[ 0] = org1[0] + width * right1[0];
4352         vert[ 1] = org1[1] + width * right1[1];
4353         vert[ 2] = org1[2] + width * right1[2];
4354         vert[ 3] = org1[0] - width * right1[0];
4355         vert[ 4] = org1[1] - width * right1[1];
4356         vert[ 5] = org1[2] - width * right1[2];
4357         vert[ 6] = org2[0] - width * right2[0];
4358         vert[ 7] = org2[1] - width * right2[1];
4359         vert[ 8] = org2[2] - width * right2[2];
4360         vert[ 9] = org2[0] + width * right2[0];
4361         vert[10] = org2[1] + width * right2[1];
4362         vert[11] = org2[2] + width * right2[2];
4363 }
4364
4365 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4366
4367 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)
4368 {
4369         float fog = 1.0f;
4370         float vertex3f[12];
4371
4372         if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4373                 fog = FogPoint_World(origin);
4374
4375         R_Mesh_Matrix(&identitymatrix);
4376         GL_BlendFunc(blendfunc1, blendfunc2);
4377
4378         if(v_flipped_state)
4379         {
4380                 scalex1 = -scalex1;
4381                 scalex2 = -scalex2;
4382                 GL_CullFace(r_refdef.view.cullface_front);
4383         }
4384         else
4385                 GL_CullFace(r_refdef.view.cullface_back);
4386         GL_CullFace(GL_NONE);
4387
4388         GL_DepthMask(false);
4389         GL_DepthRange(0, depthshort ? 0.0625 : 1);
4390         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4391         GL_DepthTest(!depthdisable);
4392
4393         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4394         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4395         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4396         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
4397         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
4398         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
4399         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
4400         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
4401         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
4402         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
4403         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
4404         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
4405
4406         R_Mesh_VertexPointer(vertex3f, 0, 0);
4407         R_Mesh_ColorPointer(NULL, 0, 0);
4408         R_Mesh_ResetTextureState();
4409         R_SetupGenericShader(true);
4410         R_Mesh_TexBind(0, R_GetTexture(texture));
4411         R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
4412         // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
4413         GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
4414         R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4415
4416         if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
4417         {
4418                 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
4419                 GL_BlendFunc(blendfunc1, GL_ONE);
4420                 fog = 1 - fog;
4421                 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
4422                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4423         }
4424 }
4425
4426 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
4427 {
4428         int i;
4429         float *vertex3f;
4430         float v[3];
4431         VectorSet(v, x, y, z);
4432         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
4433                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
4434                         break;
4435         if (i == mesh->numvertices)
4436         {
4437                 if (mesh->numvertices < mesh->maxvertices)
4438                 {
4439                         VectorCopy(v, vertex3f);
4440                         mesh->numvertices++;
4441                 }
4442                 return mesh->numvertices;
4443         }
4444         else
4445                 return i;
4446 }
4447
4448 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
4449 {
4450         int i;
4451         int *e, element[3];
4452         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4453         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4454         e = mesh->element3i + mesh->numtriangles * 3;
4455         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
4456         {
4457                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
4458                 if (mesh->numtriangles < mesh->maxtriangles)
4459                 {
4460                         *e++ = element[0];
4461                         *e++ = element[1];
4462                         *e++ = element[2];
4463                         mesh->numtriangles++;
4464                 }
4465                 element[1] = element[2];
4466         }
4467 }
4468
4469 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
4470 {
4471         int i;
4472         int *e, element[3];
4473         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4474         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4475         e = mesh->element3i + mesh->numtriangles * 3;
4476         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
4477         {
4478                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
4479                 if (mesh->numtriangles < mesh->maxtriangles)
4480                 {
4481                         *e++ = element[0];
4482                         *e++ = element[1];
4483                         *e++ = element[2];
4484                         mesh->numtriangles++;
4485                 }
4486                 element[1] = element[2];
4487         }
4488 }
4489
4490 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
4491 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
4492 {
4493         int planenum, planenum2;
4494         int w;
4495         int tempnumpoints;
4496         mplane_t *plane, *plane2;
4497         double maxdist;
4498         double temppoints[2][256*3];
4499         // figure out how large a bounding box we need to properly compute this brush
4500         maxdist = 0;
4501         for (w = 0;w < numplanes;w++)
4502                 maxdist = max(maxdist, planes[w].dist);
4503         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4504         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4505         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4506         {
4507                 w = 0;
4508                 tempnumpoints = 4;
4509                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4510                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4511                 {
4512                         if (planenum2 == planenum)
4513                                 continue;
4514                         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);
4515                         w = !w;
4516                 }
4517                 if (tempnumpoints < 3)
4518                         continue;
4519                 // generate elements forming a triangle fan for this polygon
4520                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4521         }
4522 }
4523
4524 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)
4525 {
4526         texturelayer_t *layer;
4527         layer = t->currentlayers + t->currentnumlayers++;
4528         layer->type = type;
4529         layer->depthmask = depthmask;
4530         layer->blendfunc1 = blendfunc1;
4531         layer->blendfunc2 = blendfunc2;
4532         layer->texture = texture;
4533         layer->texmatrix = *matrix;
4534         layer->color[0] = r * r_refdef.view.colorscale;
4535         layer->color[1] = g * r_refdef.view.colorscale;
4536         layer->color[2] = b * r_refdef.view.colorscale;
4537         layer->color[3] = a;
4538 }
4539
4540 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4541 {
4542         double index, f;
4543         index = parms[2] + r_refdef.scene.time * parms[3];
4544         index -= floor(index);
4545         switch (func)
4546         {
4547         default:
4548         case Q3WAVEFUNC_NONE:
4549         case Q3WAVEFUNC_NOISE:
4550         case Q3WAVEFUNC_COUNT:
4551                 f = 0;
4552                 break;
4553         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4554         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4555         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4556         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4557         case Q3WAVEFUNC_TRIANGLE:
4558                 index *= 4;
4559                 f = index - floor(index);
4560                 if (index < 1)
4561                         f = f;
4562                 else if (index < 2)
4563                         f = 1 - f;
4564                 else if (index < 3)
4565                         f = -f;
4566                 else
4567                         f = -(1 - f);
4568                 break;
4569         }
4570         return (float)(parms[0] + parms[1] * f);
4571 }
4572
4573 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
4574 {
4575         int w, h, idx;
4576         int i;
4577         dp_model_t *model = ent->model;
4578         float f;
4579         float tcmat[12];
4580         q3shaderinfo_layer_tcmod_t *tcmod;
4581
4582         if (t->basematerialflags & MATERIALFLAG_NODRAW)
4583         {
4584                 t->currentmaterialflags = MATERIALFLAG_NODRAW;
4585                 return;
4586         }
4587
4588         // switch to an alternate material if this is a q1bsp animated material
4589         {
4590                 texture_t *texture = t;
4591                 int s = ent->skinnum;
4592                 if ((unsigned int)s >= (unsigned int)model->numskins)
4593                         s = 0;
4594                 if (model->skinscenes)
4595                 {
4596                         if (model->skinscenes[s].framecount > 1)
4597                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4598                         else
4599                                 s = model->skinscenes[s].firstframe;
4600                 }
4601                 if (s > 0)
4602                         t = t + s * model->num_surfaces;
4603                 if (t->animated)
4604                 {
4605                         // use an alternate animation if the entity's frame is not 0,
4606                         // and only if the texture has an alternate animation
4607                         if (ent->frame2 != 0 && t->anim_total[1])
4608                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4609                         else
4610                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4611                 }
4612                 texture->currentframe = t;
4613         }
4614
4615         // update currentskinframe to be a qw skin or animation frame
4616         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"))
4617         {
4618                 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4619                 {
4620                         strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4621                         if (developer_loading.integer)
4622                                 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
4623                         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);
4624                 }
4625                 t->currentskinframe = r_qwskincache_skinframe[i];
4626                 if (t->currentskinframe == NULL)
4627                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4628         }
4629         else if (t->numskinframes >= 2)
4630                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4631         if (t->backgroundnumskinframes >= 2)
4632                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
4633
4634         t->currentmaterialflags = t->basematerialflags;
4635         t->currentalpha = ent->alpha;
4636         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4637                 t->currentalpha *= r_wateralpha.value;
4638         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
4639                 t->currentalpha *= t->r_water_wateralpha;
4640         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
4641                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4642         if (!(ent->flags & RENDER_LIGHT))
4643                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4644         else if (rsurface.modeltexcoordlightmap2f == NULL)
4645         {
4646                 // pick a model lighting mode
4647                 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4648                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4649                 else
4650                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4651         }
4652         if (ent->effects & EF_ADDITIVE)
4653                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4654         else if (t->currentalpha < 1)
4655                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4656         if (ent->effects & EF_DOUBLESIDED)
4657                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4658         if (ent->effects & EF_NODEPTHTEST)
4659                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4660         if (ent->flags & RENDER_VIEWMODEL)
4661                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4662         if (t->backgroundnumskinframes)
4663                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4664         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
4665         {
4666                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
4667                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
4668         }
4669         else
4670                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
4671
4672         // there is no tcmod
4673         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4674                 t->currenttexmatrix = r_waterscrollmatrix;
4675
4676         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4677         {
4678                 matrix4x4_t matrix;
4679                 switch(tcmod->tcmod)
4680                 {
4681                 case Q3TCMOD_COUNT:
4682                 case Q3TCMOD_NONE:
4683                         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4684                                 matrix = r_waterscrollmatrix;
4685                         else
4686                                 matrix = identitymatrix;
4687                         break;
4688                 case Q3TCMOD_ENTITYTRANSLATE:
4689                         // this is used in Q3 to allow the gamecode to control texcoord
4690                         // scrolling on the entity, which is not supported in darkplaces yet.
4691                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4692                         break;
4693                 case Q3TCMOD_ROTATE:
4694                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4695                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4696                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4697                         break;
4698                 case Q3TCMOD_SCALE:
4699                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4700                         break;
4701                 case Q3TCMOD_SCROLL:
4702                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4703                         break;
4704                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
4705                         w = tcmod->parms[0];
4706                         h = tcmod->parms[1];
4707                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
4708                         f = f - floor(f);
4709                         idx = floor(f * w * h);
4710                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
4711                         break;
4712                 case Q3TCMOD_STRETCH:
4713                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4714                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4715                         break;
4716                 case Q3TCMOD_TRANSFORM:
4717                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
4718                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
4719                         VectorSet(tcmat +  6, 0                   , 0                , 1);
4720                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
4721                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4722                         break;
4723                 case Q3TCMOD_TURBULENT:
4724                         // this is handled in the RSurf_PrepareVertices function
4725                         matrix = identitymatrix;
4726                         break;
4727                 }
4728                 // either replace or concatenate the transformation
4729                 if (i < 1)
4730                         t->currenttexmatrix = matrix;
4731                 else
4732                 {
4733                         matrix4x4_t temp = t->currenttexmatrix;
4734                         Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4735                 }
4736         }
4737
4738         t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4739         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4740         t->glosstexture = r_texture_black;
4741         t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4742         t->backgroundglosstexture = r_texture_black;
4743         t->specularpower = r_shadow_glossexponent.value;
4744         // TODO: store reference values for these in the texture?
4745         t->specularscale = 0;
4746         if (r_shadow_gloss.integer > 0)
4747         {
4748                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4749                 {
4750                         if (r_shadow_glossintensity.value > 0)
4751                         {
4752                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4753                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4754                                 t->specularscale = r_shadow_glossintensity.value;
4755                         }
4756                 }
4757                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4758                 {
4759                         t->glosstexture = r_texture_white;
4760                         t->backgroundglosstexture = r_texture_white;
4761                         t->specularscale = r_shadow_gloss2intensity.value;
4762                 }
4763         }
4764
4765         // lightmaps mode looks bad with dlights using actual texturing, so turn
4766         // off the colormap and glossmap, but leave the normalmap on as it still
4767         // accurately represents the shading involved
4768         if (gl_lightmaps.integer)
4769         {
4770                 t->basetexture = r_texture_grey128;
4771                 t->backgroundbasetexture = NULL;
4772                 t->specularscale = 0;
4773                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
4774         }
4775
4776         Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4777         VectorClear(t->dlightcolor);
4778         t->currentnumlayers = 0;
4779         if (t->currentmaterialflags & MATERIALFLAG_WALL)
4780         {
4781                 int layerflags = 0;
4782                 int blendfunc1, blendfunc2, depthmask;
4783                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4784                 {
4785                         blendfunc1 = GL_SRC_ALPHA;
4786                         blendfunc2 = GL_ONE;
4787                 }
4788                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4789                 {
4790                         blendfunc1 = GL_SRC_ALPHA;
4791                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4792                 }
4793                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4794                 {
4795                         blendfunc1 = t->customblendfunc[0];
4796                         blendfunc2 = t->customblendfunc[1];
4797                 }
4798                 else
4799                 {
4800                         blendfunc1 = GL_ONE;
4801                         blendfunc2 = GL_ZERO;
4802                 }
4803                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4804                 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4805                         layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4806                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4807                 {
4808                         // fullbright is not affected by r_refdef.lightmapintensity
4809                         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]);
4810                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4811                                 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]);
4812                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4813                                 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]);
4814                 }
4815                 else
4816                 {
4817                         vec3_t ambientcolor;
4818                         float colorscale;
4819                         // set the color tint used for lights affecting this surface
4820                         VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
4821                         colorscale = 2;
4822                         // q3bsp has no lightmap updates, so the lightstylevalue that
4823                         // would normally be baked into the lightmap must be
4824                         // applied to the color
4825                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4826                         if (ent->model->type == mod_brushq3)
4827                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
4828                         colorscale *= r_refdef.lightmapintensity;
4829                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
4830                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4831                         // basic lit geometry
4832                         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]);
4833                         // add pants/shirt if needed
4834                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4835                                 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]);
4836                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4837                                 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]);
4838                         // now add ambient passes if needed
4839                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
4840                         {
4841                                 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]);
4842                                 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4843                                         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]);
4844                                 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4845                                         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]);
4846                         }
4847                 }
4848                 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
4849                         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]);
4850                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4851                 {
4852                         // if this is opaque use alpha blend which will darken the earlier
4853                         // passes cheaply.
4854                         //
4855                         // if this is an alpha blended material, all the earlier passes
4856                         // were darkened by fog already, so we only need to add the fog
4857                         // color ontop through the fog mask texture
4858                         //
4859                         // if this is an additive blended material, all the earlier passes
4860                         // were darkened by fog already, and we should not add fog color
4861                         // (because the background was not darkened, there is no fog color
4862                         // that was lost behind it).
4863                         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]);
4864                 }
4865         }
4866 }
4867
4868 void R_UpdateAllTextureInfo(entity_render_t *ent)
4869 {
4870         int i;
4871         if (ent->model)
4872                 for (i = 0;i < ent->model->num_texturesperskin;i++)
4873                         R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4874 }
4875
4876 rsurfacestate_t rsurface;
4877
4878 void R_Mesh_ResizeArrays(int newvertices)
4879 {
4880         float *base;
4881         if (rsurface.array_size >= newvertices)
4882                 return;
4883         if (rsurface.array_modelvertex3f)
4884                 Mem_Free(rsurface.array_modelvertex3f);
4885         rsurface.array_size = (newvertices + 1023) & ~1023;
4886         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4887         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
4888         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
4889         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
4890         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
4891         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
4892         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4893         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4894         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
4895         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
4896         rsurface.array_color4f           = base + rsurface.array_size * 27;
4897         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4898 }
4899
4900 void RSurf_ActiveWorldEntity(void)
4901 {
4902         dp_model_t *model = r_refdef.scene.worldmodel;
4903         if (rsurface.array_size < model->surfmesh.num_vertices)
4904                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4905         rsurface.matrix = identitymatrix;
4906         rsurface.inversematrix = identitymatrix;
4907         R_Mesh_Matrix(&identitymatrix);
4908         VectorCopy(r_refdef.view.origin, rsurface.modelorg);
4909         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4910         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4911         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4912         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4913         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4914         rsurface.frameblend[0].frame = 0;
4915         rsurface.frameblend[0].lerp = 1;
4916         rsurface.frameblend[1].frame = 0;
4917         rsurface.frameblend[1].lerp = 0;
4918         rsurface.frameblend[2].frame = 0;
4919         rsurface.frameblend[2].lerp = 0;
4920         rsurface.frameblend[3].frame = 0;
4921         rsurface.frameblend[3].lerp = 0;
4922         rsurface.basepolygonfactor = r_refdef.polygonfactor;
4923         rsurface.basepolygonoffset = r_refdef.polygonoffset;
4924         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
4925         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4926         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4927         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4928         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4929         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4930         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4931         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4932         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4933         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
4934         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4935         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4936         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
4937         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4938         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4939         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
4940         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4941         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4942         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
4943         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4944         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4945         rsurface.modelelement3i = model->surfmesh.data_element3i;
4946         rsurface.modelelement3s = model->surfmesh.data_element3s;
4947         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
4948         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
4949         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4950         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4951         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4952         rsurface.modelsurfaces = model->data_surfaces;
4953         rsurface.generatedvertex = false;
4954         rsurface.vertex3f  = rsurface.modelvertex3f;
4955         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4956         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4957         rsurface.svector3f = rsurface.modelsvector3f;
4958         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4959         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4960         rsurface.tvector3f = rsurface.modeltvector3f;
4961         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4962         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4963         rsurface.normal3f  = rsurface.modelnormal3f;
4964         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4965         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4966         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4967 }
4968
4969 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4970 {
4971         dp_model_t *model = ent->model;
4972         if (rsurface.array_size < model->surfmesh.num_vertices)
4973                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4974         rsurface.matrix = ent->matrix;
4975         rsurface.inversematrix = ent->inversematrix;
4976         R_Mesh_Matrix(&rsurface.matrix);
4977         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
4978         rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
4979         rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
4980         rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
4981         rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
4982         rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
4983         rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
4984         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4985         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4986         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4987         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4988         rsurface.frameblend[0] = ent->frameblend[0];
4989         rsurface.frameblend[1] = ent->frameblend[1];
4990         rsurface.frameblend[2] = ent->frameblend[2];
4991         rsurface.frameblend[3] = ent->frameblend[3];
4992         rsurface.basepolygonfactor = r_refdef.polygonfactor;
4993         rsurface.basepolygonoffset = r_refdef.polygonoffset;
4994         if (ent->model->brush.submodel)
4995         {
4996                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
4997                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
4998         }
4999         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
5000         {
5001                 if (wanttangents)
5002                 {
5003                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5004                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5005                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5006                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5007                         model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5008                 }
5009                 else if (wantnormals)
5010                 {
5011                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5012                         rsurface.modelsvector3f = NULL;
5013                         rsurface.modeltvector3f = NULL;
5014                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5015                         model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5016                 }
5017                 else
5018                 {
5019                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5020                         rsurface.modelsvector3f = NULL;
5021                         rsurface.modeltvector3f = NULL;
5022                         rsurface.modelnormal3f = NULL;
5023                         model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5024                 }
5025                 rsurface.modelvertex3f_bufferobject = 0;
5026                 rsurface.modelvertex3f_bufferoffset = 0;
5027                 rsurface.modelsvector3f_bufferobject = 0;
5028                 rsurface.modelsvector3f_bufferoffset = 0;
5029                 rsurface.modeltvector3f_bufferobject = 0;
5030                 rsurface.modeltvector3f_bufferoffset = 0;
5031                 rsurface.modelnormal3f_bufferobject = 0;
5032                 rsurface.modelnormal3f_bufferoffset = 0;
5033                 rsurface.generatedvertex = true;
5034         }
5035         else
5036         {
5037                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
5038                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5039                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5040                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5041                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5042                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5043                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5044                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5045                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5046                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
5047                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5048                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5049                 rsurface.generatedvertex = false;
5050         }
5051         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
5052         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5053         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5054         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
5055         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5056         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5057         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
5058         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5059         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5060         rsurface.modelelement3i = model->surfmesh.data_element3i;
5061         rsurface.modelelement3s = model->surfmesh.data_element3s;
5062         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5063         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5064         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5065         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5066         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5067         rsurface.modelsurfaces = model->data_surfaces;
5068         rsurface.vertex3f  = rsurface.modelvertex3f;
5069         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5070         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5071         rsurface.svector3f = rsurface.modelsvector3f;
5072         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5073         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5074         rsurface.tvector3f = rsurface.modeltvector3f;
5075         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5076         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5077         rsurface.normal3f  = rsurface.modelnormal3f;
5078         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5079         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5080         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5081 }
5082
5083 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5084 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5085 {
5086         int deformindex;
5087         int texturesurfaceindex;
5088         int i, j;
5089         float amplitude;
5090         float animpos;
5091         float scale;
5092         const float *v1, *in_tc;
5093         float *out_tc;
5094         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5095         float waveparms[4];
5096         q3shaderinfo_deform_t *deform;
5097         // 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
5098         if (rsurface.generatedvertex)
5099         {
5100                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5101                         generatenormals = true;
5102                 for (i = 0;i < Q3MAXDEFORMS;i++)
5103                 {
5104                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5105                         {
5106                                 generatetangents = true;
5107                                 generatenormals = true;
5108                         }
5109                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5110                                 generatenormals = true;
5111                 }
5112                 if (generatenormals && !rsurface.modelnormal3f)
5113                 {
5114                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5115                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5116                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5117                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
5118                 }
5119                 if (generatetangents && !rsurface.modelsvector3f)
5120                 {
5121                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5122                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5123                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5124                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5125                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5126                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5127                         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);
5128                 }
5129         }
5130         rsurface.vertex3f  = rsurface.modelvertex3f;
5131         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5132         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5133         rsurface.svector3f = rsurface.modelsvector3f;
5134         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5135         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5136         rsurface.tvector3f = rsurface.modeltvector3f;
5137         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5138         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5139         rsurface.normal3f  = rsurface.modelnormal3f;
5140         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5141         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5142         // if vertices are deformed (sprite flares and things in maps, possibly
5143         // water waves, bulges and other deformations), generate them into
5144         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5145         // (may be static model data or generated data for an animated model, or
5146         //  the previous deform pass)
5147         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5148         {
5149                 switch (deform->deform)
5150                 {
5151                 default:
5152                 case Q3DEFORM_PROJECTIONSHADOW:
5153                 case Q3DEFORM_TEXT0:
5154                 case Q3DEFORM_TEXT1:
5155                 case Q3DEFORM_TEXT2:
5156                 case Q3DEFORM_TEXT3:
5157                 case Q3DEFORM_TEXT4:
5158                 case Q3DEFORM_TEXT5:
5159                 case Q3DEFORM_TEXT6:
5160                 case Q3DEFORM_TEXT7:
5161                 case Q3DEFORM_NONE:
5162                         break;
5163                 case Q3DEFORM_AUTOSPRITE:
5164                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5165                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5166                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5167                         VectorNormalize(newforward);
5168                         VectorNormalize(newright);
5169                         VectorNormalize(newup);
5170                         // make deformed versions of only the model vertices used by the specified surfaces
5171                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5172                         {
5173                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5174                                 // a single autosprite surface can contain multiple sprites...
5175                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
5176                                 {
5177                                         VectorClear(center);
5178                                         for (i = 0;i < 4;i++)
5179                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5180                                         VectorScale(center, 0.25f, center);
5181                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
5182                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5183                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5184                                         for (i = 0;i < 4;i++)
5185                                         {
5186                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5187                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5188                                         }
5189                                 }
5190                                 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);
5191                                 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);
5192                         }
5193                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5194                         rsurface.vertex3f_bufferobject = 0;
5195                         rsurface.vertex3f_bufferoffset = 0;
5196                         rsurface.svector3f = rsurface.array_deformedsvector3f;
5197                         rsurface.svector3f_bufferobject = 0;
5198                         rsurface.svector3f_bufferoffset = 0;
5199                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
5200                         rsurface.tvector3f_bufferobject = 0;
5201                         rsurface.tvector3f_bufferoffset = 0;
5202                         rsurface.normal3f = rsurface.array_deformednormal3f;
5203                         rsurface.normal3f_bufferobject = 0;
5204                         rsurface.normal3f_bufferoffset = 0;
5205                         break;
5206                 case Q3DEFORM_AUTOSPRITE2:
5207                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5208                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5209                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5210                         VectorNormalize(newforward);
5211                         VectorNormalize(newright);
5212                         VectorNormalize(newup);
5213                         // make deformed versions of only the model vertices used by the specified surfaces
5214                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5215                         {
5216                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5217                                 const float *v1, *v2;
5218                                 vec3_t start, end;
5219                                 float f, l;
5220                                 struct
5221                                 {
5222                                         float length2;
5223                                         const float *v1;
5224                                         const float *v2;
5225                                 }
5226                                 shortest[2];
5227                                 memset(shortest, 0, sizeof(shortest));
5228                                 // a single autosprite surface can contain multiple sprites...
5229                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
5230                                 {
5231                                         VectorClear(center);
5232                                         for (i = 0;i < 4;i++)
5233                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5234                                         VectorScale(center, 0.25f, center);
5235                                         // find the two shortest edges, then use them to define the
5236                                         // axis vectors for rotating around the central axis
5237                                         for (i = 0;i < 6;i++)
5238                                         {
5239                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5240                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5241 #if 0
5242                                                 Debug_PolygonBegin(NULL, 0);
5243                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5244                                                 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);
5245                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5246                                                 Debug_PolygonEnd();
5247 #endif
5248                                                 l = VectorDistance2(v1, v2);
5249                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5250                                                 if (v1[2] != v2[2])
5251                                                         l += (1.0f / 1024.0f);
5252                                                 if (shortest[0].length2 > l || i == 0)
5253                                                 {
5254                                                         shortest[1] = shortest[0];
5255                                                         shortest[0].length2 = l;
5256                                                         shortest[0].v1 = v1;
5257                                                         shortest[0].v2 = v2;
5258                                                 }
5259                                                 else if (shortest[1].length2 > l || i == 1)
5260                                                 {
5261                                                         shortest[1].length2 = l;
5262                                                         shortest[1].v1 = v1;
5263                                                         shortest[1].v2 = v2;
5264                                                 }
5265                                         }
5266                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5267                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5268 #if 0
5269                                         Debug_PolygonBegin(NULL, 0);
5270                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5271                                         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);
5272                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5273                                         Debug_PolygonEnd();
5274 #endif
5275                                         // this calculates the right vector from the shortest edge
5276                                         // and the up vector from the edge midpoints
5277                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5278                                         VectorNormalize(right);
5279                                         VectorSubtract(end, start, up);
5280                                         VectorNormalize(up);
5281                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5282                                         //VectorSubtract(rsurface.modelorg, center, forward);
5283                                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5284                                         VectorNegate(forward, forward);
5285                                         VectorReflect(forward, 0, up, forward);
5286                                         VectorNormalize(forward);
5287                                         CrossProduct(up, forward, newright);
5288                                         VectorNormalize(newright);
5289 #if 0
5290                                         Debug_PolygonBegin(NULL, 0);
5291                                         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);
5292                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5293                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
5294                                         Debug_PolygonEnd();
5295 #endif
5296 #if 0
5297                                         Debug_PolygonBegin(NULL, 0);
5298                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5299                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5300                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
5301                                         Debug_PolygonEnd();
5302 #endif
5303                                         // rotate the quad around the up axis vector, this is made
5304                                         // especially easy by the fact we know the quad is flat,
5305                                         // so we only have to subtract the center position and
5306                                         // measure distance along the right vector, and then
5307                                         // multiply that by the newright vector and add back the
5308                                         // center position
5309                                         // we also need to subtract the old position to undo the
5310                                         // displacement from the center, which we do with a
5311                                         // DotProduct, the subtraction/addition of center is also
5312                                         // optimized into DotProducts here
5313                                         l = DotProduct(right, center);
5314                                         for (i = 0;i < 4;i++)
5315                                         {
5316                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5317                                                 f = DotProduct(right, v1) - l;
5318                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5319                                         }
5320                                 }
5321                                 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);
5322                                 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);
5323                         }
5324                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5325                         rsurface.vertex3f_bufferobject = 0;
5326                         rsurface.vertex3f_bufferoffset = 0;
5327                         rsurface.svector3f = rsurface.array_deformedsvector3f;
5328                         rsurface.svector3f_bufferobject = 0;
5329                         rsurface.svector3f_bufferoffset = 0;
5330                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
5331                         rsurface.tvector3f_bufferobject = 0;
5332                         rsurface.tvector3f_bufferoffset = 0;
5333                         rsurface.normal3f = rsurface.array_deformednormal3f;
5334                         rsurface.normal3f_bufferobject = 0;
5335                         rsurface.normal3f_bufferoffset = 0;
5336                         break;
5337                 case Q3DEFORM_NORMAL:
5338                         // deform the normals to make reflections wavey
5339                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5340                         {
5341                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5342                                 for (j = 0;j < surface->num_vertices;j++)
5343                                 {
5344                                         float vertex[3];
5345                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
5346                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5347                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
5348                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5349                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5350                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5351                                         VectorNormalize(normal);
5352                                 }
5353                                 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);
5354                         }
5355                         rsurface.svector3f = rsurface.array_deformedsvector3f;
5356                         rsurface.svector3f_bufferobject = 0;
5357                         rsurface.svector3f_bufferoffset = 0;
5358                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
5359                         rsurface.tvector3f_bufferobject = 0;
5360                         rsurface.tvector3f_bufferoffset = 0;
5361                         rsurface.normal3f = rsurface.array_deformednormal3f;
5362                         rsurface.normal3f_bufferobject = 0;
5363                         rsurface.normal3f_bufferoffset = 0;
5364                         break;
5365                 case Q3DEFORM_WAVE:
5366                         // deform vertex array to make wavey water and flags and such
5367                         waveparms[0] = deform->waveparms[0];
5368                         waveparms[1] = deform->waveparms[1];
5369                         waveparms[2] = deform->waveparms[2];
5370                         waveparms[3] = deform->waveparms[3];
5371                         // this is how a divisor of vertex influence on deformation
5372                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5373                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5374                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5375                         {
5376                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5377                                 for (j = 0;j < surface->num_vertices;j++)
5378                                 {
5379                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
5380                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
5381                                         // if the wavefunc depends on time, evaluate it per-vertex
5382                                         if (waveparms[3])
5383                                         {
5384                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5385                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5386                                         }
5387                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
5388                                 }
5389                         }
5390                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5391                         rsurface.vertex3f_bufferobject = 0;
5392                         rsurface.vertex3f_bufferoffset = 0;
5393                         break;
5394                 case Q3DEFORM_BULGE:
5395                         // deform vertex array to make the surface have moving bulges
5396                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5397                         {
5398                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5399                                 for (j = 0;j < surface->num_vertices;j++)
5400                                 {
5401                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
5402                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5403                                 }
5404                         }
5405                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5406                         rsurface.vertex3f_bufferobject = 0;
5407                         rsurface.vertex3f_bufferoffset = 0;
5408                         break;
5409                 case Q3DEFORM_MOVE:
5410                         // deform vertex array
5411                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
5412                         VectorScale(deform->parms, scale, waveparms);
5413                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5414                         {
5415                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5416                                 for (j = 0;j < surface->num_vertices;j++)
5417                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5418                         }
5419                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5420                         rsurface.vertex3f_bufferobject = 0;
5421                         rsurface.vertex3f_bufferoffset = 0;
5422                         break;
5423                 }
5424         }
5425         // generate texcoords based on the chosen texcoord source
5426         switch(rsurface.texture->tcgen.tcgen)
5427         {
5428         default:
5429         case Q3TCGEN_TEXTURE:
5430                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
5431                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
5432                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
5433                 break;
5434         case Q3TCGEN_LIGHTMAP:
5435                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
5436                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
5437                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
5438                 break;
5439         case Q3TCGEN_VECTOR:
5440                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5441                 {
5442                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5443                         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)
5444                         {
5445                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
5446                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
5447                         }
5448                 }
5449                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
5450                 rsurface.texcoordtexture2f_bufferobject  = 0;
5451                 rsurface.texcoordtexture2f_bufferoffset  = 0;
5452                 break;
5453         case Q3TCGEN_ENVIRONMENT:
5454                 // make environment reflections using a spheremap
5455                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5456                 {
5457                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5458                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
5459                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
5460                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
5461                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
5462                         {
5463                                 float l, d, eyedir[3];
5464                                 VectorSubtract(rsurface.modelorg, vertex, eyedir);
5465                                 l = 0.5f / VectorLength(eyedir);
5466                                 d = DotProduct(normal, eyedir)*2;
5467                                 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
5468                                 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
5469                         }
5470                 }
5471                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
5472                 rsurface.texcoordtexture2f_bufferobject  = 0;
5473                 rsurface.texcoordtexture2f_bufferoffset  = 0;
5474                 break;
5475         }
5476         // the only tcmod that needs software vertex processing is turbulent, so
5477         // check for it here and apply the changes if needed
5478         // and we only support that as the first one
5479         // (handling a mixture of turbulent and other tcmods would be problematic
5480         //  without punting it entirely to a software path)
5481         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
5482         {
5483                 amplitude = rsurface.texture->tcmods[0].parms[1];
5484                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
5485                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5486                 {
5487                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5488                         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)
5489                         {
5490                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5491                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5492                         }
5493                 }
5494                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
5495                 rsurface.texcoordtexture2f_bufferobject  = 0;
5496                 rsurface.texcoordtexture2f_bufferoffset  = 0;
5497         }
5498         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
5499         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5500         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5501         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5502 }
5503
5504 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5505 {
5506         int i, j;
5507         const msurface_t *surface = texturesurfacelist[0];
5508         const msurface_t *surface2;
5509         int firstvertex;
5510         int endvertex;
5511         int numvertices;
5512         int numtriangles;
5513         // TODO: lock all array ranges before render, rather than on each surface
5514         if (texturenumsurfaces == 1)
5515         {
5516                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5517                 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);
5518         }
5519         else if (r_batchmode.integer == 2)
5520         {
5521                 #define MAXBATCHTRIANGLES 4096
5522                 int batchtriangles = 0;
5523                 int batchelements[MAXBATCHTRIANGLES*3];
5524                 for (i = 0;i < texturenumsurfaces;i = j)
5525                 {
5526                         surface = texturesurfacelist[i];
5527                         j = i + 1;
5528                         if (surface->num_triangles > MAXBATCHTRIANGLES)
5529                         {
5530                                 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);
5531                                 continue;
5532                         }
5533                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5534                         batchtriangles = surface->num_triangles;
5535                         firstvertex = surface->num_firstvertex;
5536                         endvertex = surface->num_firstvertex + surface->num_vertices;
5537                         for (;j < texturenumsurfaces;j++)
5538                         {
5539                                 surface2 = texturesurfacelist[j];
5540                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5541                                         break;
5542                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5543                                 batchtriangles += surface2->num_triangles;
5544                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
5545                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5546                         }
5547                         surface2 = texturesurfacelist[j-1];
5548                         numvertices = endvertex - firstvertex;
5549                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5550                 }
5551         }
5552         else if (r_batchmode.integer == 1)
5553         {
5554                 for (i = 0;i < texturenumsurfaces;i = j)
5555                 {
5556                         surface = texturesurfacelist[i];
5557                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5558                                 if (texturesurfacelist[j] != surface2)
5559                                         break;
5560                         surface2 = texturesurfacelist[j-1];
5561                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5562                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5563                         GL_LockArrays(surface->num_firstvertex, numvertices);
5564                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5565                 }
5566         }
5567         else
5568         {
5569                 for (i = 0;i < texturenumsurfaces;i++)
5570                 {
5571                         surface = texturesurfacelist[i];
5572                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5573                         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);
5574                 }
5575         }
5576 }
5577
5578 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5579 {
5580         int i, planeindex, vertexindex;
5581         float d, bestd;
5582         vec3_t vert;
5583         const float *v;
5584         r_waterstate_waterplane_t *p, *bestp;
5585         msurface_t *surface;
5586         if (r_waterstate.renderingscene)
5587                 return;
5588         for (i = 0;i < texturenumsurfaces;i++)
5589         {
5590                 surface = texturesurfacelist[i];
5591                 if (lightmaptexunit >= 0)
5592                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5593                 if (deluxemaptexunit >= 0)
5594                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5595                 // pick the closest matching water plane
5596                 bestd = 0;
5597                 bestp = NULL;
5598                 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5599                 {
5600                         d = 0;
5601                         for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5602                         {
5603                                 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5604                                 d += fabs(PlaneDiff(vert, &p->plane));
5605                         }
5606                         if (bestd > d || !bestp)
5607                         {
5608                                 bestd = d;
5609                                 bestp = p;
5610                         }
5611                 }
5612                 if (bestp)
5613                 {
5614                         if (refractiontexunit >= 0)
5615                                 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5616                         if (reflectiontexunit >= 0)
5617                                 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5618                 }
5619                 else
5620                 {
5621                         if (refractiontexunit >= 0)
5622                                 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5623                         if (reflectiontexunit >= 0)
5624                                 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5625                 }
5626                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5627                 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);
5628         }
5629 }
5630
5631 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5632 {
5633         int i;
5634         int j;
5635         const msurface_t *surface = texturesurfacelist[0];
5636         const msurface_t *surface2;
5637         int firstvertex;
5638         int endvertex;
5639         int numvertices;
5640         int numtriangles;
5641         // TODO: lock all array ranges before render, rather than on each surface
5642         if (texturenumsurfaces == 1)
5643         {
5644                 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5645                 if (deluxemaptexunit >= 0)
5646                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5647                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5648                 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);
5649         }
5650         else if (r_batchmode.integer == 2)
5651         {
5652                 #define MAXBATCHTRIANGLES 4096
5653                 int batchtriangles = 0;
5654                 int batchelements[MAXBATCHTRIANGLES*3];
5655                 for (i = 0;i < texturenumsurfaces;i = j)
5656                 {
5657                         surface = texturesurfacelist[i];
5658                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5659                         if (deluxemaptexunit >= 0)
5660                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5661                         j = i + 1;
5662                         if (surface->num_triangles > MAXBATCHTRIANGLES)
5663                         {
5664                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5665                                 continue;
5666                         }
5667                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5668                         batchtriangles = surface->num_triangles;
5669                         firstvertex = surface->num_firstvertex;
5670                         endvertex = surface->num_firstvertex + surface->num_vertices;
5671                         for (;j < texturenumsurfaces;j++)
5672                         {
5673                                 surface2 = texturesurfacelist[j];
5674                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5675                                         break;
5676                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5677                                 batchtriangles += surface2->num_triangles;
5678                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
5679                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5680                         }
5681                         surface2 = texturesurfacelist[j-1];
5682                         numvertices = endvertex - firstvertex;
5683                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5684                 }
5685         }
5686         else if (r_batchmode.integer == 1)
5687         {
5688 #if 0
5689                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5690                 for (i = 0;i < texturenumsurfaces;i = j)
5691                 {
5692                         surface = texturesurfacelist[i];
5693                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5694                                 if (texturesurfacelist[j] != surface2)
5695                                         break;
5696                         Con_Printf(" %i", j - i);
5697                 }
5698                 Con_Printf("\n");
5699                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5700 #endif
5701                 for (i = 0;i < texturenumsurfaces;i = j)
5702                 {
5703                         surface = texturesurfacelist[i];
5704                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5705                         if (deluxemaptexunit >= 0)
5706                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5707                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5708                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5709                                         break;
5710 #if 0
5711                         Con_Printf(" %i", j - i);
5712 #endif
5713                         surface2 = texturesurfacelist[j-1];
5714                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5715                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5716                         GL_LockArrays(surface->num_firstvertex, numvertices);
5717                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5718                 }
5719 #if 0
5720                 Con_Printf("\n");
5721 #endif
5722         }
5723         else
5724         {
5725                 for (i = 0;i < texturenumsurfaces;i++)
5726                 {
5727                         surface = texturesurfacelist[i];
5728                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5729                         if (deluxemaptexunit >= 0)
5730                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5731                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5732                         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);
5733                 }
5734         }
5735 }
5736
5737 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5738 {
5739         int j;
5740         int texturesurfaceindex;
5741         if (r_showsurfaces.integer == 2)
5742         {
5743                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5744                 {
5745                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5746                         for (j = 0;j < surface->num_triangles;j++)
5747                         {
5748                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
5749                                 GL_Color(f, f, f, 1);
5750                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5751                         }
5752                 }
5753         }
5754         else
5755         {
5756                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5757                 {
5758                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5759                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
5760                         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);
5761                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5762                         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);
5763                 }
5764         }
5765 }
5766
5767 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5768 {
5769         int texturesurfaceindex;
5770         int i;
5771         float f;
5772         float *v, *c, *c2;
5773         if (rsurface.lightmapcolor4f)
5774         {
5775                 // generate color arrays for the surfaces in this list
5776                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5777                 {
5778                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5779                         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)
5780                         {
5781                                 f = FogPoint_Model(v);
5782                                 c2[0] = c[0] * f;
5783                                 c2[1] = c[1] * f;
5784                                 c2[2] = c[2] * f;
5785                                 c2[3] = c[3];
5786                         }
5787                 }
5788         }
5789         else
5790         {
5791                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5792                 {
5793                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5794                         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)
5795                         {
5796                                 f = FogPoint_Model(v);
5797                                 c2[0] = f;
5798                                 c2[1] = f;
5799                                 c2[2] = f;
5800                                 c2[3] = 1;
5801                         }
5802                 }
5803         }
5804         rsurface.lightmapcolor4f = rsurface.array_color4f;
5805         rsurface.lightmapcolor4f_bufferobject = 0;
5806         rsurface.lightmapcolor4f_bufferoffset = 0;
5807 }
5808
5809 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5810 {
5811         int texturesurfaceindex;
5812         int i;
5813         float *c, *c2;
5814         if (!rsurface.lightmapcolor4f)
5815                 return;
5816         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5817         {
5818                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5819                 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)
5820                 {
5821                         c2[0] = c[0] * r;
5822                         c2[1] = c[1] * g;
5823                         c2[2] = c[2] * b;
5824                         c2[3] = c[3] * a;
5825                 }
5826         }
5827         rsurface.lightmapcolor4f = rsurface.array_color4f;
5828         rsurface.lightmapcolor4f_bufferobject = 0;
5829         rsurface.lightmapcolor4f_bufferoffset = 0;
5830 }
5831
5832 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5833 {
5834         // TODO: optimize
5835         rsurface.lightmapcolor4f = NULL;
5836         rsurface.lightmapcolor4f_bufferobject = 0;
5837         rsurface.lightmapcolor4f_bufferoffset = 0;
5838         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5839         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5840         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5841         GL_Color(r, g, b, a);
5842         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5843 }
5844
5845 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5846 {
5847         // TODO: optimize applyfog && applycolor case
5848         // just apply fog if necessary, and tint the fog color array if necessary
5849         rsurface.lightmapcolor4f = NULL;
5850         rsurface.lightmapcolor4f_bufferobject = 0;
5851         rsurface.lightmapcolor4f_bufferoffset = 0;
5852         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5853         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5854         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5855         GL_Color(r, g, b, a);
5856         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5857 }
5858
5859 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5860 {
5861         int texturesurfaceindex;
5862         int i;
5863         float *c;
5864         // TODO: optimize
5865         if (texturesurfacelist[0]->lightmapinfo)
5866         {
5867                 // generate color arrays for the surfaces in this list
5868                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5869                 {
5870                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5871                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5872                         {
5873                                 if (surface->lightmapinfo->samples)
5874                                 {
5875                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5876                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5877                                         VectorScale(lm, scale, c);
5878                                         if (surface->lightmapinfo->styles[1] != 255)
5879                                         {
5880                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5881                                                 lm += size3;
5882                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5883                                                 VectorMA(c, scale, lm, c);
5884                                                 if (surface->lightmapinfo->styles[2] != 255)
5885                                                 {
5886                                                         lm += size3;
5887                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5888                                                         VectorMA(c, scale, lm, c);
5889                                                         if (surface->lightmapinfo->styles[3] != 255)
5890                                                         {
5891                                                                 lm += size3;
5892                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5893                                                                 VectorMA(c, scale, lm, c);
5894                                                         }
5895                                                 }
5896                                         }
5897                                 }
5898                                 else
5899                                         VectorClear(c);
5900                                 c[3] = 1;
5901                         }
5902                 }
5903                 rsurface.lightmapcolor4f = rsurface.array_color4f;
5904                 rsurface.lightmapcolor4f_bufferobject = 0;
5905                 rsurface.lightmapcolor4f_bufferoffset = 0;
5906         }
5907         else
5908         {
5909                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5910                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5911                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5912         }
5913         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5914         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5915         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5916         GL_Color(r, g, b, a);
5917         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5918 }
5919
5920 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5921 {
5922         int texturesurfaceindex;
5923         int i;
5924         float f;
5925         float *v, *c, *c2;
5926         vec3_t ambientcolor;
5927         vec3_t diffusecolor;
5928         vec3_t lightdir;
5929         // TODO: optimize
5930         // model lighting
5931         VectorCopy(rsurface.modellight_lightdir, lightdir);
5932         f = 0.5f * r_refdef.lightmapintensity;
5933         ambientcolor[0] = rsurface.modellight_ambient[0] * r * f;
5934         ambientcolor[1] = rsurface.modellight_ambient[1] * g * f;
5935         ambientcolor[2] = rsurface.modellight_ambient[2] * b * f;
5936         diffusecolor[0] = rsurface.modellight_diffuse[0] * r * f;
5937         diffusecolor[1] = rsurface.modellight_diffuse[1] * g * f;
5938         diffusecolor[2] = rsurface.modellight_diffuse[2] * b * f;
5939         if (VectorLength2(diffusecolor) > 0)
5940         {
5941                 // generate color arrays for the surfaces in this list
5942                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5943                 {
5944                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5945                         int numverts = surface->num_vertices;
5946                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5947                         c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5948                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5949                         // q3-style directional shading
5950                         for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5951                         {
5952                                 if ((f = DotProduct(c2, lightdir)) > 0)
5953                                         VectorMA(ambientcolor, f, diffusecolor, c);
5954                                 else
5955                                         VectorCopy(ambientcolor, c);
5956                                 c[3] = a;
5957                         }
5958                 }
5959                 r = 1;
5960                 g = 1;
5961                 b = 1;
5962                 a = 1;
5963                 applycolor = false;
5964                 rsurface.lightmapcolor4f = rsurface.array_color4f;
5965                 rsurface.lightmapcolor4f_bufferobject = 0;
5966                 rsurface.lightmapcolor4f_bufferoffset = 0;
5967         }
5968         else
5969         {
5970                 r = ambientcolor[0];
5971                 g = ambientcolor[1];
5972                 b = ambientcolor[2];
5973                 rsurface.lightmapcolor4f = NULL;
5974                 rsurface.lightmapcolor4f_bufferobject = 0;
5975                 rsurface.lightmapcolor4f_bufferoffset = 0;
5976         }
5977         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5978         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5979         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5980         GL_Color(r, g, b, a);
5981         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5982 }
5983
5984 void RSurf_SetupDepthAndCulling(void)
5985 {
5986         // submodels are biased to avoid z-fighting with world surfaces that they
5987         // may be exactly overlapping (avoids z-fighting artifacts on certain
5988         // doors and things in Quake maps)
5989         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5990         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
5991         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5992         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
5993 }
5994
5995 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5996 {
5997         // transparent sky would be ridiculous
5998         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5999                 return;
6000         R_SetupGenericShader(false);
6001         if (skyrendernow)
6002         {
6003                 skyrendernow = false;
6004                 // we have to force off the water clipping plane while rendering sky
6005                 R_SetupView(false);
6006                 R_Sky();
6007                 R_SetupView(true);
6008                 // restore entity matrix
6009                 R_Mesh_Matrix(&rsurface.matrix);
6010         }
6011         RSurf_SetupDepthAndCulling();
6012         GL_DepthMask(true);
6013         // LordHavoc: HalfLife maps have freaky skypolys so don't use
6014         // skymasking on them, and Quake3 never did sky masking (unlike
6015         // software Quake and software Quake2), so disable the sky masking
6016         // in Quake3 maps as it causes problems with q3map2 sky tricks,
6017         // and skymasking also looks very bad when noclipping outside the
6018         // level, so don't use it then either.
6019         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6020         {
6021                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6022                 R_Mesh_ColorPointer(NULL, 0, 0);
6023                 R_Mesh_ResetTextureState();
6024                 if (skyrendermasked)
6025                 {
6026                         R_SetupDepthOrShadowShader();
6027                         // depth-only (masking)
6028                         GL_ColorMask(0,0,0,0);
6029                         // just to make sure that braindead drivers don't draw
6030                         // anything despite that colormask...
6031                         GL_BlendFunc(GL_ZERO, GL_ONE);
6032                 }
6033                 else
6034                 {
6035                         R_SetupGenericShader(false);
6036                         // fog sky
6037                         GL_BlendFunc(GL_ONE, GL_ZERO);
6038                 }
6039                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6040                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6041                 if (skyrendermasked)
6042                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6043         }
6044         R_Mesh_ResetTextureState();
6045         GL_Color(1, 1, 1, 1);
6046 }
6047
6048 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6049 {
6050         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6051                 return;
6052
6053         R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6054         R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6055         R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6056         R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6057         R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6058         if (rsurface.texture->backgroundcurrentskinframe)
6059         {
6060                 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6061                 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6062                 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6063                 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6064         }
6065         if(rsurface.texture->colormapping)
6066         {
6067                 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6068                 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6069         }
6070         R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6071         if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6072                 R_Mesh_ColorPointer(NULL, 0, 0);
6073         else
6074                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6075
6076         if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6077         {
6078                 // render background
6079                 GL_BlendFunc(GL_ONE, GL_ZERO);
6080                 GL_DepthMask(true);
6081                 GL_AlphaTest(false);
6082
6083                 GL_Color(1, 1, 1, 1);
6084                 R_Mesh_ColorPointer(NULL, 0, 0);
6085
6086                 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6087                 if (r_glsl_permutation)
6088                 {
6089                         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6090                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6091                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6092                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6093                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6094                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6095                         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);
6096                 }
6097                 GL_LockArrays(0, 0);
6098
6099                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6100                 GL_DepthMask(false);
6101                 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6102                         R_Mesh_ColorPointer(NULL, 0, 0);
6103                 else
6104                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6105                 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6106                 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6107         }
6108
6109         R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6110         if (!r_glsl_permutation)
6111                 return;
6112
6113         RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
6114         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6115         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6116         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6117         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6118         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6119
6120         if (r_glsl_permutation->loc_Texture_Refraction >= 0)
6121         {
6122                 GL_BlendFunc(GL_ONE, GL_ZERO);
6123                 GL_DepthMask(true);
6124                 GL_AlphaTest(false);
6125         }
6126         else
6127         {
6128                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6129                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6130                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6131         }
6132
6133         if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6134         {
6135                 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6136                         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);
6137                 else
6138                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
6139         }
6140         else
6141         {
6142                 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6143                         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);
6144                 else
6145                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6146         }
6147         GL_LockArrays(0, 0);
6148 }
6149
6150 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6151 {
6152         // OpenGL 1.3 path - anything not completely ancient
6153         int texturesurfaceindex;
6154         qboolean applycolor;
6155         qboolean applyfog;
6156         rmeshstate_t m;
6157         int layerindex;
6158         const texturelayer_t *layer;
6159         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6160
6161         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6162         {
6163                 vec4_t layercolor;
6164                 int layertexrgbscale;
6165                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6166                 {
6167                         if (layerindex == 0)
6168                                 GL_AlphaTest(true);
6169                         else
6170                         {
6171                                 GL_AlphaTest(false);
6172                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6173                         }
6174                 }
6175                 GL_DepthMask(layer->depthmask && writedepth);
6176                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6177                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
6178                 {
6179                         layertexrgbscale = 4;
6180                         VectorScale(layer->color, 0.25f, layercolor);
6181                 }
6182                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
6183                 {
6184                         layertexrgbscale = 2;
6185                         VectorScale(layer->color, 0.5f, layercolor);
6186                 }
6187                 else
6188                 {
6189                         layertexrgbscale = 1;
6190                         VectorScale(layer->color, 1.0f, layercolor);
6191                 }
6192                 layercolor[3] = layer->color[3];
6193                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6194                 R_Mesh_ColorPointer(NULL, 0, 0);
6195                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6196                 switch (layer->type)
6197                 {
6198                 case TEXTURELAYERTYPE_LITTEXTURE:
6199                         memset(&m, 0, sizeof(m));
6200                         m.tex[0] = R_GetTexture(r_texture_white);
6201                         m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6202                         m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6203                         m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6204                         m.tex[1] = R_GetTexture(layer->texture);
6205                         m.texmatrix[1] = layer->texmatrix;
6206                         m.texrgbscale[1] = layertexrgbscale;
6207                         m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
6208                         m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
6209                         m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
6210                         R_Mesh_TextureState(&m);
6211                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6212                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6213                         else if (rsurface.uselightmaptexture)
6214                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6215                         else
6216                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6217                         break;
6218                 case TEXTURELAYERTYPE_TEXTURE:
6219                         memset(&m, 0, sizeof(m));
6220                         m.tex[0] = R_GetTexture(layer->texture);
6221                         m.texmatrix[0] = layer->texmatrix;
6222                         m.texrgbscale[0] = layertexrgbscale;
6223                         m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6224                         m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6225                         m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6226                         R_Mesh_TextureState(&m);
6227                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6228                         break;
6229                 case TEXTURELAYERTYPE_FOG:
6230                         memset(&m, 0, sizeof(m));
6231                         m.texrgbscale[0] = layertexrgbscale;
6232                         if (layer->texture)
6233                         {
6234                                 m.tex[0] = R_GetTexture(layer->texture);
6235                                 m.texmatrix[0] = layer->texmatrix;
6236                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6237                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6238                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6239                         }
6240                         R_Mesh_TextureState(&m);
6241                         // generate a color array for the fog pass
6242                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6243                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6244                         {
6245                                 int i;
6246                                 float f, *v, *c;
6247                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6248                                 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)
6249                                 {
6250                                         f = 1 - FogPoint_Model(v);
6251                                         c[0] = layercolor[0];
6252                                         c[1] = layercolor[1];
6253                                         c[2] = layercolor[2];
6254                                         c[3] = f * layercolor[3];
6255                                 }
6256                         }
6257                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6258                         break;
6259                 default:
6260                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6261                 }
6262                 GL_LockArrays(0, 0);
6263         }
6264         CHECKGLERROR
6265         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6266         {
6267                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6268                 GL_AlphaTest(false);
6269         }
6270 }
6271
6272 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6273 {
6274         // OpenGL 1.1 - crusty old voodoo path
6275         int texturesurfaceindex;
6276         qboolean applyfog;
6277         rmeshstate_t m;
6278         int layerindex;
6279         const texturelayer_t *layer;
6280         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6281
6282         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6283         {
6284                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6285                 {
6286                         if (layerindex == 0)
6287                                 GL_AlphaTest(true);
6288                         else
6289                         {
6290                                 GL_AlphaTest(false);
6291                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6292                         }
6293                 }
6294                 GL_DepthMask(layer->depthmask && writedepth);
6295                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6296                 R_Mesh_ColorPointer(NULL, 0, 0);
6297                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6298                 switch (layer->type)
6299                 {
6300                 case TEXTURELAYERTYPE_LITTEXTURE:
6301                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
6302                         {
6303                                 // two-pass lit texture with 2x rgbscale
6304                                 // first the lightmap pass
6305                                 memset(&m, 0, sizeof(m));
6306                                 m.tex[0] = R_GetTexture(r_texture_white);
6307                                 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6308                                 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6309                                 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6310                                 R_Mesh_TextureState(&m);
6311                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6312                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6313                                 else if (rsurface.uselightmaptexture)
6314                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6315                                 else
6316                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6317                                 GL_LockArrays(0, 0);
6318                                 // then apply the texture to it
6319                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6320                                 memset(&m, 0, sizeof(m));
6321                                 m.tex[0] = R_GetTexture(layer->texture);
6322                                 m.texmatrix[0] = layer->texmatrix;
6323                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6324                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6325                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6326                                 R_Mesh_TextureState(&m);
6327                                 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);
6328                         }
6329                         else
6330                         {
6331                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6332                                 memset(&m, 0, sizeof(m));
6333                                 m.tex[0] = R_GetTexture(layer->texture);
6334                                 m.texmatrix[0] = layer->texmatrix;
6335                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6336                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6337                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6338                                 R_Mesh_TextureState(&m);
6339                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6340                                         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);
6341                                 else
6342                                         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);
6343                         }
6344                         break;
6345                 case TEXTURELAYERTYPE_TEXTURE:
6346                         // singletexture unlit texture with transparency support
6347                         memset(&m, 0, sizeof(m));
6348                         m.tex[0] = R_GetTexture(layer->texture);
6349                         m.texmatrix[0] = layer->texmatrix;
6350                         m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6351                         m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6352                         m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6353                         R_Mesh_TextureState(&m);
6354                         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);
6355                         break;
6356                 case TEXTURELAYERTYPE_FOG:
6357                         // singletexture fogging
6358                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6359                         if (layer->texture)
6360                         {
6361                                 memset(&m, 0, sizeof(m));
6362                                 m.tex[0] = R_GetTexture(layer->texture);
6363                                 m.texmatrix[0] = layer->texmatrix;
6364                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6365                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6366                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6367                                 R_Mesh_TextureState(&m);
6368                         }
6369                         else
6370                                 R_Mesh_ResetTextureState();
6371                         // generate a color array for the fog pass
6372                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6373                         {
6374                                 int i;
6375                                 float f, *v, *c;
6376                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6377                                 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)
6378                                 {
6379                                         f = 1 - FogPoint_Model(v);
6380                                         c[0] = layer->color[0];
6381                                         c[1] = layer->color[1];
6382                                         c[2] = layer->color[2];
6383                                         c[3] = f * layer->color[3];
6384                                 }
6385                         }
6386                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6387                         break;
6388                 default:
6389                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6390                 }
6391                 GL_LockArrays(0, 0);
6392         }
6393         CHECKGLERROR
6394         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6395         {
6396                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6397                 GL_AlphaTest(false);
6398         }
6399 }
6400
6401 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6402 {
6403         CHECKGLERROR
6404         RSurf_SetupDepthAndCulling();
6405         if (r_glsl.integer && gl_support_fragment_shader)
6406                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6407         else if (gl_combine.integer && r_textureunits.integer >= 2)
6408                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6409         else
6410                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6411         CHECKGLERROR
6412 }
6413
6414 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6415 {
6416         int i, j;
6417         int texturenumsurfaces, endsurface;
6418         texture_t *texture;
6419         msurface_t *surface;
6420         msurface_t *texturesurfacelist[1024];
6421
6422         // if the model is static it doesn't matter what value we give for
6423         // wantnormals and wanttangents, so this logic uses only rules applicable
6424         // to a model, knowing that they are meaningless otherwise
6425         if (ent == r_refdef.scene.worldentity)
6426                 RSurf_ActiveWorldEntity();
6427         else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6428                 RSurf_ActiveModelEntity(ent, false, false);
6429         else
6430                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6431
6432         for (i = 0;i < numsurfaces;i = j)
6433         {
6434                 j = i + 1;
6435                 surface = rsurface.modelsurfaces + surfacelist[i];
6436                 texture = surface->texture;
6437                 R_UpdateTextureInfo(ent, texture);
6438                 rsurface.texture = texture->currentframe;
6439                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6440                 // scan ahead until we find a different texture
6441                 endsurface = min(i + 1024, numsurfaces);
6442                 texturenumsurfaces = 0;
6443                 texturesurfacelist[texturenumsurfaces++] = surface;
6444                 for (;j < endsurface;j++)
6445                 {
6446                         surface = rsurface.modelsurfaces + surfacelist[j];
6447                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6448                                 break;
6449                         texturesurfacelist[texturenumsurfaces++] = surface;
6450                 }
6451                 // render the range of surfaces
6452                 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6453         }
6454         GL_AlphaTest(false);
6455 }
6456
6457 static void R_ProcessTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
6458 {
6459         CHECKGLERROR
6460         if (depthonly)
6461         {
6462                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6463                         return;
6464                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6465                         return;
6466                 RSurf_SetupDepthAndCulling();
6467                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6468                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6469         }
6470         else if (r_showsurfaces.integer)
6471         {
6472                 RSurf_SetupDepthAndCulling();
6473                 GL_DepthTest(true);
6474                 GL_BlendFunc(GL_ONE, GL_ZERO);
6475                 GL_DepthMask(true);
6476                 GL_AlphaTest(false);
6477                 R_Mesh_ColorPointer(NULL, 0, 0);
6478                 R_Mesh_ResetTextureState();
6479                 R_SetupGenericShader(false);
6480                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6481                 if (!r_refdef.view.showdebug)
6482                 {
6483                         GL_Color(0, 0, 0, 1);
6484                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6485                 }
6486                 else if (r_showsurfaces.integer == 3)
6487                 {
6488                         const float cbase[4] = {1, 0, 1, 1};
6489                         const float *c = cbase;
6490                         if(rsurface.texture && rsurface.texture->currentskinframe)
6491                                 c = rsurface.texture->currentskinframe->avgcolor;
6492                         GL_Color(c[0], c[1], c[2], c[3]);
6493                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6494                         // TODO how to apply vertex light here?
6495                 }
6496                 else 
6497                         RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6498         }
6499         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6500                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6501         else if (!rsurface.texture->currentnumlayers)
6502                 return;
6503         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) && queueentity)
6504         {
6505                 // transparent surfaces get pushed off into the transparent queue
6506                 int surfacelistindex;
6507                 const msurface_t *surface;
6508                 vec3_t tempcenter, center;
6509                 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6510                 {
6511                         surface = texturesurfacelist[surfacelistindex];
6512                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6513                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6514                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6515                         Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6516                         R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6517                 }
6518         }
6519         else
6520         {
6521                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6522                 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6523         }
6524         CHECKGLERROR
6525 }
6526
6527 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
6528 {
6529         int i, j;
6530         texture_t *texture;
6531         // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
6532         if (addwaterplanes)
6533         {
6534                 for (i = 0;i < numsurfaces;i++)
6535                         if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
6536                                 R_Water_AddWaterPlane(surfacelist[i]);
6537                 return;
6538         }
6539         // break the surface list down into batches by texture and use of lightmapping
6540         for (i = 0;i < numsurfaces;i = j)
6541         {
6542                 j = i + 1;
6543                 // texture is the base texture pointer, rsurface.texture is the
6544                 // current frame/skin the texture is directing us to use (for example
6545                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6546                 // use skin 1 instead)
6547                 texture = surfacelist[i]->texture;
6548                 rsurface.texture = texture->currentframe;
6549                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6550                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6551                 {
6552                         // if this texture is not the kind we want, skip ahead to the next one
6553                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6554                                 ;
6555                         continue;
6556                 }
6557                 // simply scan ahead until we find a different texture or lightmap state
6558                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6559                         ;
6560                 // render the range of surfaces
6561                 R_ProcessTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
6562         }
6563 }
6564
6565 float locboxvertex3f[6*4*3] =
6566 {
6567         1,0,1, 1,0,0, 1,1,0, 1,1,1,
6568         0,1,1, 0,1,0, 0,0,0, 0,0,1,
6569         1,1,1, 1,1,0, 0,1,0, 0,1,1,
6570         0,0,1, 0,0,0, 1,0,0, 1,0,1,
6571         0,0,1, 1,0,1, 1,1,1, 0,1,1,
6572         1,0,0, 0,0,0, 0,1,0, 1,1,0
6573 };
6574
6575 unsigned short locboxelements[6*2*3] =
6576 {
6577          0, 1, 2, 0, 2, 3,
6578          4, 5, 6, 4, 6, 7,
6579          8, 9,10, 8,10,11,
6580         12,13,14, 12,14,15,
6581         16,17,18, 16,18,19,
6582         20,21,22, 20,22,23
6583 };
6584
6585 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6586 {
6587         int i, j;
6588         cl_locnode_t *loc = (cl_locnode_t *)ent;
6589         vec3_t mins, size;
6590         float vertex3f[6*4*3];
6591         CHECKGLERROR
6592         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6593         GL_DepthMask(false);
6594         GL_DepthRange(0, 1);
6595         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6596         GL_DepthTest(true);
6597         GL_CullFace(GL_NONE);
6598         R_Mesh_Matrix(&identitymatrix);
6599
6600         R_Mesh_VertexPointer(vertex3f, 0, 0);
6601         R_Mesh_ColorPointer(NULL, 0, 0);
6602         R_Mesh_ResetTextureState();
6603         R_SetupGenericShader(false);
6604
6605         i = surfacelist[0];
6606         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6607                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6608                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6609                         surfacelist[0] < 0 ? 0.5f : 0.125f);
6610
6611         if (VectorCompare(loc->mins, loc->maxs))
6612         {
6613                 VectorSet(size, 2, 2, 2);
6614                 VectorMA(loc->mins, -0.5f, size, mins);
6615         }
6616         else
6617         {
6618                 VectorCopy(loc->mins, mins);
6619                 VectorSubtract(loc->maxs, loc->mins, size);
6620         }
6621
6622         for (i = 0;i < 6*4*3;)
6623                 for (j = 0;j < 3;j++, i++)
6624                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6625
6626         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
6627 }
6628
6629 void R_DrawLocs(void)
6630 {
6631         int index;
6632         cl_locnode_t *loc, *nearestloc;
6633         vec3_t center;
6634         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6635         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6636         {
6637                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6638                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6639         }
6640 }
6641
6642 void R_DrawDebugModel(entity_render_t *ent)
6643 {
6644         int i, j, k, l, flagsmask;
6645         const int *elements;
6646         q3mbrush_t *brush;
6647         msurface_t *surface;
6648         dp_model_t *model = ent->model;
6649         vec3_t v;
6650
6651         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
6652
6653         R_Mesh_ColorPointer(NULL, 0, 0);
6654         R_Mesh_ResetTextureState();
6655         R_SetupGenericShader(false);
6656         GL_DepthRange(0, 1);
6657         GL_DepthTest(!r_showdisabledepthtest.integer);
6658         GL_DepthMask(false);
6659         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6660
6661         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6662         {
6663                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6664                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6665                 {
6666                         if (brush->colbrushf && brush->colbrushf->numtriangles)
6667                         {
6668                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6669                                 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);
6670                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
6671                         }
6672                 }
6673                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6674                 {
6675                         if (surface->num_collisiontriangles)
6676                         {
6677                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6678                                 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);
6679                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
6680                         }
6681                 }
6682         }
6683
6684         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6685
6686         if (r_showtris.integer || r_shownormals.integer)
6687         {
6688                 if (r_showdisabledepthtest.integer)
6689                 {
6690                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6691                         GL_DepthMask(false);
6692                 }
6693                 else
6694                 {
6695                         GL_BlendFunc(GL_ONE, GL_ZERO);
6696                         GL_DepthMask(true);
6697                 }
6698                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6699                 {
6700                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
6701                                 continue;
6702                         rsurface.texture = surface->texture->currentframe;
6703                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6704                         {
6705                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6706                                 if (r_showtris.value > 0)
6707                                 {
6708                                         if (!rsurface.texture->currentlayers->depthmask)
6709                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
6710                                         else if (ent == r_refdef.scene.worldentity)
6711                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
6712                                         else
6713                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
6714                                         elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6715                                         CHECKGLERROR
6716                                         qglBegin(GL_LINES);
6717                                         for (k = 0;k < surface->num_triangles;k++, elements += 3)
6718                                         {
6719 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6720                                                 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6721                                                 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6722                                                 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6723                                         }
6724                                         qglEnd();
6725                                         CHECKGLERROR
6726                                 }
6727                                 if (r_shownormals.value > 0)
6728                                 {
6729                                         qglBegin(GL_LINES);
6730                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6731                                         {
6732                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
6733                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
6734                                                 qglVertex3f(v[0], v[1], v[2]);
6735                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
6736                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6737                                                 qglVertex3f(v[0], v[1], v[2]);
6738                                         }
6739                                         qglEnd();
6740                                         CHECKGLERROR
6741                                         qglBegin(GL_LINES);
6742                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6743                                         {
6744                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
6745                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
6746                                                 qglVertex3f(v[0], v[1], v[2]);
6747                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
6748                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6749                                                 qglVertex3f(v[0], v[1], v[2]);
6750                                         }
6751                                         qglEnd();
6752                                         CHECKGLERROR
6753                                         qglBegin(GL_LINES);
6754                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6755                                         {
6756                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
6757                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
6758                                                 qglVertex3f(v[0], v[1], v[2]);
6759                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
6760                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6761                                                 qglVertex3f(v[0], v[1], v[2]);
6762                                         }
6763                                         qglEnd();
6764                                         CHECKGLERROR
6765                                 }
6766                         }
6767                 }
6768                 rsurface.texture = NULL;
6769         }
6770 }
6771
6772 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6773 int r_maxsurfacelist = 0;
6774 msurface_t **r_surfacelist = NULL;
6775 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6776 {
6777         int i, j, endj, f, flagsmask;
6778         texture_t *t;
6779         dp_model_t *model = r_refdef.scene.worldmodel;
6780         msurface_t *surfaces;
6781         unsigned char *update;
6782         int numsurfacelist = 0;
6783         if (model == NULL)
6784                 return;
6785
6786         if (r_maxsurfacelist < model->num_surfaces)
6787         {
6788                 r_maxsurfacelist = model->num_surfaces;
6789                 if (r_surfacelist)
6790                         Mem_Free(r_surfacelist);
6791                 r_surfacelist = Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
6792         }
6793
6794         RSurf_ActiveWorldEntity();
6795
6796         surfaces = model->data_surfaces;
6797         update = model->brushq1.lightmapupdateflags;
6798
6799         // update light styles on this submodel
6800         if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6801         {
6802                 model_brush_lightstyleinfo_t *style;
6803                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6804                 {
6805                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
6806                         {
6807                                 int *list = style->surfacelist;
6808                                 style->value = r_refdef.scene.lightstylevalue[style->style];
6809                                 for (j = 0;j < style->numsurfaces;j++)
6810                                         update[list[j]] = true;
6811                         }
6812                 }
6813         }
6814
6815         R_UpdateAllTextureInfo(r_refdef.scene.worldentity);
6816         flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL);
6817
6818         if (debug)
6819         {
6820                 R_DrawDebugModel(r_refdef.scene.worldentity);
6821                 return;
6822         }
6823
6824         f = 0;
6825         t = NULL;
6826         rsurface.uselightmaptexture = false;
6827         rsurface.texture = NULL;
6828         rsurface.rtlight = NULL;
6829         numsurfacelist = 0;
6830         // add visible surfaces to draw list
6831         j = model->firstmodelsurface;
6832         endj = j + model->nummodelsurfaces;
6833         if (update)
6834         {
6835                 for (;j < endj;j++)
6836                 {
6837                         if (r_refdef.viewcache.world_surfacevisible[j])
6838                         {
6839                                 r_surfacelist[numsurfacelist++] = surfaces + j;
6840                                 // update lightmap if needed
6841                                 if (update[j])
6842                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
6843                         }
6844                 }
6845         }
6846         else
6847                 for (;j < endj;j++)
6848                         if (r_refdef.viewcache.world_surfacevisible[j])
6849                                 r_surfacelist[numsurfacelist++] = surfaces + j;
6850         // don't do anything if there were no surfaces
6851         if (!numsurfacelist)
6852                 return;
6853         R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6854         GL_AlphaTest(false);
6855
6856         // add to stats if desired
6857         if (r_speeds.integer && !skysurfaces && !depthonly && !addwaterplanes)
6858         {
6859                 r_refdef.stats.world_surfaces += numsurfacelist;
6860                 for (j = 0;j < numsurfacelist;j++)
6861                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
6862         }
6863 }
6864
6865 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6866 {
6867         int i, j, endj, f, flagsmask;
6868         texture_t *t;
6869         dp_model_t *model = ent->model;
6870         msurface_t *surfaces;
6871         unsigned char *update;
6872         int numsurfacelist = 0;
6873         if (model == NULL)
6874                 return;
6875
6876         if (r_maxsurfacelist < model->num_surfaces)
6877         {
6878                 r_maxsurfacelist = model->num_surfaces;
6879                 if (r_surfacelist)
6880                         Mem_Free(r_surfacelist);
6881                 r_surfacelist = Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
6882         }
6883
6884         // if the model is static it doesn't matter what value we give for
6885         // wantnormals and wanttangents, so this logic uses only rules applicable
6886         // to a model, knowing that they are meaningless otherwise
6887         if (ent == r_refdef.scene.worldentity)
6888                 RSurf_ActiveWorldEntity();
6889         else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6890                 RSurf_ActiveModelEntity(ent, false, false);
6891         else
6892                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6893
6894         surfaces = model->data_surfaces;
6895         update = model->brushq1.lightmapupdateflags;
6896
6897         // update light styles
6898         if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6899         {
6900                 model_brush_lightstyleinfo_t *style;
6901                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6902                 {
6903                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
6904                         {
6905                                 int *list = style->surfacelist;
6906                                 style->value = r_refdef.scene.lightstylevalue[style->style];
6907                                 for (j = 0;j < style->numsurfaces;j++)
6908                                         update[list[j]] = true;
6909                         }
6910                 }
6911         }
6912
6913         R_UpdateAllTextureInfo(ent);
6914         flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL);
6915
6916         if (debug)
6917         {
6918                 R_DrawDebugModel(ent);
6919                 return;
6920         }
6921
6922         f = 0;
6923         t = NULL;
6924         rsurface.uselightmaptexture = false;
6925         rsurface.texture = NULL;
6926         rsurface.rtlight = NULL;
6927         numsurfacelist = 0;
6928         // add visible surfaces to draw list
6929         j = model->firstmodelsurface;
6930         endj = j + model->nummodelsurfaces;
6931         for (;j < endj;j++)
6932                 r_surfacelist[numsurfacelist++] = surfaces + j;
6933         // don't do anything if there were no surfaces
6934         if (!numsurfacelist)
6935                 return;
6936         // update lightmaps if needed
6937         if (update)
6938                 for (j = model->firstmodelsurface;j < endj;j++)
6939                         if (update[j])
6940                                 R_BuildLightMap(ent, surfaces + j);
6941         R_QueueSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6942         GL_AlphaTest(false);
6943
6944         // add to stats if desired
6945         if (r_speeds.integer && !skysurfaces && !depthonly && !addwaterplanes)
6946         {
6947                 r_refdef.stats.entities++;
6948                 r_refdef.stats.entities_surfaces += numsurfacelist;
6949                 for (j = 0;j < numsurfacelist;j++)
6950                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
6951         }
6952 }