]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
refactored and reformatted animcache code, now generates caches on
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
30
31 static int r_frame = 0; ///< used only by R_GetCurrentTexture
32
33 //
34 // screen size info
35 //
36 r_refdef_t r_refdef;
37
38 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
39 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
40 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
41 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
42 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
43 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
44 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
45 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
46 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 //==================================================================================
2779
2780 static void R_View_UpdateEntityLighting (void)
2781 {
2782         int i;
2783         entity_render_t *ent;
2784         vec3_t tempdiffusenormal;
2785
2786         for (i = 0;i < r_refdef.scene.numentities;i++)
2787         {
2788                 ent = r_refdef.scene.entities[i];
2789
2790                 // skip unseen models
2791                 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
2792                         continue;
2793
2794                 // skip bsp models
2795                 if (ent->model && ent->model->brush.num_leafs)
2796                 {
2797                         // TODO: use modellight for r_ambient settings on world?
2798                         VectorSet(ent->modellight_ambient, 0, 0, 0);
2799                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
2800                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
2801                         continue;
2802                 }
2803
2804                 // fetch the lighting from the worldmodel data
2805                 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));
2806                 VectorClear(ent->modellight_diffuse);
2807                 VectorClear(tempdiffusenormal);
2808                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
2809                 {
2810                         vec3_t org;
2811                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2812                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
2813                 }
2814                 else // highly rare
2815                         VectorSet(ent->modellight_ambient, 1, 1, 1);
2816
2817                 // move the light direction into modelspace coordinates for lighting code
2818                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
2819                 if(VectorLength2(ent->modellight_lightdir) == 0)
2820                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
2821                 VectorNormalize(ent->modellight_lightdir);
2822         }
2823 }
2824
2825 static void R_View_UpdateEntityVisible (void)
2826 {
2827         int i, renderimask;
2828         entity_render_t *ent;
2829
2830         if (!r_drawentities.integer)
2831                 return;
2832
2833         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2834         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2835         {
2836                 // worldmodel can check visibility
2837                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
2838                 for (i = 0;i < r_refdef.scene.numentities;i++)
2839                 {
2840                         ent = r_refdef.scene.entities[i];
2841                         if (!(ent->flags & renderimask))
2842                         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)))
2843                         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))
2844                                 r_refdef.viewcache.entityvisible[i] = true;
2845                 }
2846                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2847                 {
2848                         for (i = 0;i < r_refdef.scene.numentities;i++)
2849                         {
2850                                 ent = r_refdef.scene.entities[i];
2851                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2852                                 {
2853                                         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))
2854                                                 ent->last_trace_visibility = realtime;
2855                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2856                                                 r_refdef.viewcache.entityvisible[i] = 0;
2857                                 }
2858                         }
2859                 }
2860         }
2861         else
2862         {
2863                 // no worldmodel or it can't check visibility
2864                 for (i = 0;i < r_refdef.scene.numentities;i++)
2865                 {
2866                         ent = r_refdef.scene.entities[i];
2867                         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));
2868                 }
2869         }
2870 }
2871
2872 /// only used if skyrendermasked, and normally returns false
2873 int R_DrawBrushModelsSky (void)
2874 {
2875         int i, sky;
2876         entity_render_t *ent;
2877
2878         if (!r_drawentities.integer)
2879                 return false;
2880
2881         sky = false;
2882         for (i = 0;i < r_refdef.scene.numentities;i++)
2883         {
2884                 if (!r_refdef.viewcache.entityvisible[i])
2885                         continue;
2886                 ent = r_refdef.scene.entities[i];
2887                 if (!ent->model || !ent->model->DrawSky)
2888                         continue;
2889                 ent->model->DrawSky(ent);
2890                 sky = true;
2891         }
2892         return sky;
2893 }
2894
2895 static void R_DrawNoModel(entity_render_t *ent);
2896 static void R_DrawModels(void)
2897 {
2898         int i;
2899         entity_render_t *ent;
2900
2901         if (!r_drawentities.integer)
2902                 return;
2903
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                 r_refdef.stats.entities++;
2910                 if (ent->model && ent->model->Draw != NULL)
2911                         ent->model->Draw(ent);
2912                 else
2913                         R_DrawNoModel(ent);
2914         }
2915 }
2916
2917 static void R_DrawModelsDepth(void)
2918 {
2919         int i;
2920         entity_render_t *ent;
2921
2922         if (!r_drawentities.integer)
2923                 return;
2924
2925         for (i = 0;i < r_refdef.scene.numentities;i++)
2926         {
2927                 if (!r_refdef.viewcache.entityvisible[i])
2928                         continue;
2929                 ent = r_refdef.scene.entities[i];
2930                 if (ent->model && ent->model->DrawDepth != NULL)
2931                         ent->model->DrawDepth(ent);
2932         }
2933 }
2934
2935 static void R_DrawModelsDebug(void)
2936 {
2937         int i;
2938         entity_render_t *ent;
2939
2940         if (!r_drawentities.integer)
2941                 return;
2942
2943         for (i = 0;i < r_refdef.scene.numentities;i++)
2944         {
2945                 if (!r_refdef.viewcache.entityvisible[i])
2946                         continue;
2947                 ent = r_refdef.scene.entities[i];
2948                 if (ent->model && ent->model->DrawDebug != NULL)
2949                         ent->model->DrawDebug(ent);
2950         }
2951 }
2952
2953 static void R_DrawModelsAddWaterPlanes(void)
2954 {
2955         int i;
2956         entity_render_t *ent;
2957
2958         if (!r_drawentities.integer)
2959                 return;
2960
2961         for (i = 0;i < r_refdef.scene.numentities;i++)
2962         {
2963                 if (!r_refdef.viewcache.entityvisible[i])
2964                         continue;
2965                 ent = r_refdef.scene.entities[i];
2966                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2967                         ent->model->DrawAddWaterPlanes(ent);
2968         }
2969 }
2970
2971 static void R_View_SetFrustum(void)
2972 {
2973         int i;
2974         double slopex, slopey;
2975         vec3_t forward, left, up, origin;
2976
2977         // we can't trust r_refdef.view.forward and friends in reflected scenes
2978         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
2979
2980 #if 0
2981         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2982         r_refdef.view.frustum[0].normal[1] = 0 - 0;
2983         r_refdef.view.frustum[0].normal[2] = -1 - 0;
2984         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2985         r_refdef.view.frustum[1].normal[1] = 0 + 0;
2986         r_refdef.view.frustum[1].normal[2] = -1 + 0;
2987         r_refdef.view.frustum[2].normal[0] = 0 - 0;
2988         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2989         r_refdef.view.frustum[2].normal[2] = -1 - 0;
2990         r_refdef.view.frustum[3].normal[0] = 0 + 0;
2991         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2992         r_refdef.view.frustum[3].normal[2] = -1 + 0;
2993 #endif
2994
2995 #if 0
2996         zNear = r_refdef.nearclip;
2997         nudge = 1.0 - 1.0 / (1<<23);
2998         r_refdef.view.frustum[4].normal[0] = 0 - 0;
2999         r_refdef.view.frustum[4].normal[1] = 0 - 0;
3000         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3001         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3002         r_refdef.view.frustum[5].normal[0] = 0 + 0;
3003         r_refdef.view.frustum[5].normal[1] = 0 + 0;
3004         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3005         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3006 #endif
3007
3008
3009
3010 #if 0
3011         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3012         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3013         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3014         r_refdef.view.frustum[0].dist = m[15] - m[12];
3015
3016         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3017         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3018         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3019         r_refdef.view.frustum[1].dist = m[15] + m[12];
3020
3021         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3022         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3023         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3024         r_refdef.view.frustum[2].dist = m[15] - m[13];
3025
3026         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3027         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3028         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3029         r_refdef.view.frustum[3].dist = m[15] + m[13];
3030
3031         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3032         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3033         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3034         r_refdef.view.frustum[4].dist = m[15] - m[14];
3035
3036         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3037         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3038         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3039         r_refdef.view.frustum[5].dist = m[15] + m[14];
3040 #endif
3041
3042         if (r_refdef.view.useperspective)
3043         {
3044                 slopex = 1.0 / r_refdef.view.frustum_x;
3045                 slopey = 1.0 / r_refdef.view.frustum_y;
3046                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3047                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
3048                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
3049                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
3050                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3051
3052                 // Leaving those out was a mistake, those were in the old code, and they
3053                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3054                 // I couldn't reproduce it after adding those normalizations. --blub
3055                 VectorNormalize(r_refdef.view.frustum[0].normal);
3056                 VectorNormalize(r_refdef.view.frustum[1].normal);
3057                 VectorNormalize(r_refdef.view.frustum[2].normal);
3058                 VectorNormalize(r_refdef.view.frustum[3].normal);
3059
3060                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3061                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
3062                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
3063                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left,  1024 * slopey, up, r_refdef.view.frustumcorner[2]);
3064                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * slopex, left,  1024 * slopey, up, r_refdef.view.frustumcorner[3]);
3065
3066                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3067                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3068                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3069                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3070                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3071         }
3072         else
3073         {
3074                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3075                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3076                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3077                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3078                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3079                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3080                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3081                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3082                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3083                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3084         }
3085         r_refdef.view.numfrustumplanes = 5;
3086
3087         if (r_refdef.view.useclipplane)
3088         {
3089                 r_refdef.view.numfrustumplanes = 6;
3090                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3091         }
3092
3093         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3094                 PlaneClassify(r_refdef.view.frustum + i);
3095
3096         // LordHavoc: note to all quake engine coders, Quake had a special case
3097         // for 90 degrees which assumed a square view (wrong), so I removed it,
3098         // Quake2 has it disabled as well.
3099
3100         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3101         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3102         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3103         //PlaneClassify(&frustum[0]);
3104
3105         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3106         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3107         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3108         //PlaneClassify(&frustum[1]);
3109
3110         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3111         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3112         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3113         //PlaneClassify(&frustum[2]);
3114
3115         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3116         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3117         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3118         //PlaneClassify(&frustum[3]);
3119
3120         // nearclip plane
3121         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3122         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3123         //PlaneClassify(&frustum[4]);
3124 }
3125
3126 void R_View_Update(void)
3127 {
3128         R_View_SetFrustum();
3129         R_View_WorldVisibility(r_refdef.view.useclipplane);
3130         R_View_UpdateEntityVisible();
3131         R_View_UpdateEntityLighting();
3132 }
3133
3134 void R_SetupView(qboolean allowwaterclippingplane)
3135 {
3136         if (!r_refdef.view.useperspective)
3137                 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);
3138         else if (gl_stencil && r_useinfinitefarclip.integer)
3139                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
3140         else
3141                 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
3142
3143         GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
3144
3145         if (r_refdef.view.useclipplane && allowwaterclippingplane)
3146         {
3147                 // LordHavoc: couldn't figure out how to make this approach the
3148                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3149                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3150                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3151                         dist = r_refdef.view.clipplane.dist;
3152                 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
3153         }
3154 }
3155
3156 void R_ResetViewRendering2D(void)
3157 {
3158         DrawQ_Finish();
3159
3160         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3161         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3162         GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
3163         GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
3164         GL_Color(1, 1, 1, 1);
3165         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3166         GL_BlendFunc(GL_ONE, GL_ZERO);
3167         GL_AlphaTest(false);
3168         GL_ScissorTest(false);
3169         GL_DepthMask(false);
3170         GL_DepthRange(0, 1);
3171         GL_DepthTest(false);
3172         R_Mesh_Matrix(&identitymatrix);
3173         R_Mesh_ResetTextureState();
3174         GL_PolygonOffset(0, 0);
3175         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3176         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3177         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3178         qglStencilMask(~0);CHECKGLERROR
3179         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3180         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3181         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3182         R_SetupGenericShader(true);
3183 }
3184
3185 void R_ResetViewRendering3D(void)
3186 {
3187         DrawQ_Finish();
3188
3189         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3190         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3191         R_SetupView(true);
3192         GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
3193         GL_Color(1, 1, 1, 1);
3194         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3195         GL_BlendFunc(GL_ONE, GL_ZERO);
3196         GL_AlphaTest(false);
3197         GL_ScissorTest(true);
3198         GL_DepthMask(true);
3199         GL_DepthRange(0, 1);
3200         GL_DepthTest(true);
3201         R_Mesh_Matrix(&identitymatrix);
3202         R_Mesh_ResetTextureState();
3203         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3204         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3205         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3206         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3207         qglStencilMask(~0);CHECKGLERROR
3208         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3209         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3210         GL_CullFace(r_refdef.view.cullface_back);
3211         R_SetupGenericShader(true);
3212 }
3213
3214 void R_RenderScene(void);
3215 void R_RenderWaterPlanes(void);
3216
3217 static void R_Water_StartFrame(void)
3218 {
3219         int i;
3220         int waterwidth, waterheight, texturewidth, textureheight;
3221         r_waterstate_waterplane_t *p;
3222
3223         // set waterwidth and waterheight to the water resolution that will be
3224         // used (often less than the screen resolution for faster rendering)
3225         waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3226         waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3227
3228         // calculate desired texture sizes
3229         // can't use water if the card does not support the texture size
3230         if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3231                 texturewidth = textureheight = waterwidth = waterheight = 0;
3232         else if (gl_support_arb_texture_non_power_of_two)
3233         {
3234                 texturewidth = waterwidth;
3235                 textureheight = waterheight;
3236         }
3237         else
3238         {
3239                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
3240                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
3241         }
3242
3243         // allocate textures as needed
3244         if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3245         {
3246                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3247                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3248                 {
3249                         if (p->texture_refraction)
3250                                 R_FreeTexture(p->texture_refraction);
3251                         p->texture_refraction = NULL;
3252                         if (p->texture_reflection)
3253                                 R_FreeTexture(p->texture_reflection);
3254                         p->texture_reflection = NULL;
3255                 }
3256                 memset(&r_waterstate, 0, sizeof(r_waterstate));
3257                 r_waterstate.waterwidth = waterwidth;
3258                 r_waterstate.waterheight = waterheight;
3259                 r_waterstate.texturewidth = texturewidth;
3260                 r_waterstate.textureheight = textureheight;
3261         }
3262
3263         if (r_waterstate.waterwidth)
3264         {
3265                 r_waterstate.enabled = true;
3266
3267                 // set up variables that will be used in shader setup
3268                 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3269                 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
3270                 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3271                 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
3272         }
3273
3274         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3275         r_waterstate.numwaterplanes = 0;
3276 }
3277
3278 void R_Water_AddWaterPlane(msurface_t *surface)
3279 {
3280         int triangleindex, planeindex;
3281         const int *e;
3282         vec3_t vert[3];
3283         vec3_t normal;
3284         vec3_t center;
3285         mplane_t plane;
3286         r_waterstate_waterplane_t *p;
3287         texture_t *t = R_GetCurrentTexture(surface->texture);
3288         // just use the first triangle with a valid normal for any decisions
3289         VectorClear(normal);
3290         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3291         {
3292                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3293                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3294                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3295                 TriangleNormal(vert[0], vert[1], vert[2], normal);
3296                 if (VectorLength2(normal) >= 0.001)
3297                         break;
3298         }
3299
3300         VectorCopy(normal, plane.normal);
3301         VectorNormalize(plane.normal);
3302         plane.dist = DotProduct(vert[0], plane.normal);
3303         PlaneClassify(&plane);
3304         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3305         {
3306                 // skip backfaces (except if nocullface is set)
3307                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3308                         return;
3309                 VectorNegate(plane.normal, plane.normal);
3310                 plane.dist *= -1;
3311                 PlaneClassify(&plane);
3312         }
3313
3314
3315         // find a matching plane if there is one
3316         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3317                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3318                         break;
3319         if (planeindex >= r_waterstate.maxwaterplanes)
3320                 return; // nothing we can do, out of planes
3321
3322         // if this triangle does not fit any known plane rendered this frame, add one
3323         if (planeindex >= r_waterstate.numwaterplanes)
3324         {
3325                 // store the new plane
3326                 r_waterstate.numwaterplanes++;
3327                 p->plane = plane;
3328                 // clear materialflags and pvs
3329                 p->materialflags = 0;
3330                 p->pvsvalid = false;
3331         }
3332         // merge this surface's materialflags into the waterplane
3333         p->materialflags |= t->currentmaterialflags;
3334         // merge this surface's PVS into the waterplane
3335         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3336         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3337          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3338         {
3339                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3340                 p->pvsvalid = true;
3341         }
3342 }
3343
3344 static void R_Water_ProcessPlanes(void)
3345 {
3346         r_refdef_view_t originalview;
3347         r_refdef_view_t myview;
3348         int planeindex;
3349         r_waterstate_waterplane_t *p;
3350
3351         originalview = r_refdef.view;
3352
3353         // make sure enough textures are allocated
3354         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3355         {
3356                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3357                 {
3358                         if (!p->texture_refraction)
3359                                 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);
3360                         if (!p->texture_refraction)
3361                                 goto error;
3362                 }
3363
3364                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3365                 {
3366                         if (!p->texture_reflection)
3367                                 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);
3368                         if (!p->texture_reflection)
3369                                 goto error;
3370                 }
3371         }
3372
3373         // render views
3374         r_refdef.view = originalview;
3375         r_refdef.view.showdebug = false;
3376         r_refdef.view.width = r_waterstate.waterwidth;
3377         r_refdef.view.height = r_waterstate.waterheight;
3378         r_refdef.view.useclipplane = true;
3379         myview = r_refdef.view;
3380         r_waterstate.renderingscene = true;
3381         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3382         {
3383                 // render the normal view scene and copy into texture
3384                 // (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)
3385                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3386                 {
3387                         r_refdef.view = myview;
3388                         r_refdef.view.clipplane = p->plane;
3389                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3390                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3391                         PlaneClassify(&r_refdef.view.clipplane);
3392
3393                         R_ResetViewRendering3D();
3394                         R_ClearScreen(r_refdef.fogenabled);
3395                         R_View_Update();
3396                         R_RenderScene();
3397
3398                         // copy view into the screen texture
3399                         R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3400                         GL_ActiveTexture(0);
3401                         CHECKGLERROR
3402                         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
3403                 }
3404
3405                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3406                 {
3407                         r_refdef.view = myview;
3408                         // render reflected scene and copy into texture
3409                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3410                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3411                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3412                         r_refdef.view.clipplane = p->plane;
3413                         // reverse the cullface settings for this render
3414                         r_refdef.view.cullface_front = GL_FRONT;
3415                         r_refdef.view.cullface_back = GL_BACK;
3416                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3417                         {
3418                                 r_refdef.view.usecustompvs = true;
3419                                 if (p->pvsvalid)
3420                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3421                                 else
3422                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3423                         }
3424
3425                         R_ResetViewRendering3D();
3426                         R_ClearScreen(r_refdef.fogenabled);
3427                         R_View_Update();
3428                         R_RenderScene();
3429
3430                         R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3431                         GL_ActiveTexture(0);
3432                         CHECKGLERROR
3433                         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
3434                 }
3435         }
3436         r_waterstate.renderingscene = false;
3437         r_refdef.view = originalview;
3438         R_ResetViewRendering3D();
3439         R_ClearScreen(r_refdef.fogenabled);
3440         R_View_Update();
3441         return;
3442 error:
3443         r_refdef.view = originalview;
3444         r_waterstate.renderingscene = false;
3445         Cvar_SetValueQuick(&r_water, 0);
3446         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
3447         return;
3448 }
3449
3450 void R_Bloom_StartFrame(void)
3451 {
3452         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3453
3454         // set bloomwidth and bloomheight to the bloom resolution that will be
3455         // used (often less than the screen resolution for faster rendering)
3456         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3457         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3458         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3459         r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3460         r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3461
3462         // calculate desired texture sizes
3463         if (gl_support_arb_texture_non_power_of_two)
3464         {
3465                 screentexturewidth = r_refdef.view.width;
3466                 screentextureheight = r_refdef.view.height;
3467                 bloomtexturewidth = r_bloomstate.bloomwidth;
3468                 bloomtextureheight = r_bloomstate.bloomheight;
3469         }
3470         else
3471         {
3472                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
3473                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
3474                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
3475                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
3476         }
3477
3478         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))
3479         {
3480                 Cvar_SetValueQuick(&r_hdr, 0);
3481                 Cvar_SetValueQuick(&r_bloom, 0);
3482                 Cvar_SetValueQuick(&r_motionblur, 0);
3483                 Cvar_SetValueQuick(&r_damageblur, 0);
3484         }
3485
3486         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)))
3487                 screentexturewidth = screentextureheight = 0;
3488         if (!r_hdr.integer && !r_bloom.integer)
3489                 bloomtexturewidth = bloomtextureheight = 0;
3490
3491         // allocate textures as needed
3492         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3493         {
3494                 if (r_bloomstate.texture_screen)
3495                         R_FreeTexture(r_bloomstate.texture_screen);
3496                 r_bloomstate.texture_screen = NULL;
3497                 r_bloomstate.screentexturewidth = screentexturewidth;
3498                 r_bloomstate.screentextureheight = screentextureheight;
3499                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3500                         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);
3501         }
3502         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3503         {
3504                 if (r_bloomstate.texture_bloom)
3505                         R_FreeTexture(r_bloomstate.texture_bloom);
3506                 r_bloomstate.texture_bloom = NULL;
3507                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3508                 r_bloomstate.bloomtextureheight = bloomtextureheight;
3509                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3510                         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);
3511         }
3512
3513         // set up a texcoord array for the full resolution screen image
3514         // (we have to keep this around to copy back during final render)
3515         r_bloomstate.screentexcoord2f[0] = 0;
3516         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
3517         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
3518         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
3519         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
3520         r_bloomstate.screentexcoord2f[5] = 0;
3521         r_bloomstate.screentexcoord2f[6] = 0;
3522         r_bloomstate.screentexcoord2f[7] = 0;
3523
3524         // set up a texcoord array for the reduced resolution bloom image
3525         // (which will be additive blended over the screen image)
3526         r_bloomstate.bloomtexcoord2f[0] = 0;
3527         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3528         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
3529         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3530         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
3531         r_bloomstate.bloomtexcoord2f[5] = 0;
3532         r_bloomstate.bloomtexcoord2f[6] = 0;
3533         r_bloomstate.bloomtexcoord2f[7] = 0;
3534
3535         if (r_hdr.integer || r_bloom.integer)
3536         {
3537                 r_bloomstate.enabled = true;
3538                 r_bloomstate.hdr = r_hdr.integer != 0;
3539         }
3540 }
3541
3542 void R_Bloom_CopyBloomTexture(float colorscale)
3543 {
3544         r_refdef.stats.bloom++;
3545
3546         // scale down screen texture to the bloom texture size
3547         CHECKGLERROR
3548         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3549         GL_BlendFunc(GL_ONE, GL_ZERO);
3550         GL_Color(colorscale, colorscale, colorscale, 1);
3551         // TODO: optimize with multitexture or GLSL
3552         R_SetupGenericShader(true);
3553         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3554         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3555         R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3556         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3557
3558         // we now have a bloom image in the framebuffer
3559         // copy it into the bloom image texture for later processing
3560         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3561         GL_ActiveTexture(0);
3562         CHECKGLERROR
3563         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
3564         r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3565 }
3566
3567 void R_Bloom_CopyHDRTexture(void)
3568 {
3569         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3570         GL_ActiveTexture(0);
3571         CHECKGLERROR
3572         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
3573         r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3574 }
3575
3576 void R_Bloom_MakeTexture(void)
3577 {
3578         int x, range, dir;
3579         float xoffset, yoffset, r, brighten;
3580
3581         r_refdef.stats.bloom++;
3582
3583         R_ResetViewRendering2D();
3584         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3585         R_Mesh_ColorPointer(NULL, 0, 0);
3586         R_SetupGenericShader(true);
3587
3588         // we have a bloom image in the framebuffer
3589         CHECKGLERROR
3590         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3591
3592         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3593         {
3594                 x *= 2;
3595                 r = bound(0, r_bloom_colorexponent.value / x, 1);
3596                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3597                 GL_Color(r, r, r, 1);
3598                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3599                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3600                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3601                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3602
3603                 // copy the vertically blurred bloom view to a texture
3604                 GL_ActiveTexture(0);
3605                 CHECKGLERROR
3606                 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
3607                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3608         }
3609
3610         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3611         brighten = r_bloom_brighten.value;
3612         if (r_hdr.integer)
3613                 brighten *= r_hdr_range.value;
3614         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3615         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3616
3617         for (dir = 0;dir < 2;dir++)
3618         {
3619                 // blend on at multiple vertical offsets to achieve a vertical blur
3620                 // TODO: do offset blends using GLSL
3621                 GL_BlendFunc(GL_ONE, GL_ZERO);
3622                 for (x = -range;x <= range;x++)
3623                 {
3624                         if (!dir){xoffset = 0;yoffset = x;}
3625                         else {xoffset = x;yoffset = 0;}
3626                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
3627                         yoffset /= (float)r_bloomstate.bloomtextureheight;
3628                         // compute a texcoord array with the specified x and y offset
3629                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3630                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3631                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3632                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3633                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3634                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3635                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3636                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3637                         // this r value looks like a 'dot' particle, fading sharply to
3638                         // black at the edges
3639                         // (probably not realistic but looks good enough)
3640                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3641                         //r = (dir ? 1.0f : brighten)/(range*2+1);
3642                         r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3643                         GL_Color(r, r, r, 1);
3644                         R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3645                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3646                         GL_BlendFunc(GL_ONE, GL_ONE);
3647                 }
3648
3649                 // copy the vertically blurred bloom view to a texture
3650                 GL_ActiveTexture(0);
3651                 CHECKGLERROR
3652                 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
3653                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3654         }
3655
3656         // apply subtract last
3657         // (just like it would be in a GLSL shader)
3658         if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3659         {
3660                 GL_BlendFunc(GL_ONE, GL_ZERO);
3661                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3662                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3663                 GL_Color(1, 1, 1, 1);
3664                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3665                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3666
3667                 GL_BlendFunc(GL_ONE, GL_ONE);
3668                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3669                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3670                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3671                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3672                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3673                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3674                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3675
3676                 // copy the darkened bloom view to a texture
3677                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3678                 GL_ActiveTexture(0);
3679                 CHECKGLERROR
3680                 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
3681                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3682         }
3683 }
3684
3685 void R_HDR_RenderBloomTexture(void)
3686 {
3687         int oldwidth, oldheight;
3688         float oldcolorscale;
3689
3690         oldcolorscale = r_refdef.view.colorscale;
3691         oldwidth = r_refdef.view.width;
3692         oldheight = r_refdef.view.height;
3693         r_refdef.view.width = r_bloomstate.bloomwidth;
3694         r_refdef.view.height = r_bloomstate.bloomheight;
3695
3696         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
3697         // TODO: add exposure compensation features
3698         // TODO: add fp16 framebuffer support
3699
3700         r_refdef.view.showdebug = false;
3701         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3702
3703         R_ResetViewRendering3D();
3704
3705         R_ClearScreen(r_refdef.fogenabled);
3706         if (r_timereport_active)
3707                 R_TimeReport("HDRclear");
3708
3709         R_View_Update();
3710         if (r_timereport_active)
3711                 R_TimeReport("visibility");
3712
3713         r_waterstate.numwaterplanes = 0;
3714         if (r_waterstate.enabled)
3715                 R_RenderWaterPlanes();
3716
3717         r_refdef.view.showdebug = true;
3718         R_RenderScene();
3719         r_waterstate.numwaterplanes = 0;
3720
3721         R_ResetViewRendering2D();
3722
3723         R_Bloom_CopyHDRTexture();
3724         R_Bloom_MakeTexture();
3725
3726         // restore the view settings
3727         r_refdef.view.width = oldwidth;
3728         r_refdef.view.height = oldheight;
3729         r_refdef.view.colorscale = oldcolorscale;
3730
3731         R_ResetViewRendering3D();
3732
3733         R_ClearScreen(r_refdef.fogenabled);
3734         if (r_timereport_active)
3735                 R_TimeReport("viewclear");
3736 }
3737
3738 static void R_BlendView(void)
3739 {
3740         if (r_bloomstate.texture_screen)
3741         {
3742                 // make sure the buffer is available
3743                 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
3744
3745                 R_ResetViewRendering2D();
3746                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3747                 R_Mesh_ColorPointer(NULL, 0, 0);
3748                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3749                 GL_ActiveTexture(0);CHECKGLERROR
3750
3751                 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
3752                 {  
3753                         // declare alpha variable
3754                         float a;
3755                         float speed;
3756                         static float avgspeed;
3757
3758                         speed = VectorLength(cl.movement_velocity);
3759
3760                         a = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
3761                         avgspeed = avgspeed * (1 - a) + speed * a;
3762
3763                         speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
3764                         speed = bound(0, speed, 1);
3765                         speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
3766
3767                         // calculate values into a standard alpha
3768                         a = 1 - exp(-
3769                                         (
3770                                          (r_motionblur.value * speed / 80)
3771                                          +
3772                                          (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
3773                                         )
3774                                         /
3775                                         max(0.0001, cl.time - cl.oldtime) // fps independent
3776                                    );
3777
3778                         a *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
3779                         a = bound(0, a, r_motionblur_maxblur.value);
3780
3781                         // developer debug of current value
3782                         if (r_motionblur_debug.value) { Con_Printf("blur alpha = %f\n", a); }
3783
3784                         // apply the blur
3785                         if (a > 0)
3786                         {
3787                                 R_SetupGenericShader(true);
3788                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3789                                 GL_Color(1, 1, 1, a); // to do: add color changing support for damage blur
3790                                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3791                                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3792                                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3793                                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3794                         }
3795                 }
3796
3797                 // copy view into the screen texture
3798                 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
3799                 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3800         }
3801
3802         if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
3803         {
3804                 unsigned int permutation =
3805                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
3806                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)
3807                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
3808                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
3809                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
3810
3811                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
3812                 {
3813                         // render simple bloom effect
3814                         // copy the screen and shrink it and darken it for the bloom process
3815                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3816                         // make the bloom texture
3817                         R_Bloom_MakeTexture();
3818                 }
3819
3820                 R_ResetViewRendering2D();
3821                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3822                 R_Mesh_ColorPointer(NULL, 0, 0);
3823                 GL_Color(1, 1, 1, 1);
3824                 GL_BlendFunc(GL_ONE, GL_ZERO);
3825                 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
3826                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3827                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3828                 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
3829                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3830                 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
3831                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
3832                 if (r_glsl_permutation->loc_TintColor >= 0)
3833                         qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3834                 if (r_glsl_permutation->loc_ClientTime >= 0)
3835                         qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3836                 if (r_glsl_permutation->loc_PixelSize >= 0)
3837                         qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
3838                 if (r_glsl_permutation->loc_UserVec1 >= 0)
3839                 {
3840                         float a=0, b=0, c=0, d=0;
3841 #if _MSC_VER >= 1400
3842 #define sscanf sscanf_s
3843 #endif
3844                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
3845                         qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
3846                 }
3847                 if (r_glsl_permutation->loc_UserVec2 >= 0)
3848                 {
3849                         float a=0, b=0, c=0, d=0;
3850                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
3851                         qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
3852                 }
3853                 if (r_glsl_permutation->loc_UserVec3 >= 0)
3854                 {
3855                         float a=0, b=0, c=0, d=0;
3856                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
3857                         qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
3858                 }
3859                 if (r_glsl_permutation->loc_UserVec4 >= 0)
3860                 {
3861                         float a=0, b=0, c=0, d=0;
3862                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
3863                         qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
3864                 }
3865                 if (r_glsl_permutation->loc_Saturation >= 0)
3866                         qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
3867                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3868                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3869                 return;
3870         }
3871
3872
3873
3874         if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
3875         {
3876                 // render high dynamic range bloom effect
3877                 // the bloom texture was made earlier this render, so we just need to
3878                 // blend it onto the screen...
3879                 R_ResetViewRendering2D();
3880                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3881                 R_Mesh_ColorPointer(NULL, 0, 0);
3882                 R_SetupGenericShader(true);
3883                 GL_Color(1, 1, 1, 1);
3884                 GL_BlendFunc(GL_ONE, GL_ONE);
3885                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3886                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3887                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3888                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3889         }
3890         else if (r_bloomstate.texture_bloom)
3891         {
3892                 // render simple bloom effect
3893                 // copy the screen and shrink it and darken it for the bloom process
3894                 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3895                 // make the bloom texture
3896                 R_Bloom_MakeTexture();
3897                 // put the original screen image back in place and blend the bloom
3898                 // texture on it
3899                 R_ResetViewRendering2D();
3900                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3901                 R_Mesh_ColorPointer(NULL, 0, 0);
3902                 GL_Color(1, 1, 1, 1);
3903                 GL_BlendFunc(GL_ONE, GL_ZERO);
3904                 // do both in one pass if possible
3905                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3906                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3907                 if (r_textureunits.integer >= 2 && gl_combine.integer)
3908                 {
3909                         R_SetupGenericTwoTextureShader(GL_ADD);
3910                         R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3911                         R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3912                 }
3913                 else
3914                 {
3915                         R_SetupGenericShader(true);
3916                         R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3917                         r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3918                         // now blend on the bloom texture
3919                         GL_BlendFunc(GL_ONE, GL_ONE);
3920                         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3921                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3922                 }
3923                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3924                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3925         }
3926         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3927         {
3928                 // apply a color tint to the whole view
3929                 R_ResetViewRendering2D();
3930                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3931                 R_Mesh_ColorPointer(NULL, 0, 0);
3932                 R_SetupGenericShader(false);
3933                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3934                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3935                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3936         }
3937 }
3938
3939 matrix4x4_t r_waterscrollmatrix;
3940
3941 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3942 {
3943         if (r_refdef.fog_density)
3944         {
3945                 r_refdef.fogcolor[0] = r_refdef.fog_red;
3946                 r_refdef.fogcolor[1] = r_refdef.fog_green;
3947                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3948
3949                 {
3950                         vec3_t fogvec;
3951                         VectorCopy(r_refdef.fogcolor, fogvec);
3952                         if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3953                         {
3954                                 //   color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3955                                 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3956                                 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3957                                 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3958                         }
3959                         //   color.rgb *= ContrastBoost * SceneBrightness;
3960                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3961                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3962                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3963                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3964                 }
3965         }
3966 }
3967
3968 void R_UpdateVariables(void)
3969 {
3970         R_Textures_Frame();
3971
3972         r_refdef.scene.ambient = r_ambient.value;
3973
3974         r_refdef.farclip = 4096;
3975         if (r_refdef.scene.worldmodel)
3976                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
3977         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3978
3979         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3980                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3981         r_refdef.polygonfactor = 0;
3982         r_refdef.polygonoffset = 0;
3983         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3984         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3985
3986         r_refdef.scene.rtworld = r_shadow_realtime_world.integer;
3987         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3988         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3989         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3990         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3991         if (r_showsurfaces.integer)
3992         {
3993                 r_refdef.scene.rtworld = false;
3994                 r_refdef.scene.rtworldshadows = false;
3995                 r_refdef.scene.rtdlight = false;
3996                 r_refdef.scene.rtdlightshadows = false;
3997                 r_refdef.lightmapintensity = 0;
3998         }
3999
4000         if (gamemode == GAME_NEHAHRA)
4001         {
4002                 if (gl_fogenable.integer)
4003                 {
4004                         r_refdef.oldgl_fogenable = true;
4005                         r_refdef.fog_density = gl_fogdensity.value;
4006                         r_refdef.fog_red = gl_fogred.value;
4007                         r_refdef.fog_green = gl_foggreen.value;
4008                         r_refdef.fog_blue = gl_fogblue.value;
4009                         r_refdef.fog_alpha = 1;
4010                         r_refdef.fog_start = 0;
4011                         r_refdef.fog_end = gl_skyclip.value;
4012                 }
4013                 else if (r_refdef.oldgl_fogenable)
4014                 {
4015                         r_refdef.oldgl_fogenable = false;
4016                         r_refdef.fog_density = 0;
4017                         r_refdef.fog_red = 0;
4018                         r_refdef.fog_green = 0;
4019                         r_refdef.fog_blue = 0;
4020                         r_refdef.fog_alpha = 0;
4021                         r_refdef.fog_start = 0;
4022                         r_refdef.fog_end = 0;
4023                 }
4024         }
4025
4026         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4027         r_refdef.fog_start = max(0, r_refdef.fog_start);
4028         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4029
4030         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4031
4032         if (r_refdef.fog_density && r_drawfog.integer)
4033         {
4034                 r_refdef.fogenabled = true;
4035                 // this is the point where the fog reaches 0.9986 alpha, which we
4036                 // consider a good enough cutoff point for the texture
4037                 // (0.9986 * 256 == 255.6)
4038                 if (r_fog_exp2.integer)
4039                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4040                 else
4041                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4042                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4043                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4044                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4045                 // fog color was already set
4046                 // update the fog texture
4047                 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)
4048                         R_BuildFogTexture();
4049         }
4050         else
4051                 r_refdef.fogenabled = false;
4052
4053         if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4054         {
4055                 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4056                 {
4057                         // build GLSL gamma texture
4058 #define RAMPWIDTH 256
4059                         unsigned short ramp[RAMPWIDTH * 3];
4060                         unsigned char rampbgr[RAMPWIDTH][4];
4061                         int i;
4062
4063                         r_texture_gammaramps_serial = vid_gammatables_serial;
4064
4065                         VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4066                         for(i = 0; i < RAMPWIDTH; ++i)
4067                         {
4068                                 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4069                                 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4070                                 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4071                                 rampbgr[i][3] = 0;
4072                         }
4073                         if (r_texture_gammaramps)
4074                         {
4075                                 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4076                         }
4077                         else
4078                         {
4079                                 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);
4080                         }
4081                 }
4082         }
4083         else
4084         {
4085                 // remove GLSL gamma texture
4086         }
4087 }
4088
4089 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4090 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4091 /*
4092 ================
4093 R_SelectScene
4094 ================
4095 */
4096 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4097         if( scenetype != r_currentscenetype ) {
4098                 // store the old scenetype
4099                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4100                 r_currentscenetype = scenetype;
4101                 // move in the new scene
4102                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4103         }
4104 }
4105
4106 /*
4107 ================
4108 R_GetScenePointer
4109 ================
4110 */
4111 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4112 {
4113         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4114         if( scenetype == r_currentscenetype ) {
4115                 return &r_refdef.scene;
4116         } else {
4117                 return &r_scenes_store[ scenetype ];
4118         }
4119 }
4120
4121 /*
4122 ================
4123 R_RenderView
4124 ================
4125 */
4126 void R_RenderView(void)
4127 {
4128         r_frame++; // used only by R_GetCurrentTexture
4129         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4130
4131         R_AnimCache_NewFrame();
4132
4133         if (r_refdef.view.isoverlay)
4134         {
4135                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4136                 GL_Clear( GL_DEPTH_BUFFER_BIT );
4137                 R_TimeReport("depthclear");
4138
4139                 r_refdef.view.showdebug = false;
4140
4141                 r_waterstate.enabled = false;
4142                 r_waterstate.numwaterplanes = 0;
4143
4144                 R_RenderScene();
4145
4146                 CHECKGLERROR
4147                 return;
4148         }
4149
4150         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
4151                 return; //Host_Error ("R_RenderView: NULL worldmodel");
4152
4153         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4154
4155         // break apart the view matrix into vectors for various purposes
4156         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4157         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4158         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4159         VectorNegate(r_refdef.view.left, r_refdef.view.right);
4160         // make an inverted copy of the view matrix for tracking sprites
4161         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4162
4163         R_Shadow_UpdateWorldLightSelection();
4164
4165         R_Bloom_StartFrame();
4166         R_Water_StartFrame();
4167
4168         CHECKGLERROR
4169         if (r_timereport_active)
4170                 R_TimeReport("viewsetup");
4171
4172         R_ResetViewRendering3D();
4173
4174         if (r_refdef.view.clear || r_refdef.fogenabled)
4175         {
4176                 R_ClearScreen(r_refdef.fogenabled);
4177                 if (r_timereport_active)
4178                         R_TimeReport("viewclear");
4179         }
4180         r_refdef.view.clear = true;
4181
4182         // this produces a bloom texture to be used in R_BlendView() later
4183         if (r_hdr.integer)
4184                 R_HDR_RenderBloomTexture();
4185
4186         r_refdef.view.showdebug = true;
4187
4188         R_View_Update();
4189         if (r_timereport_active)
4190                 R_TimeReport("visibility");
4191
4192         r_waterstate.numwaterplanes = 0;
4193         if (r_waterstate.enabled)
4194                 R_RenderWaterPlanes();
4195
4196         R_RenderScene();
4197         r_waterstate.numwaterplanes = 0;
4198
4199         R_BlendView();
4200         if (r_timereport_active)
4201                 R_TimeReport("blendview");
4202
4203         GL_Scissor(0, 0, vid.width, vid.height);
4204         GL_ScissorTest(false);
4205         CHECKGLERROR
4206 }
4207
4208 void R_RenderWaterPlanes(void)
4209 {
4210         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4211         {
4212                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4213                 if (r_timereport_active)
4214                         R_TimeReport("waterworld");
4215         }
4216
4217         // don't let sound skip if going slow
4218         if (r_refdef.scene.extraupdate)
4219                 S_ExtraUpdate ();
4220
4221         R_DrawModelsAddWaterPlanes();
4222         if (r_timereport_active)
4223                 R_TimeReport("watermodels");
4224
4225         if (r_waterstate.numwaterplanes)
4226         {
4227                 R_Water_ProcessPlanes();
4228                 if (r_timereport_active)
4229                         R_TimeReport("waterscenes");
4230         }
4231 }
4232
4233 extern void R_DrawLightningBeams (void);
4234 extern void VM_CL_AddPolygonsToMeshQueue (void);
4235 extern void R_DrawPortals (void);
4236 extern cvar_t cl_locs_show;
4237 static void R_DrawLocs(void);
4238 static void R_DrawEntityBBoxes(void);
4239 void R_RenderScene(void)
4240 {
4241         r_refdef.stats.renders++;
4242
4243         R_UpdateFogColor();
4244
4245         // don't let sound skip if going slow
4246         if (r_refdef.scene.extraupdate)
4247                 S_ExtraUpdate ();
4248
4249         R_MeshQueue_BeginScene();
4250
4251         R_SkyStartFrame();
4252
4253         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);
4254
4255         if (cl.csqc_vidvars.drawworld)
4256         {
4257                 // don't let sound skip if going slow
4258                 if (r_refdef.scene.extraupdate)
4259                         S_ExtraUpdate ();
4260
4261                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4262                 {
4263                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4264                         if (r_timereport_active)
4265                                 R_TimeReport("worldsky");
4266                 }
4267
4268                 if (R_DrawBrushModelsSky() && r_timereport_active)
4269                         R_TimeReport("bmodelsky");
4270         }
4271
4272         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4273         {
4274                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4275                 if (r_timereport_active)
4276                         R_TimeReport("worlddepth");
4277         }
4278         if (r_depthfirst.integer >= 2)
4279         {
4280                 R_DrawModelsDepth();
4281                 if (r_timereport_active)
4282                         R_TimeReport("modeldepth");
4283         }
4284
4285         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4286         {
4287                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4288                 if (r_timereport_active)
4289                         R_TimeReport("world");
4290         }
4291
4292         // don't let sound skip if going slow
4293         if (r_refdef.scene.extraupdate)
4294                 S_ExtraUpdate ();
4295
4296         R_DrawModels();
4297         if (r_timereport_active)
4298                 R_TimeReport("models");
4299
4300         // don't let sound skip if going slow
4301         if (r_refdef.scene.extraupdate)
4302                 S_ExtraUpdate ();
4303
4304         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
4305         {
4306                 R_DrawModelShadows();
4307
4308                 R_ResetViewRendering3D();
4309
4310                 // don't let sound skip if going slow
4311                 if (r_refdef.scene.extraupdate)
4312                         S_ExtraUpdate ();
4313         }
4314
4315         R_ShadowVolumeLighting(false);
4316         if (r_timereport_active)
4317                 R_TimeReport("rtlights");
4318
4319         // don't let sound skip if going slow
4320         if (r_refdef.scene.extraupdate)
4321                 S_ExtraUpdate ();
4322
4323         if (cl.csqc_vidvars.drawworld)
4324         {
4325                 R_DrawLightningBeams();
4326                 if (r_timereport_active)
4327                         R_TimeReport("lightning");
4328
4329                 R_DrawDecals();
4330                 if (r_timereport_active)
4331                         R_TimeReport("decals");
4332
4333                 R_DrawParticles();
4334                 if (r_timereport_active)
4335                         R_TimeReport("particles");
4336
4337                 R_DrawExplosions();
4338                 if (r_timereport_active)
4339                         R_TimeReport("explosions");
4340         }
4341
4342         R_SetupGenericShader(true);
4343         VM_CL_AddPolygonsToMeshQueue();
4344
4345         if (r_refdef.view.showdebug)
4346         {
4347                 if (cl_locs_show.integer)
4348                 {
4349                         R_DrawLocs();
4350                         if (r_timereport_active)
4351                                 R_TimeReport("showlocs");
4352                 }
4353
4354                 if (r_drawportals.integer)
4355                 {
4356                         R_DrawPortals();
4357                         if (r_timereport_active)
4358                                 R_TimeReport("portals");
4359                 }
4360
4361                 if (r_showbboxes.value > 0)
4362                 {
4363                         R_DrawEntityBBoxes();
4364                         if (r_timereport_active)
4365                                 R_TimeReport("bboxes");
4366                 }
4367         }
4368
4369         R_SetupGenericShader(true);
4370         R_MeshQueue_RenderTransparent();
4371         if (r_timereport_active)
4372                 R_TimeReport("drawtrans");
4373
4374         R_SetupGenericShader(true);
4375
4376         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))
4377         {
4378                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4379                 if (r_timereport_active)
4380                         R_TimeReport("worlddebug");
4381                 R_DrawModelsDebug();
4382                 if (r_timereport_active)
4383                         R_TimeReport("modeldebug");
4384         }
4385
4386         R_SetupGenericShader(true);
4387
4388         if (cl.csqc_vidvars.drawworld)
4389         {
4390                 R_DrawCoronas();
4391                 if (r_timereport_active)
4392                         R_TimeReport("coronas");
4393         }
4394
4395         // don't let sound skip if going slow
4396         if (r_refdef.scene.extraupdate)
4397                 S_ExtraUpdate ();
4398
4399         R_ResetViewRendering2D();
4400 }
4401
4402 static const unsigned short bboxelements[36] =
4403 {
4404         5, 1, 3, 5, 3, 7,
4405         6, 2, 0, 6, 0, 4,
4406         7, 3, 2, 7, 2, 6,
4407         4, 0, 1, 4, 1, 5,
4408         4, 5, 7, 4, 7, 6,
4409         1, 0, 2, 1, 2, 3,
4410 };
4411
4412 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4413 {
4414         int i;
4415         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4416         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4417         GL_DepthMask(false);
4418         GL_DepthRange(0, 1);
4419         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4420         R_Mesh_Matrix(&identitymatrix);
4421         R_Mesh_ResetTextureState();
4422
4423         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4424         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4425         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4426         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4427         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4428         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4429         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4430         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4431         R_FillColors(color4f, 8, cr, cg, cb, ca);
4432         if (r_refdef.fogenabled)
4433         {
4434                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4435                 {
4436                         f1 = FogPoint_World(v);
4437                         f2 = 1 - f1;
4438                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4439                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4440                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4441                 }
4442         }
4443         R_Mesh_VertexPointer(vertex3f, 0, 0);
4444         R_Mesh_ColorPointer(color4f, 0, 0);
4445         R_Mesh_ResetTextureState();
4446         R_SetupGenericShader(false);
4447         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4448 }
4449
4450 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4451 {
4452         int i;
4453         float color[4];
4454         prvm_edict_t *edict;
4455         prvm_prog_t *prog_save = prog;
4456
4457         // this function draws bounding boxes of server entities
4458         if (!sv.active)
4459                 return;
4460
4461         GL_CullFace(GL_NONE);
4462         R_SetupGenericShader(false);
4463
4464         prog = 0;
4465         SV_VM_Begin();
4466         for (i = 0;i < numsurfaces;i++)
4467         {
4468                 edict = PRVM_EDICT_NUM(surfacelist[i]);
4469                 switch ((int)edict->fields.server->solid)
4470                 {
4471                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
4472                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
4473                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
4474                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4475                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
4476                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
4477                 }
4478                 color[3] *= r_showbboxes.value;
4479                 color[3] = bound(0, color[3], 1);
4480                 GL_DepthTest(!r_showdisabledepthtest.integer);
4481                 GL_CullFace(r_refdef.view.cullface_front);
4482                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4483         }
4484         SV_VM_End();
4485         prog = prog_save;
4486 }
4487
4488 static void R_DrawEntityBBoxes(void)
4489 {
4490         int i;
4491         prvm_edict_t *edict;
4492         vec3_t center;
4493         prvm_prog_t *prog_save = prog;
4494
4495         // this function draws bounding boxes of server entities
4496         if (!sv.active)
4497                 return;
4498
4499         prog = 0;
4500         SV_VM_Begin();
4501         for (i = 0;i < prog->num_edicts;i++)
4502         {
4503                 edict = PRVM_EDICT_NUM(i);
4504                 if (edict->priv.server->free)
4505                         continue;
4506                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
4507                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
4508                         continue;
4509                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
4510                         continue;
4511                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4512                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4513         }
4514         SV_VM_End();
4515         prog = prog_save;
4516 }
4517
4518 unsigned short nomodelelements[24] =
4519 {
4520         5, 2, 0,
4521         5, 1, 2,
4522         5, 0, 3,
4523         5, 3, 1,
4524         0, 2, 4,
4525         2, 1, 4,
4526         3, 0, 4,
4527         1, 3, 4
4528 };
4529
4530 float nomodelvertex3f[6*3] =
4531 {
4532         -16,   0,   0,
4533          16,   0,   0,
4534           0, -16,   0,
4535           0,  16,   0,
4536           0,   0, -16,
4537           0,   0,  16
4538 };
4539
4540 float nomodelcolor4f[6*4] =
4541 {
4542         0.0f, 0.0f, 0.5f, 1.0f,
4543         0.0f, 0.0f, 0.5f, 1.0f,
4544         0.0f, 0.5f, 0.0f, 1.0f,
4545         0.0f, 0.5f, 0.0f, 1.0f,
4546         0.5f, 0.0f, 0.0f, 1.0f,
4547         0.5f, 0.0f, 0.0f, 1.0f
4548 };
4549
4550 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4551 {
4552         int i;
4553         float f1, f2, *c;
4554         float color4f[6*4];
4555         // this is only called once per entity so numsurfaces is always 1, and
4556         // surfacelist is always {0}, so this code does not handle batches
4557         R_Mesh_Matrix(&ent->matrix);
4558
4559         if (ent->flags & EF_ADDITIVE)
4560         {
4561                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4562                 GL_DepthMask(false);
4563         }
4564         else if (ent->alpha < 1)
4565         {
4566                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4567                 GL_DepthMask(false);
4568         }
4569         else
4570         {
4571                 GL_BlendFunc(GL_ONE, GL_ZERO);
4572                 GL_DepthMask(true);
4573         }
4574         GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4575         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4576         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4577         GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4578         R_SetupGenericShader(false);
4579         R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4580         if (r_refdef.fogenabled)
4581         {
4582                 vec3_t org;
4583                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4584                 R_Mesh_ColorPointer(color4f, 0, 0);
4585                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4586                 f1 = FogPoint_World(org);
4587                 f2 = 1 - f1;
4588                 for (i = 0, c = color4f;i < 6;i++, c += 4)
4589                 {
4590                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4591                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4592                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4593                         c[3] *= ent->alpha;
4594                 }
4595         }
4596         else if (ent->alpha != 1)
4597         {
4598                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4599                 R_Mesh_ColorPointer(color4f, 0, 0);
4600                 for (i = 0, c = color4f;i < 6;i++, c += 4)
4601                         c[3] *= ent->alpha;
4602         }
4603         else
4604                 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4605         R_Mesh_ResetTextureState();
4606         R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
4607 }
4608
4609 void R_DrawNoModel(entity_render_t *ent)
4610 {
4611         vec3_t org;
4612         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4613         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4614                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4615         //else
4616         //      R_DrawNoModelCallback(ent, 0);
4617 }
4618
4619 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4620 {
4621         vec3_t right1, right2, diff, normal;
4622
4623         VectorSubtract (org2, org1, normal);
4624
4625         // calculate 'right' vector for start
4626         VectorSubtract (r_refdef.view.origin, org1, diff);
4627         CrossProduct (normal, diff, right1);
4628         VectorNormalize (right1);
4629
4630         // calculate 'right' vector for end
4631         VectorSubtract (r_refdef.view.origin, org2, diff);
4632         CrossProduct (normal, diff, right2);
4633         VectorNormalize (right2);
4634
4635         vert[ 0] = org1[0] + width * right1[0];
4636         vert[ 1] = org1[1] + width * right1[1];
4637         vert[ 2] = org1[2] + width * right1[2];
4638         vert[ 3] = org1[0] - width * right1[0];
4639         vert[ 4] = org1[1] - width * right1[1];
4640         vert[ 5] = org1[2] - width * right1[2];
4641         vert[ 6] = org2[0] - width * right2[0];
4642         vert[ 7] = org2[1] - width * right2[1];
4643         vert[ 8] = org2[2] - width * right2[2];
4644         vert[ 9] = org2[0] + width * right2[0];
4645         vert[10] = org2[1] + width * right2[1];
4646         vert[11] = org2[2] + width * right2[2];
4647 }
4648
4649 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4650
4651 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)
4652 {
4653         // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
4654         float fog = 1.0f;
4655         float vertex3f[12];
4656
4657         if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4658                 fog = FogPoint_World(origin);
4659
4660         R_Mesh_Matrix(&identitymatrix);
4661         GL_BlendFunc(blendfunc1, blendfunc2);
4662
4663         GL_CullFace(GL_NONE);
4664
4665         GL_DepthMask(false);
4666         GL_DepthRange(0, depthshort ? 0.0625 : 1);
4667         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4668         GL_DepthTest(!depthdisable);
4669
4670         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4671         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4672         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4673         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
4674         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
4675         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
4676         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
4677         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
4678         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
4679         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
4680         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
4681         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
4682
4683         R_Mesh_VertexPointer(vertex3f, 0, 0);
4684         R_Mesh_ColorPointer(NULL, 0, 0);
4685         R_Mesh_ResetTextureState();
4686         R_SetupGenericShader(true);
4687         R_Mesh_TexBind(0, R_GetTexture(texture));
4688         R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
4689         // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
4690         GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
4691         R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4692
4693         if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
4694         {
4695                 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
4696                 GL_BlendFunc(blendfunc1, GL_ONE);
4697                 fog = 1 - fog;
4698                 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
4699                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4700         }
4701 }
4702
4703 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
4704 {
4705         int i;
4706         float *vertex3f;
4707         float v[3];
4708         VectorSet(v, x, y, z);
4709         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
4710                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
4711                         break;
4712         if (i == mesh->numvertices)
4713         {
4714                 if (mesh->numvertices < mesh->maxvertices)
4715                 {
4716                         VectorCopy(v, vertex3f);
4717                         mesh->numvertices++;
4718                 }
4719                 return mesh->numvertices;
4720         }
4721         else
4722                 return i;
4723 }
4724
4725 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
4726 {
4727         int i;
4728         int *e, element[3];
4729         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4730         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4731         e = mesh->element3i + mesh->numtriangles * 3;
4732         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
4733         {
4734                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
4735                 if (mesh->numtriangles < mesh->maxtriangles)
4736                 {
4737                         *e++ = element[0];
4738                         *e++ = element[1];
4739                         *e++ = element[2];
4740                         mesh->numtriangles++;
4741                 }
4742                 element[1] = element[2];
4743         }
4744 }
4745
4746 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
4747 {
4748         int i;
4749         int *e, element[3];
4750         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4751         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4752         e = mesh->element3i + mesh->numtriangles * 3;
4753         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
4754         {
4755                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
4756                 if (mesh->numtriangles < mesh->maxtriangles)
4757                 {
4758                         *e++ = element[0];
4759                         *e++ = element[1];
4760                         *e++ = element[2];
4761                         mesh->numtriangles++;
4762                 }
4763                 element[1] = element[2];
4764         }
4765 }
4766
4767 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
4768 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
4769 {
4770         int planenum, planenum2;
4771         int w;
4772         int tempnumpoints;
4773         mplane_t *plane, *plane2;
4774         double maxdist;
4775         double temppoints[2][256*3];
4776         // figure out how large a bounding box we need to properly compute this brush
4777         maxdist = 0;
4778         for (w = 0;w < numplanes;w++)
4779                 maxdist = max(maxdist, planes[w].dist);
4780         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4781         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4782         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4783         {
4784                 w = 0;
4785                 tempnumpoints = 4;
4786                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4787                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4788                 {
4789                         if (planenum2 == planenum)
4790                                 continue;
4791                         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);
4792                         w = !w;
4793                 }
4794                 if (tempnumpoints < 3)
4795                         continue;
4796                 // generate elements forming a triangle fan for this polygon
4797                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4798         }
4799 }
4800
4801 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)
4802 {
4803         texturelayer_t *layer;
4804         layer = t->currentlayers + t->currentnumlayers++;
4805         layer->type = type;
4806         layer->depthmask = depthmask;
4807         layer->blendfunc1 = blendfunc1;
4808         layer->blendfunc2 = blendfunc2;
4809         layer->texture = texture;
4810         layer->texmatrix = *matrix;
4811         layer->color[0] = r * r_refdef.view.colorscale;
4812         layer->color[1] = g * r_refdef.view.colorscale;
4813         layer->color[2] = b * r_refdef.view.colorscale;
4814         layer->color[3] = a;
4815 }
4816
4817 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4818 {
4819         double index, f;
4820         index = parms[2] + r_refdef.scene.time * parms[3];
4821         index -= floor(index);
4822         switch (func)
4823         {
4824         default:
4825         case Q3WAVEFUNC_NONE:
4826         case Q3WAVEFUNC_NOISE:
4827         case Q3WAVEFUNC_COUNT:
4828                 f = 0;
4829                 break;
4830         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4831         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4832         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4833         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4834         case Q3WAVEFUNC_TRIANGLE:
4835                 index *= 4;
4836                 f = index - floor(index);
4837                 if (index < 1)
4838                         f = f;
4839                 else if (index < 2)
4840                         f = 1 - f;
4841                 else if (index < 3)
4842                         f = -f;
4843                 else
4844                         f = -(1 - f);
4845                 break;
4846         }
4847         return (float)(parms[0] + parms[1] * f);
4848 }
4849
4850 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
4851 {
4852         int w, h, idx;
4853         float f;
4854         float tcmat[12];
4855         matrix4x4_t matrix, temp;
4856         switch(tcmod->tcmod)
4857         {
4858                 case Q3TCMOD_COUNT:
4859                 case Q3TCMOD_NONE:
4860                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4861                                 matrix = r_waterscrollmatrix;
4862                         else
4863                                 matrix = identitymatrix;
4864                         break;
4865                 case Q3TCMOD_ENTITYTRANSLATE:
4866                         // this is used in Q3 to allow the gamecode to control texcoord
4867                         // scrolling on the entity, which is not supported in darkplaces yet.
4868                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4869                         break;
4870                 case Q3TCMOD_ROTATE:
4871                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4872                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4873                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4874                         break;
4875                 case Q3TCMOD_SCALE:
4876                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4877                         break;
4878                 case Q3TCMOD_SCROLL:
4879                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4880                         break;
4881                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
4882                         w = (int) tcmod->parms[0];
4883                         h = (int) tcmod->parms[1];
4884                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
4885                         f = f - floor(f);
4886                         idx = (int) floor(f * w * h);
4887                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
4888                         break;
4889                 case Q3TCMOD_STRETCH:
4890                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4891                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4892                         break;
4893                 case Q3TCMOD_TRANSFORM:
4894                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
4895                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
4896                         VectorSet(tcmat +  6, 0                   , 0                , 1);
4897                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
4898                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4899                         break;
4900                 case Q3TCMOD_TURBULENT:
4901                         // this is handled in the RSurf_PrepareVertices function
4902                         matrix = identitymatrix;
4903                         break;
4904         }
4905         temp = *texmatrix;
4906         Matrix4x4_Concat(texmatrix, &matrix, &temp);
4907 }
4908
4909 texture_t *R_GetCurrentTexture(texture_t *t)
4910 {
4911         int i;
4912         const entity_render_t *ent = rsurface.entity;
4913         dp_model_t *model = ent->model;
4914         q3shaderinfo_layer_tcmod_t *tcmod;
4915
4916         if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
4917                 return t->currentframe;
4918         t->update_lastrenderframe = r_frame;
4919         t->update_lastrenderentity = (void *)ent;
4920
4921         // switch to an alternate material if this is a q1bsp animated material
4922         {
4923                 texture_t *texture = t;
4924                 int s = ent->skinnum;
4925                 if ((unsigned int)s >= (unsigned int)model->numskins)
4926                         s = 0;
4927                 if (model->skinscenes)
4928                 {
4929                         if (model->skinscenes[s].framecount > 1)
4930                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4931                         else
4932                                 s = model->skinscenes[s].firstframe;
4933                 }
4934                 if (s > 0)
4935                         t = t + s * model->num_surfaces;
4936                 if (t->animated)
4937                 {
4938                         // use an alternate animation if the entity's frame is not 0,
4939                         // and only if the texture has an alternate animation
4940                         if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
4941                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4942                         else
4943                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4944                 }
4945                 texture->currentframe = t;
4946         }
4947
4948         // update currentskinframe to be a qw skin or animation frame
4949         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"))
4950         {
4951                 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4952                 {
4953                         strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4954                         if (developer_loading.integer)
4955                                 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
4956                         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);
4957                 }
4958                 t->currentskinframe = r_qwskincache_skinframe[i];
4959                 if (t->currentskinframe == NULL)
4960                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4961         }
4962         else if (t->numskinframes >= 2)
4963                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4964         if (t->backgroundnumskinframes >= 2)
4965                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
4966
4967         t->currentmaterialflags = t->basematerialflags;
4968         t->currentalpha = ent->alpha;
4969         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4970                 t->currentalpha *= r_wateralpha.value;
4971         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
4972                 t->currentalpha *= t->r_water_wateralpha;
4973         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
4974                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4975         if (!(ent->flags & RENDER_LIGHT))
4976                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4977         else if (rsurface.modeltexcoordlightmap2f == NULL)
4978         {
4979                 // pick a model lighting mode
4980                 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4981                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4982                 else
4983                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4984         }
4985         if (ent->effects & EF_ADDITIVE)
4986                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4987         else if (t->currentalpha < 1)
4988                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4989         if (ent->effects & EF_DOUBLESIDED)
4990                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4991         if (ent->effects & EF_NODEPTHTEST)
4992                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4993         if (ent->flags & RENDER_VIEWMODEL)
4994                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4995         if (t->backgroundnumskinframes)
4996                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4997         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
4998         {
4999                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5000                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5001         }
5002         else
5003                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5004
5005         // there is no tcmod
5006         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5007         {
5008                 t->currenttexmatrix = r_waterscrollmatrix;
5009                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5010         }
5011         else
5012         {
5013                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5014                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5015         }
5016
5017         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5018                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5019         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5020                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5021
5022         t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
5023         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5024         t->glosstexture = r_texture_black;
5025         t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5026         t->backgroundglosstexture = r_texture_black;
5027         t->specularpower = r_shadow_glossexponent.value;
5028         // TODO: store reference values for these in the texture?
5029         t->specularscale = 0;
5030         if (r_shadow_gloss.integer > 0)
5031         {
5032                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5033                 {
5034                         if (r_shadow_glossintensity.value > 0)
5035                         {
5036                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5037                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5038                                 t->specularscale = r_shadow_glossintensity.value;
5039                         }
5040                 }
5041                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5042                 {
5043                         t->glosstexture = r_texture_white;
5044                         t->backgroundglosstexture = r_texture_white;
5045                         t->specularscale = r_shadow_gloss2intensity.value;
5046                 }
5047         }
5048
5049         // lightmaps mode looks bad with dlights using actual texturing, so turn
5050         // off the colormap and glossmap, but leave the normalmap on as it still
5051         // accurately represents the shading involved
5052         if (gl_lightmaps.integer)
5053         {
5054                 t->basetexture = r_texture_grey128;
5055                 t->backgroundbasetexture = NULL;
5056                 t->specularscale = 0;
5057                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5058         }
5059
5060         Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
5061         VectorClear(t->dlightcolor);
5062         t->currentnumlayers = 0;
5063         if (t->currentmaterialflags & MATERIALFLAG_WALL)
5064         {
5065                 int layerflags = 0;
5066                 int blendfunc1, blendfunc2, depthmask;
5067                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5068                 {
5069                         blendfunc1 = GL_SRC_ALPHA;
5070                         blendfunc2 = GL_ONE;
5071                 }
5072                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5073                 {
5074                         blendfunc1 = GL_SRC_ALPHA;
5075                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5076                 }
5077                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5078                 {
5079                         blendfunc1 = t->customblendfunc[0];
5080                         blendfunc2 = t->customblendfunc[1];
5081                 }
5082                 else
5083                 {
5084                         blendfunc1 = GL_ONE;
5085                         blendfunc2 = GL_ZERO;
5086                 }
5087                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5088                 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5089                         layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5090                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5091                 {
5092                         // fullbright is not affected by r_refdef.lightmapintensity
5093                         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]);
5094                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5095                                 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]);
5096                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5097                                 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]);
5098                 }
5099                 else
5100                 {
5101                         vec3_t ambientcolor;
5102                         float colorscale;
5103                         // set the color tint used for lights affecting this surface
5104                         VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
5105                         colorscale = 2;
5106                         // q3bsp has no lightmap updates, so the lightstylevalue that
5107                         // would normally be baked into the lightmap must be
5108                         // applied to the color
5109                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5110                         if (ent->model->type == mod_brushq3)
5111                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5112                         colorscale *= r_refdef.lightmapintensity;
5113                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5114                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5115                         // basic lit geometry
5116                         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]);
5117                         // add pants/shirt if needed
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_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]);
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_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]);
5122                         // now add ambient passes if needed
5123                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5124                         {
5125                                 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]);
5126                                 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5127                                         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]);
5128                                 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5129                                         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]);
5130                         }
5131                 }
5132                 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5133                         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]);
5134                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5135                 {
5136                         // if this is opaque use alpha blend which will darken the earlier
5137                         // passes cheaply.
5138                         //
5139                         // if this is an alpha blended material, all the earlier passes
5140                         // were darkened by fog already, so we only need to add the fog
5141                         // color ontop through the fog mask texture
5142                         //
5143                         // if this is an additive blended material, all the earlier passes
5144                         // were darkened by fog already, and we should not add fog color
5145                         // (because the background was not darkened, there is no fog color
5146                         // that was lost behind it).
5147                         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]);
5148                 }
5149         }
5150
5151         return t->currentframe;
5152 }
5153
5154 rsurfacestate_t rsurface;
5155
5156 void R_Mesh_ResizeArrays(int newvertices)
5157 {
5158         float *base;
5159         if (rsurface.array_size >= newvertices)
5160                 return;
5161         if (rsurface.array_modelvertex3f)
5162                 Mem_Free(rsurface.array_modelvertex3f);
5163         rsurface.array_size = (newvertices + 1023) & ~1023;
5164         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5165         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
5166         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
5167         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
5168         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
5169         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
5170         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5171         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5172         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
5173         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
5174         rsurface.array_color4f           = base + rsurface.array_size * 27;
5175         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5176 }
5177
5178 void RSurf_ActiveWorldEntity(void)
5179 {
5180         dp_model_t *model = r_refdef.scene.worldmodel;
5181         //if (rsurface.entity == r_refdef.scene.worldentity)
5182         //      return;
5183         rsurface.entity = r_refdef.scene.worldentity;
5184         if (rsurface.array_size < model->surfmesh.num_vertices)
5185                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5186         rsurface.matrix = identitymatrix;
5187         rsurface.inversematrix = identitymatrix;
5188         R_Mesh_Matrix(&identitymatrix);
5189         VectorCopy(r_refdef.view.origin, rsurface.modelorg);
5190         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5191         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5192         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5193         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5194         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5195         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5196         rsurface.frameblend[0].lerp = 1;
5197         rsurface.basepolygonfactor = r_refdef.polygonfactor;
5198         rsurface.basepolygonoffset = r_refdef.polygonoffset;
5199         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
5200         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5201         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5202         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5203         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5204         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5205         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5206         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5207         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5208         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
5209         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5210         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5211         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
5212         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5213         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5214         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
5215         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5216         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5217         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
5218         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5219         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5220         rsurface.modelelement3i = model->surfmesh.data_element3i;
5221         rsurface.modelelement3s = model->surfmesh.data_element3s;
5222         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5223         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5224         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5225         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5226         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5227         rsurface.modelsurfaces = model->data_surfaces;
5228         rsurface.generatedvertex = false;
5229         rsurface.vertex3f  = rsurface.modelvertex3f;
5230         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5231         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5232         rsurface.svector3f = rsurface.modelsvector3f;
5233         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5234         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5235         rsurface.tvector3f = rsurface.modeltvector3f;
5236         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5237         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5238         rsurface.normal3f  = rsurface.modelnormal3f;
5239         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5240         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5241         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5242 }
5243
5244 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5245 {
5246         dp_model_t *model = ent->model;
5247         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5248         //      return;
5249         rsurface.entity = (entity_render_t *)ent;
5250         if (rsurface.array_size < model->surfmesh.num_vertices)
5251                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5252         rsurface.matrix = ent->matrix;
5253         rsurface.inversematrix = ent->inversematrix;
5254         R_Mesh_Matrix(&rsurface.matrix);
5255         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
5256         rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5257         rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5258         rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5259         rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5260         rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5261         rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5262         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5263         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5264         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5265         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5266         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5267         rsurface.basepolygonfactor = r_refdef.polygonfactor;
5268         rsurface.basepolygonoffset = r_refdef.polygonoffset;
5269         if (ent->model->brush.submodel)
5270         {
5271                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5272                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5273         }
5274         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5275         {
5276                 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
5277                 {
5278                         rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
5279                         rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
5280                         rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
5281                         rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
5282                 }
5283                 else if (wanttangents)
5284                 {
5285                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5286                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5287                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5288                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5289                         model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5290                 }
5291                 else if (wantnormals)
5292                 {
5293                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5294                         rsurface.modelsvector3f = NULL;
5295                         rsurface.modeltvector3f = NULL;
5296                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5297                         model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5298                 }
5299                 else
5300                 {
5301                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5302                         rsurface.modelsvector3f = NULL;
5303                         rsurface.modeltvector3f = NULL;
5304                         rsurface.modelnormal3f = NULL;
5305                         model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5306                 }
5307                 rsurface.modelvertex3f_bufferobject = 0;
5308                 rsurface.modelvertex3f_bufferoffset = 0;
5309                 rsurface.modelsvector3f_bufferobject = 0;
5310                 rsurface.modelsvector3f_bufferoffset = 0;
5311                 rsurface.modeltvector3f_bufferobject = 0;
5312                 rsurface.modeltvector3f_bufferoffset = 0;
5313                 rsurface.modelnormal3f_bufferobject = 0;
5314                 rsurface.modelnormal3f_bufferoffset = 0;
5315                 rsurface.generatedvertex = true;
5316         }
5317         else
5318         {
5319                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
5320                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5321                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5322                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5323                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5324                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5325                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5326                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5327                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5328                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
5329                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5330                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5331                 rsurface.generatedvertex = false;
5332         }
5333         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
5334         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5335         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5336         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
5337         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5338         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5339         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
5340         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5341         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5342         rsurface.modelelement3i = model->surfmesh.data_element3i;
5343         rsurface.modelelement3s = model->surfmesh.data_element3s;
5344         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5345         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5346         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5347         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5348         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5349         rsurface.modelsurfaces = model->data_surfaces;
5350         rsurface.vertex3f  = rsurface.modelvertex3f;
5351         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5352         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5353         rsurface.svector3f = rsurface.modelsvector3f;
5354         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5355         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5356         rsurface.tvector3f = rsurface.modeltvector3f;
5357         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5358         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5359         rsurface.normal3f  = rsurface.modelnormal3f;
5360         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5361         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5362         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5363 }
5364
5365 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5366 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5367 {
5368         int deformindex;
5369         int texturesurfaceindex;
5370         int i, j;
5371         float amplitude;
5372         float animpos;
5373         float scale;
5374         const float *v1, *in_tc;
5375         float *out_tc;
5376         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5377         float waveparms[4];
5378         q3shaderinfo_deform_t *deform;
5379         // 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
5380         if (rsurface.generatedvertex)
5381         {
5382                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5383                         generatenormals = true;
5384                 for (i = 0;i < Q3MAXDEFORMS;i++)
5385                 {
5386                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5387                         {
5388                                 generatetangents = true;
5389                                 generatenormals = true;
5390                         }
5391                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5392                                 generatenormals = true;
5393                 }
5394                 if (generatenormals && !rsurface.modelnormal3f)
5395                 {
5396                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5397                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5398                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5399                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
5400                 }
5401                 if (generatetangents && !rsurface.modelsvector3f)
5402                 {
5403                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5404                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5405                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5406                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5407                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5408                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5409                         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);
5410                 }
5411         }
5412         rsurface.vertex3f  = rsurface.modelvertex3f;
5413         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5414         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5415         rsurface.svector3f = rsurface.modelsvector3f;
5416         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5417         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5418         rsurface.tvector3f = rsurface.modeltvector3f;
5419         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5420         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5421         rsurface.normal3f  = rsurface.modelnormal3f;
5422         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5423         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5424         // if vertices are deformed (sprite flares and things in maps, possibly
5425         // water waves, bulges and other deformations), generate them into
5426         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5427         // (may be static model data or generated data for an animated model, or
5428         //  the previous deform pass)
5429         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5430         {
5431                 switch (deform->deform)
5432                 {
5433                 default:
5434                 case Q3DEFORM_PROJECTIONSHADOW:
5435                 case Q3DEFORM_TEXT0:
5436                 case Q3DEFORM_TEXT1:
5437                 case Q3DEFORM_TEXT2:
5438                 case Q3DEFORM_TEXT3:
5439                 case Q3DEFORM_TEXT4:
5440                 case Q3DEFORM_TEXT5:
5441                 case Q3DEFORM_TEXT6:
5442                 case Q3DEFORM_TEXT7:
5443                 case Q3DEFORM_NONE:
5444                         break;
5445                 case Q3DEFORM_AUTOSPRITE:
5446                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5447                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5448                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5449                         VectorNormalize(newforward);
5450                         VectorNormalize(newright);
5451                         VectorNormalize(newup);
5452                         // make deformed versions of only the model vertices used by the specified surfaces
5453                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5454                         {
5455                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5456                                 // a single autosprite surface can contain multiple sprites...
5457                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
5458                                 {
5459                                         VectorClear(center);
5460                                         for (i = 0;i < 4;i++)
5461                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5462                                         VectorScale(center, 0.25f, center);
5463                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
5464                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5465                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5466                                         for (i = 0;i < 4;i++)
5467                                         {
5468                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5469                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5470                                         }
5471                                 }
5472                                 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);
5473                                 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);
5474                         }
5475                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5476                         rsurface.vertex3f_bufferobject = 0;
5477                         rsurface.vertex3f_bufferoffset = 0;
5478                         rsurface.svector3f = rsurface.array_deformedsvector3f;
5479                         rsurface.svector3f_bufferobject = 0;
5480                         rsurface.svector3f_bufferoffset = 0;
5481                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
5482                         rsurface.tvector3f_bufferobject = 0;
5483                         rsurface.tvector3f_bufferoffset = 0;
5484                         rsurface.normal3f = rsurface.array_deformednormal3f;
5485                         rsurface.normal3f_bufferobject = 0;
5486                         rsurface.normal3f_bufferoffset = 0;
5487                         break;
5488                 case Q3DEFORM_AUTOSPRITE2:
5489                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5490                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5491                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5492                         VectorNormalize(newforward);
5493                         VectorNormalize(newright);
5494                         VectorNormalize(newup);
5495                         // make deformed versions of only the model vertices used by the specified surfaces
5496                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5497                         {
5498                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5499                                 const float *v1, *v2;
5500                                 vec3_t start, end;
5501                                 float f, l;
5502                                 struct
5503                                 {
5504                                         float length2;
5505                                         const float *v1;
5506                                         const float *v2;
5507                                 }
5508                                 shortest[2];
5509                                 memset(shortest, 0, sizeof(shortest));
5510                                 // a single autosprite surface can contain multiple sprites...
5511                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
5512                                 {
5513                                         VectorClear(center);
5514                                         for (i = 0;i < 4;i++)
5515                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5516                                         VectorScale(center, 0.25f, center);
5517                                         // find the two shortest edges, then use them to define the
5518                                         // axis vectors for rotating around the central axis
5519                                         for (i = 0;i < 6;i++)
5520                                         {
5521                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5522                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5523 #if 0
5524                                                 Debug_PolygonBegin(NULL, 0);
5525                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5526                                                 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);
5527                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5528                                                 Debug_PolygonEnd();
5529 #endif
5530                                                 l = VectorDistance2(v1, v2);
5531                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5532                                                 if (v1[2] != v2[2])
5533                                                         l += (1.0f / 1024.0f);
5534                                                 if (shortest[0].length2 > l || i == 0)
5535                                                 {
5536                                                         shortest[1] = shortest[0];
5537                                                         shortest[0].length2 = l;
5538                                                         shortest[0].v1 = v1;
5539                                                         shortest[0].v2 = v2;
5540                                                 }
5541                                                 else if (shortest[1].length2 > l || i == 1)
5542                                                 {
5543                                                         shortest[1].length2 = l;
5544                                                         shortest[1].v1 = v1;
5545                                                         shortest[1].v2 = v2;
5546                                                 }
5547                                         }
5548                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5549                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5550 #if 0
5551                                         Debug_PolygonBegin(NULL, 0);
5552                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5553                                         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);
5554                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5555                                         Debug_PolygonEnd();
5556 #endif
5557                                         // this calculates the right vector from the shortest edge
5558                                         // and the up vector from the edge midpoints
5559                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5560                                         VectorNormalize(right);
5561                                         VectorSubtract(end, start, up);
5562                                         VectorNormalize(up);
5563                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5564                                         VectorSubtract(rsurface.modelorg, center, forward);
5565                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5566                                         VectorNegate(forward, forward);
5567                                         VectorReflect(forward, 0, up, forward);
5568                                         VectorNormalize(forward);
5569                                         CrossProduct(up, forward, newright);
5570                                         VectorNormalize(newright);
5571 #if 0
5572                                         Debug_PolygonBegin(NULL, 0);
5573                                         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);
5574                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5575                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
5576                                         Debug_PolygonEnd();
5577 #endif
5578 #if 0
5579                                         Debug_PolygonBegin(NULL, 0);
5580                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5581                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5582                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
5583                                         Debug_PolygonEnd();
5584 #endif
5585                                         // rotate the quad around the up axis vector, this is made
5586                                         // especially easy by the fact we know the quad is flat,
5587                                         // so we only have to subtract the center position and
5588                                         // measure distance along the right vector, and then
5589                                         // multiply that by the newright vector and add back the
5590                                         // center position
5591                                         // we also need to subtract the old position to undo the
5592                                         // displacement from the center, which we do with a
5593                                         // DotProduct, the subtraction/addition of center is also
5594                                         // optimized into DotProducts here
5595                                         l = DotProduct(right, center);
5596                                         for (i = 0;i < 4;i++)
5597                                         {
5598                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5599                                                 f = DotProduct(right, v1) - l;
5600                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5601                                         }
5602                                 }
5603                                 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);
5604                                 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);
5605                         }
5606                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5607                         rsurface.vertex3f_bufferobject = 0;
5608                         rsurface.vertex3f_bufferoffset = 0;
5609                         rsurface.svector3f = rsurface.array_deformedsvector3f;
5610                         rsurface.svector3f_bufferobject = 0;
5611                         rsurface.svector3f_bufferoffset = 0;
5612                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
5613                         rsurface.tvector3f_bufferobject = 0;
5614                         rsurface.tvector3f_bufferoffset = 0;
5615                         rsurface.normal3f = rsurface.array_deformednormal3f;
5616                         rsurface.normal3f_bufferobject = 0;
5617                         rsurface.normal3f_bufferoffset = 0;
5618                         break;
5619                 case Q3DEFORM_NORMAL:
5620                         // deform the normals to make reflections wavey
5621                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5622                         {
5623                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5624                                 for (j = 0;j < surface->num_vertices;j++)
5625                                 {
5626                                         float vertex[3];
5627                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
5628                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5629                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
5630                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5631                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5632                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5633                                         VectorNormalize(normal);
5634                                 }
5635                                 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);
5636                         }
5637                         rsurface.svector3f = rsurface.array_deformedsvector3f;
5638                         rsurface.svector3f_bufferobject = 0;
5639                         rsurface.svector3f_bufferoffset = 0;
5640                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
5641                         rsurface.tvector3f_bufferobject = 0;
5642                         rsurface.tvector3f_bufferoffset = 0;
5643                         rsurface.normal3f = rsurface.array_deformednormal3f;
5644                         rsurface.normal3f_bufferobject = 0;
5645                         rsurface.normal3f_bufferoffset = 0;
5646                         break;
5647                 case Q3DEFORM_WAVE:
5648                         // deform vertex array to make wavey water and flags and such
5649                         waveparms[0] = deform->waveparms[0];
5650                         waveparms[1] = deform->waveparms[1];
5651                         waveparms[2] = deform->waveparms[2];
5652                         waveparms[3] = deform->waveparms[3];
5653                         // this is how a divisor of vertex influence on deformation
5654                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5655                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5656                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5657                         {
5658                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5659                                 for (j = 0;j < surface->num_vertices;j++)
5660                                 {
5661                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
5662                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
5663                                         // if the wavefunc depends on time, evaluate it per-vertex
5664                                         if (waveparms[3])
5665                                         {
5666                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5667                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5668                                         }
5669                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
5670                                 }
5671                         }
5672                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5673                         rsurface.vertex3f_bufferobject = 0;
5674                         rsurface.vertex3f_bufferoffset = 0;
5675                         break;
5676                 case Q3DEFORM_BULGE:
5677                         // deform vertex array to make the surface have moving bulges
5678                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5679                         {
5680                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5681                                 for (j = 0;j < surface->num_vertices;j++)
5682                                 {
5683                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
5684                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5685                                 }
5686                         }
5687                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5688                         rsurface.vertex3f_bufferobject = 0;
5689                         rsurface.vertex3f_bufferoffset = 0;
5690                         break;
5691                 case Q3DEFORM_MOVE:
5692                         // deform vertex array
5693                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
5694                         VectorScale(deform->parms, scale, waveparms);
5695                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5696                         {
5697                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5698                                 for (j = 0;j < surface->num_vertices;j++)
5699                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5700                         }
5701                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5702                         rsurface.vertex3f_bufferobject = 0;
5703                         rsurface.vertex3f_bufferoffset = 0;
5704                         break;
5705                 }
5706         }
5707         // generate texcoords based on the chosen texcoord source
5708         switch(rsurface.texture->tcgen.tcgen)
5709         {
5710         default:
5711         case Q3TCGEN_TEXTURE:
5712                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
5713                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
5714                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
5715                 break;
5716         case Q3TCGEN_LIGHTMAP:
5717                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
5718                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
5719                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
5720                 break;
5721         case Q3TCGEN_VECTOR:
5722                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5723                 {
5724                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5725                         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)
5726                         {
5727                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
5728                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
5729                         }
5730                 }
5731                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
5732                 rsurface.texcoordtexture2f_bufferobject  = 0;
5733                 rsurface.texcoordtexture2f_bufferoffset  = 0;
5734                 break;
5735         case Q3TCGEN_ENVIRONMENT:
5736                 // make environment reflections using a spheremap
5737                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5738                 {
5739                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5740                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
5741                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
5742                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
5743                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
5744                         {
5745                                 // identical to Q3A's method, but executed in worldspace so
5746                                 // carried models can be shiny too
5747
5748                                 float viewer[3], d, reflected[3], worldreflected[3];
5749
5750                                 VectorSubtract(rsurface.modelorg, vertex, viewer);
5751                                 // VectorNormalize(viewer);
5752
5753                                 d = DotProduct(normal, viewer);
5754
5755                                 reflected[0] = normal[0]*2*d - viewer[0];
5756                                 reflected[1] = normal[1]*2*d - viewer[1];
5757                                 reflected[2] = normal[2]*2*d - viewer[2];
5758                                 // note: this is proportinal to viewer, so we can normalize later
5759
5760                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
5761                                 VectorNormalize(worldreflected);
5762
5763                                 // note: this sphere map only uses world x and z!
5764                                 // so positive and negative y will LOOK THE SAME.
5765                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
5766                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
5767                         }
5768                 }
5769                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
5770                 rsurface.texcoordtexture2f_bufferobject  = 0;
5771                 rsurface.texcoordtexture2f_bufferoffset  = 0;
5772                 break;
5773         }
5774         // the only tcmod that needs software vertex processing is turbulent, so
5775         // check for it here and apply the changes if needed
5776         // and we only support that as the first one
5777         // (handling a mixture of turbulent and other tcmods would be problematic
5778         //  without punting it entirely to a software path)
5779         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
5780         {
5781                 amplitude = rsurface.texture->tcmods[0].parms[1];
5782                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
5783                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5784                 {
5785                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5786                         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)
5787                         {
5788                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5789                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5790                         }
5791                 }
5792                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
5793                 rsurface.texcoordtexture2f_bufferobject  = 0;
5794                 rsurface.texcoordtexture2f_bufferoffset  = 0;
5795         }
5796         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
5797         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5798         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5799         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5800 }
5801
5802 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5803 {
5804         int i, j;
5805         const msurface_t *surface = texturesurfacelist[0];
5806         const msurface_t *surface2;
5807         int firstvertex;
5808         int endvertex;
5809         int numvertices;
5810         int numtriangles;
5811         // TODO: lock all array ranges before render, rather than on each surface
5812         if (texturenumsurfaces == 1)
5813         {
5814                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5815                 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);
5816         }
5817         else if (r_batchmode.integer == 2)
5818         {
5819                 #define MAXBATCHTRIANGLES 4096
5820                 int batchtriangles = 0;
5821                 int batchelements[MAXBATCHTRIANGLES*3];
5822                 for (i = 0;i < texturenumsurfaces;i = j)
5823                 {
5824                         surface = texturesurfacelist[i];
5825                         j = i + 1;
5826                         if (surface->num_triangles > MAXBATCHTRIANGLES)
5827                         {
5828                                 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);
5829                                 continue;
5830                         }
5831                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5832                         batchtriangles = surface->num_triangles;
5833                         firstvertex = surface->num_firstvertex;
5834                         endvertex = surface->num_firstvertex + surface->num_vertices;
5835                         for (;j < texturenumsurfaces;j++)
5836                         {
5837                                 surface2 = texturesurfacelist[j];
5838                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5839                                         break;
5840                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5841                                 batchtriangles += surface2->num_triangles;
5842                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
5843                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5844                         }
5845                         surface2 = texturesurfacelist[j-1];
5846                         numvertices = endvertex - firstvertex;
5847                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5848                 }
5849         }
5850         else if (r_batchmode.integer == 1)
5851         {
5852                 for (i = 0;i < texturenumsurfaces;i = j)
5853                 {
5854                         surface = texturesurfacelist[i];
5855                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5856                                 if (texturesurfacelist[j] != surface2)
5857                                         break;
5858                         surface2 = texturesurfacelist[j-1];
5859                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5860                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5861                         GL_LockArrays(surface->num_firstvertex, numvertices);
5862                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5863                 }
5864         }
5865         else
5866         {
5867                 for (i = 0;i < texturenumsurfaces;i++)
5868                 {
5869                         surface = texturesurfacelist[i];
5870                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5871                         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);
5872                 }
5873         }
5874 }
5875
5876 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5877 {
5878         int i, planeindex, vertexindex;
5879         float d, bestd;
5880         vec3_t vert;
5881         const float *v;
5882         r_waterstate_waterplane_t *p, *bestp;
5883         msurface_t *surface;
5884         if (r_waterstate.renderingscene)
5885                 return;
5886         for (i = 0;i < texturenumsurfaces;i++)
5887         {
5888                 surface = texturesurfacelist[i];
5889                 if (lightmaptexunit >= 0)
5890                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5891                 if (deluxemaptexunit >= 0)
5892                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5893                 // pick the closest matching water plane
5894                 bestd = 0;
5895                 bestp = NULL;
5896                 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5897                 {
5898                         d = 0;
5899                         for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5900                         {
5901                                 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5902                                 d += fabs(PlaneDiff(vert, &p->plane));
5903                         }
5904                         if (bestd > d || !bestp)
5905                         {
5906                                 bestd = d;
5907                                 bestp = p;
5908                         }
5909                 }
5910                 if (bestp)
5911                 {
5912                         if (refractiontexunit >= 0)
5913                                 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5914                         if (reflectiontexunit >= 0)
5915                                 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5916                 }
5917                 else
5918                 {
5919                         if (refractiontexunit >= 0)
5920                                 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5921                         if (reflectiontexunit >= 0)
5922                                 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5923                 }
5924                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5925                 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);
5926         }
5927 }
5928
5929 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5930 {
5931         int i;
5932         int j;
5933         const msurface_t *surface = texturesurfacelist[0];
5934         const msurface_t *surface2;
5935         int firstvertex;
5936         int endvertex;
5937         int numvertices;
5938         int numtriangles;
5939         // TODO: lock all array ranges before render, rather than on each surface
5940         if (texturenumsurfaces == 1)
5941         {
5942                 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5943                 if (deluxemaptexunit >= 0)
5944                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5945                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5946                 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);
5947         }
5948         else if (r_batchmode.integer == 2)
5949         {
5950                 #define MAXBATCHTRIANGLES 4096
5951                 int batchtriangles = 0;
5952                 int batchelements[MAXBATCHTRIANGLES*3];
5953                 for (i = 0;i < texturenumsurfaces;i = j)
5954                 {
5955                         surface = texturesurfacelist[i];
5956                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5957                         if (deluxemaptexunit >= 0)
5958                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5959                         j = i + 1;
5960                         if (surface->num_triangles > MAXBATCHTRIANGLES)
5961                         {
5962                                 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);
5963                                 continue;
5964                         }
5965                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5966                         batchtriangles = surface->num_triangles;
5967                         firstvertex = surface->num_firstvertex;
5968                         endvertex = surface->num_firstvertex + surface->num_vertices;
5969                         for (;j < texturenumsurfaces;j++)
5970                         {
5971                                 surface2 = texturesurfacelist[j];
5972                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5973                                         break;
5974                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5975                                 batchtriangles += surface2->num_triangles;
5976                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
5977                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5978                         }
5979                         surface2 = texturesurfacelist[j-1];
5980                         numvertices = endvertex - firstvertex;
5981                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5982                 }
5983         }
5984         else if (r_batchmode.integer == 1)
5985         {
5986 #if 0
5987                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5988                 for (i = 0;i < texturenumsurfaces;i = j)
5989                 {
5990                         surface = texturesurfacelist[i];
5991                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5992                                 if (texturesurfacelist[j] != surface2)
5993                                         break;
5994                         Con_Printf(" %i", j - i);
5995                 }
5996                 Con_Printf("\n");
5997                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5998 #endif
5999                 for (i = 0;i < texturenumsurfaces;i = j)
6000                 {
6001                         surface = texturesurfacelist[i];
6002                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6003                         if (deluxemaptexunit >= 0)
6004                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6005                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6006                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6007                                         break;
6008 #if 0
6009                         Con_Printf(" %i", j - i);
6010 #endif
6011                         surface2 = texturesurfacelist[j-1];
6012                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6013                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6014                         GL_LockArrays(surface->num_firstvertex, numvertices);
6015                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6016                 }
6017 #if 0
6018                 Con_Printf("\n");
6019 #endif
6020         }
6021         else
6022         {
6023                 for (i = 0;i < texturenumsurfaces;i++)
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                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6030                         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);
6031                 }
6032         }
6033 }
6034
6035 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
6036 {
6037         int j;
6038         int texturesurfaceindex;
6039         if (r_showsurfaces.integer == 2)
6040         {
6041                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6042                 {
6043                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6044                         for (j = 0;j < surface->num_triangles;j++)
6045                         {
6046                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
6047                                 GL_Color(f, f, f, 1);
6048                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6049                         }
6050                 }
6051         }
6052         else
6053         {
6054                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6055                 {
6056                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6057                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
6058                         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);
6059                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6060                         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);
6061                 }
6062         }
6063 }
6064
6065 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
6066 {
6067         int texturesurfaceindex;
6068         int i;
6069         float *v, *c2;
6070         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6071         {
6072                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6073                 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)
6074                 {
6075                         c2[0] = 0.5;
6076                         c2[1] = 0.5;
6077                         c2[2] = 0.5;
6078                         c2[3] = 1;
6079                 }
6080         }
6081         rsurface.lightmapcolor4f = rsurface.array_color4f;
6082         rsurface.lightmapcolor4f_bufferobject = 0;
6083         rsurface.lightmapcolor4f_bufferoffset = 0;
6084 }
6085
6086 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
6087 {
6088         int texturesurfaceindex;
6089         int i;
6090         float f;
6091         float *v, *c, *c2;
6092         if (rsurface.lightmapcolor4f)
6093         {
6094                 // generate color arrays for the surfaces in this list
6095                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6096                 {
6097                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6098                         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)
6099                         {
6100                                 f = FogPoint_Model(v);
6101                                 c2[0] = c[0] * f;
6102                                 c2[1] = c[1] * f;
6103                                 c2[2] = c[2] * f;
6104                                 c2[3] = c[3];
6105                         }
6106                 }
6107         }
6108         else
6109         {
6110                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6111                 {
6112                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6113                         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)
6114                         {
6115                                 f = FogPoint_Model(v);
6116                                 c2[0] = f;
6117                                 c2[1] = f;
6118                                 c2[2] = f;
6119                                 c2[3] = 1;
6120                         }
6121                 }
6122         }
6123         rsurface.lightmapcolor4f = rsurface.array_color4f;
6124         rsurface.lightmapcolor4f_bufferobject = 0;
6125         rsurface.lightmapcolor4f_bufferoffset = 0;
6126 }
6127
6128 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
6129 {
6130         int texturesurfaceindex;
6131         int i;
6132         float f;
6133         float *v, *c, *c2;
6134         if (!rsurface.lightmapcolor4f)
6135                 return;
6136         // generate color arrays for the surfaces in this list
6137         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6138         {
6139                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6140                 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)
6141                 {
6142                         f = FogPoint_Model(v);
6143                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
6144                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
6145                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
6146                         c2[3] = c[3];
6147                 }
6148         }
6149         rsurface.lightmapcolor4f = rsurface.array_color4f;
6150         rsurface.lightmapcolor4f_bufferobject = 0;
6151         rsurface.lightmapcolor4f_bufferoffset = 0;
6152 }
6153
6154 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
6155 {
6156         int texturesurfaceindex;
6157         int i;
6158         float *c, *c2;
6159         if (!rsurface.lightmapcolor4f)
6160                 return;
6161         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6162         {
6163                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6164                 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)
6165                 {
6166                         c2[0] = c[0] * r;
6167                         c2[1] = c[1] * g;
6168                         c2[2] = c[2] * b;
6169                         c2[3] = c[3] * a;
6170                 }
6171         }
6172         rsurface.lightmapcolor4f = rsurface.array_color4f;
6173         rsurface.lightmapcolor4f_bufferobject = 0;
6174         rsurface.lightmapcolor4f_bufferoffset = 0;
6175 }
6176
6177 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
6178 {
6179         int texturesurfaceindex;
6180         int i;
6181         float *c, *c2;
6182         if (!rsurface.lightmapcolor4f)
6183                 return;
6184         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6185         {
6186                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6187                 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)
6188                 {
6189                         c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
6190                         c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
6191                         c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
6192                         c2[3] = c[3];
6193                 }
6194         }
6195         rsurface.lightmapcolor4f = rsurface.array_color4f;
6196         rsurface.lightmapcolor4f_bufferobject = 0;
6197         rsurface.lightmapcolor4f_bufferoffset = 0;
6198 }
6199
6200 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6201 {
6202         // TODO: optimize
6203         rsurface.lightmapcolor4f = NULL;
6204         rsurface.lightmapcolor4f_bufferobject = 0;
6205         rsurface.lightmapcolor4f_bufferoffset = 0;
6206         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6207         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6208         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6209         GL_Color(r, g, b, a);
6210         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
6211 }
6212
6213 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6214 {
6215         // TODO: optimize applyfog && applycolor case
6216         // just apply fog if necessary, and tint the fog color array if necessary
6217         rsurface.lightmapcolor4f = NULL;
6218         rsurface.lightmapcolor4f_bufferobject = 0;
6219         rsurface.lightmapcolor4f_bufferoffset = 0;
6220         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6221         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6222         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6223         GL_Color(r, g, b, a);
6224         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6225 }
6226
6227 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6228 {
6229         int texturesurfaceindex;
6230         int i;
6231         float *c;
6232         // TODO: optimize
6233         if (texturesurfacelist[0]->lightmapinfo)
6234         {
6235                 // generate color arrays for the surfaces in this list
6236                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6237                 {
6238                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6239                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
6240                         {
6241                                 if (surface->lightmapinfo->samples)
6242                                 {
6243                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
6244                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
6245                                         VectorScale(lm, scale, c);
6246                                         if (surface->lightmapinfo->styles[1] != 255)
6247                                         {
6248                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
6249                                                 lm += size3;
6250                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
6251                                                 VectorMA(c, scale, lm, c);
6252                                                 if (surface->lightmapinfo->styles[2] != 255)
6253                                                 {
6254                                                         lm += size3;
6255                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6256                                                         VectorMA(c, scale, lm, c);
6257                                                         if (surface->lightmapinfo->styles[3] != 255)
6258                                                         {
6259                                                                 lm += size3;
6260                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6261                                                                 VectorMA(c, scale, lm, c);
6262                                                         }
6263                                                 }
6264                                         }
6265                                 }
6266                                 else
6267                                         VectorClear(c);
6268                                 c[3] = 1;
6269                         }
6270                 }
6271                 rsurface.lightmapcolor4f = rsurface.array_color4f;
6272                 rsurface.lightmapcolor4f_bufferobject = 0;
6273                 rsurface.lightmapcolor4f_bufferoffset = 0;
6274         }
6275         else
6276         {
6277                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6278                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6279                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6280         }
6281         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6282         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6283         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6284         GL_Color(r, g, b, a);
6285         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6286 }
6287
6288 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6289 {
6290         int texturesurfaceindex;
6291         int i;
6292         float f;
6293         float *v, *c, *c2, alpha;
6294         vec3_t ambientcolor;
6295         vec3_t diffusecolor;
6296         vec3_t lightdir;
6297         // TODO: optimize
6298         // model lighting
6299         VectorCopy(rsurface.modellight_lightdir, lightdir);
6300         f = 0.5f * r_refdef.lightmapintensity;
6301         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6302         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6303         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6304         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6305         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6306         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6307         alpha = *a;
6308         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6309         {
6310                 // generate color arrays for the surfaces in this list
6311                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6312                 {
6313                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6314                         int numverts = surface->num_vertices;
6315                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6316                         c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6317                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6318                         // q3-style directional shading
6319                         for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6320                         {
6321                                 if ((f = DotProduct(c2, lightdir)) > 0)
6322                                         VectorMA(ambientcolor, f, diffusecolor, c);
6323                                 else
6324                                         VectorCopy(ambientcolor, c);
6325                                 c[3] = alpha;
6326                         }
6327                 }
6328                 *r = 1;
6329                 *g = 1;
6330                 *b = 1;
6331                 *a = 1;
6332                 rsurface.lightmapcolor4f = rsurface.array_color4f;
6333                 rsurface.lightmapcolor4f_bufferobject = 0;
6334                 rsurface.lightmapcolor4f_bufferoffset = 0;
6335                 *applycolor = false;
6336         }
6337         else
6338         {
6339                 *r = ambientcolor[0];
6340                 *g = ambientcolor[1];
6341                 *b = ambientcolor[2];
6342                 rsurface.lightmapcolor4f = NULL;
6343                 rsurface.lightmapcolor4f_bufferobject = 0;
6344                 rsurface.lightmapcolor4f_bufferoffset = 0;
6345         }
6346 }
6347
6348 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6349 {
6350         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6351         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6352         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6353         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6354         GL_Color(r, g, b, a);
6355         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6356 }
6357
6358 void RSurf_SetupDepthAndCulling(void)
6359 {
6360         // submodels are biased to avoid z-fighting with world surfaces that they
6361         // may be exactly overlapping (avoids z-fighting artifacts on certain
6362         // doors and things in Quake maps)
6363         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6364         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6365         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6366         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6367 }
6368
6369 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6370 {
6371         // transparent sky would be ridiculous
6372         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6373                 return;
6374         R_SetupGenericShader(false);
6375         if (skyrendernow)
6376         {
6377                 skyrendernow = false;
6378                 // we have to force off the water clipping plane while rendering sky
6379                 R_SetupView(false);
6380                 R_Sky();
6381                 R_SetupView(true);
6382                 // restore entity matrix
6383                 R_Mesh_Matrix(&rsurface.matrix);
6384         }
6385         RSurf_SetupDepthAndCulling();
6386         GL_DepthMask(true);
6387         // LordHavoc: HalfLife maps have freaky skypolys so don't use
6388         // skymasking on them, and Quake3 never did sky masking (unlike
6389         // software Quake and software Quake2), so disable the sky masking
6390         // in Quake3 maps as it causes problems with q3map2 sky tricks,
6391         // and skymasking also looks very bad when noclipping outside the
6392         // level, so don't use it then either.
6393         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6394         {
6395                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6396                 R_Mesh_ColorPointer(NULL, 0, 0);
6397                 R_Mesh_ResetTextureState();
6398                 if (skyrendermasked)
6399                 {
6400                         R_SetupDepthOrShadowShader();
6401                         // depth-only (masking)
6402                         GL_ColorMask(0,0,0,0);
6403                         // just to make sure that braindead drivers don't draw
6404                         // anything despite that colormask...
6405                         GL_BlendFunc(GL_ZERO, GL_ONE);
6406                 }
6407                 else
6408                 {
6409                         R_SetupGenericShader(false);
6410                         // fog sky
6411                         GL_BlendFunc(GL_ONE, GL_ZERO);
6412                 }
6413                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6414                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6415                 if (skyrendermasked)
6416                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6417         }
6418         R_Mesh_ResetTextureState();
6419         GL_Color(1, 1, 1, 1);
6420 }
6421
6422 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6423 {
6424         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6425                 return;
6426
6427         R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6428         R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
6429         R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6430         R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6431         R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6432         R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6433         if (rsurface.texture->backgroundcurrentskinframe)
6434         {
6435                 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6436                 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6437                 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6438                 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6439         }
6440         if(rsurface.texture->colormapping)
6441         {
6442                 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6443                 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6444         }
6445         R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6446         if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6447                 R_Mesh_ColorPointer(NULL, 0, 0);
6448         else
6449                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6450
6451         if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6452         {
6453                 // render background
6454                 GL_BlendFunc(GL_ONE, GL_ZERO);
6455                 GL_DepthMask(true);
6456                 GL_AlphaTest(false);
6457
6458                 GL_Color(1, 1, 1, 1);
6459                 R_Mesh_ColorPointer(NULL, 0, 0);
6460
6461                 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6462                 if (r_glsl_permutation)
6463                 {
6464                         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6465                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6466                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6467                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6468                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6469                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6470                         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);
6471                 }
6472                 GL_LockArrays(0, 0);
6473
6474                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6475                 GL_DepthMask(false);
6476                 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6477                         R_Mesh_ColorPointer(NULL, 0, 0);
6478                 else
6479                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6480                 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6481                 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6482         }
6483
6484         R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6485         if (!r_glsl_permutation)
6486                 return;
6487
6488         RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, 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
6495         if (r_glsl_permutation->loc_Texture_Refraction >= 0)
6496         {
6497                 GL_BlendFunc(GL_ONE, GL_ZERO);
6498                 GL_DepthMask(true);
6499                 GL_AlphaTest(false);
6500         }
6501         else
6502         {
6503                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6504                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6505                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6506         }
6507
6508         if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6509         {
6510                 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6511                         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);
6512                 else
6513                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
6514         }
6515         else
6516         {
6517                 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6518                         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);
6519                 else
6520                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6521         }
6522         GL_LockArrays(0, 0);
6523 }
6524
6525 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6526 {
6527         // OpenGL 1.3 path - anything not completely ancient
6528         int texturesurfaceindex;
6529         qboolean applycolor;
6530         qboolean applyfog;
6531         rmeshstate_t m;
6532         int layerindex;
6533         const texturelayer_t *layer;
6534         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6535
6536         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6537         {
6538                 vec4_t layercolor;
6539                 int layertexrgbscale;
6540                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6541                 {
6542                         if (layerindex == 0)
6543                                 GL_AlphaTest(true);
6544                         else
6545                         {
6546                                 GL_AlphaTest(false);
6547                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6548                         }
6549                 }
6550                 GL_DepthMask(layer->depthmask && writedepth);
6551                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6552                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
6553                 {
6554                         layertexrgbscale = 4;
6555                         VectorScale(layer->color, 0.25f, layercolor);
6556                 }
6557                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
6558                 {
6559                         layertexrgbscale = 2;
6560                         VectorScale(layer->color, 0.5f, layercolor);
6561                 }
6562                 else
6563                 {
6564                         layertexrgbscale = 1;
6565                         VectorScale(layer->color, 1.0f, layercolor);
6566                 }
6567                 layercolor[3] = layer->color[3];
6568                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6569                 R_Mesh_ColorPointer(NULL, 0, 0);
6570                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6571                 switch (layer->type)
6572                 {
6573                 case TEXTURELAYERTYPE_LITTEXTURE:
6574                         memset(&m, 0, sizeof(m));
6575                         m.tex[0] = R_GetTexture(r_texture_white);
6576                         m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6577                         m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6578                         m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6579                         m.tex[1] = R_GetTexture(layer->texture);
6580                         m.texmatrix[1] = layer->texmatrix;
6581                         m.texrgbscale[1] = layertexrgbscale;
6582                         m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
6583                         m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
6584                         m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
6585                         R_Mesh_TextureState(&m);
6586                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6587                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6588                         else if (rsurface.uselightmaptexture)
6589                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6590                         else
6591                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6592                         break;
6593                 case TEXTURELAYERTYPE_TEXTURE:
6594                         memset(&m, 0, sizeof(m));
6595                         m.tex[0] = R_GetTexture(layer->texture);
6596                         m.texmatrix[0] = layer->texmatrix;
6597                         m.texrgbscale[0] = layertexrgbscale;
6598                         m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6599                         m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6600                         m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6601                         R_Mesh_TextureState(&m);
6602                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6603                         break;
6604                 case TEXTURELAYERTYPE_FOG:
6605                         memset(&m, 0, sizeof(m));
6606                         m.texrgbscale[0] = layertexrgbscale;
6607                         if (layer->texture)
6608                         {
6609                                 m.tex[0] = R_GetTexture(layer->texture);
6610                                 m.texmatrix[0] = layer->texmatrix;
6611                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6612                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6613                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6614                         }
6615                         R_Mesh_TextureState(&m);
6616                         // generate a color array for the fog pass
6617                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6618                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6619                         {
6620                                 int i;
6621                                 float f, *v, *c;
6622                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6623                                 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)
6624                                 {
6625                                         f = 1 - FogPoint_Model(v);
6626                                         c[0] = layercolor[0];
6627                                         c[1] = layercolor[1];
6628                                         c[2] = layercolor[2];
6629                                         c[3] = f * layercolor[3];
6630                                 }
6631                         }
6632                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6633                         break;
6634                 default:
6635                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6636                 }
6637                 GL_LockArrays(0, 0);
6638         }
6639         CHECKGLERROR
6640         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6641         {
6642                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6643                 GL_AlphaTest(false);
6644         }
6645 }
6646
6647 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6648 {
6649         // OpenGL 1.1 - crusty old voodoo path
6650         int texturesurfaceindex;
6651         qboolean applyfog;
6652         rmeshstate_t m;
6653         int layerindex;
6654         const texturelayer_t *layer;
6655         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6656
6657         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6658         {
6659                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6660                 {
6661                         if (layerindex == 0)
6662                                 GL_AlphaTest(true);
6663                         else
6664                         {
6665                                 GL_AlphaTest(false);
6666                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6667                         }
6668                 }
6669                 GL_DepthMask(layer->depthmask && writedepth);
6670                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6671                 R_Mesh_ColorPointer(NULL, 0, 0);
6672                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6673                 switch (layer->type)
6674                 {
6675                 case TEXTURELAYERTYPE_LITTEXTURE:
6676                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
6677                         {
6678                                 // two-pass lit texture with 2x rgbscale
6679                                 // first the lightmap pass
6680                                 memset(&m, 0, sizeof(m));
6681                                 m.tex[0] = R_GetTexture(r_texture_white);
6682                                 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6683                                 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6684                                 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6685                                 R_Mesh_TextureState(&m);
6686                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6687                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6688                                 else if (rsurface.uselightmaptexture)
6689                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6690                                 else
6691                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6692                                 GL_LockArrays(0, 0);
6693                                 // then apply the texture to it
6694                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6695                                 memset(&m, 0, sizeof(m));
6696                                 m.tex[0] = R_GetTexture(layer->texture);
6697                                 m.texmatrix[0] = layer->texmatrix;
6698                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6699                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6700                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6701                                 R_Mesh_TextureState(&m);
6702                                 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);
6703                         }
6704                         else
6705                         {
6706                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6707                                 memset(&m, 0, sizeof(m));
6708                                 m.tex[0] = R_GetTexture(layer->texture);
6709                                 m.texmatrix[0] = layer->texmatrix;
6710                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6711                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6712                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6713                                 R_Mesh_TextureState(&m);
6714                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6715                                         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);
6716                                 else
6717                                         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);
6718                         }
6719                         break;
6720                 case TEXTURELAYERTYPE_TEXTURE:
6721                         // singletexture unlit texture with transparency support
6722                         memset(&m, 0, sizeof(m));
6723                         m.tex[0] = R_GetTexture(layer->texture);
6724                         m.texmatrix[0] = layer->texmatrix;
6725                         m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6726                         m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6727                         m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6728                         R_Mesh_TextureState(&m);
6729                         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);
6730                         break;
6731                 case TEXTURELAYERTYPE_FOG:
6732                         // singletexture fogging
6733                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6734                         if (layer->texture)
6735                         {
6736                                 memset(&m, 0, sizeof(m));
6737                                 m.tex[0] = R_GetTexture(layer->texture);
6738                                 m.texmatrix[0] = layer->texmatrix;
6739                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6740                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6741                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6742                                 R_Mesh_TextureState(&m);
6743                         }
6744                         else
6745                                 R_Mesh_ResetTextureState();
6746                         // generate a color array for the fog pass
6747                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6748                         {
6749                                 int i;
6750                                 float f, *v, *c;
6751                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6752                                 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)
6753                                 {
6754                                         f = 1 - FogPoint_Model(v);
6755                                         c[0] = layer->color[0];
6756                                         c[1] = layer->color[1];
6757                                         c[2] = layer->color[2];
6758                                         c[3] = f * layer->color[3];
6759                                 }
6760                         }
6761                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6762                         break;
6763                 default:
6764                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6765                 }
6766                 GL_LockArrays(0, 0);
6767         }
6768         CHECKGLERROR
6769         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6770         {
6771                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6772                 GL_AlphaTest(false);
6773         }
6774 }
6775
6776 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6777 {
6778         float c[4];
6779
6780         GL_AlphaTest(false);
6781         R_Mesh_ColorPointer(NULL, 0, 0);
6782         R_Mesh_ResetTextureState();
6783         R_SetupGenericShader(false);
6784
6785         if(rsurface.texture && rsurface.texture->currentskinframe)
6786         {
6787                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
6788                 c[3] *= rsurface.texture->currentalpha;
6789         }
6790         else
6791         {
6792                 c[0] = 1;
6793                 c[1] = 0;
6794                 c[2] = 1;
6795                 c[3] = 1;
6796         }
6797
6798         if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
6799         {
6800                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
6801                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
6802                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
6803         }
6804
6805         // brighten it up (as texture value 127 means "unlit")
6806         c[0] *= 2 * r_refdef.view.colorscale;
6807         c[1] *= 2 * r_refdef.view.colorscale;
6808         c[2] *= 2 * r_refdef.view.colorscale;
6809
6810         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
6811                 c[3] *= r_wateralpha.value;
6812
6813         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
6814         {
6815                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6816                 GL_DepthMask(false);
6817         }
6818         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6819         {
6820                 GL_BlendFunc(GL_ONE, GL_ONE);
6821                 GL_DepthMask(false);
6822         }
6823         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6824         {
6825                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
6826                 GL_DepthMask(false);
6827         }
6828         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6829         {
6830                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
6831                 GL_DepthMask(false);
6832         }
6833         else
6834         {
6835                 GL_BlendFunc(GL_ONE, GL_ZERO);
6836                 GL_DepthMask(writedepth);
6837         }
6838
6839         rsurface.lightmapcolor4f = NULL;
6840
6841         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6842         {
6843                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6844
6845                 rsurface.lightmapcolor4f = NULL;
6846                 rsurface.lightmapcolor4f_bufferobject = 0;
6847                 rsurface.lightmapcolor4f_bufferoffset = 0;
6848         }
6849         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6850         {
6851                 qboolean applycolor = true;
6852                 float one = 1.0;
6853
6854                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6855
6856                 r_refdef.lightmapintensity = 1;
6857                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
6858                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
6859         }
6860         else
6861         {
6862                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6863
6864                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6865                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6866                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6867         }
6868
6869         if(!rsurface.lightmapcolor4f)
6870                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
6871
6872         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
6873         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
6874         if(r_refdef.fogenabled)
6875                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
6876
6877         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6878         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6879 }
6880
6881 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6882 {
6883         CHECKGLERROR
6884         RSurf_SetupDepthAndCulling();
6885         if (r_showsurfaces.integer == 3)
6886                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6887         else if (r_glsl.integer && gl_support_fragment_shader)
6888                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6889         else if (gl_combine.integer && r_textureunits.integer >= 2)
6890                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6891         else
6892                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6893         CHECKGLERROR
6894 }
6895
6896 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6897 {
6898         CHECKGLERROR
6899         RSurf_SetupDepthAndCulling();
6900         if (r_showsurfaces.integer == 3)
6901                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6902         else if (r_glsl.integer && gl_support_fragment_shader)
6903                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6904         else if (gl_combine.integer && r_textureunits.integer >= 2)
6905                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6906         else
6907                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6908         CHECKGLERROR
6909 }
6910
6911 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6912 {
6913         int i, j;
6914         int texturenumsurfaces, endsurface;
6915         texture_t *texture;
6916         msurface_t *surface;
6917         msurface_t *texturesurfacelist[1024];
6918
6919         // if the model is static it doesn't matter what value we give for
6920         // wantnormals and wanttangents, so this logic uses only rules applicable
6921         // to a model, knowing that they are meaningless otherwise
6922         if (ent == r_refdef.scene.worldentity)
6923                 RSurf_ActiveWorldEntity();
6924         else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3))
6925                 RSurf_ActiveModelEntity(ent, false, false);
6926         else
6927                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6928
6929         for (i = 0;i < numsurfaces;i = j)
6930         {
6931                 j = i + 1;
6932                 surface = rsurface.modelsurfaces + surfacelist[i];
6933                 texture = surface->texture;
6934                 rsurface.texture = R_GetCurrentTexture(texture);
6935                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6936                 // scan ahead until we find a different texture
6937                 endsurface = min(i + 1024, numsurfaces);
6938                 texturenumsurfaces = 0;
6939                 texturesurfacelist[texturenumsurfaces++] = surface;
6940                 for (;j < endsurface;j++)
6941                 {
6942                         surface = rsurface.modelsurfaces + surfacelist[j];
6943                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6944                                 break;
6945                         texturesurfacelist[texturenumsurfaces++] = surface;
6946                 }
6947                 // render the range of surfaces
6948                 if (ent == r_refdef.scene.worldentity)
6949                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6950                 else
6951                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6952         }
6953         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6954         GL_AlphaTest(false);
6955 }
6956
6957 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
6958 {
6959         const entity_render_t *queueentity = r_refdef.scene.worldentity;
6960         CHECKGLERROR
6961         if (depthonly)
6962         {
6963                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6964                         return;
6965                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6966                         return;
6967                 RSurf_SetupDepthAndCulling();
6968                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6969                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6970         }
6971         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
6972         {
6973                 RSurf_SetupDepthAndCulling();
6974                 GL_AlphaTest(false);
6975                 R_Mesh_ColorPointer(NULL, 0, 0);
6976                 R_Mesh_ResetTextureState();
6977                 R_SetupGenericShader(false);
6978                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6979                 GL_DepthMask(true);
6980                 GL_BlendFunc(GL_ONE, GL_ZERO);
6981                 GL_Color(0, 0, 0, 1);
6982                 GL_DepthTest(writedepth);
6983                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6984         }
6985         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
6986         {
6987                 RSurf_SetupDepthAndCulling();
6988                 GL_AlphaTest(false);
6989                 R_Mesh_ColorPointer(NULL, 0, 0);
6990                 R_Mesh_ResetTextureState();
6991                 R_SetupGenericShader(false);
6992                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6993                 GL_DepthMask(true);
6994                 GL_BlendFunc(GL_ONE, GL_ZERO);
6995                 GL_DepthTest(true);
6996                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6997         }
6998         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6999                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7000         else if (!rsurface.texture->currentnumlayers)
7001                 return;
7002         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7003         {
7004                 // transparent surfaces get pushed off into the transparent queue
7005                 int surfacelistindex;
7006                 const msurface_t *surface;
7007                 vec3_t tempcenter, center;
7008                 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7009                 {
7010                         surface = texturesurfacelist[surfacelistindex];
7011                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7012                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7013                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7014                         Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7015                         R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7016                 }
7017         }
7018         else
7019         {
7020                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7021                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7022         }
7023         CHECKGLERROR
7024 }
7025
7026 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7027 {
7028         int i, j;
7029         texture_t *texture;
7030         // break the surface list down into batches by texture and use of lightmapping
7031         for (i = 0;i < numsurfaces;i = j)
7032         {
7033                 j = i + 1;
7034                 // texture is the base texture pointer, rsurface.texture is the
7035                 // current frame/skin the texture is directing us to use (for example
7036                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7037                 // use skin 1 instead)
7038                 texture = surfacelist[i]->texture;
7039                 rsurface.texture = R_GetCurrentTexture(texture);
7040                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7041                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7042                 {
7043                         // if this texture is not the kind we want, skip ahead to the next one
7044                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7045                                 ;
7046                         continue;
7047                 }
7048                 // simply scan ahead until we find a different texture or lightmap state
7049                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7050                         ;
7051                 // render the range of surfaces
7052                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
7053         }
7054 }
7055
7056 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
7057 {
7058         CHECKGLERROR
7059         if (depthonly)
7060         {
7061                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7062                         return;
7063                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7064                         return;
7065                 RSurf_SetupDepthAndCulling();
7066                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7067                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7068         }
7069         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7070         {
7071                 RSurf_SetupDepthAndCulling();
7072                 GL_AlphaTest(false);
7073                 R_Mesh_ColorPointer(NULL, 0, 0);
7074                 R_Mesh_ResetTextureState();
7075                 R_SetupGenericShader(false);
7076                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7077                 GL_DepthMask(true);
7078                 GL_BlendFunc(GL_ONE, GL_ZERO);
7079                 GL_Color(0, 0, 0, 1);
7080                 GL_DepthTest(writedepth);
7081                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7082         }
7083         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7084         {
7085                 RSurf_SetupDepthAndCulling();
7086                 GL_AlphaTest(false);
7087                 R_Mesh_ColorPointer(NULL, 0, 0);
7088                 R_Mesh_ResetTextureState();
7089                 R_SetupGenericShader(false);
7090                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7091                 GL_DepthMask(true);
7092                 GL_BlendFunc(GL_ONE, GL_ZERO);
7093                 GL_DepthTest(true);
7094                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7095         }
7096         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7097                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7098         else if (!rsurface.texture->currentnumlayers)
7099                 return;
7100         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7101         {
7102                 // transparent surfaces get pushed off into the transparent queue
7103                 int surfacelistindex;
7104                 const msurface_t *surface;
7105                 vec3_t tempcenter, center;
7106                 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7107                 {
7108                         surface = texturesurfacelist[surfacelistindex];
7109                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7110                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7111                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7112                         Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7113                         R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7114                 }
7115         }
7116         else
7117         {
7118                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7119                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7120         }
7121         CHECKGLERROR
7122 }
7123
7124 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7125 {
7126         int i, j;
7127         texture_t *texture;
7128         // break the surface list down into batches by texture and use of lightmapping
7129         for (i = 0;i < numsurfaces;i = j)
7130         {
7131                 j = i + 1;
7132                 // texture is the base texture pointer, rsurface.texture is the
7133                 // current frame/skin the texture is directing us to use (for example
7134                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7135                 // use skin 1 instead)
7136                 texture = surfacelist[i]->texture;
7137                 rsurface.texture = R_GetCurrentTexture(texture);
7138                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7139                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7140                 {
7141                         // if this texture is not the kind we want, skip ahead to the next one
7142                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7143                                 ;
7144                         continue;
7145                 }
7146                 // simply scan ahead until we find a different texture or lightmap state
7147                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7148                         ;
7149                 // render the range of surfaces
7150                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
7151         }
7152 }
7153
7154 float locboxvertex3f[6*4*3] =
7155 {
7156         1,0,1, 1,0,0, 1,1,0, 1,1,1,
7157         0,1,1, 0,1,0, 0,0,0, 0,0,1,
7158         1,1,1, 1,1,0, 0,1,0, 0,1,1,
7159         0,0,1, 0,0,0, 1,0,0, 1,0,1,
7160         0,0,1, 1,0,1, 1,1,1, 0,1,1,
7161         1,0,0, 0,0,0, 0,1,0, 1,1,0
7162 };
7163
7164 unsigned short locboxelements[6*2*3] =
7165 {
7166          0, 1, 2, 0, 2, 3,
7167          4, 5, 6, 4, 6, 7,
7168          8, 9,10, 8,10,11,
7169         12,13,14, 12,14,15,
7170         16,17,18, 16,18,19,
7171         20,21,22, 20,22,23
7172 };
7173
7174 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7175 {
7176         int i, j;
7177         cl_locnode_t *loc = (cl_locnode_t *)ent;
7178         vec3_t mins, size;
7179         float vertex3f[6*4*3];
7180         CHECKGLERROR
7181         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7182         GL_DepthMask(false);
7183         GL_DepthRange(0, 1);
7184         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7185         GL_DepthTest(true);
7186         GL_CullFace(GL_NONE);
7187         R_Mesh_Matrix(&identitymatrix);
7188
7189         R_Mesh_VertexPointer(vertex3f, 0, 0);
7190         R_Mesh_ColorPointer(NULL, 0, 0);
7191         R_Mesh_ResetTextureState();
7192         R_SetupGenericShader(false);
7193
7194         i = surfacelist[0];
7195         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7196                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7197                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7198                         surfacelist[0] < 0 ? 0.5f : 0.125f);
7199
7200         if (VectorCompare(loc->mins, loc->maxs))
7201         {
7202                 VectorSet(size, 2, 2, 2);
7203                 VectorMA(loc->mins, -0.5f, size, mins);
7204         }
7205         else
7206         {
7207                 VectorCopy(loc->mins, mins);
7208                 VectorSubtract(loc->maxs, loc->mins, size);
7209         }
7210
7211         for (i = 0;i < 6*4*3;)
7212                 for (j = 0;j < 3;j++, i++)
7213                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
7214
7215         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
7216 }
7217
7218 void R_DrawLocs(void)
7219 {
7220         int index;
7221         cl_locnode_t *loc, *nearestloc;
7222         vec3_t center;
7223         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
7224         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
7225         {
7226                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
7227                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
7228         }
7229 }
7230
7231 void R_DrawDebugModel(entity_render_t *ent)
7232 {
7233         int i, j, k, l, flagsmask;
7234         const int *elements;
7235         q3mbrush_t *brush;
7236         msurface_t *surface;
7237         dp_model_t *model = ent->model;
7238         vec3_t v;
7239
7240         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
7241
7242         R_Mesh_ColorPointer(NULL, 0, 0);
7243         R_Mesh_ResetTextureState();
7244         R_SetupGenericShader(false);
7245         GL_DepthRange(0, 1);
7246         GL_DepthTest(!r_showdisabledepthtest.integer);
7247         GL_DepthMask(false);
7248         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7249
7250         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
7251         {
7252                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
7253                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
7254                 {
7255                         if (brush->colbrushf && brush->colbrushf->numtriangles)
7256                         {
7257                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
7258                                 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);
7259                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7260                         }
7261                 }
7262                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7263                 {
7264                         if (surface->num_collisiontriangles)
7265                         {
7266                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7267                                 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);
7268                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7269                         }
7270                 }
7271         }
7272
7273         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7274
7275         if (r_showtris.integer || r_shownormals.integer)
7276         {
7277                 if (r_showdisabledepthtest.integer)
7278                 {
7279                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7280                         GL_DepthMask(false);
7281                 }
7282                 else
7283                 {
7284                         GL_BlendFunc(GL_ONE, GL_ZERO);
7285                         GL_DepthMask(true);
7286                 }
7287                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7288                 {
7289                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7290                                 continue;
7291                         rsurface.texture = R_GetCurrentTexture(surface->texture);
7292                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7293                         {
7294                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7295                                 if (r_showtris.value > 0)
7296                                 {
7297                                         if (!rsurface.texture->currentlayers->depthmask)
7298                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7299                                         else if (ent == r_refdef.scene.worldentity)
7300                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7301                                         else
7302                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7303                                         elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7304                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7305                                         R_Mesh_ColorPointer(NULL, 0, 0);
7306                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7307                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7308                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7309                                         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);
7310                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7311                                         CHECKGLERROR
7312                                 }
7313                                 if (r_shownormals.value < 0)
7314                                 {
7315                                         qglBegin(GL_LINES);
7316                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7317                                         {
7318                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
7319                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7320                                                 qglVertex3f(v[0], v[1], v[2]);
7321                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7322                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7323                                                 qglVertex3f(v[0], v[1], v[2]);
7324                                         }
7325                                         qglEnd();
7326                                         CHECKGLERROR
7327                                 }
7328                                 if (r_shownormals.value > 0)
7329                                 {
7330                                         qglBegin(GL_LINES);
7331                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7332                                         {
7333                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
7334                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7335                                                 qglVertex3f(v[0], v[1], v[2]);
7336                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7337                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7338                                                 qglVertex3f(v[0], v[1], v[2]);
7339                                         }
7340                                         qglEnd();
7341                                         CHECKGLERROR
7342                                         qglBegin(GL_LINES);
7343                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7344                                         {
7345                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
7346                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
7347                                                 qglVertex3f(v[0], v[1], v[2]);
7348                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
7349                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7350                                                 qglVertex3f(v[0], v[1], v[2]);
7351                                         }
7352                                         qglEnd();
7353                                         CHECKGLERROR
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(0, 0, r_refdef.view.colorscale, 1);
7359                                                 qglVertex3f(v[0], v[1], v[2]);
7360                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + 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                                 }
7367                         }
7368                 }
7369                 rsurface.texture = NULL;
7370         }
7371 }
7372
7373 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
7374 int r_maxsurfacelist = 0;
7375 msurface_t **r_surfacelist = NULL;
7376 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7377 {
7378         int i, j, endj, f, flagsmask;
7379         texture_t *t;
7380         dp_model_t *model = r_refdef.scene.worldmodel;
7381         msurface_t *surfaces;
7382         unsigned char *update;
7383         int numsurfacelist = 0;
7384         if (model == NULL)
7385                 return;
7386
7387         if (r_maxsurfacelist < model->num_surfaces)
7388         {
7389                 r_maxsurfacelist = model->num_surfaces;
7390                 if (r_surfacelist)
7391                         Mem_Free(r_surfacelist);
7392                 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7393         }
7394
7395         RSurf_ActiveWorldEntity();
7396
7397         surfaces = model->data_surfaces;
7398         update = model->brushq1.lightmapupdateflags;
7399
7400         // update light styles on this submodel
7401         if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7402         {
7403                 model_brush_lightstyleinfo_t *style;
7404                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7405                 {
7406                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
7407                         {
7408                                 int *list = style->surfacelist;
7409                                 style->value = r_refdef.scene.lightstylevalue[style->style];
7410                                 for (j = 0;j < style->numsurfaces;j++)
7411                                         update[list[j]] = true;
7412                         }
7413                 }
7414         }
7415
7416         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7417
7418         if (debug)
7419         {
7420                 R_DrawDebugModel(r_refdef.scene.worldentity);
7421                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7422                 return;
7423         }
7424
7425         f = 0;
7426         t = NULL;
7427         rsurface.uselightmaptexture = false;
7428         rsurface.texture = NULL;
7429         rsurface.rtlight = NULL;
7430         numsurfacelist = 0;
7431         // add visible surfaces to draw list
7432         for (i = 0;i < model->nummodelsurfaces;i++)
7433         {
7434                 j = model->sortedmodelsurfaces[i];
7435                 if (r_refdef.viewcache.world_surfacevisible[j])
7436                         r_surfacelist[numsurfacelist++] = surfaces + j;
7437         }
7438         // update lightmaps if needed
7439         if (update)
7440                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7441                         if (r_refdef.viewcache.world_surfacevisible[j])
7442                                 if (update[j])
7443                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
7444         // don't do anything if there were no surfaces
7445         if (!numsurfacelist)
7446         {
7447                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7448                 return;
7449         }
7450         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7451         GL_AlphaTest(false);
7452
7453         // add to stats if desired
7454         if (r_speeds.integer && !skysurfaces && !depthonly)
7455         {
7456                 r_refdef.stats.world_surfaces += numsurfacelist;
7457                 for (j = 0;j < numsurfacelist;j++)
7458                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
7459         }
7460         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7461 }
7462
7463 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7464 {
7465         int i, j, endj, f, flagsmask;
7466         texture_t *t;
7467         dp_model_t *model = ent->model;
7468         msurface_t *surfaces;
7469         unsigned char *update;
7470         int numsurfacelist = 0;
7471         if (model == NULL)
7472                 return;
7473
7474         if (r_maxsurfacelist < model->num_surfaces)
7475         {
7476                 r_maxsurfacelist = model->num_surfaces;
7477                 if (r_surfacelist)
7478                         Mem_Free(r_surfacelist);
7479                 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7480         }
7481
7482         // if the model is static it doesn't matter what value we give for
7483         // wantnormals and wanttangents, so this logic uses only rules applicable
7484         // to a model, knowing that they are meaningless otherwise
7485         if (ent == r_refdef.scene.worldentity)
7486                 RSurf_ActiveWorldEntity();
7487         else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3))
7488                 RSurf_ActiveModelEntity(ent, false, false);
7489         else
7490                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
7491
7492         surfaces = model->data_surfaces;
7493         update = model->brushq1.lightmapupdateflags;
7494
7495         // update light styles
7496         if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7497         {
7498                 model_brush_lightstyleinfo_t *style;
7499                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7500                 {
7501                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
7502                         {
7503                                 int *list = style->surfacelist;
7504                                 style->value = r_refdef.scene.lightstylevalue[style->style];
7505                                 for (j = 0;j < style->numsurfaces;j++)
7506                                         update[list[j]] = true;
7507                         }
7508                 }
7509         }
7510
7511         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7512
7513         if (debug)
7514         {
7515                 R_DrawDebugModel(ent);
7516                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7517                 return;
7518         }
7519
7520         f = 0;
7521         t = NULL;
7522         rsurface.uselightmaptexture = false;
7523         rsurface.texture = NULL;
7524         rsurface.rtlight = NULL;
7525         numsurfacelist = 0;
7526         // add visible surfaces to draw list
7527         for (i = 0;i < model->nummodelsurfaces;i++)
7528                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
7529         // don't do anything if there were no surfaces
7530         if (!numsurfacelist)
7531         {
7532                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7533                 return;
7534         }
7535         // update lightmaps if needed
7536         if (update)
7537                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7538                         if (update[j])
7539                                 R_BuildLightMap(ent, surfaces + j);
7540         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7541         GL_AlphaTest(false);
7542
7543         // add to stats if desired
7544         if (r_speeds.integer && !skysurfaces && !depthonly)
7545         {
7546                 r_refdef.stats.entities_surfaces += numsurfacelist;
7547                 for (j = 0;j < numsurfacelist;j++)
7548                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
7549         }
7550         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7551 }