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