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