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