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