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