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