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