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