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