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