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