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