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