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