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