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