]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
fix bug with alt textures (pressed buttons in q1bsp)
[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.ent_alttextures && 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.ent_alttextures = false;
5967         rsurface.basepolygonfactor = r_refdef.polygonfactor;
5968         rsurface.basepolygonoffset = r_refdef.polygonoffset;
5969         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
5970         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5971         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5972         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5973         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5974         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5975         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5976         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5977         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5978         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
5979         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5980         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5981         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
5982         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5983         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5984         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
5985         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5986         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5987         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
5988         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5989         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5990         rsurface.modelelement3i = model->surfmesh.data_element3i;
5991         rsurface.modelelement3s = model->surfmesh.data_element3s;
5992         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5993         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5994         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5995         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5996         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5997         rsurface.modelsurfaces = model->data_surfaces;
5998         rsurface.generatedvertex = false;
5999         rsurface.vertex3f  = rsurface.modelvertex3f;
6000         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6001         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6002         rsurface.svector3f = rsurface.modelsvector3f;
6003         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6004         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6005         rsurface.tvector3f = rsurface.modeltvector3f;
6006         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6007         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6008         rsurface.normal3f  = rsurface.modelnormal3f;
6009         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6010         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6011         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6012 }
6013
6014 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6015 {
6016         dp_model_t *model = ent->model;
6017         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
6018         //      return;
6019         rsurface.entity = (entity_render_t *)ent;
6020         rsurface.ent_skinnum = ent->skinnum;
6021         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;
6022         rsurface.ent_shadertime = ent->shadertime;
6023         Vector4Set(rsurface.ent_color, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha);
6024         rsurface.ent_flags = ent->flags;
6025         if (rsurface.array_size < model->surfmesh.num_vertices)
6026                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6027         rsurface.matrix = ent->matrix;
6028         rsurface.inversematrix = ent->inversematrix;
6029         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6030         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6031         R_Mesh_Matrix(&rsurface.matrix);
6032         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6033         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6034         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6035         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6036         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6037         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6038         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
6039         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
6040         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
6041         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
6042         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
6043         VectorCopy(ent->glowmod, rsurface.glowmod);
6044         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
6045         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
6046         rsurface.basepolygonfactor = r_refdef.polygonfactor;
6047         rsurface.basepolygonoffset = r_refdef.polygonoffset;
6048         if (ent->model->brush.submodel)
6049         {
6050                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
6051                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
6052         }
6053         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
6054         {
6055                 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
6056                 {
6057                         rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
6058                         rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
6059                         rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
6060                         rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
6061                 }
6062                 else if (wanttangents)
6063                 {
6064                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6065                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6066                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6067                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6068                         model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
6069                 }
6070                 else if (wantnormals)
6071                 {
6072                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6073                         rsurface.modelsvector3f = NULL;
6074                         rsurface.modeltvector3f = NULL;
6075                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6076                         model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
6077                 }
6078                 else
6079                 {
6080                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6081                         rsurface.modelsvector3f = NULL;
6082                         rsurface.modeltvector3f = NULL;
6083                         rsurface.modelnormal3f = NULL;
6084                         model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
6085                 }
6086                 rsurface.modelvertex3f_bufferobject = 0;
6087                 rsurface.modelvertex3f_bufferoffset = 0;
6088                 rsurface.modelsvector3f_bufferobject = 0;
6089                 rsurface.modelsvector3f_bufferoffset = 0;
6090                 rsurface.modeltvector3f_bufferobject = 0;
6091                 rsurface.modeltvector3f_bufferoffset = 0;
6092                 rsurface.modelnormal3f_bufferobject = 0;
6093                 rsurface.modelnormal3f_bufferoffset = 0;
6094                 rsurface.generatedvertex = true;
6095         }
6096         else
6097         {
6098                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
6099                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6100                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6101                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6102                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6103                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6104                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6105                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6106                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6107                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
6108                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6109                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6110                 rsurface.generatedvertex = false;
6111         }
6112         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
6113         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6114         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6115         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
6116         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6117         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6118         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
6119         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6120         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6121         rsurface.modelelement3i = model->surfmesh.data_element3i;
6122         rsurface.modelelement3s = model->surfmesh.data_element3s;
6123         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6124         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6125         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6126         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6127         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6128         rsurface.modelsurfaces = model->data_surfaces;
6129         rsurface.vertex3f  = rsurface.modelvertex3f;
6130         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6131         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6132         rsurface.svector3f = rsurface.modelsvector3f;
6133         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6134         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6135         rsurface.tvector3f = rsurface.modeltvector3f;
6136         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6137         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6138         rsurface.normal3f  = rsurface.modelnormal3f;
6139         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6140         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6141         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6142 }
6143
6144 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)
6145 {
6146         rsurface.entity = r_refdef.scene.worldentity;
6147         rsurface.ent_skinnum = 0;
6148         rsurface.ent_qwskin = -1;
6149         rsurface.ent_shadertime = shadertime;
6150         Vector4Set(rsurface.ent_color, r, g, b, a);
6151         rsurface.ent_flags = entflags;
6152         rsurface.modelnum_vertices = numvertices;
6153         rsurface.modelnum_triangles = numtriangles;
6154         if (rsurface.array_size < rsurface.modelnum_vertices)
6155                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
6156         rsurface.matrix = *matrix;
6157         rsurface.inversematrix = *inversematrix;
6158         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6159         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6160         R_Mesh_Matrix(&rsurface.matrix);
6161         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6162         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6163         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6164         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6165         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6166         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6167         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6168         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6169         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6170         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6171         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6172         VectorSet(rsurface.glowmod, 1, 1, 1);
6173         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6174         rsurface.frameblend[0].lerp = 1;
6175         rsurface.ent_alttextures = false;
6176         rsurface.basepolygonfactor = r_refdef.polygonfactor;
6177         rsurface.basepolygonoffset = r_refdef.polygonoffset;
6178         if (wanttangents)
6179         {
6180                 rsurface.modelvertex3f = vertex3f;
6181                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
6182                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
6183                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6184         }
6185         else if (wantnormals)
6186         {
6187                 rsurface.modelvertex3f = vertex3f;
6188                 rsurface.modelsvector3f = NULL;
6189                 rsurface.modeltvector3f = NULL;
6190                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6191         }
6192         else
6193         {
6194                 rsurface.modelvertex3f = vertex3f;
6195                 rsurface.modelsvector3f = NULL;
6196                 rsurface.modeltvector3f = NULL;
6197                 rsurface.modelnormal3f = NULL;
6198         }
6199         rsurface.modelvertex3f_bufferobject = 0;
6200         rsurface.modelvertex3f_bufferoffset = 0;
6201         rsurface.modelsvector3f_bufferobject = 0;
6202         rsurface.modelsvector3f_bufferoffset = 0;
6203         rsurface.modeltvector3f_bufferobject = 0;
6204         rsurface.modeltvector3f_bufferoffset = 0;
6205         rsurface.modelnormal3f_bufferobject = 0;
6206         rsurface.modelnormal3f_bufferoffset = 0;
6207         rsurface.generatedvertex = true;
6208         rsurface.modellightmapcolor4f  = color4f;
6209         rsurface.modellightmapcolor4f_bufferobject = 0;
6210         rsurface.modellightmapcolor4f_bufferoffset = 0;
6211         rsurface.modeltexcoordtexture2f  = texcoord2f;
6212         rsurface.modeltexcoordtexture2f_bufferobject = 0;
6213         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
6214         rsurface.modeltexcoordlightmap2f  = NULL;
6215         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
6216         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
6217         rsurface.modelelement3i = element3i;
6218         rsurface.modelelement3s = element3s;
6219         rsurface.modelelement3i_bufferobject = 0;
6220         rsurface.modelelement3s_bufferobject = 0;
6221         rsurface.modellightmapoffsets = NULL;
6222         rsurface.modelsurfaces = NULL;
6223         rsurface.vertex3f  = rsurface.modelvertex3f;
6224         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6225         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6226         rsurface.svector3f = rsurface.modelsvector3f;
6227         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6228         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6229         rsurface.tvector3f = rsurface.modeltvector3f;
6230         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6231         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6232         rsurface.normal3f  = rsurface.modelnormal3f;
6233         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6234         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6235         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6236
6237         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
6238         {
6239                 if ((wantnormals || wanttangents) && !normal3f)
6240                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6241                 if (wanttangents && !svector3f)
6242                         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);
6243         }
6244 }
6245
6246 float RSurf_FogPoint(const float *v)
6247 {
6248         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6249         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
6250         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
6251         float FogHeightFade = r_refdef.fogheightfade;
6252         float fogfrac;
6253         unsigned int fogmasktableindex;
6254         if (r_refdef.fogplaneviewabove)
6255                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6256         else
6257                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6258         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
6259         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6260 }
6261
6262 float RSurf_FogVertex(const float *v)
6263 {
6264         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6265         float FogPlaneViewDist = rsurface.fogplaneviewdist;
6266         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
6267         float FogHeightFade = rsurface.fogheightfade;
6268         float fogfrac;
6269         unsigned int fogmasktableindex;
6270         if (r_refdef.fogplaneviewabove)
6271                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6272         else
6273                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6274         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
6275         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6276 }
6277
6278 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6279 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
6280 {
6281         int deformindex;
6282         int texturesurfaceindex;
6283         int i, j;
6284         float amplitude;
6285         float animpos;
6286         float scale;
6287         const float *v1, *in_tc;
6288         float *out_tc;
6289         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6290         float waveparms[4];
6291         q3shaderinfo_deform_t *deform;
6292         // 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
6293         if (rsurface.generatedvertex)
6294         {
6295                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6296                         generatenormals = true;
6297                 for (i = 0;i < Q3MAXDEFORMS;i++)
6298                 {
6299                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6300                         {
6301                                 generatetangents = true;
6302                                 generatenormals = true;
6303                         }
6304                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6305                                 generatenormals = true;
6306                 }
6307                 if (generatenormals && !rsurface.modelnormal3f)
6308                 {
6309                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6310                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6311                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6312                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6313                 }
6314                 if (generatetangents && !rsurface.modelsvector3f)
6315                 {
6316                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6317                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6318                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6319                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6320                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6321                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6322                         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);
6323                 }
6324         }
6325         rsurface.vertex3f  = rsurface.modelvertex3f;
6326         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6327         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6328         rsurface.svector3f = rsurface.modelsvector3f;
6329         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6330         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6331         rsurface.tvector3f = rsurface.modeltvector3f;
6332         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6333         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6334         rsurface.normal3f  = rsurface.modelnormal3f;
6335         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6336         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6337         // if vertices are deformed (sprite flares and things in maps, possibly
6338         // water waves, bulges and other deformations), generate them into
6339         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6340         // (may be static model data or generated data for an animated model, or
6341         //  the previous deform pass)
6342         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6343         {
6344                 switch (deform->deform)
6345                 {
6346                 default:
6347                 case Q3DEFORM_PROJECTIONSHADOW:
6348                 case Q3DEFORM_TEXT0:
6349                 case Q3DEFORM_TEXT1:
6350                 case Q3DEFORM_TEXT2:
6351                 case Q3DEFORM_TEXT3:
6352                 case Q3DEFORM_TEXT4:
6353                 case Q3DEFORM_TEXT5:
6354                 case Q3DEFORM_TEXT6:
6355                 case Q3DEFORM_TEXT7:
6356                 case Q3DEFORM_NONE:
6357                         break;
6358                 case Q3DEFORM_AUTOSPRITE:
6359                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6360                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6361                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6362                         VectorNormalize(newforward);
6363                         VectorNormalize(newright);
6364                         VectorNormalize(newup);
6365                         // make deformed versions of only the model vertices used by the specified surfaces
6366                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6367                         {
6368                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6369                                 // a single autosprite surface can contain multiple sprites...
6370                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
6371                                 {
6372                                         VectorClear(center);
6373                                         for (i = 0;i < 4;i++)
6374                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6375                                         VectorScale(center, 0.25f, center);
6376                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
6377                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6378                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6379                                         for (i = 0;i < 4;i++)
6380                                         {
6381                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6382                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6383                                         }
6384                                 }
6385                                 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);
6386                                 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);
6387                         }
6388                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
6389                         rsurface.vertex3f_bufferobject = 0;
6390                         rsurface.vertex3f_bufferoffset = 0;
6391                         rsurface.svector3f = rsurface.array_deformedsvector3f;
6392                         rsurface.svector3f_bufferobject = 0;
6393                         rsurface.svector3f_bufferoffset = 0;
6394                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
6395                         rsurface.tvector3f_bufferobject = 0;
6396                         rsurface.tvector3f_bufferoffset = 0;
6397                         rsurface.normal3f = rsurface.array_deformednormal3f;
6398                         rsurface.normal3f_bufferobject = 0;
6399                         rsurface.normal3f_bufferoffset = 0;
6400                         break;
6401                 case Q3DEFORM_AUTOSPRITE2:
6402                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6403                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6404                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6405                         VectorNormalize(newforward);
6406                         VectorNormalize(newright);
6407                         VectorNormalize(newup);
6408                         // make deformed versions of only the model vertices used by the specified surfaces
6409                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6410                         {
6411                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6412                                 const float *v1, *v2;
6413                                 vec3_t start, end;
6414                                 float f, l;
6415                                 struct
6416                                 {
6417                                         float length2;
6418                                         const float *v1;
6419                                         const float *v2;
6420                                 }
6421                                 shortest[2];
6422                                 memset(shortest, 0, sizeof(shortest));
6423                                 // a single autosprite surface can contain multiple sprites...
6424                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
6425                                 {
6426                                         VectorClear(center);
6427                                         for (i = 0;i < 4;i++)
6428                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6429                                         VectorScale(center, 0.25f, center);
6430                                         // find the two shortest edges, then use them to define the
6431                                         // axis vectors for rotating around the central axis
6432                                         for (i = 0;i < 6;i++)
6433                                         {
6434                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6435                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6436 #if 0
6437                                                 Debug_PolygonBegin(NULL, 0);
6438                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6439                                                 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);
6440                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6441                                                 Debug_PolygonEnd();
6442 #endif
6443                                                 l = VectorDistance2(v1, v2);
6444                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6445                                                 if (v1[2] != v2[2])
6446                                                         l += (1.0f / 1024.0f);
6447                                                 if (shortest[0].length2 > l || i == 0)
6448                                                 {
6449                                                         shortest[1] = shortest[0];
6450                                                         shortest[0].length2 = l;
6451                                                         shortest[0].v1 = v1;
6452                                                         shortest[0].v2 = v2;
6453                                                 }
6454                                                 else if (shortest[1].length2 > l || i == 1)
6455                                                 {
6456                                                         shortest[1].length2 = l;
6457                                                         shortest[1].v1 = v1;
6458                                                         shortest[1].v2 = v2;
6459                                                 }
6460                                         }
6461                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6462                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6463 #if 0
6464                                         Debug_PolygonBegin(NULL, 0);
6465                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6466                                         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);
6467                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6468                                         Debug_PolygonEnd();
6469 #endif
6470                                         // this calculates the right vector from the shortest edge
6471                                         // and the up vector from the edge midpoints
6472                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6473                                         VectorNormalize(right);
6474                                         VectorSubtract(end, start, up);
6475                                         VectorNormalize(up);
6476                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6477                                         VectorSubtract(rsurface.localvieworigin, center, forward);
6478                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6479                                         VectorNegate(forward, forward);
6480                                         VectorReflect(forward, 0, up, forward);
6481                                         VectorNormalize(forward);
6482                                         CrossProduct(up, forward, newright);
6483                                         VectorNormalize(newright);
6484 #if 0
6485                                         Debug_PolygonBegin(NULL, 0);
6486                                         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);
6487                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6488                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
6489                                         Debug_PolygonEnd();
6490 #endif
6491 #if 0
6492                                         Debug_PolygonBegin(NULL, 0);
6493                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6494                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6495                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
6496                                         Debug_PolygonEnd();
6497 #endif
6498                                         // rotate the quad around the up axis vector, this is made
6499                                         // especially easy by the fact we know the quad is flat,
6500                                         // so we only have to subtract the center position and
6501                                         // measure distance along the right vector, and then
6502                                         // multiply that by the newright vector and add back the
6503                                         // center position
6504                                         // we also need to subtract the old position to undo the
6505                                         // displacement from the center, which we do with a
6506                                         // DotProduct, the subtraction/addition of center is also
6507                                         // optimized into DotProducts here
6508                                         l = DotProduct(right, center);
6509                                         for (i = 0;i < 4;i++)
6510                                         {
6511                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6512                                                 f = DotProduct(right, v1) - l;
6513                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6514                                         }
6515                                 }
6516                                 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);
6517                                 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);
6518                         }
6519                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
6520                         rsurface.vertex3f_bufferobject = 0;
6521                         rsurface.vertex3f_bufferoffset = 0;
6522                         rsurface.svector3f = rsurface.array_deformedsvector3f;
6523                         rsurface.svector3f_bufferobject = 0;
6524                         rsurface.svector3f_bufferoffset = 0;
6525                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
6526                         rsurface.tvector3f_bufferobject = 0;
6527                         rsurface.tvector3f_bufferoffset = 0;
6528                         rsurface.normal3f = rsurface.array_deformednormal3f;
6529                         rsurface.normal3f_bufferobject = 0;
6530                         rsurface.normal3f_bufferoffset = 0;
6531                         break;
6532                 case Q3DEFORM_NORMAL:
6533                         // deform the normals to make reflections wavey
6534                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6535                         {
6536                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6537                                 for (j = 0;j < surface->num_vertices;j++)
6538                                 {
6539                                         float vertex[3];
6540                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
6541                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6542                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
6543                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6544                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6545                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6546                                         VectorNormalize(normal);
6547                                 }
6548                                 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);
6549                         }
6550                         rsurface.svector3f = rsurface.array_deformedsvector3f;
6551                         rsurface.svector3f_bufferobject = 0;
6552                         rsurface.svector3f_bufferoffset = 0;
6553                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
6554                         rsurface.tvector3f_bufferobject = 0;
6555                         rsurface.tvector3f_bufferoffset = 0;
6556                         rsurface.normal3f = rsurface.array_deformednormal3f;
6557                         rsurface.normal3f_bufferobject = 0;
6558                         rsurface.normal3f_bufferoffset = 0;
6559                         break;
6560                 case Q3DEFORM_WAVE:
6561                         // deform vertex array to make wavey water and flags and such
6562                         waveparms[0] = deform->waveparms[0];
6563                         waveparms[1] = deform->waveparms[1];
6564                         waveparms[2] = deform->waveparms[2];
6565                         waveparms[3] = deform->waveparms[3];
6566                         // this is how a divisor of vertex influence on deformation
6567                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6568                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6569                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6570                         {
6571                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6572                                 for (j = 0;j < surface->num_vertices;j++)
6573                                 {
6574                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
6575                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
6576                                         // if the wavefunc depends on time, evaluate it per-vertex
6577                                         if (waveparms[3])
6578                                         {
6579                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6580                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6581                                         }
6582                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
6583                                 }
6584                         }
6585                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
6586                         rsurface.vertex3f_bufferobject = 0;
6587                         rsurface.vertex3f_bufferoffset = 0;
6588                         break;
6589                 case Q3DEFORM_BULGE:
6590                         // deform vertex array to make the surface have moving bulges
6591                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6592                         {
6593                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6594                                 for (j = 0;j < surface->num_vertices;j++)
6595                                 {
6596                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6597                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6598                                 }
6599                         }
6600                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
6601                         rsurface.vertex3f_bufferobject = 0;
6602                         rsurface.vertex3f_bufferoffset = 0;
6603                         break;
6604                 case Q3DEFORM_MOVE:
6605                         // deform vertex array
6606                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6607                         VectorScale(deform->parms, scale, waveparms);
6608                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6609                         {
6610                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6611                                 for (j = 0;j < surface->num_vertices;j++)
6612                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6613                         }
6614                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
6615                         rsurface.vertex3f_bufferobject = 0;
6616                         rsurface.vertex3f_bufferoffset = 0;
6617                         break;
6618                 }
6619         }
6620         // generate texcoords based on the chosen texcoord source
6621         switch(rsurface.texture->tcgen.tcgen)
6622         {
6623         default:
6624         case Q3TCGEN_TEXTURE:
6625                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
6626                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
6627                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
6628                 break;
6629         case Q3TCGEN_LIGHTMAP:
6630                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
6631                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
6632                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
6633                 break;
6634         case Q3TCGEN_VECTOR:
6635                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6636                 {
6637                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6638                         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)
6639                         {
6640                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6641                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6642                         }
6643                 }
6644                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
6645                 rsurface.texcoordtexture2f_bufferobject  = 0;
6646                 rsurface.texcoordtexture2f_bufferoffset  = 0;
6647                 break;
6648         case Q3TCGEN_ENVIRONMENT:
6649                 // make environment reflections using a spheremap
6650                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6651                 {
6652                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6653                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6654                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6655                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6656                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6657                         {
6658                                 // identical to Q3A's method, but executed in worldspace so
6659                                 // carried models can be shiny too
6660
6661                                 float viewer[3], d, reflected[3], worldreflected[3];
6662
6663                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
6664                                 // VectorNormalize(viewer);
6665
6666                                 d = DotProduct(normal, viewer);
6667
6668                                 reflected[0] = normal[0]*2*d - viewer[0];
6669                                 reflected[1] = normal[1]*2*d - viewer[1];
6670                                 reflected[2] = normal[2]*2*d - viewer[2];
6671                                 // note: this is proportinal to viewer, so we can normalize later
6672
6673                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6674                                 VectorNormalize(worldreflected);
6675
6676                                 // note: this sphere map only uses world x and z!
6677                                 // so positive and negative y will LOOK THE SAME.
6678                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6679                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6680                         }
6681                 }
6682                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
6683                 rsurface.texcoordtexture2f_bufferobject  = 0;
6684                 rsurface.texcoordtexture2f_bufferoffset  = 0;
6685                 break;
6686         }
6687         // the only tcmod that needs software vertex processing is turbulent, so
6688         // check for it here and apply the changes if needed
6689         // and we only support that as the first one
6690         // (handling a mixture of turbulent and other tcmods would be problematic
6691         //  without punting it entirely to a software path)
6692         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6693         {
6694                 amplitude = rsurface.texture->tcmods[0].parms[1];
6695                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6696                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6697                 {
6698                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6699                         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)
6700                         {
6701                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6702                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6703                         }
6704                 }
6705                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
6706                 rsurface.texcoordtexture2f_bufferobject  = 0;
6707                 rsurface.texcoordtexture2f_bufferoffset  = 0;
6708         }
6709         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
6710         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6711         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6712         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6713 }
6714
6715 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6716 {
6717         int i, j;
6718         const msurface_t *surface = texturesurfacelist[0];
6719         const msurface_t *surface2;
6720         int firstvertex;
6721         int endvertex;
6722         int numvertices;
6723         int numtriangles;
6724         // TODO: lock all array ranges before render, rather than on each surface
6725         if (texturenumsurfaces == 1)
6726         {
6727                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6728                 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);
6729         }
6730         else if (r_batchmode.integer == 2)
6731         {
6732                 #define MAXBATCHTRIANGLES 4096
6733                 int batchtriangles = 0;
6734                 int batchelements[MAXBATCHTRIANGLES*3];
6735                 for (i = 0;i < texturenumsurfaces;i = j)
6736                 {
6737                         surface = texturesurfacelist[i];
6738                         j = i + 1;
6739                         if (surface->num_triangles > MAXBATCHTRIANGLES)
6740                         {
6741                                 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);
6742                                 continue;
6743                         }
6744                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6745                         batchtriangles = surface->num_triangles;
6746                         firstvertex = surface->num_firstvertex;
6747                         endvertex = surface->num_firstvertex + surface->num_vertices;
6748                         for (;j < texturenumsurfaces;j++)
6749                         {
6750                                 surface2 = texturesurfacelist[j];
6751                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6752                                         break;
6753                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6754                                 batchtriangles += surface2->num_triangles;
6755                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
6756                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6757                         }
6758                         surface2 = texturesurfacelist[j-1];
6759                         numvertices = endvertex - firstvertex;
6760                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6761                 }
6762         }
6763         else if (r_batchmode.integer == 1)
6764         {
6765                 for (i = 0;i < texturenumsurfaces;i = j)
6766                 {
6767                         surface = texturesurfacelist[i];
6768                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6769                                 if (texturesurfacelist[j] != surface2)
6770                                         break;
6771                         surface2 = texturesurfacelist[j-1];
6772                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6773                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6774                         GL_LockArrays(surface->num_firstvertex, numvertices);
6775                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6776                 }
6777         }
6778         else
6779         {
6780                 for (i = 0;i < texturenumsurfaces;i++)
6781                 {
6782                         surface = texturesurfacelist[i];
6783                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6784                         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);
6785                 }
6786         }
6787 }
6788
6789 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6790 {
6791         int i, planeindex, vertexindex;
6792         float d, bestd;
6793         vec3_t vert;
6794         const float *v;
6795         r_waterstate_waterplane_t *p, *bestp;
6796         const msurface_t *surface;
6797         if (r_waterstate.renderingscene)
6798                 return;
6799         for (i = 0;i < texturenumsurfaces;i++)
6800         {
6801                 surface = texturesurfacelist[i];
6802                 if (lightmaptexunit >= 0)
6803                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6804                 if (deluxemaptexunit >= 0)
6805                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6806                 // pick the closest matching water plane
6807                 bestd = 0;
6808                 bestp = NULL;
6809                 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6810                 {
6811                         d = 0;
6812                         for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6813                         {
6814                                 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6815                                 d += fabs(PlaneDiff(vert, &p->plane));
6816                         }
6817                         if (bestd > d || !bestp)
6818                         {
6819                                 bestd = d;
6820                                 bestp = p;
6821                         }
6822                 }
6823                 if (bestp)
6824                 {
6825                         if (refractiontexunit >= 0)
6826                                 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6827                         if (reflectiontexunit >= 0)
6828                                 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6829                 }
6830                 else
6831                 {
6832                         if (refractiontexunit >= 0)
6833                                 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6834                         if (reflectiontexunit >= 0)
6835                                 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6836                 }
6837                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6838                 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);
6839         }
6840 }
6841
6842 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6843 {
6844         int i;
6845         int j;
6846         const msurface_t *surface = texturesurfacelist[0];
6847         const msurface_t *surface2;
6848         int firstvertex;
6849         int endvertex;
6850         int numvertices;
6851         int numtriangles;
6852         // TODO: lock all array ranges before render, rather than on each surface
6853         if (texturenumsurfaces == 1)
6854         {
6855                 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6856                 if (deluxemaptexunit >= 0)
6857                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6858                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6859                 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);
6860         }
6861         else if (r_batchmode.integer == 2)
6862         {
6863                 #define MAXBATCHTRIANGLES 4096
6864                 int batchtriangles = 0;
6865                 int batchelements[MAXBATCHTRIANGLES*3];
6866                 for (i = 0;i < texturenumsurfaces;i = j)
6867                 {
6868                         surface = texturesurfacelist[i];
6869                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6870                         if (deluxemaptexunit >= 0)
6871                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6872                         j = i + 1;
6873                         if (surface->num_triangles > MAXBATCHTRIANGLES)
6874                         {
6875                                 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);
6876                                 continue;
6877                         }
6878                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6879                         batchtriangles = surface->num_triangles;
6880                         firstvertex = surface->num_firstvertex;
6881                         endvertex = surface->num_firstvertex + surface->num_vertices;
6882                         for (;j < texturenumsurfaces;j++)
6883                         {
6884                                 surface2 = texturesurfacelist[j];
6885                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6886                                         break;
6887                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6888                                 batchtriangles += surface2->num_triangles;
6889                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
6890                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6891                         }
6892                         surface2 = texturesurfacelist[j-1];
6893                         numvertices = endvertex - firstvertex;
6894                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6895                 }
6896         }
6897         else if (r_batchmode.integer == 1)
6898         {
6899 #if 0
6900                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6901                 for (i = 0;i < texturenumsurfaces;i = j)
6902                 {
6903                         surface = texturesurfacelist[i];
6904                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6905                                 if (texturesurfacelist[j] != surface2)
6906                                         break;
6907                         Con_Printf(" %i", j - i);
6908                 }
6909                 Con_Printf("\n");
6910                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6911 #endif
6912                 for (i = 0;i < texturenumsurfaces;i = j)
6913                 {
6914                         surface = texturesurfacelist[i];
6915                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6916                         if (deluxemaptexunit >= 0)
6917                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6918                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6919                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6920                                         break;
6921 #if 0
6922                         Con_Printf(" %i", j - i);
6923 #endif
6924                         surface2 = texturesurfacelist[j-1];
6925                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6926                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6927                         GL_LockArrays(surface->num_firstvertex, numvertices);
6928                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6929                 }
6930 #if 0
6931                 Con_Printf("\n");
6932 #endif
6933         }
6934         else
6935         {
6936                 for (i = 0;i < texturenumsurfaces;i++)
6937                 {
6938                         surface = texturesurfacelist[i];
6939                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6940                         if (deluxemaptexunit >= 0)
6941                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6942                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6943                         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);
6944                 }
6945         }
6946 }
6947
6948 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6949 {
6950         int j;
6951         int texturesurfaceindex;
6952         if (r_showsurfaces.integer == 2)
6953         {
6954                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6955                 {
6956                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6957                         for (j = 0;j < surface->num_triangles;j++)
6958                         {
6959                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
6960                                 GL_Color(f, f, f, 1);
6961                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6962                         }
6963                 }
6964         }
6965         else
6966         {
6967                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6968                 {
6969                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6970                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
6971                         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);
6972                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6973                         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);
6974                 }
6975         }
6976 }
6977
6978 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6979 {
6980         int texturesurfaceindex;
6981         int i;
6982         const float *v;
6983         float *c2;
6984         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6985         {
6986                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6987                 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)
6988                 {
6989                         c2[0] = 0.5;
6990                         c2[1] = 0.5;
6991                         c2[2] = 0.5;
6992                         c2[3] = 1;
6993                 }
6994         }
6995         rsurface.lightmapcolor4f = rsurface.array_color4f;
6996         rsurface.lightmapcolor4f_bufferobject = 0;
6997         rsurface.lightmapcolor4f_bufferoffset = 0;
6998 }
6999
7000 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7001 {
7002         int texturesurfaceindex;
7003         int i;
7004         float f;
7005         const float *v;
7006         const float *c;
7007         float *c2;
7008         if (rsurface.lightmapcolor4f)
7009         {
7010                 // generate color arrays for the surfaces in this list
7011                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7012                 {
7013                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7014                         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)
7015                         {
7016                                 f = RSurf_FogVertex(v);
7017                                 c2[0] = c[0] * f;
7018                                 c2[1] = c[1] * f;
7019                                 c2[2] = c[2] * f;
7020                                 c2[3] = c[3];
7021                         }
7022                 }
7023         }
7024         else
7025         {
7026                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7027                 {
7028                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7029                         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)
7030                         {
7031                                 f = RSurf_FogVertex(v);
7032                                 c2[0] = f;
7033                                 c2[1] = f;
7034                                 c2[2] = f;
7035                                 c2[3] = 1;
7036                         }
7037                 }
7038         }
7039         rsurface.lightmapcolor4f = rsurface.array_color4f;
7040         rsurface.lightmapcolor4f_bufferobject = 0;
7041         rsurface.lightmapcolor4f_bufferoffset = 0;
7042 }
7043
7044 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7045 {
7046         int texturesurfaceindex;
7047         int i;
7048         float f;
7049         const float *v;
7050         const float *c;
7051         float *c2;
7052         if (!rsurface.lightmapcolor4f)
7053                 return;
7054         // generate color arrays for the surfaces in this list
7055         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7056         {
7057                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7058                 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)
7059                 {
7060                         f = RSurf_FogVertex(v);
7061                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
7062                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
7063                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
7064                         c2[3] = c[3];
7065                 }
7066         }
7067         rsurface.lightmapcolor4f = rsurface.array_color4f;
7068         rsurface.lightmapcolor4f_bufferobject = 0;
7069         rsurface.lightmapcolor4f_bufferoffset = 0;
7070 }
7071
7072 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
7073 {
7074         int texturesurfaceindex;
7075         int i;
7076         const float *c;
7077         float *c2;
7078         if (!rsurface.lightmapcolor4f)
7079                 return;
7080         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7081         {
7082                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7083                 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)
7084                 {
7085                         c2[0] = c[0] * r;
7086                         c2[1] = c[1] * g;
7087                         c2[2] = c[2] * b;
7088                         c2[3] = c[3] * a;
7089                 }
7090         }
7091         rsurface.lightmapcolor4f = rsurface.array_color4f;
7092         rsurface.lightmapcolor4f_bufferobject = 0;
7093         rsurface.lightmapcolor4f_bufferoffset = 0;
7094 }
7095
7096 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7097 {
7098         int texturesurfaceindex;
7099         int i;
7100         const float *c;
7101         float *c2;
7102         if (!rsurface.lightmapcolor4f)
7103                 return;
7104         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7105         {
7106                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7107                 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)
7108                 {
7109                         c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
7110                         c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
7111                         c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
7112                         c2[3] = c[3];
7113                 }
7114         }
7115         rsurface.lightmapcolor4f = rsurface.array_color4f;
7116         rsurface.lightmapcolor4f_bufferobject = 0;
7117         rsurface.lightmapcolor4f_bufferoffset = 0;
7118 }
7119
7120 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7121 {
7122         // TODO: optimize
7123         rsurface.lightmapcolor4f = NULL;
7124         rsurface.lightmapcolor4f_bufferobject = 0;
7125         rsurface.lightmapcolor4f_bufferoffset = 0;
7126         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7127         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7128         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7129         GL_Color(r, g, b, a);
7130         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
7131 }
7132
7133 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7134 {
7135         // TODO: optimize applyfog && applycolor case
7136         // just apply fog if necessary, and tint the fog color array if necessary
7137         rsurface.lightmapcolor4f = NULL;
7138         rsurface.lightmapcolor4f_bufferobject = 0;
7139         rsurface.lightmapcolor4f_bufferoffset = 0;
7140         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7141         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7142         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7143         GL_Color(r, g, b, a);
7144         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7145 }
7146
7147 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7148 {
7149         int texturesurfaceindex;
7150         int i;
7151         float *c;
7152         // TODO: optimize
7153         if (texturesurfacelist[0]->lightmapinfo)
7154         {
7155                 // generate color arrays for the surfaces in this list
7156                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7157                 {
7158                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7159                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
7160                         {
7161                                 if (surface->lightmapinfo->samples)
7162                                 {
7163                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
7164                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
7165                                         VectorScale(lm, scale, c);
7166                                         if (surface->lightmapinfo->styles[1] != 255)
7167                                         {
7168                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
7169                                                 lm += size3;
7170                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
7171                                                 VectorMA(c, scale, lm, c);
7172                                                 if (surface->lightmapinfo->styles[2] != 255)
7173                                                 {
7174                                                         lm += size3;
7175                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
7176                                                         VectorMA(c, scale, lm, c);
7177                                                         if (surface->lightmapinfo->styles[3] != 255)
7178                                                         {
7179                                                                 lm += size3;
7180                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
7181                                                                 VectorMA(c, scale, lm, c);
7182                                                         }
7183                                                 }
7184                                         }
7185                                 }
7186                                 else
7187                                         VectorClear(c);
7188                                 c[3] = 1;
7189                         }
7190                 }
7191                 rsurface.lightmapcolor4f = rsurface.array_color4f;
7192                 rsurface.lightmapcolor4f_bufferobject = 0;
7193                 rsurface.lightmapcolor4f_bufferoffset = 0;
7194         }
7195         else
7196         {
7197                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7198                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7199                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7200         }
7201         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7202         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7203         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7204         GL_Color(r, g, b, a);
7205         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7206 }
7207
7208 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
7209 {
7210         int texturesurfaceindex;
7211         int i;
7212         float f;
7213         float alpha;
7214         const float *v;
7215         const float *n;
7216         float *c;
7217         vec3_t ambientcolor;
7218         vec3_t diffusecolor;
7219         vec3_t lightdir;
7220         // TODO: optimize
7221         // model lighting
7222         VectorCopy(rsurface.modellight_lightdir, lightdir);
7223         f = 0.5f * r_refdef.lightmapintensity;
7224         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
7225         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7226         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7227         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7228         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7229         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7230         alpha = *a;
7231         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7232         {
7233                 // generate color arrays for the surfaces in this list
7234                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7235                 {
7236                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7237                         int numverts = surface->num_vertices;
7238                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7239                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
7240                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7241                         // q3-style directional shading
7242                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
7243                         {
7244                                 if ((f = DotProduct(n, lightdir)) > 0)
7245                                         VectorMA(ambientcolor, f, diffusecolor, c);
7246                                 else
7247                                         VectorCopy(ambientcolor, c);
7248                                 c[3] = alpha;
7249                         }
7250                 }
7251                 *r = 1;
7252                 *g = 1;
7253                 *b = 1;
7254                 *a = 1;
7255                 rsurface.lightmapcolor4f = rsurface.array_color4f;
7256                 rsurface.lightmapcolor4f_bufferobject = 0;
7257                 rsurface.lightmapcolor4f_bufferoffset = 0;
7258                 *applycolor = false;
7259         }
7260         else
7261         {
7262                 *r = ambientcolor[0];
7263                 *g = ambientcolor[1];
7264                 *b = ambientcolor[2];
7265                 rsurface.lightmapcolor4f = NULL;
7266                 rsurface.lightmapcolor4f_bufferobject = 0;
7267                 rsurface.lightmapcolor4f_bufferoffset = 0;
7268         }
7269 }
7270
7271 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7272 {
7273         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7274         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7275         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7276         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7277         GL_Color(r, g, b, a);
7278         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7279 }
7280
7281 void RSurf_SetupDepthAndCulling(void)
7282 {
7283         // submodels are biased to avoid z-fighting with world surfaces that they
7284         // may be exactly overlapping (avoids z-fighting artifacts on certain
7285         // doors and things in Quake maps)
7286         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7287         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7288         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7289         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7290 }
7291
7292 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7293 {
7294         // transparent sky would be ridiculous
7295         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7296                 return;
7297         R_SetupGenericShader(false);
7298         skyrenderlater = true;
7299         RSurf_SetupDepthAndCulling();
7300         GL_DepthMask(true);
7301         // LordHavoc: HalfLife maps have freaky skypolys so don't use
7302         // skymasking on them, and Quake3 never did sky masking (unlike
7303         // software Quake and software Quake2), so disable the sky masking
7304         // in Quake3 maps as it causes problems with q3map2 sky tricks,
7305         // and skymasking also looks very bad when noclipping outside the
7306         // level, so don't use it then either.
7307         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7308         {
7309                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7310                 R_Mesh_ColorPointer(NULL, 0, 0);
7311                 R_Mesh_ResetTextureState();
7312                 if (skyrendermasked)
7313                 {
7314                         R_SetupDepthOrShadowShader();
7315                         // depth-only (masking)
7316                         GL_ColorMask(0,0,0,0);
7317                         // just to make sure that braindead drivers don't draw
7318                         // anything despite that colormask...
7319                         GL_BlendFunc(GL_ZERO, GL_ONE);
7320                 }
7321                 else
7322                 {
7323                         R_SetupGenericShader(false);
7324                         // fog sky
7325                         GL_BlendFunc(GL_ONE, GL_ZERO);
7326                 }
7327                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7328                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7329                 if (skyrendermasked)
7330                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7331         }
7332         R_Mesh_ResetTextureState();
7333         GL_Color(1, 1, 1, 1);
7334 }
7335
7336 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7337 {
7338         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7339                 return;
7340
7341         R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
7342         R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
7343         R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7344         R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7345         R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7346         R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7347         if (rsurface.texture->backgroundcurrentskinframe)
7348         {
7349                 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7350                 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7351                 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7352                 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7353         }
7354         if(rsurface.texture->colormapping)
7355         {
7356                 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7357                 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7358         }
7359         R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7360         if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7361                 R_Mesh_ColorPointer(NULL, 0, 0);
7362         else
7363                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7364
7365         if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7366         {
7367                 // render background
7368                 GL_BlendFunc(GL_ONE, GL_ZERO);
7369                 GL_DepthMask(true);
7370                 GL_AlphaTest(false);
7371
7372                 GL_Color(1, 1, 1, 1);
7373                 R_Mesh_ColorPointer(NULL, 0, 0);
7374
7375                 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7376                 if (r_glsl_permutation)
7377                 {
7378                         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7379                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7380                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7381                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7382                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7383                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7384                         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);
7385                 }
7386                 GL_LockArrays(0, 0);
7387
7388                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7389                 GL_DepthMask(false);
7390                 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7391                         R_Mesh_ColorPointer(NULL, 0, 0);
7392                 else
7393                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7394                 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7395                 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7396         }
7397
7398         R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
7399         if (!r_glsl_permutation)
7400                 return;
7401
7402         RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7403         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7404         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7405         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7406         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7407         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7408
7409         if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7410         {
7411                 GL_BlendFunc(GL_ONE, GL_ZERO);
7412                 GL_DepthMask(true);
7413                 GL_AlphaTest(false);
7414         }
7415         else
7416         {
7417                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7418                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7419                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7420         }
7421
7422         if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7423         {
7424                 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7425                         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);
7426                 else
7427                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7428         }
7429         else
7430         {
7431                 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7432                         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);
7433                 else
7434                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7435         }
7436         GL_LockArrays(0, 0);
7437 }
7438
7439 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7440 {
7441         // OpenGL 1.3 path - anything not completely ancient
7442         int texturesurfaceindex;
7443         qboolean applycolor;
7444         qboolean applyfog;
7445         rmeshstate_t m;
7446         int layerindex;
7447         const texturelayer_t *layer;
7448         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7449
7450         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7451         {
7452                 vec4_t layercolor;
7453                 int layertexrgbscale;
7454                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7455                 {
7456                         if (layerindex == 0)
7457                                 GL_AlphaTest(true);
7458                         else
7459                         {
7460                                 GL_AlphaTest(false);
7461                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7462                         }
7463                 }
7464                 GL_DepthMask(layer->depthmask && writedepth);
7465                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7466                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7467                 {
7468                         layertexrgbscale = 4;
7469                         VectorScale(layer->color, 0.25f, layercolor);
7470                 }
7471                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7472                 {
7473                         layertexrgbscale = 2;
7474                         VectorScale(layer->color, 0.5f, layercolor);
7475                 }
7476                 else
7477                 {
7478                         layertexrgbscale = 1;
7479                         VectorScale(layer->color, 1.0f, layercolor);
7480                 }
7481                 layercolor[3] = layer->color[3];
7482                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7483                 R_Mesh_ColorPointer(NULL, 0, 0);
7484                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7485                 switch (layer->type)
7486                 {
7487                 case TEXTURELAYERTYPE_LITTEXTURE:
7488                         memset(&m, 0, sizeof(m));
7489                         m.tex[0] = R_GetTexture(r_texture_white);
7490                         m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7491                         m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7492                         m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7493                         m.tex[1] = R_GetTexture(layer->texture);
7494                         m.texmatrix[1] = layer->texmatrix;
7495                         m.texrgbscale[1] = layertexrgbscale;
7496                         m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7497                         m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7498                         m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7499                         R_Mesh_TextureState(&m);
7500                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7501                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7502                         else if (rsurface.uselightmaptexture)
7503                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7504                         else
7505                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7506                         break;
7507                 case TEXTURELAYERTYPE_TEXTURE:
7508                         memset(&m, 0, sizeof(m));
7509                         m.tex[0] = R_GetTexture(layer->texture);
7510                         m.texmatrix[0] = layer->texmatrix;
7511                         m.texrgbscale[0] = layertexrgbscale;
7512                         m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7513                         m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7514                         m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7515                         R_Mesh_TextureState(&m);
7516                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7517                         break;
7518                 case TEXTURELAYERTYPE_FOG:
7519                         memset(&m, 0, sizeof(m));
7520                         m.texrgbscale[0] = layertexrgbscale;
7521                         if (layer->texture)
7522                         {
7523                                 m.tex[0] = R_GetTexture(layer->texture);
7524                                 m.texmatrix[0] = layer->texmatrix;
7525                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7526                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7527                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7528                         }
7529                         R_Mesh_TextureState(&m);
7530                         // generate a color array for the fog pass
7531                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7532                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7533                         {
7534                                 int i;
7535                                 float f;
7536                                 const float *v;
7537                                 float *c;
7538                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7539                                 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)
7540                                 {
7541                                         f = 1 - RSurf_FogVertex(v);
7542                                         c[0] = layercolor[0];
7543                                         c[1] = layercolor[1];
7544                                         c[2] = layercolor[2];
7545                                         c[3] = f * layercolor[3];
7546                                 }
7547                         }
7548                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7549                         break;
7550                 default:
7551                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7552                 }
7553                 GL_LockArrays(0, 0);
7554         }
7555         CHECKGLERROR
7556         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7557         {
7558                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7559                 GL_AlphaTest(false);
7560         }
7561 }
7562
7563 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7564 {
7565         // OpenGL 1.1 - crusty old voodoo path
7566         int texturesurfaceindex;
7567         qboolean applyfog;
7568         rmeshstate_t m;
7569         int layerindex;
7570         const texturelayer_t *layer;
7571         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7572
7573         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7574         {
7575                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7576                 {
7577                         if (layerindex == 0)
7578                                 GL_AlphaTest(true);
7579                         else
7580                         {
7581                                 GL_AlphaTest(false);
7582                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7583                         }
7584                 }
7585                 GL_DepthMask(layer->depthmask && writedepth);
7586                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7587                 R_Mesh_ColorPointer(NULL, 0, 0);
7588                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7589                 switch (layer->type)
7590                 {
7591                 case TEXTURELAYERTYPE_LITTEXTURE:
7592                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7593                         {
7594                                 // two-pass lit texture with 2x rgbscale
7595                                 // first the lightmap pass
7596                                 memset(&m, 0, sizeof(m));
7597                                 m.tex[0] = R_GetTexture(r_texture_white);
7598                                 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7599                                 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7600                                 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7601                                 R_Mesh_TextureState(&m);
7602                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7603                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7604                                 else if (rsurface.uselightmaptexture)
7605                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7606                                 else
7607                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7608                                 GL_LockArrays(0, 0);
7609                                 // then apply the texture to it
7610                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7611                                 memset(&m, 0, sizeof(m));
7612                                 m.tex[0] = R_GetTexture(layer->texture);
7613                                 m.texmatrix[0] = layer->texmatrix;
7614                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7615                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7616                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7617                                 R_Mesh_TextureState(&m);
7618                                 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);
7619                         }
7620                         else
7621                         {
7622                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7623                                 memset(&m, 0, sizeof(m));
7624                                 m.tex[0] = R_GetTexture(layer->texture);
7625                                 m.texmatrix[0] = layer->texmatrix;
7626                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7627                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7628                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7629                                 R_Mesh_TextureState(&m);
7630                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7631                                         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);
7632                                 else
7633                                         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);
7634                         }
7635                         break;
7636                 case TEXTURELAYERTYPE_TEXTURE:
7637                         // singletexture unlit texture with transparency support
7638                         memset(&m, 0, sizeof(m));
7639                         m.tex[0] = R_GetTexture(layer->texture);
7640                         m.texmatrix[0] = layer->texmatrix;
7641                         m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7642                         m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7643                         m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7644                         R_Mesh_TextureState(&m);
7645                         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);
7646                         break;
7647                 case TEXTURELAYERTYPE_FOG:
7648                         // singletexture fogging
7649                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7650                         if (layer->texture)
7651                         {
7652                                 memset(&m, 0, sizeof(m));
7653                                 m.tex[0] = R_GetTexture(layer->texture);
7654                                 m.texmatrix[0] = layer->texmatrix;
7655                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7656                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7657                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7658                                 R_Mesh_TextureState(&m);
7659                         }
7660                         else
7661                                 R_Mesh_ResetTextureState();
7662                         // generate a color array for the fog pass
7663                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7664                         {
7665                                 int i;
7666                                 float f;
7667                                 const float *v;
7668                                 float *c;
7669                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7670                                 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)
7671                                 {
7672                                         f = 1 - RSurf_FogVertex(v);
7673                                         c[0] = layer->color[0];
7674                                         c[1] = layer->color[1];
7675                                         c[2] = layer->color[2];
7676                                         c[3] = f * layer->color[3];
7677                                 }
7678                         }
7679                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7680                         break;
7681                 default:
7682                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7683                 }
7684                 GL_LockArrays(0, 0);
7685         }
7686         CHECKGLERROR
7687         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7688         {
7689                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7690                 GL_AlphaTest(false);
7691         }
7692 }
7693
7694 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7695 {
7696         float c[4];
7697
7698         GL_AlphaTest(false);
7699         R_Mesh_ColorPointer(NULL, 0, 0);
7700         R_Mesh_ResetTextureState();
7701         R_SetupGenericShader(false);
7702
7703         if(rsurface.texture && rsurface.texture->currentskinframe)
7704         {
7705                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7706                 c[3] *= rsurface.texture->currentalpha;
7707         }
7708         else
7709         {
7710                 c[0] = 1;
7711                 c[1] = 0;
7712                 c[2] = 1;
7713                 c[3] = 1;
7714         }
7715
7716         if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7717         {
7718                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7719                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7720                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7721         }
7722
7723         // brighten it up (as texture value 127 means "unlit")
7724         c[0] *= 2 * r_refdef.view.colorscale;
7725         c[1] *= 2 * r_refdef.view.colorscale;
7726         c[2] *= 2 * r_refdef.view.colorscale;
7727
7728         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7729                 c[3] *= r_wateralpha.value;
7730
7731         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7732         {
7733                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7734                 GL_DepthMask(false);
7735         }
7736         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7737         {
7738                 GL_BlendFunc(GL_ONE, GL_ONE);
7739                 GL_DepthMask(false);
7740         }
7741         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7742         {
7743                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7744                 GL_DepthMask(false);
7745         }
7746         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7747         {
7748                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7749                 GL_DepthMask(false);
7750         }
7751         else
7752         {
7753                 GL_BlendFunc(GL_ONE, GL_ZERO);
7754                 GL_DepthMask(writedepth);
7755         }
7756
7757         rsurface.lightmapcolor4f = NULL;
7758
7759         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7760         {
7761                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7762
7763                 rsurface.lightmapcolor4f = NULL;
7764                 rsurface.lightmapcolor4f_bufferobject = 0;
7765                 rsurface.lightmapcolor4f_bufferoffset = 0;
7766         }
7767         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7768         {
7769                 qboolean applycolor = true;
7770                 float one = 1.0;
7771
7772                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7773
7774                 r_refdef.lightmapintensity = 1;
7775                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7776                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7777         }
7778         else
7779         {
7780                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7781
7782                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7783                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7784                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7785         }
7786
7787         if(!rsurface.lightmapcolor4f)
7788                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7789
7790         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7791         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7792         if(r_refdef.fogenabled)
7793                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7794
7795         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7796         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7797 }
7798
7799 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7800 {
7801         CHECKGLERROR
7802         RSurf_SetupDepthAndCulling();
7803         if (r_showsurfaces.integer == 3)
7804                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7805         else if (r_glsl.integer && gl_support_fragment_shader)
7806                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7807         else if (gl_combine.integer && r_textureunits.integer >= 2)
7808                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7809         else
7810                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7811         CHECKGLERROR
7812 }
7813
7814 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7815 {
7816         CHECKGLERROR
7817         RSurf_SetupDepthAndCulling();
7818         if (r_showsurfaces.integer == 3)
7819                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7820         else if (r_glsl.integer && gl_support_fragment_shader)
7821                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7822         else if (gl_combine.integer && r_textureunits.integer >= 2)
7823                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7824         else
7825                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7826         CHECKGLERROR
7827 }
7828
7829 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7830 {
7831         int i, j;
7832         int texturenumsurfaces, endsurface;
7833         texture_t *texture;
7834         const msurface_t *surface;
7835         const msurface_t *texturesurfacelist[1024];
7836
7837         // if the model is static it doesn't matter what value we give for
7838         // wantnormals and wanttangents, so this logic uses only rules applicable
7839         // to a model, knowing that they are meaningless otherwise
7840         if (ent == r_refdef.scene.worldentity)
7841                 RSurf_ActiveWorldEntity();
7842         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7843                 RSurf_ActiveModelEntity(ent, false, false);
7844         else
7845                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7846
7847         for (i = 0;i < numsurfaces;i = j)
7848         {
7849                 j = i + 1;
7850                 surface = rsurface.modelsurfaces + surfacelist[i];
7851                 texture = surface->texture;
7852                 rsurface.texture = R_GetCurrentTexture(texture);
7853                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7854                 // scan ahead until we find a different texture
7855                 endsurface = min(i + 1024, numsurfaces);
7856                 texturenumsurfaces = 0;
7857                 texturesurfacelist[texturenumsurfaces++] = surface;
7858                 for (;j < endsurface;j++)
7859                 {
7860                         surface = rsurface.modelsurfaces + surfacelist[j];
7861                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7862                                 break;
7863                         texturesurfacelist[texturenumsurfaces++] = surface;
7864                 }
7865                 // render the range of surfaces
7866                 if (ent == r_refdef.scene.worldentity)
7867                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7868                 else
7869                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7870         }
7871         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7872         GL_AlphaTest(false);
7873 }
7874
7875 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7876 {
7877         const entity_render_t *queueentity = r_refdef.scene.worldentity;
7878         CHECKGLERROR
7879         if (depthonly)
7880         {
7881                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7882                         return;
7883                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7884                         return;
7885                 RSurf_SetupDepthAndCulling();
7886                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7887                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7888         }
7889         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7890         {
7891                 RSurf_SetupDepthAndCulling();
7892                 GL_AlphaTest(false);
7893                 R_Mesh_ColorPointer(NULL, 0, 0);
7894                 R_Mesh_ResetTextureState();
7895                 R_SetupGenericShader(false);
7896                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7897                 GL_DepthMask(true);
7898                 GL_BlendFunc(GL_ONE, GL_ZERO);
7899                 GL_Color(0, 0, 0, 1);
7900                 GL_DepthTest(writedepth);
7901                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7902         }
7903         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7904         {
7905                 RSurf_SetupDepthAndCulling();
7906                 GL_AlphaTest(false);
7907                 R_Mesh_ColorPointer(NULL, 0, 0);
7908                 R_Mesh_ResetTextureState();
7909                 R_SetupGenericShader(false);
7910                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7911                 GL_DepthMask(true);
7912                 GL_BlendFunc(GL_ONE, GL_ZERO);
7913                 GL_DepthTest(true);
7914                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7915         }
7916         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7917                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7918         else if (!rsurface.texture->currentnumlayers)
7919                 return;
7920         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7921         {
7922                 // transparent surfaces get pushed off into the transparent queue
7923                 int surfacelistindex;
7924                 const msurface_t *surface;
7925                 vec3_t tempcenter, center;
7926                 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7927                 {
7928                         surface = texturesurfacelist[surfacelistindex];
7929                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7930                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7931                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7932                         Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7933                         R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7934                 }
7935         }
7936         else
7937         {
7938                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7939                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7940         }
7941         CHECKGLERROR
7942 }
7943
7944 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7945 {
7946         int i, j;
7947         texture_t *texture;
7948         // break the surface list down into batches by texture and use of lightmapping
7949         for (i = 0;i < numsurfaces;i = j)
7950         {
7951                 j = i + 1;
7952                 // texture is the base texture pointer, rsurface.texture is the
7953                 // current frame/skin the texture is directing us to use (for example
7954                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7955                 // use skin 1 instead)
7956                 texture = surfacelist[i]->texture;
7957                 rsurface.texture = R_GetCurrentTexture(texture);
7958                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7959                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7960                 {
7961                         // if this texture is not the kind we want, skip ahead to the next one
7962                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7963                                 ;
7964                         continue;
7965                 }
7966                 // simply scan ahead until we find a different texture or lightmap state
7967                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7968                         ;
7969                 // render the range of surfaces
7970                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
7971         }
7972 }
7973
7974 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
7975 {
7976         CHECKGLERROR
7977         if (depthonly)
7978         {
7979                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7980                         return;
7981                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7982                         return;
7983                 RSurf_SetupDepthAndCulling();
7984                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7985                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7986         }
7987         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7988         {
7989                 RSurf_SetupDepthAndCulling();
7990                 GL_AlphaTest(false);
7991                 R_Mesh_ColorPointer(NULL, 0, 0);
7992                 R_Mesh_ResetTextureState();
7993                 R_SetupGenericShader(false);
7994                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7995                 GL_DepthMask(true);
7996                 GL_BlendFunc(GL_ONE, GL_ZERO);
7997                 GL_Color(0, 0, 0, 1);
7998                 GL_DepthTest(writedepth);
7999                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8000         }
8001         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8002         {
8003                 RSurf_SetupDepthAndCulling();
8004                 GL_AlphaTest(false);
8005                 R_Mesh_ColorPointer(NULL, 0, 0);
8006                 R_Mesh_ResetTextureState();
8007                 R_SetupGenericShader(false);
8008                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8009                 GL_DepthMask(true);
8010                 GL_BlendFunc(GL_ONE, GL_ZERO);
8011                 GL_DepthTest(true);
8012                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8013         }
8014         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8015                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8016         else if (!rsurface.texture->currentnumlayers)
8017                 return;
8018         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8019         {
8020                 // transparent surfaces get pushed off into the transparent queue
8021                 int surfacelistindex;
8022                 const msurface_t *surface;
8023                 vec3_t tempcenter, center;
8024                 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8025                 {
8026                         surface = texturesurfacelist[surfacelistindex];
8027                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8028                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8029                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8030                         Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8031                         if (queueentity->transparent_offset) // transparent offset
8032                         {
8033                                 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
8034                                 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
8035                                 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
8036                         }
8037                         R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8038                 }
8039         }
8040         else
8041         {
8042                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8043                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
8044         }
8045         CHECKGLERROR
8046 }
8047
8048 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
8049 {
8050         int i, j;
8051         texture_t *texture;
8052         // break the surface list down into batches by texture and use of lightmapping
8053         for (i = 0;i < numsurfaces;i = j)
8054         {
8055                 j = i + 1;
8056                 // texture is the base texture pointer, rsurface.texture is the
8057                 // current frame/skin the texture is directing us to use (for example
8058                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8059                 // use skin 1 instead)
8060                 texture = surfacelist[i]->texture;
8061                 rsurface.texture = R_GetCurrentTexture(texture);
8062                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8063                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8064                 {
8065                         // if this texture is not the kind we want, skip ahead to the next one
8066                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8067                                 ;
8068                         continue;
8069                 }
8070                 // simply scan ahead until we find a different texture or lightmap state
8071                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8072                         ;
8073                 // render the range of surfaces
8074                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
8075         }
8076 }
8077
8078 float locboxvertex3f[6*4*3] =
8079 {
8080         1,0,1, 1,0,0, 1,1,0, 1,1,1,
8081         0,1,1, 0,1,0, 0,0,0, 0,0,1,
8082         1,1,1, 1,1,0, 0,1,0, 0,1,1,
8083         0,0,1, 0,0,0, 1,0,0, 1,0,1,
8084         0,0,1, 1,0,1, 1,1,1, 0,1,1,
8085         1,0,0, 0,0,0, 0,1,0, 1,1,0
8086 };
8087
8088 unsigned short locboxelements[6*2*3] =
8089 {
8090          0, 1, 2, 0, 2, 3,
8091          4, 5, 6, 4, 6, 7,
8092          8, 9,10, 8,10,11,
8093         12,13,14, 12,14,15,
8094         16,17,18, 16,18,19,
8095         20,21,22, 20,22,23
8096 };
8097
8098 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8099 {
8100         int i, j;
8101         cl_locnode_t *loc = (cl_locnode_t *)ent;
8102         vec3_t mins, size;
8103         float vertex3f[6*4*3];
8104         CHECKGLERROR
8105         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8106         GL_DepthMask(false);
8107         GL_DepthRange(0, 1);
8108         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8109         GL_DepthTest(true);
8110         GL_CullFace(GL_NONE);
8111         R_Mesh_Matrix(&identitymatrix);
8112
8113         R_Mesh_VertexPointer(vertex3f, 0, 0);
8114         R_Mesh_ColorPointer(NULL, 0, 0);
8115         R_Mesh_ResetTextureState();
8116         R_SetupGenericShader(false);
8117
8118         i = surfacelist[0];
8119         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8120                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8121                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8122                         surfacelist[0] < 0 ? 0.5f : 0.125f);
8123
8124         if (VectorCompare(loc->mins, loc->maxs))
8125         {
8126                 VectorSet(size, 2, 2, 2);
8127                 VectorMA(loc->mins, -0.5f, size, mins);
8128         }
8129         else
8130         {
8131                 VectorCopy(loc->mins, mins);
8132                 VectorSubtract(loc->maxs, loc->mins, size);
8133         }
8134
8135         for (i = 0;i < 6*4*3;)
8136                 for (j = 0;j < 3;j++, i++)
8137                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
8138
8139         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
8140 }
8141
8142 void R_DrawLocs(void)
8143 {
8144         int index;
8145         cl_locnode_t *loc, *nearestloc;
8146         vec3_t center;
8147         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
8148         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
8149         {
8150                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
8151                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
8152         }
8153 }
8154
8155 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
8156 {
8157         if (decalsystem->decals)
8158                 Mem_Free(decalsystem->decals);
8159         memset(decalsystem, 0, sizeof(*decalsystem));
8160 }
8161
8162 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)
8163 {
8164         float *v3f;
8165         float *tc2f;
8166         float *c4f;
8167         float ca;
8168         tridecal_t *decal;
8169         tridecal_t *decals;
8170         int i;
8171         int maxdecals;
8172
8173         // expand or initialize the system
8174         if (decalsystem->maxdecals <= decalsystem->numdecals)
8175         {
8176                 decalsystem_t old = *decalsystem;
8177                 qboolean useshortelements;
8178                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
8179                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
8180                 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)));
8181                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
8182                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
8183                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
8184                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
8185                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
8186                 if (decalsystem->numdecals)
8187                 {
8188                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
8189                         memcpy(decalsystem->vertex3f, old.vertex3f, decalsystem->numdecals * sizeof(float[3][3]));
8190                         memcpy(decalsystem->texcoord2f, old.texcoord2f, decalsystem->numdecals * sizeof(float[3][2]));
8191                         memcpy(decalsystem->color4f, old.color4f, decalsystem->numdecals * sizeof(float[3][4]));
8192                 }
8193                 Mem_Free(old.decals);
8194                 for (i = 0;i < decalsystem->maxdecals*3;i++)
8195                         decalsystem->element3i[i] = i;
8196                 if (useshortelements)
8197                         for (i = 0;i < decalsystem->maxdecals*3;i++)
8198                                 decalsystem->element3s[i] = i;
8199         }
8200
8201         // grab a decal and search for another free slot for the next one
8202         maxdecals = decalsystem->maxdecals;
8203         decals = decalsystem->decals;
8204         decal = decalsystem->decals + (i = decalsystem->freedecal++);
8205         v3f = decalsystem->vertex3f + 9*i;
8206         tc2f = decalsystem->texcoord2f + 6*i;
8207         c4f = decalsystem->color4f + 12*i;
8208         for (i = decalsystem->freedecal;i < maxdecals && decals[i].colors[0][3];i++)
8209                 ;
8210         decalsystem->freedecal = i;
8211         if (decalsystem->numdecals <= i)
8212                 decalsystem->numdecals = i + 1;
8213
8214         // initialize the decal
8215         decal->lived = 0;
8216         decal->triangleindex = triangleindex;
8217         decal->colors[0][0] = (unsigned char)(c0[0]*255.0f);
8218         decal->colors[0][1] = (unsigned char)(c0[1]*255.0f);
8219         decal->colors[0][2] = (unsigned char)(c0[2]*255.0f);
8220         decal->colors[0][3] = 255;
8221         decal->colors[1][0] = (unsigned char)(c1[0]*255.0f);
8222         decal->colors[1][1] = (unsigned char)(c1[1]*255.0f);
8223         decal->colors[1][2] = (unsigned char)(c1[2]*255.0f);
8224         decal->colors[1][3] = 255;
8225         decal->colors[2][0] = (unsigned char)(c2[0]*255.0f);
8226         decal->colors[2][1] = (unsigned char)(c2[1]*255.0f);
8227         decal->colors[2][2] = (unsigned char)(c2[2]*255.0f);
8228         decal->colors[2][3] = 255;
8229         v3f[0] = v0[0];
8230         v3f[1] = v0[1];
8231         v3f[2] = v0[2];
8232         v3f[3] = v1[0];
8233         v3f[4] = v1[1];
8234         v3f[5] = v1[2];
8235         v3f[6] = v2[0];
8236         v3f[7] = v2[1];
8237         v3f[8] = v2[2];
8238         tc2f[0] = t0[0];
8239         tc2f[1] = t0[1];
8240         tc2f[2] = t1[0];
8241         tc2f[3] = t1[1];
8242         tc2f[4] = t2[0];
8243         tc2f[5] = t2[1];
8244         ca = (1.0f/255.0f);
8245         c4f[ 0] = decal->colors[0][0] * ca;
8246         c4f[ 1] = decal->colors[0][1] * ca;
8247         c4f[ 2] = decal->colors[0][2] * ca;
8248         c4f[ 3] = 1;
8249         c4f[ 4] = decal->colors[1][0] * ca;
8250         c4f[ 5] = decal->colors[1][1] * ca;
8251         c4f[ 6] = decal->colors[1][2] * ca;
8252         c4f[ 7] = 1;
8253         c4f[ 8] = decal->colors[2][0] * ca;
8254         c4f[ 9] = decal->colors[2][1] * ca;
8255         c4f[10] = decal->colors[2][2] * ca;
8256         c4f[11] = 1;
8257 }
8258
8259 extern cvar_t cl_decals_bias;
8260 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)
8261 {
8262         matrix4x4_t projection;
8263         decalsystem_t *decalsystem;
8264         qboolean dynamic;
8265         dp_model_t *model;
8266         const float *vertex3f;
8267         const msurface_t *surface;
8268         const msurface_t *surfaces;
8269         const int *surfacelist;
8270         int numvertices;
8271         int numtriangles;
8272         int numsurfacelist;
8273         int surfacelistindex;
8274         int triangleindex;
8275         int cornerindex;
8276         int index;
8277         int numpoints;
8278         const int *e;
8279         float localorigin[3];
8280         float localnormal[3];
8281         float localmins[3];
8282         float localmaxs[3];
8283         float localsize;
8284         float ilocalsize;
8285         float v[9][3];
8286         float tc[9][2];
8287         float c[9][4];
8288         //float normal[3];
8289         float planes[6][4];
8290         float f;
8291         float points[2][9][3];
8292         float angles[3];
8293         float temp[3];
8294
8295         model = ent->model;
8296         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
8297         {
8298                 R_DecalSystem_Reset(&ent->decalsystem);
8299                 return;
8300         }
8301
8302         decalsystem = &ent->decalsystem;
8303         if (decalsystem->model != model)
8304                 R_DecalSystem_Reset(decalsystem);
8305         decalsystem->model = model;
8306
8307         RSurf_ActiveModelEntity(ent, false, false);
8308
8309         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
8310         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
8311         VectorNormalize(localnormal);
8312         localsize = worldsize*rsurface.inversematrixscale;
8313         ilocalsize = 1.0f / localsize;
8314         localmins[0] = localorigin[0] - localsize;
8315         localmins[1] = localorigin[1] - localsize;
8316         localmins[2] = localorigin[2] - localsize;
8317         localmaxs[0] = localorigin[0] + localsize;
8318         localmaxs[1] = localorigin[1] + localsize;
8319         localmaxs[2] = localorigin[2] + localsize;
8320
8321         //VectorCopy(localnormal, planes[4]);
8322         //VectorVectors(planes[4], planes[2], planes[0]);
8323         AnglesFromVectors(angles, localnormal, NULL, false);
8324         AngleVectors(angles, planes[0], planes[2], planes[4]);
8325         VectorNegate(planes[0], planes[1]);
8326         VectorNegate(planes[2], planes[3]);
8327         VectorNegate(planes[4], planes[5]);
8328         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
8329         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
8330         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
8331         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
8332         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
8333         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
8334
8335 #if 1
8336 // works
8337 {
8338         matrix4x4_t forwardprojection;
8339         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
8340         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
8341 }
8342 #else
8343 // broken
8344 {
8345         float projectionvector[4][3];
8346         VectorScale(planes[0], ilocalsize, projectionvector[0]);
8347         VectorScale(planes[2], ilocalsize, projectionvector[1]);
8348         VectorScale(planes[4], ilocalsize, projectionvector[2]);
8349         projectionvector[0][0] = planes[0][0] * ilocalsize;
8350         projectionvector[0][1] = planes[1][0] * ilocalsize;
8351         projectionvector[0][2] = planes[2][0] * ilocalsize;
8352         projectionvector[1][0] = planes[0][1] * ilocalsize;
8353         projectionvector[1][1] = planes[1][1] * ilocalsize;
8354         projectionvector[1][2] = planes[2][1] * ilocalsize;
8355         projectionvector[2][0] = planes[0][2] * ilocalsize;
8356         projectionvector[2][1] = planes[1][2] * ilocalsize;
8357         projectionvector[2][2] = planes[2][2] * ilocalsize;
8358         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
8359         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
8360         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
8361         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
8362 }
8363 #endif
8364
8365         dynamic = model->surfmesh.isanimated;
8366         vertex3f = rsurface.modelvertex3f;
8367         numsurfacelist = model->nummodelsurfaces;
8368         surfacelist = model->sortedmodelsurfaces;
8369         surfaces = model->data_surfaces;
8370         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
8371         {
8372                 surface = surfaces + surfacelist[surfacelistindex];
8373                 // skip transparent surfaces
8374                 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)))
8375                         continue;
8376                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
8377                         continue;
8378                 numvertices = surface->num_vertices;
8379                 numtriangles = surface->num_triangles;
8380                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
8381                 {
8382                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
8383                         {
8384                                 index = 3*e[cornerindex];
8385                                 VectorCopy(vertex3f + index, v[cornerindex]);
8386                         }
8387                         // cull backfaces
8388                         //TriangleNormal(v[0], v[1], v[2], normal);
8389                         //if (DotProduct(normal, localnormal) < 0.0f)
8390                         //      continue;
8391                         // clip by each of the box planes formed from the projection matrix
8392                         // if anything survives, we emit the decal
8393                         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]);
8394                         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]);
8395                         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]);
8396                         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]);
8397                         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]);
8398                         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]);
8399                         if (numpoints < 3)
8400                                 continue;
8401                         // some part of the triangle survived, so we have to accept it...
8402                         if (dynamic)
8403                         {
8404                                 // dynamic always uses the original triangle
8405                                 numpoints = 3;
8406                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8407                                 {
8408                                         index = 3*e[cornerindex];
8409                                         VectorCopy(vertex3f + index, v[cornerindex]);
8410                                 }
8411                         }
8412                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
8413                         {
8414                                 // convert vertex positions to texcoords
8415                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
8416                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
8417                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
8418                                 // calculate distance fade from the projection origin
8419                                 f = a * (1.0f-fabs(temp[0]));
8420                                 f = max(0.0f, f);
8421                                 c[cornerindex][0] = r * f;
8422                                 c[cornerindex][1] = g * f;
8423                                 c[cornerindex][2] = b * f;
8424                                 c[cornerindex][3] = 1.0f;
8425                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
8426                         }
8427                         if (dynamic)
8428                                 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex);
8429                         else
8430                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
8431                                         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);
8432                 }
8433         }
8434 }
8435
8436 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)
8437 {
8438         int renderentityindex;
8439         float worldmins[3];
8440         float worldmaxs[3];
8441         entity_render_t *ent;
8442
8443         worldmins[0] = worldorigin[0] - worldsize;
8444         worldmins[1] = worldorigin[1] - worldsize;
8445         worldmins[2] = worldorigin[2] - worldsize;
8446         worldmaxs[0] = worldorigin[0] + worldsize;
8447         worldmaxs[1] = worldorigin[1] + worldsize;
8448         worldmaxs[2] = worldorigin[2] + worldsize;
8449
8450         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize);
8451
8452         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
8453         {
8454                 ent = r_refdef.scene.entities[renderentityindex];
8455                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
8456                         continue;
8457
8458                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize);
8459         }
8460 }
8461
8462 extern skinframe_t *decalskinframe;
8463 static void R_DrawModelDecals_Entity(entity_render_t *ent)
8464 {
8465         int i;
8466         decalsystem_t *decalsystem = &ent->decalsystem;
8467         int numdecals;
8468         tridecal_t *decal;
8469         float frametime;
8470         float fadedelay;
8471         float faderate;
8472         float alpha;
8473         float *v3f;
8474         float *c4f;
8475         const int *e;
8476
8477         if (!decalsystem->numdecals)
8478                 return;
8479
8480         if (r_showsurfaces.integer)
8481                 return;
8482
8483         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8484         {
8485                 R_DecalSystem_Reset(decalsystem);
8486                 return;
8487         }
8488
8489         // if the model is static it doesn't matter what value we give for
8490         // wantnormals and wanttangents, so this logic uses only rules applicable
8491         // to a model, knowing that they are meaningless otherwise
8492         if (ent == r_refdef.scene.worldentity)
8493                 RSurf_ActiveWorldEntity();
8494         else
8495                 RSurf_ActiveModelEntity(ent, false, false);
8496
8497         if (decalsystem->lastupdatetime)
8498                 frametime = cl.time - decalsystem->lastupdatetime;
8499         else
8500                 frametime = 0;
8501         decalsystem->lastupdatetime = cl.time;
8502         decal = decalsystem->decals;
8503         numdecals = decalsystem->numdecals;
8504
8505         fadedelay = cl_decals_time.value;
8506         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
8507
8508         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8509         {
8510                 if (!decal->colors[0][3])
8511                         continue;
8512
8513                 decal->lived += frametime;
8514                 if (decal->lived >= fadedelay)
8515                 {
8516                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
8517                         if (alpha <= 0)
8518                         {
8519                                 // kill the decal by zeroing vertex data
8520                                 memset(decalsystem->vertex3f + 9*i, 0, sizeof(float[3][3]));
8521                                 memset(decalsystem->texcoord2f + 6*i, 0, sizeof(float[3][2]));
8522                                 memset(decalsystem->color4f + 12*i, 0, sizeof(float[3][4]));
8523                                 memset(decal, 0, sizeof(*decal));
8524                                 if (decalsystem->freedecal > i)
8525                                         decalsystem->freedecal = i;
8526                                 continue;
8527                         }
8528
8529                         // update color values for fading decals
8530                         alpha *= (1.0f/255.0f);
8531                         c4f = decalsystem->color4f + 12*i;
8532                         c4f[ 0] = decal->colors[0][0] * alpha;
8533                         c4f[ 1] = decal->colors[0][1] * alpha;
8534                         c4f[ 2] = decal->colors[0][2] * alpha;
8535                         c4f[ 3] = 1;
8536                         c4f[ 4] = decal->colors[1][0] * alpha;
8537                         c4f[ 5] = decal->colors[1][1] * alpha;
8538                         c4f[ 6] = decal->colors[1][2] * alpha;
8539                         c4f[ 7] = 1;
8540                         c4f[ 8] = decal->colors[2][0] * alpha;
8541                         c4f[ 9] = decal->colors[2][1] * alpha;
8542                         c4f[10] = decal->colors[2][2] * alpha;
8543                         c4f[11] = 1;
8544                 }
8545
8546                 // update vertex positions for animated models
8547                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
8548                 {
8549                         e = rsurface.modelelement3i + 3*decal->triangleindex;
8550                         v3f = decalsystem->vertex3f + 9*i;
8551                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
8552                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
8553                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
8554                 }
8555         }
8556
8557         // reduce numdecals if possible
8558         while (numdecals > 0 && !decalsystem->decals[numdecals - 1].colors[0][3])
8559                 numdecals--;
8560         decalsystem->numdecals = numdecals;
8561
8562         if (numdecals > 0)
8563         {
8564                 r_refdef.stats.decals += numdecals;
8565                 // now render the decals all at once
8566                 // (this assumes they all use one particle font texture!)
8567                 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);
8568                 R_Mesh_ResetTextureState();
8569                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
8570                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
8571                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
8572                 R_SetupGenericShader(true);
8573                 GL_DepthMask(false);
8574                 GL_DepthRange(0, 1);
8575                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
8576                 GL_DepthTest(true);
8577                 GL_CullFace(GL_NONE);
8578                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
8579                 R_Mesh_TexBind(0, R_GetTexture(decalskinframe->base));
8580                 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
8581                 GL_LockArrays(0, numdecals * 3);
8582                 R_Mesh_Draw(0, numdecals * 3, 0, numdecals, decalsystem->element3i, decalsystem->element3s, 0, 0);
8583                 GL_LockArrays(0, 0);
8584         }
8585
8586         if (numdecals <= 0)
8587         {
8588                 // if there are no decals left, reset decalsystem
8589                 R_DecalSystem_Reset(decalsystem);
8590         }
8591 }
8592
8593 void R_DrawDebugModel(void)
8594 {
8595         entity_render_t *ent = rsurface.entity;
8596         int i, j, k, l, flagsmask;
8597         const int *elements;
8598         q3mbrush_t *brush;
8599         const msurface_t *surface;
8600         dp_model_t *model = ent->model;
8601         vec3_t v;
8602
8603         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
8604
8605         R_Mesh_ColorPointer(NULL, 0, 0);
8606         R_Mesh_ResetTextureState();
8607         R_SetupGenericShader(false);
8608         GL_DepthRange(0, 1);
8609         GL_DepthTest(!r_showdisabledepthtest.integer);
8610         GL_DepthMask(false);
8611         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8612
8613         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
8614         {
8615                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
8616                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
8617                 {
8618                         if (brush->colbrushf && brush->colbrushf->numtriangles)
8619                         {
8620                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
8621                                 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);
8622                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
8623                         }
8624                 }
8625                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
8626                 {
8627                         if (surface->num_collisiontriangles)
8628                         {
8629                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
8630                                 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);
8631                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
8632                         }
8633                 }
8634         }
8635
8636         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8637
8638         if (r_showtris.integer || r_shownormals.integer)
8639         {
8640                 if (r_showdisabledepthtest.integer)
8641                 {
8642                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8643                         GL_DepthMask(false);
8644                 }
8645                 else
8646                 {
8647                         GL_BlendFunc(GL_ONE, GL_ZERO);
8648                         GL_DepthMask(true);
8649                 }
8650                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
8651                 {
8652                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
8653                                 continue;
8654                         rsurface.texture = R_GetCurrentTexture(surface->texture);
8655                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
8656                         {
8657                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
8658                                 if (r_showtris.value > 0)
8659                                 {
8660                                         if (!rsurface.texture->currentlayers->depthmask)
8661                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
8662                                         else if (ent == r_refdef.scene.worldentity)
8663                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
8664                                         else
8665                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
8666                                         elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
8667                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
8668                                         R_Mesh_ColorPointer(NULL, 0, 0);
8669                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
8670                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
8671                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
8672                                         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);
8673                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
8674                                         CHECKGLERROR
8675                                 }
8676                                 if (r_shownormals.value < 0)
8677                                 {
8678                                         qglBegin(GL_LINES);
8679                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8680                                         {
8681                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
8682                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8683                                                 qglVertex3f(v[0], v[1], v[2]);
8684                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
8685                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8686                                                 qglVertex3f(v[0], v[1], v[2]);
8687                                         }
8688                                         qglEnd();
8689                                         CHECKGLERROR
8690                                 }
8691                                 if (r_shownormals.value > 0)
8692                                 {
8693                                         qglBegin(GL_LINES);
8694                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8695                                         {
8696                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
8697                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8698                                                 qglVertex3f(v[0], v[1], v[2]);
8699                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
8700                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8701                                                 qglVertex3f(v[0], v[1], v[2]);
8702                                         }
8703                                         qglEnd();
8704                                         CHECKGLERROR
8705                                         qglBegin(GL_LINES);
8706                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8707                                         {
8708                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
8709                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
8710                                                 qglVertex3f(v[0], v[1], v[2]);
8711                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
8712                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8713                                                 qglVertex3f(v[0], v[1], v[2]);
8714                                         }
8715                                         qglEnd();
8716                                         CHECKGLERROR
8717                                         qglBegin(GL_LINES);
8718                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8719                                         {
8720                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
8721                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
8722                                                 qglVertex3f(v[0], v[1], v[2]);
8723                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
8724                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8725                                                 qglVertex3f(v[0], v[1], v[2]);
8726                                         }
8727                                         qglEnd();
8728                                         CHECKGLERROR
8729                                 }
8730                         }
8731                 }
8732                 rsurface.texture = NULL;
8733         }
8734 }
8735
8736 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
8737 int r_maxsurfacelist = 0;
8738 const msurface_t **r_surfacelist = NULL;
8739 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8740 {
8741         int i, j, endj, f, flagsmask;
8742         texture_t *t;
8743         dp_model_t *model = r_refdef.scene.worldmodel;
8744         msurface_t *surfaces;
8745         unsigned char *update;
8746         int numsurfacelist = 0;
8747         if (model == NULL)
8748                 return;
8749
8750         if (r_maxsurfacelist < model->num_surfaces)
8751         {
8752                 r_maxsurfacelist = model->num_surfaces;
8753                 if (r_surfacelist)
8754                         Mem_Free(r_surfacelist);
8755                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8756         }
8757
8758         RSurf_ActiveWorldEntity();
8759
8760         surfaces = model->data_surfaces;
8761         update = model->brushq1.lightmapupdateflags;
8762
8763         // update light styles on this submodel
8764         if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8765         {
8766                 model_brush_lightstyleinfo_t *style;
8767                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8768                 {
8769                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
8770                         {
8771                                 int *list = style->surfacelist;
8772                                 style->value = r_refdef.scene.lightstylevalue[style->style];
8773                                 for (j = 0;j < style->numsurfaces;j++)
8774                                         update[list[j]] = true;
8775                         }
8776                 }
8777         }
8778
8779         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8780
8781         if (debug)
8782         {
8783                 R_DrawDebugModel();
8784                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8785                 return;
8786         }
8787
8788         f = 0;
8789         t = NULL;
8790         rsurface.uselightmaptexture = false;
8791         rsurface.texture = NULL;
8792         rsurface.rtlight = NULL;
8793         numsurfacelist = 0;
8794         // add visible surfaces to draw list
8795         for (i = 0;i < model->nummodelsurfaces;i++)
8796         {
8797                 j = model->sortedmodelsurfaces[i];
8798                 if (r_refdef.viewcache.world_surfacevisible[j])
8799                         r_surfacelist[numsurfacelist++] = surfaces + j;
8800         }
8801         // update lightmaps if needed
8802         if (update)
8803                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8804                         if (r_refdef.viewcache.world_surfacevisible[j])
8805                                 if (update[j])
8806                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
8807         // don't do anything if there were no surfaces
8808         if (!numsurfacelist)
8809         {
8810                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8811                 return;
8812         }
8813         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8814         GL_AlphaTest(false);
8815
8816         // add to stats if desired
8817         if (r_speeds.integer && !skysurfaces && !depthonly)
8818         {
8819                 r_refdef.stats.world_surfaces += numsurfacelist;
8820                 for (j = 0;j < numsurfacelist;j++)
8821                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
8822         }
8823
8824         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8825 }
8826
8827 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8828 {
8829         int i, j, endj, f, flagsmask;
8830         texture_t *t;
8831         dp_model_t *model = ent->model;
8832         msurface_t *surfaces;
8833         unsigned char *update;
8834         int numsurfacelist = 0;
8835         if (model == NULL)
8836                 return;
8837
8838         if (r_maxsurfacelist < model->num_surfaces)
8839         {
8840                 r_maxsurfacelist = model->num_surfaces;
8841                 if (r_surfacelist)
8842                         Mem_Free(r_surfacelist);
8843                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8844         }
8845
8846         // if the model is static it doesn't matter what value we give for
8847         // wantnormals and wanttangents, so this logic uses only rules applicable
8848         // to a model, knowing that they are meaningless otherwise
8849         if (ent == r_refdef.scene.worldentity)
8850                 RSurf_ActiveWorldEntity();
8851         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8852                 RSurf_ActiveModelEntity(ent, false, false);
8853         else
8854                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
8855
8856         surfaces = model->data_surfaces;
8857         update = model->brushq1.lightmapupdateflags;
8858
8859         // update light styles
8860         if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8861         {
8862                 model_brush_lightstyleinfo_t *style;
8863                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8864                 {
8865                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
8866                         {
8867                                 int *list = style->surfacelist;
8868                                 style->value = r_refdef.scene.lightstylevalue[style->style];
8869                                 for (j = 0;j < style->numsurfaces;j++)
8870                                         update[list[j]] = true;
8871                         }
8872                 }
8873         }
8874
8875         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8876
8877         if (debug)
8878         {
8879                 R_DrawDebugModel();
8880                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8881                 return;
8882         }
8883
8884         f = 0;
8885         t = NULL;
8886         rsurface.uselightmaptexture = false;
8887         rsurface.texture = NULL;
8888         rsurface.rtlight = NULL;
8889         numsurfacelist = 0;
8890         // add visible surfaces to draw list
8891         for (i = 0;i < model->nummodelsurfaces;i++)
8892                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
8893         // don't do anything if there were no surfaces
8894         if (!numsurfacelist)
8895         {
8896                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8897                 return;
8898         }
8899         // update lightmaps if needed
8900         if (update)
8901                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8902                         if (update[j])
8903                                 R_BuildLightMap(ent, surfaces + j);
8904         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8905         GL_AlphaTest(false);
8906
8907         // add to stats if desired
8908         if (r_speeds.integer && !skysurfaces && !depthonly)
8909         {
8910                 r_refdef.stats.entities_surfaces += numsurfacelist;
8911                 for (j = 0;j < numsurfacelist;j++)
8912                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
8913         }
8914
8915         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8916 }
8917
8918 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth)
8919 {
8920         static texture_t texture;
8921         static msurface_t surface;
8922         const msurface_t *surfacelist = &surface;
8923
8924         // fake enough texture and surface state to render this geometry
8925
8926         texture.update_lastrenderframe = -1; // regenerate this texture
8927         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
8928         texture.currentskinframe = skinframe;
8929         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
8930         texture.specularscalemod = 1;
8931         texture.specularpowermod = 1;
8932
8933         surface.texture = &texture;
8934         surface.num_triangles = numtriangles;
8935         surface.num_firsttriangle = firsttriangle;
8936         surface.num_vertices = numvertices;
8937         surface.num_firstvertex = firstvertex;
8938
8939         // now render it
8940         rsurface.texture = R_GetCurrentTexture(surface.texture);
8941         rsurface.uselightmaptexture = false;
8942         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth);
8943 }