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