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