]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
adding two new extensions: DP_QC_WHICHPACK (identify a pk3 containing a file), and...
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
30
31 //
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(const char *name, int textureflags, qboolean complain)
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         if (cls.state == ca_dedicated)
1883                 return NULL;
1884
1885         // return an existing skinframe if already loaded
1886         // if loading of the first image fails, don't make a new skinframe as it
1887         // would cause all future lookups of this to be missing
1888         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1889         if (skinframe && skinframe->base)
1890                 return skinframe;
1891
1892         basepixels = loadimagepixelsbgra(name, complain, true);
1893         if (basepixels == NULL)
1894                 return NULL;
1895
1896         if (developer_loading.integer)
1897                 Con_Printf("loading skin \"%s\"\n", name);
1898
1899         // we've got some pixels to store, so really allocate this new texture now
1900         if (!skinframe)
1901                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1902         skinframe->stain = NULL;
1903         skinframe->merged = NULL;
1904         skinframe->base = r_texture_notexture;
1905         skinframe->pants = NULL;
1906         skinframe->shirt = NULL;
1907         skinframe->nmap = r_texture_blanknormalmap;
1908         skinframe->gloss = NULL;
1909         skinframe->glow = NULL;
1910         skinframe->fog = NULL;
1911
1912         basepixels_width = image_width;
1913         basepixels_height = image_height;
1914         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);
1915
1916         if (textureflags & TEXF_ALPHA)
1917         {
1918                 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1919                         if (basepixels[j] < 255)
1920                                 break;
1921                 if (j < basepixels_width * basepixels_height * 4)
1922                 {
1923                         // has transparent pixels
1924                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1925                         for (j = 0;j < image_width * image_height * 4;j += 4)
1926                         {
1927                                 pixels[j+0] = 255;
1928                                 pixels[j+1] = 255;
1929                                 pixels[j+2] = 255;
1930                                 pixels[j+3] = basepixels[j+3];
1931                         }
1932                         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);
1933                         Mem_Free(pixels);
1934                 }
1935         }
1936
1937         // _norm is the name used by tenebrae and has been adopted as standard
1938         if (loadnormalmap)
1939         {
1940                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
1941                 {
1942                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1943                         Mem_Free(pixels);
1944                         pixels = NULL;
1945                 }
1946                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
1947                 {
1948                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1949                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1950                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1951                         Mem_Free(pixels);
1952                         Mem_Free(bumppixels);
1953                 }
1954                 else if (r_shadow_bumpscale_basetexture.value > 0)
1955                 {
1956                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1957                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1958                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1959                         Mem_Free(pixels);
1960                 }
1961         }
1962         // _luma is supported for tenebrae compatibility
1963         // (I think it's a very stupid name, but oh well)
1964         // _glow is the preferred name
1965         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;}
1966         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;}
1967         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;}
1968         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;}
1969
1970         if (basepixels)
1971                 Mem_Free(basepixels);
1972
1973         return skinframe;
1974 }
1975
1976 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)
1977 {
1978         int i;
1979         if (!force)
1980         {
1981                 for (i = 0;i < width*height;i++)
1982                         if (((unsigned char *)&palette[in[i]])[3] > 0)
1983                                 break;
1984                 if (i == width*height)
1985                         return NULL;
1986         }
1987         return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1988 }
1989
1990 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
1991 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
1992 {
1993         int i;
1994         unsigned char *temp1, *temp2;
1995         skinframe_t *skinframe;
1996
1997         if (cls.state == ca_dedicated)
1998                 return NULL;
1999
2000         // if already loaded just return it, otherwise make a new skinframe
2001         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2002         if (skinframe && skinframe->base)
2003                 return skinframe;
2004
2005         skinframe->stain = NULL;
2006         skinframe->merged = NULL;
2007         skinframe->base = r_texture_notexture;
2008         skinframe->pants = NULL;
2009         skinframe->shirt = NULL;
2010         skinframe->nmap = r_texture_blanknormalmap;
2011         skinframe->gloss = NULL;
2012         skinframe->glow = NULL;
2013         skinframe->fog = NULL;
2014
2015         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2016         if (!skindata)
2017                 return NULL;
2018
2019         if (developer_loading.integer)
2020                 Con_Printf("loading 32bit skin \"%s\"\n", name);
2021
2022         if (r_shadow_bumpscale_basetexture.value > 0)
2023         {
2024                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2025                 temp2 = temp1 + width * height * 4;
2026                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2027                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2028                 Mem_Free(temp1);
2029         }
2030         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2031         if (textureflags & TEXF_ALPHA)
2032         {
2033                 for (i = 3;i < width * height * 4;i += 4)
2034                         if (skindata[i] < 255)
2035                                 break;
2036                 if (i < width * height * 4)
2037                 {
2038                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2039                         memcpy(fogpixels, skindata, width * height * 4);
2040                         for (i = 0;i < width * height * 4;i += 4)
2041                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2042                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2043                         Mem_Free(fogpixels);
2044                 }
2045         }
2046
2047         return skinframe;
2048 }
2049
2050 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2051 {
2052         int i;
2053         unsigned char *temp1, *temp2;
2054         skinframe_t *skinframe;
2055
2056         if (cls.state == ca_dedicated)
2057                 return NULL;
2058
2059         // if already loaded just return it, otherwise make a new skinframe
2060         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2061         if (skinframe && skinframe->base)
2062                 return skinframe;
2063
2064         skinframe->stain = NULL;
2065         skinframe->merged = NULL;
2066         skinframe->base = r_texture_notexture;
2067         skinframe->pants = NULL;
2068         skinframe->shirt = NULL;
2069         skinframe->nmap = r_texture_blanknormalmap;
2070         skinframe->gloss = NULL;
2071         skinframe->glow = NULL;
2072         skinframe->fog = NULL;
2073
2074         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2075         if (!skindata)
2076                 return NULL;
2077
2078         if (developer_loading.integer)
2079                 Con_Printf("loading quake skin \"%s\"\n", name);
2080
2081         if (r_shadow_bumpscale_basetexture.value > 0)
2082         {
2083                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2084                 temp2 = temp1 + width * height * 4;
2085                 // use either a custom palette or the quake palette
2086                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2087                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2088                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2089                 Mem_Free(temp1);
2090         }
2091         // use either a custom palette, or the quake palette
2092         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
2093         if (loadglowtexture)
2094                 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2095         if (loadpantsandshirt)
2096         {
2097                 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2098                 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2099         }
2100         if (skinframe->pants || skinframe->shirt)
2101                 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
2102         if (textureflags & TEXF_ALPHA)
2103         {
2104                 for (i = 0;i < width * height;i++)
2105                         if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2106                                 break;
2107                 if (i < width * height)
2108                         skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2109         }
2110
2111         return skinframe;
2112 }
2113
2114 skinframe_t *R_SkinFrame_LoadMissing(void)
2115 {
2116         skinframe_t *skinframe;
2117
2118         if (cls.state == ca_dedicated)
2119                 return NULL;
2120
2121         skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
2122         skinframe->stain = NULL;
2123         skinframe->merged = NULL;
2124         skinframe->base = r_texture_notexture;
2125         skinframe->pants = NULL;
2126         skinframe->shirt = NULL;
2127         skinframe->nmap = r_texture_blanknormalmap;
2128         skinframe->gloss = NULL;
2129         skinframe->glow = NULL;
2130         skinframe->fog = NULL;
2131
2132         return skinframe;
2133 }
2134
2135 void gl_main_start(void)
2136 {
2137         memset(r_qwskincache, 0, sizeof(r_qwskincache));
2138         memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2139
2140         // set up r_skinframe loading system for textures
2141         memset(&r_skinframe, 0, sizeof(r_skinframe));
2142         r_skinframe.loadsequence = 1;
2143         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2144
2145         r_main_texturepool = R_AllocTexturePool();
2146         R_BuildBlankTextures();
2147         R_BuildNoTexture();
2148         if (gl_texturecubemap)
2149         {
2150                 R_BuildWhiteCube();
2151                 R_BuildNormalizationCube();
2152         }
2153         r_texture_fogattenuation = NULL;
2154         r_texture_gammaramps = NULL;
2155         //r_texture_fogintensity = NULL;
2156         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2157         memset(&r_waterstate, 0, sizeof(r_waterstate));
2158         memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2159         memset(&r_svbsp, 0, sizeof (r_svbsp));
2160
2161         r_refdef.fogmasktable_density = 0;
2162 }
2163
2164 void gl_main_shutdown(void)
2165 {
2166         memset(r_qwskincache, 0, sizeof(r_qwskincache));
2167         memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2168
2169         // clear out the r_skinframe state
2170         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2171         memset(&r_skinframe, 0, sizeof(r_skinframe));
2172
2173         if (r_svbsp.nodes)
2174                 Mem_Free(r_svbsp.nodes);
2175         memset(&r_svbsp, 0, sizeof (r_svbsp));
2176         R_FreeTexturePool(&r_main_texturepool);
2177         r_texture_blanknormalmap = NULL;
2178         r_texture_white = NULL;
2179         r_texture_grey128 = NULL;
2180         r_texture_black = NULL;
2181         r_texture_whitecube = NULL;
2182         r_texture_normalizationcube = NULL;
2183         r_texture_fogattenuation = NULL;
2184         r_texture_gammaramps = NULL;
2185         //r_texture_fogintensity = NULL;
2186         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2187         memset(&r_waterstate, 0, sizeof(r_waterstate));
2188         R_GLSL_Restart_f();
2189 }
2190
2191 extern void CL_ParseEntityLump(char *entitystring);
2192 void gl_main_newmap(void)
2193 {
2194         // FIXME: move this code to client
2195         int l;
2196         char *entities, entname[MAX_QPATH];
2197         if (cl.worldmodel)
2198         {
2199                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2200                 l = (int)strlen(entname) - 4;
2201                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2202                 {
2203                         memcpy(entname + l, ".ent", 5);
2204                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2205                         {
2206                                 CL_ParseEntityLump(entities);
2207                                 Mem_Free(entities);
2208                                 return;
2209                         }
2210                 }
2211                 if (cl.worldmodel->brush.entities)
2212                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
2213         }
2214 }
2215
2216 void GL_Main_Init(void)
2217 {
2218         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2219
2220         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2221         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2222         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2223         if (gamemode == GAME_NEHAHRA)
2224         {
2225                 Cvar_RegisterVariable (&gl_fogenable);
2226                 Cvar_RegisterVariable (&gl_fogdensity);
2227                 Cvar_RegisterVariable (&gl_fogred);
2228                 Cvar_RegisterVariable (&gl_foggreen);
2229                 Cvar_RegisterVariable (&gl_fogblue);
2230                 Cvar_RegisterVariable (&gl_fogstart);
2231                 Cvar_RegisterVariable (&gl_fogend);
2232                 Cvar_RegisterVariable (&gl_skyclip);
2233         }
2234         Cvar_RegisterVariable(&r_depthfirst);
2235         Cvar_RegisterVariable(&r_useinfinitefarclip);
2236         Cvar_RegisterVariable(&r_nearclip);
2237         Cvar_RegisterVariable(&r_showbboxes);
2238         Cvar_RegisterVariable(&r_showsurfaces);
2239         Cvar_RegisterVariable(&r_showtris);
2240         Cvar_RegisterVariable(&r_shownormals);
2241         Cvar_RegisterVariable(&r_showlighting);
2242         Cvar_RegisterVariable(&r_showshadowvolumes);
2243         Cvar_RegisterVariable(&r_showcollisionbrushes);
2244         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2245         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2246         Cvar_RegisterVariable(&r_showdisabledepthtest);
2247         Cvar_RegisterVariable(&r_drawportals);
2248         Cvar_RegisterVariable(&r_drawentities);
2249         Cvar_RegisterVariable(&r_cullentities_trace);
2250         Cvar_RegisterVariable(&r_cullentities_trace_samples);
2251         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2252         Cvar_RegisterVariable(&r_cullentities_trace_delay);
2253         Cvar_RegisterVariable(&r_drawviewmodel);
2254         Cvar_RegisterVariable(&r_speeds);
2255         Cvar_RegisterVariable(&r_fullbrights);
2256         Cvar_RegisterVariable(&r_wateralpha);
2257         Cvar_RegisterVariable(&r_dynamic);
2258         Cvar_RegisterVariable(&r_fullbright);
2259         Cvar_RegisterVariable(&r_shadows);
2260         Cvar_RegisterVariable(&r_shadows_throwdistance);
2261         Cvar_RegisterVariable(&r_q1bsp_skymasking);
2262         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2263         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2264         Cvar_RegisterVariable(&r_fog_exp2);
2265         Cvar_RegisterVariable(&r_drawfog);
2266         Cvar_RegisterVariable(&r_textureunits);
2267         Cvar_RegisterVariable(&r_glsl);
2268         Cvar_RegisterVariable(&r_glsl_contrastboost);
2269         Cvar_RegisterVariable(&r_glsl_deluxemapping);
2270         Cvar_RegisterVariable(&r_glsl_offsetmapping);
2271         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2272         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2273         Cvar_RegisterVariable(&r_glsl_postprocess);
2274         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2275         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2276         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2277         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2278         Cvar_RegisterVariable(&r_glsl_usegeneric);
2279         Cvar_RegisterVariable(&r_water);
2280         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2281         Cvar_RegisterVariable(&r_water_clippingplanebias);
2282         Cvar_RegisterVariable(&r_water_refractdistort);
2283         Cvar_RegisterVariable(&r_water_reflectdistort);
2284         Cvar_RegisterVariable(&r_lerpsprites);
2285         Cvar_RegisterVariable(&r_lerpmodels);
2286         Cvar_RegisterVariable(&r_lerplightstyles);
2287         Cvar_RegisterVariable(&r_waterscroll);
2288         Cvar_RegisterVariable(&r_bloom);
2289         Cvar_RegisterVariable(&r_bloom_colorscale);
2290         Cvar_RegisterVariable(&r_bloom_brighten);
2291         Cvar_RegisterVariable(&r_bloom_blur);
2292         Cvar_RegisterVariable(&r_bloom_resolution);
2293         Cvar_RegisterVariable(&r_bloom_colorexponent);
2294         Cvar_RegisterVariable(&r_bloom_colorsubtract);
2295         Cvar_RegisterVariable(&r_hdr);
2296         Cvar_RegisterVariable(&r_hdr_scenebrightness);
2297         Cvar_RegisterVariable(&r_hdr_glowintensity);
2298         Cvar_RegisterVariable(&r_hdr_range);
2299         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2300         Cvar_RegisterVariable(&developer_texturelogging);
2301         Cvar_RegisterVariable(&gl_lightmaps);
2302         Cvar_RegisterVariable(&r_test);
2303         Cvar_RegisterVariable(&r_batchmode);
2304         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2305                 Cvar_SetValue("r_fullbrights", 0);
2306         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2307
2308         Cvar_RegisterVariable(&r_track_sprites);
2309         Cvar_RegisterVariable(&r_track_sprites_flags);
2310         Cvar_RegisterVariable(&r_track_sprites_scalew);
2311         Cvar_RegisterVariable(&r_track_sprites_scaleh);
2312 }
2313
2314 extern void R_Textures_Init(void);
2315 extern void GL_Draw_Init(void);
2316 extern void GL_Main_Init(void);
2317 extern void R_Shadow_Init(void);
2318 extern void R_Sky_Init(void);
2319 extern void GL_Surf_Init(void);
2320 extern void R_Particles_Init(void);
2321 extern void R_Explosion_Init(void);
2322 extern void gl_backend_init(void);
2323 extern void Sbar_Init(void);
2324 extern void R_LightningBeams_Init(void);
2325 extern void Mod_RenderInit(void);
2326
2327 void Render_Init(void)
2328 {
2329         gl_backend_init();
2330         R_Textures_Init();
2331         GL_Main_Init();
2332         GL_Draw_Init();
2333         R_Shadow_Init();
2334         R_Sky_Init();
2335         GL_Surf_Init();
2336         Sbar_Init();
2337         R_Particles_Init();
2338         R_Explosion_Init();
2339         R_LightningBeams_Init();
2340         Mod_RenderInit();
2341 }
2342
2343 /*
2344 ===============
2345 GL_Init
2346 ===============
2347 */
2348 extern char *ENGINE_EXTENSIONS;
2349 void GL_Init (void)
2350 {
2351         gl_renderer = (const char *)qglGetString(GL_RENDERER);
2352         gl_vendor = (const char *)qglGetString(GL_VENDOR);
2353         gl_version = (const char *)qglGetString(GL_VERSION);
2354         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2355
2356         if (!gl_extensions)
2357                 gl_extensions = "";
2358         if (!gl_platformextensions)
2359                 gl_platformextensions = "";
2360
2361         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2362         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2363         Con_Printf("GL_VERSION: %s\n", gl_version);
2364         Con_Printf("GL_EXTENSIONS: %s\n", gl_extensions);
2365         Con_Printf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2366
2367         VID_CheckExtensions();
2368
2369         // LordHavoc: report supported extensions
2370         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2371
2372         // clear to black (loading plaque will be seen over this)
2373         CHECKGLERROR
2374         qglClearColor(0,0,0,1);CHECKGLERROR
2375         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2376 }
2377
2378 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2379 {
2380         int i;
2381         mplane_t *p;
2382         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2383         {
2384                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2385                 if (i == 4)
2386                         continue;
2387                 p = r_refdef.view.frustum + i;
2388                 switch(p->signbits)
2389                 {
2390                 default:
2391                 case 0:
2392                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2393                                 return true;
2394                         break;
2395                 case 1:
2396                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2397                                 return true;
2398                         break;
2399                 case 2:
2400                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2401                                 return true;
2402                         break;
2403                 case 3:
2404                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2405                                 return true;
2406                         break;
2407                 case 4:
2408                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2409                                 return true;
2410                         break;
2411                 case 5:
2412                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2413                                 return true;
2414                         break;
2415                 case 6:
2416                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2417                                 return true;
2418                         break;
2419                 case 7:
2420                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2421                                 return true;
2422                         break;
2423                 }
2424         }
2425         return false;
2426 }
2427
2428 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2429 {
2430         int i;
2431         const mplane_t *p;
2432         for (i = 0;i < numplanes;i++)
2433         {
2434                 p = planes + i;
2435                 switch(p->signbits)
2436                 {
2437                 default:
2438                 case 0:
2439                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2440                                 return true;
2441                         break;
2442                 case 1:
2443                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2444                                 return true;
2445                         break;
2446                 case 2:
2447                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2448                                 return true;
2449                         break;
2450                 case 3:
2451                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2452                                 return true;
2453                         break;
2454                 case 4:
2455                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2456                                 return true;
2457                         break;
2458                 case 5:
2459                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2460                                 return true;
2461                         break;
2462                 case 6:
2463                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2464                                 return true;
2465                         break;
2466                 case 7:
2467                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2468                                 return true;
2469                         break;
2470                 }
2471         }
2472         return false;
2473 }
2474
2475 //==================================================================================
2476
2477 static void R_View_UpdateEntityVisible (void)
2478 {
2479         int i, renderimask;
2480         entity_render_t *ent;
2481
2482         if (!r_drawentities.integer)
2483                 return;
2484
2485         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2486         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2487         {
2488                 // worldmodel can check visibility
2489                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
2490                 for (i = 0;i < r_refdef.scene.numentities;i++)
2491                 {
2492                         ent = r_refdef.scene.entities[i];
2493                         if (!(ent->flags & renderimask))
2494                         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)))
2495                         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))
2496                                 r_refdef.viewcache.entityvisible[i] = true;
2497                 }
2498                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2499                 {
2500                         for (i = 0;i < r_refdef.scene.numentities;i++)
2501                         {
2502                                 ent = r_refdef.scene.entities[i];
2503                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2504                                 {
2505                                         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))
2506                                                 ent->last_trace_visibility = realtime;
2507                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2508                                                 r_refdef.viewcache.entityvisible[i] = 0;
2509                                 }
2510                         }
2511                 }
2512         }
2513         else
2514         {
2515                 // no worldmodel or it can't check visibility
2516                 for (i = 0;i < r_refdef.scene.numentities;i++)
2517                 {
2518                         ent = r_refdef.scene.entities[i];
2519                         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));
2520                 }
2521         }
2522 }
2523
2524 // only used if skyrendermasked, and normally returns false
2525 int R_DrawBrushModelsSky (void)
2526 {
2527         int i, sky;
2528         entity_render_t *ent;
2529
2530         if (!r_drawentities.integer)
2531                 return false;
2532
2533         sky = false;
2534         for (i = 0;i < r_refdef.scene.numentities;i++)
2535         {
2536                 if (!r_refdef.viewcache.entityvisible[i])
2537                         continue;
2538                 ent = r_refdef.scene.entities[i];
2539                 if (!ent->model || !ent->model->DrawSky)
2540                         continue;
2541                 ent->model->DrawSky(ent);
2542                 sky = true;
2543         }
2544         return sky;
2545 }
2546
2547 static void R_DrawNoModel(entity_render_t *ent);
2548 static void R_DrawModels(void)
2549 {
2550         int i;
2551         entity_render_t *ent;
2552
2553         if (!r_drawentities.integer)
2554                 return;
2555
2556         for (i = 0;i < r_refdef.scene.numentities;i++)
2557         {
2558                 if (!r_refdef.viewcache.entityvisible[i])
2559                         continue;
2560                 ent = r_refdef.scene.entities[i];
2561                 r_refdef.stats.entities++;
2562                 if (ent->model && ent->model->Draw != NULL)
2563                         ent->model->Draw(ent);
2564                 else
2565                         R_DrawNoModel(ent);
2566         }
2567 }
2568
2569 static void R_DrawModelsDepth(void)
2570 {
2571         int i;
2572         entity_render_t *ent;
2573
2574         if (!r_drawentities.integer)
2575                 return;
2576
2577         for (i = 0;i < r_refdef.scene.numentities;i++)
2578         {
2579                 if (!r_refdef.viewcache.entityvisible[i])
2580                         continue;
2581                 ent = r_refdef.scene.entities[i];
2582                 if (ent->model && ent->model->DrawDepth != NULL)
2583                         ent->model->DrawDepth(ent);
2584         }
2585 }
2586
2587 static void R_DrawModelsDebug(void)
2588 {
2589         int i;
2590         entity_render_t *ent;
2591
2592         if (!r_drawentities.integer)
2593                 return;
2594
2595         for (i = 0;i < r_refdef.scene.numentities;i++)
2596         {
2597                 if (!r_refdef.viewcache.entityvisible[i])
2598                         continue;
2599                 ent = r_refdef.scene.entities[i];
2600                 if (ent->model && ent->model->DrawDebug != NULL)
2601                         ent->model->DrawDebug(ent);
2602         }
2603 }
2604
2605 static void R_DrawModelsAddWaterPlanes(void)
2606 {
2607         int i;
2608         entity_render_t *ent;
2609
2610         if (!r_drawentities.integer)
2611                 return;
2612
2613         for (i = 0;i < r_refdef.scene.numentities;i++)
2614         {
2615                 if (!r_refdef.viewcache.entityvisible[i])
2616                         continue;
2617                 ent = r_refdef.scene.entities[i];
2618                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2619                         ent->model->DrawAddWaterPlanes(ent);
2620         }
2621 }
2622
2623 static void R_View_SetFrustum(void)
2624 {
2625         int i;
2626         double slopex, slopey;
2627         vec3_t forward, left, up, origin;
2628
2629         // we can't trust r_refdef.view.forward and friends in reflected scenes
2630         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
2631
2632 #if 0
2633         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2634         r_refdef.view.frustum[0].normal[1] = 0 - 0;
2635         r_refdef.view.frustum[0].normal[2] = -1 - 0;
2636         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2637         r_refdef.view.frustum[1].normal[1] = 0 + 0;
2638         r_refdef.view.frustum[1].normal[2] = -1 + 0;
2639         r_refdef.view.frustum[2].normal[0] = 0 - 0;
2640         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2641         r_refdef.view.frustum[2].normal[2] = -1 - 0;
2642         r_refdef.view.frustum[3].normal[0] = 0 + 0;
2643         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2644         r_refdef.view.frustum[3].normal[2] = -1 + 0;
2645 #endif
2646
2647 #if 0
2648         zNear = r_refdef.nearclip;
2649         nudge = 1.0 - 1.0 / (1<<23);
2650         r_refdef.view.frustum[4].normal[0] = 0 - 0;
2651         r_refdef.view.frustum[4].normal[1] = 0 - 0;
2652         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
2653         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
2654         r_refdef.view.frustum[5].normal[0] = 0 + 0;
2655         r_refdef.view.frustum[5].normal[1] = 0 + 0;
2656         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
2657         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
2658 #endif
2659
2660
2661
2662 #if 0
2663         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
2664         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
2665         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
2666         r_refdef.view.frustum[0].dist = m[15] - m[12];
2667
2668         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
2669         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
2670         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
2671         r_refdef.view.frustum[1].dist = m[15] + m[12];
2672
2673         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
2674         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
2675         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
2676         r_refdef.view.frustum[2].dist = m[15] - m[13];
2677
2678         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
2679         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
2680         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
2681         r_refdef.view.frustum[3].dist = m[15] + m[13];
2682
2683         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
2684         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
2685         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
2686         r_refdef.view.frustum[4].dist = m[15] - m[14];
2687
2688         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
2689         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
2690         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
2691         r_refdef.view.frustum[5].dist = m[15] + m[14];
2692 #endif
2693
2694         if (r_refdef.view.useperspective)
2695         {
2696                 slopex = 1.0 / r_refdef.view.frustum_x;
2697                 slopey = 1.0 / r_refdef.view.frustum_y;
2698                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
2699                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
2700                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
2701                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
2702                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2703
2704                 // Leaving those out was a mistake, those were in the old code, and they
2705                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2706                 // I couldn't reproduce it after adding those normalizations. --blub
2707                 VectorNormalize(r_refdef.view.frustum[0].normal);
2708                 VectorNormalize(r_refdef.view.frustum[1].normal);
2709                 VectorNormalize(r_refdef.view.frustum[2].normal);
2710                 VectorNormalize(r_refdef.view.frustum[3].normal);
2711
2712                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2713                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
2714                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
2715                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left,  1024 * slopey, up, r_refdef.view.frustumcorner[2]);
2716                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * slopex, left,  1024 * slopey, up, r_refdef.view.frustumcorner[3]);
2717
2718                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
2719                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
2720                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
2721                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
2722                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2723         }
2724         else
2725         {
2726                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
2727                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
2728                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
2729                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
2730                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2731                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
2732                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
2733                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
2734                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
2735                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2736         }
2737         r_refdef.view.numfrustumplanes = 5;
2738
2739         if (r_refdef.view.useclipplane)
2740         {
2741                 r_refdef.view.numfrustumplanes = 6;
2742                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
2743         }
2744
2745         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2746                 PlaneClassify(r_refdef.view.frustum + i);
2747
2748         // LordHavoc: note to all quake engine coders, Quake had a special case
2749         // for 90 degrees which assumed a square view (wrong), so I removed it,
2750         // Quake2 has it disabled as well.
2751
2752         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2753         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
2754         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
2755         //PlaneClassify(&frustum[0]);
2756
2757         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2758         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
2759         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
2760         //PlaneClassify(&frustum[1]);
2761
2762         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2763         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
2764         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
2765         //PlaneClassify(&frustum[2]);
2766
2767         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2768         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
2769         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
2770         //PlaneClassify(&frustum[3]);
2771
2772         // nearclip plane
2773         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
2774         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
2775         //PlaneClassify(&frustum[4]);
2776 }
2777
2778 void R_View_Update(void)
2779 {
2780         R_View_SetFrustum();
2781         R_View_WorldVisibility(r_refdef.view.useclipplane);
2782         R_View_UpdateEntityVisible();
2783 }
2784
2785 void R_SetupView(qboolean allowwaterclippingplane)
2786 {
2787         if (!r_refdef.view.useperspective)
2788                 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);
2789         else if (gl_stencil && r_useinfinitefarclip.integer)
2790                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
2791         else
2792                 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2793
2794         GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
2795
2796         if (r_refdef.view.useclipplane && allowwaterclippingplane)
2797         {
2798                 // LordHavoc: couldn't figure out how to make this approach the
2799                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
2800                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
2801                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
2802                         dist = r_refdef.view.clipplane.dist;
2803                 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
2804         }
2805 }
2806
2807 void R_ResetViewRendering2D(void)
2808 {
2809         DrawQ_Finish();
2810
2811         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2812         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2813         GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2814         GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2815         GL_Color(1, 1, 1, 1);
2816         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2817         GL_BlendFunc(GL_ONE, GL_ZERO);
2818         GL_AlphaTest(false);
2819         GL_ScissorTest(false);
2820         GL_DepthMask(false);
2821         GL_DepthRange(0, 1);
2822         GL_DepthTest(false);
2823         R_Mesh_Matrix(&identitymatrix);
2824         R_Mesh_ResetTextureState();
2825         GL_PolygonOffset(0, 0);
2826         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2827         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2828         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2829         qglStencilMask(~0);CHECKGLERROR
2830         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2831         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2832         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2833         R_SetupGenericShader(true);
2834 }
2835
2836 void R_ResetViewRendering3D(void)
2837 {
2838         DrawQ_Finish();
2839
2840         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2841         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2842         R_SetupView(true);
2843         GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2844         GL_Color(1, 1, 1, 1);
2845         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2846         GL_BlendFunc(GL_ONE, GL_ZERO);
2847         GL_AlphaTest(false);
2848         GL_ScissorTest(true);
2849         GL_DepthMask(true);
2850         GL_DepthRange(0, 1);
2851         GL_DepthTest(true);
2852         R_Mesh_Matrix(&identitymatrix);
2853         R_Mesh_ResetTextureState();
2854         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2855         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2856         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2857         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2858         qglStencilMask(~0);CHECKGLERROR
2859         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2860         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2861         GL_CullFace(r_refdef.view.cullface_back);
2862         R_SetupGenericShader(true);
2863 }
2864
2865 void R_RenderScene(qboolean addwaterplanes);
2866
2867 static void R_Water_StartFrame(void)
2868 {
2869         int i;
2870         int waterwidth, waterheight, texturewidth, textureheight;
2871         r_waterstate_waterplane_t *p;
2872
2873         // set waterwidth and waterheight to the water resolution that will be
2874         // used (often less than the screen resolution for faster rendering)
2875         waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
2876         waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
2877
2878         // calculate desired texture sizes
2879         // can't use water if the card does not support the texture size
2880         if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2881                 texturewidth = textureheight = waterwidth = waterheight = 0;
2882         else if (gl_support_arb_texture_non_power_of_two)
2883         {
2884                 texturewidth = waterwidth;
2885                 textureheight = waterheight;
2886         }
2887         else
2888         {
2889                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
2890                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
2891         }
2892
2893         // allocate textures as needed
2894         if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2895         {
2896                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2897                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2898                 {
2899                         if (p->texture_refraction)
2900                                 R_FreeTexture(p->texture_refraction);
2901                         p->texture_refraction = NULL;
2902                         if (p->texture_reflection)
2903                                 R_FreeTexture(p->texture_reflection);
2904                         p->texture_reflection = NULL;
2905                 }
2906                 memset(&r_waterstate, 0, sizeof(r_waterstate));
2907                 r_waterstate.waterwidth = waterwidth;
2908                 r_waterstate.waterheight = waterheight;
2909                 r_waterstate.texturewidth = texturewidth;
2910                 r_waterstate.textureheight = textureheight;
2911         }
2912
2913         if (r_waterstate.waterwidth)
2914         {
2915                 r_waterstate.enabled = true;
2916
2917                 // set up variables that will be used in shader setup
2918                 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2919                 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2920                 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2921                 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2922         }
2923
2924         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2925         r_waterstate.numwaterplanes = 0;
2926 }
2927
2928 static void R_Water_AddWaterPlane(msurface_t *surface)
2929 {
2930         int triangleindex, planeindex;
2931         const int *e;
2932         vec3_t vert[3];
2933         vec3_t normal;
2934         vec3_t center;
2935         mplane_t plane;
2936         r_waterstate_waterplane_t *p;
2937         // just use the first triangle with a valid normal for any decisions
2938         VectorClear(normal);
2939         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2940         {
2941                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2942                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2943                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2944                 TriangleNormal(vert[0], vert[1], vert[2], normal);
2945                 if (VectorLength2(normal) >= 0.001)
2946                         break;
2947         }
2948
2949         VectorCopy(normal, plane.normal);
2950         VectorNormalize(plane.normal);
2951         plane.dist = DotProduct(vert[0], plane.normal);
2952         PlaneClassify(&plane);
2953         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
2954         {
2955                 // skip backfaces (except if nocullface is set)
2956                 if (!(surface->texture->currentframe->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
2957                         return;
2958                 VectorNegate(plane.normal, plane.normal);
2959                 plane.dist *= -1;
2960                 PlaneClassify(&plane);
2961         }
2962
2963
2964         // find a matching plane if there is one
2965         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2966                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2967                         break;
2968         if (planeindex >= r_waterstate.maxwaterplanes)
2969                 return; // nothing we can do, out of planes
2970
2971         // if this triangle does not fit any known plane rendered this frame, add one
2972         if (planeindex >= r_waterstate.numwaterplanes)
2973         {
2974                 // store the new plane
2975                 r_waterstate.numwaterplanes++;
2976                 p->plane = plane;
2977                 // clear materialflags and pvs
2978                 p->materialflags = 0;
2979                 p->pvsvalid = false;
2980         }
2981         // merge this surface's materialflags into the waterplane
2982         p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2983         // merge this surface's PVS into the waterplane
2984         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
2985         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
2986          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
2987         {
2988                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2989                 p->pvsvalid = true;
2990         }
2991 }
2992
2993 static void R_Water_ProcessPlanes(void)
2994 {
2995         r_refdef_view_t originalview;
2996         int planeindex;
2997         r_waterstate_waterplane_t *p;
2998
2999         originalview = r_refdef.view;
3000
3001         // make sure enough textures are allocated
3002         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3003         {
3004                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3005                 {
3006                         if (!p->texture_refraction)
3007                                 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);
3008                         if (!p->texture_refraction)
3009                                 goto error;
3010                 }
3011
3012                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3013                 {
3014                         if (!p->texture_reflection)
3015                                 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);
3016                         if (!p->texture_reflection)
3017                                 goto error;
3018                 }
3019         }
3020
3021         // render views
3022         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3023         {
3024                 r_refdef.view.showdebug = false;
3025                 r_refdef.view.width = r_waterstate.waterwidth;
3026                 r_refdef.view.height = r_waterstate.waterheight;
3027                 r_refdef.view.useclipplane = true;
3028                 r_waterstate.renderingscene = true;
3029
3030                 // render the normal view scene and copy into texture
3031                 // (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)
3032                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3033                 {
3034                         r_refdef.view.clipplane = p->plane;
3035                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3036                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3037                         PlaneClassify(&r_refdef.view.clipplane);
3038
3039                         R_RenderScene(false);
3040
3041                         // copy view into the screen texture
3042                         R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3043                         GL_ActiveTexture(0);
3044                         CHECKGLERROR
3045                         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
3046                 }
3047
3048                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3049                 {
3050                         // render reflected scene and copy into texture
3051                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3052                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3053                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3054                         r_refdef.view.clipplane = p->plane;
3055                         // reverse the cullface settings for this render
3056                         r_refdef.view.cullface_front = GL_FRONT;
3057                         r_refdef.view.cullface_back = GL_BACK;
3058                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3059                         {
3060                                 r_refdef.view.usecustompvs = true;
3061                                 if (p->pvsvalid)
3062                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3063                                 else
3064                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3065                         }
3066
3067                         R_ResetViewRendering3D();
3068                         R_ClearScreen(r_refdef.fogenabled);
3069                         if (r_timereport_active)
3070                                 R_TimeReport("viewclear");
3071
3072                         R_RenderScene(false);
3073
3074                         R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3075                         GL_ActiveTexture(0);
3076                         CHECKGLERROR
3077                         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
3078
3079                         R_ResetViewRendering3D();
3080                         R_ClearScreen(r_refdef.fogenabled);
3081                         if (r_timereport_active)
3082                                 R_TimeReport("viewclear");
3083                 }
3084
3085                 r_refdef.view = originalview;
3086                 r_refdef.view.clear = true;
3087                 r_waterstate.renderingscene = false;
3088         }
3089         return;
3090 error:
3091         r_refdef.view = originalview;
3092         r_waterstate.renderingscene = false;
3093         Cvar_SetValueQuick(&r_water, 0);
3094         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
3095         return;
3096 }
3097
3098 void R_Bloom_StartFrame(void)
3099 {
3100         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3101
3102         // set bloomwidth and bloomheight to the bloom resolution that will be
3103         // used (often less than the screen resolution for faster rendering)
3104         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3105         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3106         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3107         r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3108         r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3109
3110         // calculate desired texture sizes
3111         if (gl_support_arb_texture_non_power_of_two)
3112         {
3113                 screentexturewidth = r_refdef.view.width;
3114                 screentextureheight = r_refdef.view.height;
3115                 bloomtexturewidth = r_bloomstate.bloomwidth;
3116                 bloomtextureheight = r_bloomstate.bloomheight;
3117         }
3118         else
3119         {
3120                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
3121                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
3122                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
3123                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
3124         }
3125
3126         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))
3127         {
3128                 Cvar_SetValueQuick(&r_hdr, 0);
3129                 Cvar_SetValueQuick(&r_bloom, 0);
3130         }
3131
3132         if (!(r_glsl.integer && (r_glsl_postprocess.integer || (v_glslgamma.integer && !vid_gammatables_trivial) || r_bloom.integer || r_hdr.integer)) && !r_bloom.integer)
3133                 screentexturewidth = screentextureheight = 0;
3134         if (!r_hdr.integer && !r_bloom.integer)
3135                 bloomtexturewidth = bloomtextureheight = 0;
3136
3137         // allocate textures as needed
3138         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3139         {
3140                 if (r_bloomstate.texture_screen)
3141                         R_FreeTexture(r_bloomstate.texture_screen);
3142                 r_bloomstate.texture_screen = NULL;
3143                 r_bloomstate.screentexturewidth = screentexturewidth;
3144                 r_bloomstate.screentextureheight = screentextureheight;
3145                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3146                         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);
3147         }
3148         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3149         {
3150                 if (r_bloomstate.texture_bloom)
3151                         R_FreeTexture(r_bloomstate.texture_bloom);
3152                 r_bloomstate.texture_bloom = NULL;
3153                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3154                 r_bloomstate.bloomtextureheight = bloomtextureheight;
3155                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3156                         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);
3157         }
3158
3159         // set up a texcoord array for the full resolution screen image
3160         // (we have to keep this around to copy back during final render)
3161         r_bloomstate.screentexcoord2f[0] = 0;
3162         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
3163         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
3164         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
3165         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
3166         r_bloomstate.screentexcoord2f[5] = 0;
3167         r_bloomstate.screentexcoord2f[6] = 0;
3168         r_bloomstate.screentexcoord2f[7] = 0;
3169
3170         // set up a texcoord array for the reduced resolution bloom image
3171         // (which will be additive blended over the screen image)
3172         r_bloomstate.bloomtexcoord2f[0] = 0;
3173         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3174         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
3175         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3176         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
3177         r_bloomstate.bloomtexcoord2f[5] = 0;
3178         r_bloomstate.bloomtexcoord2f[6] = 0;
3179         r_bloomstate.bloomtexcoord2f[7] = 0;
3180
3181         if (r_hdr.integer || r_bloom.integer)
3182         {
3183                 r_bloomstate.enabled = true;
3184                 r_bloomstate.hdr = r_hdr.integer != 0;
3185         }
3186 }
3187
3188 void R_Bloom_CopyBloomTexture(float colorscale)
3189 {
3190         r_refdef.stats.bloom++;
3191
3192         // scale down screen texture to the bloom texture size
3193         CHECKGLERROR
3194         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3195         GL_BlendFunc(GL_ONE, GL_ZERO);
3196         GL_Color(colorscale, colorscale, colorscale, 1);
3197         // TODO: optimize with multitexture or GLSL
3198         R_SetupGenericShader(true);
3199         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3200         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3201         R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3202         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3203
3204         // we now have a bloom image in the framebuffer
3205         // copy it into the bloom image texture for later processing
3206         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3207         GL_ActiveTexture(0);
3208         CHECKGLERROR
3209         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
3210         r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3211 }
3212
3213 void R_Bloom_CopyHDRTexture(void)
3214 {
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_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3219         r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3220 }
3221
3222 void R_Bloom_MakeTexture(void)
3223 {
3224         int x, range, dir;
3225         float xoffset, yoffset, r, brighten;
3226
3227         r_refdef.stats.bloom++;
3228
3229         R_ResetViewRendering2D();
3230         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3231         R_Mesh_ColorPointer(NULL, 0, 0);
3232         R_SetupGenericShader(true);
3233
3234         // we have a bloom image in the framebuffer
3235         CHECKGLERROR
3236         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3237
3238         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3239         {
3240                 x *= 2;
3241                 r = bound(0, r_bloom_colorexponent.value / x, 1);
3242                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3243                 GL_Color(r, r, r, 1);
3244                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3245                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3246                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3247                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3248
3249                 // copy the vertically blurred bloom view to a texture
3250                 GL_ActiveTexture(0);
3251                 CHECKGLERROR
3252                 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
3253                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3254         }
3255
3256         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3257         brighten = r_bloom_brighten.value;
3258         if (r_hdr.integer)
3259                 brighten *= r_hdr_range.value;
3260         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3261         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3262
3263         for (dir = 0;dir < 2;dir++)
3264         {
3265                 // blend on at multiple vertical offsets to achieve a vertical blur
3266                 // TODO: do offset blends using GLSL
3267                 GL_BlendFunc(GL_ONE, GL_ZERO);
3268                 for (x = -range;x <= range;x++)
3269                 {
3270                         if (!dir){xoffset = 0;yoffset = x;}
3271                         else {xoffset = x;yoffset = 0;}
3272                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
3273                         yoffset /= (float)r_bloomstate.bloomtextureheight;
3274                         // compute a texcoord array with the specified x and y offset
3275                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3276                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3277                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3278                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3279                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3280                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3281                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3282                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3283                         // this r value looks like a 'dot' particle, fading sharply to
3284                         // black at the edges
3285                         // (probably not realistic but looks good enough)
3286                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3287                         //r = (dir ? 1.0f : brighten)/(range*2+1);
3288                         r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3289                         GL_Color(r, r, r, 1);
3290                         R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3291                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3292                         GL_BlendFunc(GL_ONE, GL_ONE);
3293                 }
3294
3295                 // copy the vertically blurred bloom view to a texture
3296                 GL_ActiveTexture(0);
3297                 CHECKGLERROR
3298                 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
3299                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3300         }
3301
3302         // apply subtract last
3303         // (just like it would be in a GLSL shader)
3304         if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3305         {
3306                 GL_BlendFunc(GL_ONE, GL_ZERO);
3307                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3308                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3309                 GL_Color(1, 1, 1, 1);
3310                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3311                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3312
3313                 GL_BlendFunc(GL_ONE, GL_ONE);
3314                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3315                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3316                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3317                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3318                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3319                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3320                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3321
3322                 // copy the darkened bloom view to a texture
3323                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3324                 GL_ActiveTexture(0);
3325                 CHECKGLERROR
3326                 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
3327                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3328         }
3329 }
3330
3331 void R_HDR_RenderBloomTexture(void)
3332 {
3333         int oldwidth, oldheight;
3334         float oldcolorscale;
3335
3336         oldcolorscale = r_refdef.view.colorscale;
3337         oldwidth = r_refdef.view.width;
3338         oldheight = r_refdef.view.height;
3339         r_refdef.view.width = r_bloomstate.bloomwidth;
3340         r_refdef.view.height = r_bloomstate.bloomheight;
3341
3342         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
3343         // TODO: add exposure compensation features
3344         // TODO: add fp16 framebuffer support
3345
3346         r_refdef.view.showdebug = false;
3347         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3348
3349         R_ClearScreen(r_refdef.fogenabled);
3350         if (r_timereport_active)
3351                 R_TimeReport("HDRclear");
3352
3353         r_waterstate.numwaterplanes = 0;
3354         R_RenderScene(r_waterstate.enabled);
3355         r_refdef.view.showdebug = true;
3356
3357         R_ResetViewRendering2D();
3358
3359         R_Bloom_CopyHDRTexture();
3360         R_Bloom_MakeTexture();
3361
3362         // restore the view settings
3363         r_refdef.view.width = oldwidth;
3364         r_refdef.view.height = oldheight;
3365         r_refdef.view.colorscale = oldcolorscale;
3366
3367         R_ResetViewRendering3D();
3368
3369         R_ClearScreen(r_refdef.fogenabled);
3370         if (r_timereport_active)
3371                 R_TimeReport("viewclear");
3372 }
3373
3374 static void R_BlendView(void)
3375 {
3376         if (r_bloomstate.texture_screen)
3377         {
3378                 // copy view into the screen texture
3379                 R_ResetViewRendering2D();
3380                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3381                 R_Mesh_ColorPointer(NULL, 0, 0);
3382                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3383                 GL_ActiveTexture(0);CHECKGLERROR
3384                 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
3385                 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3386         }
3387
3388         if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
3389         {
3390                 unsigned int permutation =
3391                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
3392                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)
3393                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
3394                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0);
3395
3396                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
3397                 {
3398                         // render simple bloom effect
3399                         // copy the screen and shrink it and darken it for the bloom process
3400                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3401                         // make the bloom texture
3402                         R_Bloom_MakeTexture();
3403                 }
3404
3405                 R_ResetViewRendering2D();
3406                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3407                 R_Mesh_ColorPointer(NULL, 0, 0);
3408                 GL_Color(1, 1, 1, 1);
3409                 GL_BlendFunc(GL_ONE, GL_ZERO);
3410                 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
3411                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3412                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3413                 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
3414                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3415                 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
3416                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
3417                 if (r_glsl_permutation->loc_TintColor >= 0)
3418                         qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3419                 if (r_glsl_permutation->loc_ClientTime >= 0)
3420                         qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3421                 if (r_glsl_permutation->loc_PixelSize >= 0)
3422                         qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
3423                 if (r_glsl_permutation->loc_UserVec1 >= 0)
3424                 {
3425                         float a=0, b=0, c=0, d=0;
3426 #if _MSC_VER >= 1400
3427 #define sscanf sscanf_s
3428 #endif
3429                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
3430                         qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
3431                 }
3432                 if (r_glsl_permutation->loc_UserVec2 >= 0)
3433                 {
3434                         float a=0, b=0, c=0, d=0;
3435                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
3436                         qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
3437                 }
3438                 if (r_glsl_permutation->loc_UserVec3 >= 0)
3439                 {
3440                         float a=0, b=0, c=0, d=0;
3441                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
3442                         qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
3443                 }
3444                 if (r_glsl_permutation->loc_UserVec4 >= 0)
3445                 {
3446                         float a=0, b=0, c=0, d=0;
3447                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
3448                         qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
3449                 }
3450                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3451                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3452                 return;
3453         }
3454
3455
3456
3457         if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
3458         {
3459                 // render high dynamic range bloom effect
3460                 // the bloom texture was made earlier this render, so we just need to
3461                 // blend it onto the screen...
3462                 R_ResetViewRendering2D();
3463                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3464                 R_Mesh_ColorPointer(NULL, 0, 0);
3465                 R_SetupGenericShader(true);
3466                 GL_Color(1, 1, 1, 1);
3467                 GL_BlendFunc(GL_ONE, GL_ONE);
3468                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3469                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3470                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3471                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3472         }
3473         else if (r_bloomstate.texture_bloom)
3474         {
3475                 // render simple bloom effect
3476                 // copy the screen and shrink it and darken it for the bloom process
3477                 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3478                 // make the bloom texture
3479                 R_Bloom_MakeTexture();
3480                 // put the original screen image back in place and blend the bloom
3481                 // texture on it
3482                 R_ResetViewRendering2D();
3483                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3484                 R_Mesh_ColorPointer(NULL, 0, 0);
3485                 GL_Color(1, 1, 1, 1);
3486                 GL_BlendFunc(GL_ONE, GL_ZERO);
3487                 // do both in one pass if possible
3488                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3489                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3490                 if (r_textureunits.integer >= 2 && gl_combine.integer)
3491                 {
3492                         R_SetupGenericTwoTextureShader(GL_ADD);
3493                         R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3494                         R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3495                 }
3496                 else
3497                 {
3498                         R_SetupGenericShader(true);
3499                         R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3500                         r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3501                         // now blend on the bloom texture
3502                         GL_BlendFunc(GL_ONE, GL_ONE);
3503                         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3504                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3505                 }
3506                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3507                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3508         }
3509         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3510         {
3511                 // apply a color tint to the whole view
3512                 R_ResetViewRendering2D();
3513                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3514                 R_Mesh_ColorPointer(NULL, 0, 0);
3515                 R_SetupGenericShader(false);
3516                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3517                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3518                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3519         }
3520 }
3521
3522 void R_RenderScene(qboolean addwaterplanes);
3523
3524 matrix4x4_t r_waterscrollmatrix;
3525
3526 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3527 {
3528         if (r_refdef.fog_density)
3529         {
3530                 r_refdef.fogcolor[0] = r_refdef.fog_red;
3531                 r_refdef.fogcolor[1] = r_refdef.fog_green;
3532                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3533
3534                 {
3535                         vec3_t fogvec;
3536                         VectorCopy(r_refdef.fogcolor, fogvec);
3537                         if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3538                         {
3539                                 //   color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3540                                 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3541                                 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3542                                 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3543                         }
3544                         //   color.rgb *= ContrastBoost * SceneBrightness;
3545                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3546                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3547                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3548                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3549                 }
3550         }
3551 }
3552
3553 void R_UpdateVariables(void)
3554 {
3555         R_Textures_Frame();
3556
3557         r_refdef.scene.ambient = r_ambient.value;
3558
3559         r_refdef.farclip = 4096;
3560         if (r_refdef.scene.worldmodel)
3561                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
3562         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3563
3564         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3565                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3566         r_refdef.polygonfactor = 0;
3567         r_refdef.polygonoffset = 0;
3568         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3569         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3570
3571         r_refdef.scene.rtworld = r_shadow_realtime_world.integer;
3572         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3573         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3574         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3575         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3576         if (r_showsurfaces.integer)
3577         {
3578                 r_refdef.scene.rtworld = false;
3579                 r_refdef.scene.rtworldshadows = false;
3580                 r_refdef.scene.rtdlight = false;
3581                 r_refdef.scene.rtdlightshadows = false;
3582                 r_refdef.lightmapintensity = 0;
3583         }
3584
3585         if (gamemode == GAME_NEHAHRA)
3586         {
3587                 if (gl_fogenable.integer)
3588                 {
3589                         r_refdef.oldgl_fogenable = true;
3590                         r_refdef.fog_density = gl_fogdensity.value;
3591                         r_refdef.fog_red = gl_fogred.value;
3592                         r_refdef.fog_green = gl_foggreen.value;
3593                         r_refdef.fog_blue = gl_fogblue.value;
3594                         r_refdef.fog_alpha = 1;
3595                         r_refdef.fog_start = 0;
3596                         r_refdef.fog_end = gl_skyclip.value;
3597                 }
3598                 else if (r_refdef.oldgl_fogenable)
3599                 {
3600                         r_refdef.oldgl_fogenable = false;
3601                         r_refdef.fog_density = 0;
3602                         r_refdef.fog_red = 0;
3603                         r_refdef.fog_green = 0;
3604                         r_refdef.fog_blue = 0;
3605                         r_refdef.fog_alpha = 0;
3606                         r_refdef.fog_start = 0;
3607                         r_refdef.fog_end = 0;
3608                 }
3609         }
3610
3611         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
3612         r_refdef.fog_start = max(0, r_refdef.fog_start);
3613         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
3614
3615         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
3616
3617         if (r_refdef.fog_density && r_drawfog.integer)
3618         {
3619                 r_refdef.fogenabled = true;
3620                 // this is the point where the fog reaches 0.9986 alpha, which we
3621                 // consider a good enough cutoff point for the texture
3622                 // (0.9986 * 256 == 255.6)
3623                 if (r_fog_exp2.integer)
3624                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
3625                 else
3626                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
3627                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
3628                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3629                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3630                 // fog color was already set
3631                 // update the fog texture
3632                 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)
3633                         R_BuildFogTexture();
3634         }
3635         else
3636                 r_refdef.fogenabled = false;
3637
3638         if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
3639         {
3640                 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
3641                 {
3642                         // build GLSL gamma texture
3643 #define RAMPWIDTH 256
3644                         unsigned short ramp[RAMPWIDTH * 3];
3645                         unsigned char ramprgb[RAMPWIDTH][4];
3646                         int i;
3647
3648                         r_texture_gammaramps_serial = vid_gammatables_serial;
3649
3650                         VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
3651                         for(i = 0; i < RAMPWIDTH; ++i)
3652                         {
3653                                 ramprgb[i][0] = ramp[i] >> 8;
3654                                 ramprgb[i][1] = ramp[i + RAMPWIDTH] >> 8;
3655                                 ramprgb[i][2] = ramp[i + 2 * RAMPWIDTH] >> 8;
3656                                 ramprgb[i][3] = 0;
3657                         }
3658                         if (r_texture_gammaramps)
3659                         {
3660                                 R_UpdateTexture(r_texture_gammaramps, &ramprgb[0][0], 0, 0, RAMPWIDTH, 1);
3661                         }
3662                         else
3663                         {
3664                                 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);
3665                         }
3666                 }
3667         }
3668         else
3669         {
3670                 // remove GLSL gamma texture
3671         }
3672 }
3673
3674 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
3675 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
3676 /*
3677 ================
3678 R_SelectScene
3679 ================
3680 */
3681 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
3682         if( scenetype != r_currentscenetype ) {
3683                 // store the old scenetype
3684                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
3685                 r_currentscenetype = scenetype;
3686                 // move in the new scene
3687                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
3688         }
3689 }
3690
3691 /*
3692 ================
3693 R_GetScenePointer
3694 ================
3695 */
3696 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
3697 {
3698         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
3699         if( scenetype == r_currentscenetype ) {
3700                 return &r_refdef.scene;
3701         } else {
3702                 return &r_scenes_store[ scenetype ];
3703         }
3704 }
3705
3706 /*
3707 ================
3708 R_RenderView
3709 ================
3710 */
3711 void R_RenderView(void)
3712 {
3713         if (r_refdef.view.isoverlay)
3714         {
3715                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
3716                 GL_Clear( GL_DEPTH_BUFFER_BIT );
3717                 R_TimeReport("depthclear");
3718
3719                 r_refdef.view.showdebug = false;
3720
3721                 r_waterstate.enabled = false;
3722                 r_waterstate.numwaterplanes = 0;
3723
3724                 R_RenderScene(false);
3725
3726                 CHECKGLERROR
3727                 return;
3728         }
3729
3730         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
3731                 return; //Host_Error ("R_RenderView: NULL worldmodel");
3732
3733         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
3734
3735         // break apart the view matrix into vectors for various purposes
3736         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
3737         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
3738         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
3739         VectorNegate(r_refdef.view.left, r_refdef.view.right);
3740         // make an inverted copy of the view matrix for tracking sprites
3741         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
3742
3743         R_Shadow_UpdateWorldLightSelection();
3744
3745         R_Bloom_StartFrame();
3746         R_Water_StartFrame();
3747
3748         CHECKGLERROR
3749         if (r_timereport_active)
3750                 R_TimeReport("viewsetup");
3751
3752         R_ResetViewRendering3D();
3753
3754         if (r_refdef.view.clear || r_refdef.fogenabled)
3755         {
3756                 R_ClearScreen(r_refdef.fogenabled);
3757                 if (r_timereport_active)
3758                         R_TimeReport("viewclear");
3759         }
3760         r_refdef.view.clear = true;
3761
3762         r_refdef.view.showdebug = true;
3763
3764         // this produces a bloom texture to be used in R_BlendView() later
3765         if (r_hdr.integer)
3766                 R_HDR_RenderBloomTexture();
3767
3768         r_waterstate.numwaterplanes = 0;
3769         R_RenderScene(r_waterstate.enabled);
3770
3771         R_BlendView();
3772         if (r_timereport_active)
3773                 R_TimeReport("blendview");
3774
3775         GL_Scissor(0, 0, vid.width, vid.height);
3776         GL_ScissorTest(false);
3777         CHECKGLERROR
3778 }
3779
3780 extern void R_DrawLightningBeams (void);
3781 extern void VM_CL_AddPolygonsToMeshQueue (void);
3782 extern void R_DrawPortals (void);
3783 extern cvar_t cl_locs_show;
3784 static void R_DrawLocs(void);
3785 static void R_DrawEntityBBoxes(void);
3786 void R_RenderScene(qboolean addwaterplanes)
3787 {
3788         r_refdef.stats.renders++;
3789
3790         R_UpdateFogColor();
3791
3792         if (addwaterplanes)
3793         {
3794                 R_ResetViewRendering3D();
3795
3796                 R_View_Update();
3797                 if (r_timereport_active)
3798                         R_TimeReport("watervis");
3799
3800                 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
3801                 {
3802                         r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
3803                         if (r_timereport_active)
3804                                 R_TimeReport("waterworld");
3805                 }
3806
3807                 // don't let sound skip if going slow
3808                 if (r_refdef.scene.extraupdate)
3809                         S_ExtraUpdate ();
3810
3811                 R_DrawModelsAddWaterPlanes();
3812                 if (r_timereport_active)
3813                         R_TimeReport("watermodels");
3814
3815                 R_Water_ProcessPlanes();
3816                 if (r_timereport_active)
3817                         R_TimeReport("waterscenes");
3818         }
3819
3820         R_ResetViewRendering3D();
3821
3822         // don't let sound skip if going slow
3823         if (r_refdef.scene.extraupdate)
3824                 S_ExtraUpdate ();
3825
3826         R_MeshQueue_BeginScene();
3827
3828         R_SkyStartFrame();
3829
3830         R_View_Update();
3831         if (r_timereport_active)
3832                 R_TimeReport("visibility");
3833
3834         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);
3835
3836         if (cl.csqc_vidvars.drawworld)
3837         {
3838                 // don't let sound skip if going slow
3839                 if (r_refdef.scene.extraupdate)
3840                         S_ExtraUpdate ();
3841
3842                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
3843                 {
3844                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
3845                         if (r_timereport_active)
3846                                 R_TimeReport("worldsky");
3847                 }
3848
3849                 if (R_DrawBrushModelsSky() && r_timereport_active)
3850                         R_TimeReport("bmodelsky");
3851         }
3852
3853         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
3854         {
3855                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
3856                 if (r_timereport_active)
3857                         R_TimeReport("worlddepth");
3858         }
3859         if (r_depthfirst.integer >= 2)
3860         {
3861                 R_DrawModelsDepth();
3862                 if (r_timereport_active)
3863                         R_TimeReport("modeldepth");
3864         }
3865
3866         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
3867         {
3868                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
3869                 if (r_timereport_active)
3870                         R_TimeReport("world");
3871         }
3872
3873         // don't let sound skip if going slow
3874         if (r_refdef.scene.extraupdate)
3875                 S_ExtraUpdate ();
3876
3877         R_DrawModels();
3878         if (r_timereport_active)
3879                 R_TimeReport("models");
3880
3881         // don't let sound skip if going slow
3882         if (r_refdef.scene.extraupdate)
3883                 S_ExtraUpdate ();
3884
3885         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3886         {
3887                 R_DrawModelShadows();
3888
3889                 R_ResetViewRendering3D();
3890
3891                 // don't let sound skip if going slow
3892                 if (r_refdef.scene.extraupdate)
3893                         S_ExtraUpdate ();
3894         }
3895
3896         R_ShadowVolumeLighting(false);
3897         if (r_timereport_active)
3898                 R_TimeReport("rtlights");
3899
3900         // don't let sound skip if going slow
3901         if (r_refdef.scene.extraupdate)
3902                 S_ExtraUpdate ();
3903
3904         if (cl.csqc_vidvars.drawworld)
3905         {
3906                 R_DrawLightningBeams();
3907                 if (r_timereport_active)
3908                         R_TimeReport("lightning");
3909
3910                 R_DrawDecals();
3911                 if (r_timereport_active)
3912                         R_TimeReport("decals");
3913
3914                 R_DrawParticles();
3915                 if (r_timereport_active)
3916                         R_TimeReport("particles");
3917
3918                 R_DrawExplosions();
3919                 if (r_timereport_active)
3920                         R_TimeReport("explosions");
3921         }
3922
3923         R_SetupGenericShader(true);
3924         VM_CL_AddPolygonsToMeshQueue();
3925
3926         if (r_refdef.view.showdebug)
3927         {
3928                 if (cl_locs_show.integer)
3929                 {
3930                         R_DrawLocs();
3931                         if (r_timereport_active)
3932                                 R_TimeReport("showlocs");
3933                 }
3934
3935                 if (r_drawportals.integer)
3936                 {
3937                         R_DrawPortals();
3938                         if (r_timereport_active)
3939                                 R_TimeReport("portals");
3940                 }
3941
3942                 if (r_showbboxes.value > 0)
3943                 {
3944                         R_DrawEntityBBoxes();
3945                         if (r_timereport_active)
3946                                 R_TimeReport("bboxes");
3947                 }
3948         }
3949
3950         R_SetupGenericShader(true);
3951         R_MeshQueue_RenderTransparent();
3952         if (r_timereport_active)
3953                 R_TimeReport("drawtrans");
3954
3955         R_SetupGenericShader(true);
3956
3957         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))
3958         {
3959                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
3960                 if (r_timereport_active)
3961                         R_TimeReport("worlddebug");
3962                 R_DrawModelsDebug();
3963                 if (r_timereport_active)
3964                         R_TimeReport("modeldebug");
3965         }
3966
3967         R_SetupGenericShader(true);
3968
3969         if (cl.csqc_vidvars.drawworld)
3970         {
3971                 R_DrawCoronas();
3972                 if (r_timereport_active)
3973                         R_TimeReport("coronas");
3974         }
3975
3976         // don't let sound skip if going slow
3977         if (r_refdef.scene.extraupdate)
3978                 S_ExtraUpdate ();
3979
3980         R_ResetViewRendering2D();
3981 }
3982
3983 static const unsigned short bboxelements[36] =
3984 {
3985         5, 1, 3, 5, 3, 7,
3986         6, 2, 0, 6, 0, 4,
3987         7, 3, 2, 7, 2, 6,
3988         4, 0, 1, 4, 1, 5,
3989         4, 5, 7, 4, 7, 6,
3990         1, 0, 2, 1, 2, 3,
3991 };
3992
3993 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3994 {
3995         int i;
3996         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3997         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3998         GL_DepthMask(false);
3999         GL_DepthRange(0, 1);
4000         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4001         R_Mesh_Matrix(&identitymatrix);
4002         R_Mesh_ResetTextureState();
4003
4004         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4005         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4006         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4007         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4008         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4009         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4010         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4011         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4012         R_FillColors(color4f, 8, cr, cg, cb, ca);
4013         if (r_refdef.fogenabled)
4014         {
4015                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4016                 {
4017                         f1 = FogPoint_World(v);
4018                         f2 = 1 - f1;
4019                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4020                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4021                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4022                 }
4023         }
4024         R_Mesh_VertexPointer(vertex3f, 0, 0);
4025         R_Mesh_ColorPointer(color4f, 0, 0);
4026         R_Mesh_ResetTextureState();
4027         R_SetupGenericShader(false);
4028         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4029 }
4030
4031 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4032 {
4033         int i;
4034         float color[4];
4035         prvm_edict_t *edict;
4036         prvm_prog_t *prog_save = prog;
4037
4038         // this function draws bounding boxes of server entities
4039         if (!sv.active)
4040                 return;
4041
4042         GL_CullFace(GL_NONE);
4043         R_SetupGenericShader(false);
4044
4045         prog = 0;
4046         SV_VM_Begin();
4047         for (i = 0;i < numsurfaces;i++)
4048         {
4049                 edict = PRVM_EDICT_NUM(surfacelist[i]);
4050                 switch ((int)edict->fields.server->solid)
4051                 {
4052                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
4053                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
4054                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
4055                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4056                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
4057                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
4058                 }
4059                 color[3] *= r_showbboxes.value;
4060                 color[3] = bound(0, color[3], 1);
4061                 GL_DepthTest(!r_showdisabledepthtest.integer);
4062                 GL_CullFace(r_refdef.view.cullface_front);
4063                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4064         }
4065         SV_VM_End();
4066         prog = prog_save;
4067 }
4068
4069 static void R_DrawEntityBBoxes(void)
4070 {
4071         int i;
4072         prvm_edict_t *edict;
4073         vec3_t center;
4074         prvm_prog_t *prog_save = prog;
4075
4076         // this function draws bounding boxes of server entities
4077         if (!sv.active)
4078                 return;
4079
4080         prog = 0;
4081         SV_VM_Begin();
4082         for (i = 0;i < prog->num_edicts;i++)
4083         {
4084                 edict = PRVM_EDICT_NUM(i);
4085                 if (edict->priv.server->free)
4086                         continue;
4087                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
4088                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
4089                         continue;
4090                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
4091                         continue;
4092                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4093                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4094         }
4095         SV_VM_End();
4096         prog = prog_save;
4097 }
4098
4099 unsigned short nomodelelements[24] =
4100 {
4101         5, 2, 0,
4102         5, 1, 2,
4103         5, 0, 3,
4104         5, 3, 1,
4105         0, 2, 4,
4106         2, 1, 4,
4107         3, 0, 4,
4108         1, 3, 4
4109 };
4110
4111 float nomodelvertex3f[6*3] =
4112 {
4113         -16,   0,   0,
4114          16,   0,   0,
4115           0, -16,   0,
4116           0,  16,   0,
4117           0,   0, -16,
4118           0,   0,  16
4119 };
4120
4121 float nomodelcolor4f[6*4] =
4122 {
4123         0.0f, 0.0f, 0.5f, 1.0f,
4124         0.0f, 0.0f, 0.5f, 1.0f,
4125         0.0f, 0.5f, 0.0f, 1.0f,
4126         0.0f, 0.5f, 0.0f, 1.0f,
4127         0.5f, 0.0f, 0.0f, 1.0f,
4128         0.5f, 0.0f, 0.0f, 1.0f
4129 };
4130
4131 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4132 {
4133         int i;
4134         float f1, f2, *c;
4135         float color4f[6*4];
4136         // this is only called once per entity so numsurfaces is always 1, and
4137         // surfacelist is always {0}, so this code does not handle batches
4138         R_Mesh_Matrix(&ent->matrix);
4139
4140         if (ent->flags & EF_ADDITIVE)
4141         {
4142                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4143                 GL_DepthMask(false);
4144         }
4145         else if (ent->alpha < 1)
4146         {
4147                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4148                 GL_DepthMask(false);
4149         }
4150         else
4151         {
4152                 GL_BlendFunc(GL_ONE, GL_ZERO);
4153                 GL_DepthMask(true);
4154         }
4155         GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4156         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4157         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4158         GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4159         R_SetupGenericShader(false);
4160         R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4161         if (r_refdef.fogenabled)
4162         {
4163                 vec3_t org;
4164                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4165                 R_Mesh_ColorPointer(color4f, 0, 0);
4166                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4167                 f1 = FogPoint_World(org);
4168                 f2 = 1 - f1;
4169                 for (i = 0, c = color4f;i < 6;i++, c += 4)
4170                 {
4171                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4172                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4173                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4174                         c[3] *= ent->alpha;
4175                 }
4176         }
4177         else if (ent->alpha != 1)
4178         {
4179                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4180                 R_Mesh_ColorPointer(color4f, 0, 0);
4181                 for (i = 0, c = color4f;i < 6;i++, c += 4)
4182                         c[3] *= ent->alpha;
4183         }
4184         else
4185                 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4186         R_Mesh_ResetTextureState();
4187         R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
4188 }
4189
4190 void R_DrawNoModel(entity_render_t *ent)
4191 {
4192         vec3_t org;
4193         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4194         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4195                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4196         //else
4197         //      R_DrawNoModelCallback(ent, 0);
4198 }
4199
4200 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4201 {
4202         vec3_t right1, right2, diff, normal;
4203
4204         VectorSubtract (org2, org1, normal);
4205
4206         // calculate 'right' vector for start
4207         VectorSubtract (r_refdef.view.origin, org1, diff);
4208         CrossProduct (normal, diff, right1);
4209         VectorNormalize (right1);
4210
4211         // calculate 'right' vector for end
4212         VectorSubtract (r_refdef.view.origin, org2, diff);
4213         CrossProduct (normal, diff, right2);
4214         VectorNormalize (right2);
4215
4216         vert[ 0] = org1[0] + width * right1[0];
4217         vert[ 1] = org1[1] + width * right1[1];
4218         vert[ 2] = org1[2] + width * right1[2];
4219         vert[ 3] = org1[0] - width * right1[0];
4220         vert[ 4] = org1[1] - width * right1[1];
4221         vert[ 5] = org1[2] - width * right1[2];
4222         vert[ 6] = org2[0] - width * right2[0];
4223         vert[ 7] = org2[1] - width * right2[1];
4224         vert[ 8] = org2[2] - width * right2[2];
4225         vert[ 9] = org2[0] + width * right2[0];
4226         vert[10] = org2[1] + width * right2[1];
4227         vert[11] = org2[2] + width * right2[2];
4228 }
4229
4230 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4231
4232 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)
4233 {
4234         float fog = 1.0f;
4235         float vertex3f[12];
4236
4237         if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4238                 fog = FogPoint_World(origin);
4239
4240         R_Mesh_Matrix(&identitymatrix);
4241         GL_BlendFunc(blendfunc1, blendfunc2);
4242
4243         if(v_flipped_state)
4244         {
4245                 scalex1 = -scalex1;
4246                 scalex2 = -scalex2;
4247                 GL_CullFace(r_refdef.view.cullface_front);
4248         }
4249         else
4250                 GL_CullFace(r_refdef.view.cullface_back);
4251         GL_CullFace(GL_NONE);
4252
4253         GL_DepthMask(false);
4254         GL_DepthRange(0, depthshort ? 0.0625 : 1);
4255         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4256         GL_DepthTest(!depthdisable);
4257
4258         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4259         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4260         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4261         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
4262         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
4263         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
4264         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
4265         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
4266         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
4267         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
4268         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
4269         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
4270
4271         R_Mesh_VertexPointer(vertex3f, 0, 0);
4272         R_Mesh_ColorPointer(NULL, 0, 0);
4273         R_Mesh_ResetTextureState();
4274         R_SetupGenericShader(true);
4275         R_Mesh_TexBind(0, R_GetTexture(texture));
4276         R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
4277         // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
4278         GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
4279         R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4280
4281         if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
4282         {
4283                 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
4284                 GL_BlendFunc(blendfunc1, GL_ONE);
4285                 fog = 1 - fog;
4286                 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
4287                 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4288         }
4289 }
4290
4291 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
4292 {
4293         int i;
4294         float *vertex3f;
4295         float v[3];
4296         VectorSet(v, x, y, z);
4297         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
4298                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
4299                         break;
4300         if (i == mesh->numvertices)
4301         {
4302                 if (mesh->numvertices < mesh->maxvertices)
4303                 {
4304                         VectorCopy(v, vertex3f);
4305                         mesh->numvertices++;
4306                 }
4307                 return mesh->numvertices;
4308         }
4309         else
4310                 return i;
4311 }
4312
4313 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
4314 {
4315         int i;
4316         int *e, element[3];
4317         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4318         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4319         e = mesh->element3i + mesh->numtriangles * 3;
4320         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
4321         {
4322                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
4323                 if (mesh->numtriangles < mesh->maxtriangles)
4324                 {
4325                         *e++ = element[0];
4326                         *e++ = element[1];
4327                         *e++ = element[2];
4328                         mesh->numtriangles++;
4329                 }
4330                 element[1] = element[2];
4331         }
4332 }
4333
4334 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
4335 {
4336         int i;
4337         int *e, element[3];
4338         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4339         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4340         e = mesh->element3i + mesh->numtriangles * 3;
4341         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
4342         {
4343                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
4344                 if (mesh->numtriangles < mesh->maxtriangles)
4345                 {
4346                         *e++ = element[0];
4347                         *e++ = element[1];
4348                         *e++ = element[2];
4349                         mesh->numtriangles++;
4350                 }
4351                 element[1] = element[2];
4352         }
4353 }
4354
4355 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
4356 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
4357 {
4358         int planenum, planenum2;
4359         int w;
4360         int tempnumpoints;
4361         mplane_t *plane, *plane2;
4362         double maxdist;
4363         double temppoints[2][256*3];
4364         // figure out how large a bounding box we need to properly compute this brush
4365         maxdist = 0;
4366         for (w = 0;w < numplanes;w++)
4367                 maxdist = max(maxdist, planes[w].dist);
4368         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4369         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4370         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4371         {
4372                 w = 0;
4373                 tempnumpoints = 4;
4374                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4375                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4376                 {
4377                         if (planenum2 == planenum)
4378                                 continue;
4379                         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);
4380                         w = !w;
4381                 }
4382                 if (tempnumpoints < 3)
4383                         continue;
4384                 // generate elements forming a triangle fan for this polygon
4385                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4386         }
4387 }
4388
4389 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)
4390 {
4391         texturelayer_t *layer;
4392         layer = t->currentlayers + t->currentnumlayers++;
4393         layer->type = type;
4394         layer->depthmask = depthmask;
4395         layer->blendfunc1 = blendfunc1;
4396         layer->blendfunc2 = blendfunc2;
4397         layer->texture = texture;
4398         layer->texmatrix = *matrix;
4399         layer->color[0] = r * r_refdef.view.colorscale;
4400         layer->color[1] = g * r_refdef.view.colorscale;
4401         layer->color[2] = b * r_refdef.view.colorscale;
4402         layer->color[3] = a;
4403 }
4404
4405 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4406 {
4407         double index, f;
4408         index = parms[2] + r_refdef.scene.time * parms[3];
4409         index -= floor(index);
4410         switch (func)
4411         {
4412         default:
4413         case Q3WAVEFUNC_NONE:
4414         case Q3WAVEFUNC_NOISE:
4415         case Q3WAVEFUNC_COUNT:
4416                 f = 0;
4417                 break;
4418         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4419         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4420         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4421         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4422         case Q3WAVEFUNC_TRIANGLE:
4423                 index *= 4;
4424                 f = index - floor(index);
4425                 if (index < 1)
4426                         f = f;
4427                 else if (index < 2)
4428                         f = 1 - f;
4429                 else if (index < 3)
4430                         f = -f;
4431                 else
4432                         f = -(1 - f);
4433                 break;
4434         }
4435         return (float)(parms[0] + parms[1] * f);
4436 }
4437
4438 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
4439 {
4440         int i;
4441         dp_model_t *model = ent->model;
4442         float f;
4443         float tcmat[12];
4444         q3shaderinfo_layer_tcmod_t *tcmod;
4445
4446         if (t->basematerialflags & MATERIALFLAG_NODRAW)
4447         {
4448                 t->currentmaterialflags = MATERIALFLAG_NODRAW;
4449                 return;
4450         }
4451
4452         // switch to an alternate material if this is a q1bsp animated material
4453         {
4454                 texture_t *texture = t;
4455                 int s = ent->skinnum;
4456                 if ((unsigned int)s >= (unsigned int)model->numskins)
4457                         s = 0;
4458                 if (model->skinscenes)
4459                 {
4460                         if (model->skinscenes[s].framecount > 1)
4461                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4462                         else
4463                                 s = model->skinscenes[s].firstframe;
4464                 }
4465                 if (s > 0)
4466                         t = t + s * model->num_surfaces;
4467                 if (t->animated)
4468                 {
4469                         // use an alternate animation if the entity's frame is not 0,
4470                         // and only if the texture has an alternate animation
4471                         if (ent->frame2 != 0 && t->anim_total[1])
4472                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4473                         else
4474                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4475                 }
4476                 texture->currentframe = t;
4477         }
4478
4479         // update currentskinframe to be a qw skin or animation frame
4480         if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
4481         {
4482                 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4483                 {
4484                         strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4485                         if (developer_loading.integer)
4486                                 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
4487                         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);
4488                 }
4489                 t->currentskinframe = r_qwskincache_skinframe[i];
4490                 if (t->currentskinframe == NULL)
4491                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4492         }
4493         else if (t->numskinframes >= 2)
4494                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4495         if (t->backgroundnumskinframes >= 2)
4496                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
4497
4498         t->currentmaterialflags = t->basematerialflags;
4499         t->currentalpha = ent->alpha;
4500         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4501                 t->currentalpha *= r_wateralpha.value;
4502         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
4503                 t->currentalpha *= t->r_water_wateralpha;
4504         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
4505                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4506         if (!(ent->flags & RENDER_LIGHT))
4507                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4508         else if (rsurface.modeltexcoordlightmap2f == NULL)
4509         {
4510                 // pick a model lighting mode
4511                 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4512                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4513                 else
4514                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4515         }
4516         if (ent->effects & EF_ADDITIVE)
4517                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4518         else if (t->currentalpha < 1)
4519                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4520         if (ent->effects & EF_DOUBLESIDED)
4521                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4522         if (ent->effects & EF_NODEPTHTEST)
4523                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4524         if (ent->flags & RENDER_VIEWMODEL)
4525                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4526         if (t->backgroundnumskinframes)
4527                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4528         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
4529         {
4530                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
4531                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
4532         }
4533         else
4534                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
4535
4536         // there is no tcmod
4537         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4538                 t->currenttexmatrix = r_waterscrollmatrix;
4539
4540         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4541         {
4542                 matrix4x4_t matrix;
4543                 switch(tcmod->tcmod)
4544                 {
4545                 case Q3TCMOD_COUNT:
4546                 case Q3TCMOD_NONE:
4547                         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4548                                 matrix = r_waterscrollmatrix;
4549                         else
4550                                 matrix = identitymatrix;
4551                         break;
4552                 case Q3TCMOD_ENTITYTRANSLATE:
4553                         // this is used in Q3 to allow the gamecode to control texcoord
4554                         // scrolling on the entity, which is not supported in darkplaces yet.
4555                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4556                         break;
4557                 case Q3TCMOD_ROTATE:
4558                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4559                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4560                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4561                         break;
4562                 case Q3TCMOD_SCALE:
4563                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4564                         break;
4565                 case Q3TCMOD_SCROLL:
4566                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4567                         break;
4568                 case Q3TCMOD_STRETCH:
4569                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4570                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4571                         break;
4572                 case Q3TCMOD_TRANSFORM:
4573                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
4574                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
4575                         VectorSet(tcmat +  6, 0                   , 0                , 1);
4576                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
4577                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4578                         break;
4579                 case Q3TCMOD_TURBULENT:
4580                         // this is handled in the RSurf_PrepareVertices function
4581                         matrix = identitymatrix;
4582                         break;
4583                 }
4584                 // either replace or concatenate the transformation
4585                 if (i < 1)
4586                         t->currenttexmatrix = matrix;
4587                 else
4588                 {
4589                         matrix4x4_t temp = t->currenttexmatrix;
4590                         Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4591                 }
4592         }
4593
4594         t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4595         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4596         t->glosstexture = r_texture_black;
4597         t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4598         t->backgroundglosstexture = r_texture_black;
4599         t->specularpower = r_shadow_glossexponent.value;
4600         // TODO: store reference values for these in the texture?
4601         t->specularscale = 0;
4602         if (r_shadow_gloss.integer > 0)
4603         {
4604                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4605                 {
4606                         if (r_shadow_glossintensity.value > 0)
4607                         {
4608                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4609                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4610                                 t->specularscale = r_shadow_glossintensity.value;
4611                         }
4612                 }
4613                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4614                 {
4615                         t->glosstexture = r_texture_white;
4616                         t->backgroundglosstexture = r_texture_white;
4617                         t->specularscale = r_shadow_gloss2intensity.value;
4618                 }
4619         }
4620
4621         // lightmaps mode looks bad with dlights using actual texturing, so turn
4622         // off the colormap and glossmap, but leave the normalmap on as it still
4623         // accurately represents the shading involved
4624         if (gl_lightmaps.integer)
4625         {
4626                 t->basetexture = r_texture_grey128;
4627                 t->backgroundbasetexture = NULL;
4628                 t->specularscale = 0;
4629                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
4630         }
4631
4632         Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4633         VectorClear(t->dlightcolor);
4634         t->currentnumlayers = 0;
4635         if (t->currentmaterialflags & MATERIALFLAG_WALL)
4636         {
4637                 int layerflags = 0;
4638                 int blendfunc1, blendfunc2, depthmask;
4639                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4640                 {
4641                         blendfunc1 = GL_SRC_ALPHA;
4642                         blendfunc2 = GL_ONE;
4643                 }
4644                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4645                 {
4646                         blendfunc1 = GL_SRC_ALPHA;
4647                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4648                 }
4649                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4650                 {
4651                         blendfunc1 = t->customblendfunc[0];
4652                         blendfunc2 = t->customblendfunc[1];
4653                 }
4654                 else
4655                 {
4656                         blendfunc1 = GL_ONE;
4657                         blendfunc2 = GL_ZERO;
4658                 }
4659                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4660                 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4661                         layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4662                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4663                 {
4664                         // fullbright is not affected by r_refdef.lightmapintensity
4665                         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]);
4666                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4667                                 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]);
4668                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4669                                 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]);
4670                 }
4671                 else
4672                 {
4673                         vec3_t ambientcolor;
4674                         float colorscale;
4675                         // set the color tint used for lights affecting this surface
4676                         VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
4677                         colorscale = 2;
4678                         // q3bsp has no lightmap updates, so the lightstylevalue that
4679                         // would normally be baked into the lightmap must be
4680                         // applied to the color
4681                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4682                         if (ent->model->type == mod_brushq3)
4683                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
4684                         colorscale *= r_refdef.lightmapintensity;
4685                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
4686                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4687                         // basic lit geometry
4688                         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]);
4689                         // add pants/shirt if needed
4690                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4691                                 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]);
4692                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4693                                 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]);
4694                         // now add ambient passes if needed
4695                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
4696                         {
4697                                 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]);
4698                                 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4699                                         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]);
4700                                 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4701                                         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]);
4702                         }
4703                 }
4704                 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
4705                         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]);
4706                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4707                 {
4708                         // if this is opaque use alpha blend which will darken the earlier
4709                         // passes cheaply.
4710                         //
4711                         // if this is an alpha blended material, all the earlier passes
4712                         // were darkened by fog already, so we only need to add the fog
4713                         // color ontop through the fog mask texture
4714                         //
4715                         // if this is an additive blended material, all the earlier passes
4716                         // were darkened by fog already, and we should not add fog color
4717                         // (because the background was not darkened, there is no fog color
4718                         // that was lost behind it).
4719                         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]);
4720                 }
4721         }
4722 }
4723
4724 void R_UpdateAllTextureInfo(entity_render_t *ent)
4725 {
4726         int i;
4727         if (ent->model)
4728                 for (i = 0;i < ent->model->num_texturesperskin;i++)
4729                         R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4730 }
4731
4732 rsurfacestate_t rsurface;
4733
4734 void R_Mesh_ResizeArrays(int newvertices)
4735 {
4736         float *base;
4737         if (rsurface.array_size >= newvertices)
4738                 return;
4739         if (rsurface.array_modelvertex3f)
4740                 Mem_Free(rsurface.array_modelvertex3f);
4741         rsurface.array_size = (newvertices + 1023) & ~1023;
4742         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4743         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
4744         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
4745         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
4746         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
4747         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
4748         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4749         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4750         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
4751         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
4752         rsurface.array_color4f           = base + rsurface.array_size * 27;
4753         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4754 }
4755
4756 void RSurf_ActiveWorldEntity(void)
4757 {
4758         dp_model_t *model = r_refdef.scene.worldmodel;
4759         if (rsurface.array_size < model->surfmesh.num_vertices)
4760                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4761         rsurface.matrix = identitymatrix;
4762         rsurface.inversematrix = identitymatrix;
4763         R_Mesh_Matrix(&identitymatrix);
4764         VectorCopy(r_refdef.view.origin, rsurface.modelorg);
4765         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4766         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4767         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4768         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4769         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4770         rsurface.frameblend[0].frame = 0;
4771         rsurface.frameblend[0].lerp = 1;
4772         rsurface.frameblend[1].frame = 0;
4773         rsurface.frameblend[1].lerp = 0;
4774         rsurface.frameblend[2].frame = 0;
4775         rsurface.frameblend[2].lerp = 0;
4776         rsurface.frameblend[3].frame = 0;
4777         rsurface.frameblend[3].lerp = 0;
4778         rsurface.basepolygonfactor = r_refdef.polygonfactor;
4779         rsurface.basepolygonoffset = r_refdef.polygonoffset;
4780         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
4781         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4782         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4783         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4784         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4785         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4786         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4787         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4788         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4789         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
4790         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4791         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4792         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
4793         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4794         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4795         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
4796         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4797         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4798         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
4799         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4800         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4801         rsurface.modelelement3i = model->surfmesh.data_element3i;
4802         rsurface.modelelement3s = model->surfmesh.data_element3s;
4803         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
4804         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
4805         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4806         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4807         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4808         rsurface.modelsurfaces = model->data_surfaces;
4809         rsurface.generatedvertex = false;
4810         rsurface.vertex3f  = rsurface.modelvertex3f;
4811         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4812         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4813         rsurface.svector3f = rsurface.modelsvector3f;
4814         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4815         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4816         rsurface.tvector3f = rsurface.modeltvector3f;
4817         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4818         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4819         rsurface.normal3f  = rsurface.modelnormal3f;
4820         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4821         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4822         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4823 }
4824
4825 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4826 {
4827         dp_model_t *model = ent->model;
4828         if (rsurface.array_size < model->surfmesh.num_vertices)
4829                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4830         rsurface.matrix = ent->matrix;
4831         rsurface.inversematrix = ent->inversematrix;
4832         R_Mesh_Matrix(&rsurface.matrix);
4833         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
4834         rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
4835         rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
4836         rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
4837         rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
4838         rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
4839         rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
4840         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4841         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4842         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4843         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4844         rsurface.frameblend[0] = ent->frameblend[0];
4845         rsurface.frameblend[1] = ent->frameblend[1];
4846         rsurface.frameblend[2] = ent->frameblend[2];
4847         rsurface.frameblend[3] = ent->frameblend[3];
4848         rsurface.basepolygonfactor = r_refdef.polygonfactor;
4849         rsurface.basepolygonoffset = r_refdef.polygonoffset;
4850         if (ent->model->brush.submodel)
4851         {
4852                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
4853                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
4854         }
4855         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4856         {
4857                 if (wanttangents)
4858                 {
4859                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4860                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4861                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4862                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4863                         model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4864                 }
4865                 else if (wantnormals)
4866                 {
4867                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4868                         rsurface.modelsvector3f = NULL;
4869                         rsurface.modeltvector3f = NULL;
4870                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4871                         model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4872                 }
4873                 else
4874                 {
4875                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4876                         rsurface.modelsvector3f = NULL;
4877                         rsurface.modeltvector3f = NULL;
4878                         rsurface.modelnormal3f = NULL;
4879                         model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4880                 }
4881                 rsurface.modelvertex3f_bufferobject = 0;
4882                 rsurface.modelvertex3f_bufferoffset = 0;
4883                 rsurface.modelsvector3f_bufferobject = 0;
4884                 rsurface.modelsvector3f_bufferoffset = 0;
4885                 rsurface.modeltvector3f_bufferobject = 0;
4886                 rsurface.modeltvector3f_bufferoffset = 0;
4887                 rsurface.modelnormal3f_bufferobject = 0;
4888                 rsurface.modelnormal3f_bufferoffset = 0;
4889                 rsurface.generatedvertex = true;
4890         }
4891         else
4892         {
4893                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
4894                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4895                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4896                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4897                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4898                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4899                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4900                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4901                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4902                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
4903                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4904                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4905                 rsurface.generatedvertex = false;
4906         }
4907         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
4908         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4909         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4910         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
4911         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4912         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4913         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
4914         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4915         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4916         rsurface.modelelement3i = model->surfmesh.data_element3i;
4917         rsurface.modelelement3s = model->surfmesh.data_element3s;
4918         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
4919         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
4920         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4921         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4922         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4923         rsurface.modelsurfaces = model->data_surfaces;
4924         rsurface.vertex3f  = rsurface.modelvertex3f;
4925         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4926         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4927         rsurface.svector3f = rsurface.modelsvector3f;
4928         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4929         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4930         rsurface.tvector3f = rsurface.modeltvector3f;
4931         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4932         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4933         rsurface.normal3f  = rsurface.modelnormal3f;
4934         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4935         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4936         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4937 }
4938
4939 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4940 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4941 {
4942         int deformindex;
4943         int texturesurfaceindex;
4944         int i, j;
4945         float amplitude;
4946         float animpos;
4947         float scale;
4948         const float *v1, *in_tc;
4949         float *out_tc;
4950         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4951         float waveparms[4];
4952         q3shaderinfo_deform_t *deform;
4953         // 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
4954         if (rsurface.generatedvertex)
4955         {
4956                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4957                         generatenormals = true;
4958                 for (i = 0;i < Q3MAXDEFORMS;i++)
4959                 {
4960                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4961                         {
4962                                 generatetangents = true;
4963                                 generatenormals = true;
4964                         }
4965                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4966                                 generatenormals = true;
4967                 }
4968                 if (generatenormals && !rsurface.modelnormal3f)
4969                 {
4970                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4971                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4972                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4973                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4974                 }
4975                 if (generatetangents && !rsurface.modelsvector3f)
4976                 {
4977                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4978                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4979                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4980                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4981                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4982                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4983                         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);
4984                 }
4985         }
4986         rsurface.vertex3f  = rsurface.modelvertex3f;
4987         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4988         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4989         rsurface.svector3f = rsurface.modelsvector3f;
4990         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4991         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4992         rsurface.tvector3f = rsurface.modeltvector3f;
4993         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4994         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4995         rsurface.normal3f  = rsurface.modelnormal3f;
4996         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4997         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4998         // if vertices are deformed (sprite flares and things in maps, possibly
4999         // water waves, bulges and other deformations), generate them into
5000         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5001         // (may be static model data or generated data for an animated model, or
5002         //  the previous deform pass)
5003         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5004         {
5005                 switch (deform->deform)
5006                 {
5007                 default:
5008                 case Q3DEFORM_PROJECTIONSHADOW:
5009                 case Q3DEFORM_TEXT0:
5010                 case Q3DEFORM_TEXT1:
5011                 case Q3DEFORM_TEXT2:
5012                 case Q3DEFORM_TEXT3:
5013                 case Q3DEFORM_TEXT4:
5014                 case Q3DEFORM_TEXT5:
5015                 case Q3DEFORM_TEXT6:
5016                 case Q3DEFORM_TEXT7:
5017                 case Q3DEFORM_NONE:
5018                         break;
5019                 case Q3DEFORM_AUTOSPRITE:
5020                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5021                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5022                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5023                         VectorNormalize(newforward);
5024                         VectorNormalize(newright);
5025                         VectorNormalize(newup);
5026                         // make deformed versions of only the model vertices used by the specified surfaces
5027                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5028                         {
5029                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5030                                 // a single autosprite surface can contain multiple sprites...
5031                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
5032                                 {
5033                                         VectorClear(center);
5034                                         for (i = 0;i < 4;i++)
5035                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5036                                         VectorScale(center, 0.25f, center);
5037                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
5038                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5039                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5040                                         for (i = 0;i < 4;i++)
5041                                         {
5042                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5043                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5044                                         }
5045                                 }
5046                                 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);
5047                                 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);
5048                         }
5049                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5050                         rsurface.vertex3f_bufferobject = 0;
5051                         rsurface.vertex3f_bufferoffset = 0;
5052                         rsurface.svector3f = rsurface.array_deformedsvector3f;
5053                         rsurface.svector3f_bufferobject = 0;
5054                         rsurface.svector3f_bufferoffset = 0;
5055                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
5056                         rsurface.tvector3f_bufferobject = 0;
5057                         rsurface.tvector3f_bufferoffset = 0;
5058                         rsurface.normal3f = rsurface.array_deformednormal3f;
5059                         rsurface.normal3f_bufferobject = 0;
5060                         rsurface.normal3f_bufferoffset = 0;
5061                         break;
5062                 case Q3DEFORM_AUTOSPRITE2:
5063                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5064                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5065                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5066                         VectorNormalize(newforward);
5067                         VectorNormalize(newright);
5068                         VectorNormalize(newup);
5069                         // make deformed versions of only the model vertices used by the specified surfaces
5070                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5071                         {
5072                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5073                                 const float *v1, *v2;
5074                                 vec3_t start, end;
5075                                 float f, l;
5076                                 struct
5077                                 {
5078                                         float length2;
5079                                         const float *v1;
5080                                         const float *v2;
5081                                 }
5082                                 shortest[2];
5083                                 memset(shortest, 0, sizeof(shortest));
5084                                 // a single autosprite surface can contain multiple sprites...
5085                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
5086                                 {
5087                                         VectorClear(center);
5088                                         for (i = 0;i < 4;i++)
5089                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5090                                         VectorScale(center, 0.25f, center);
5091                                         // find the two shortest edges, then use them to define the
5092                                         // axis vectors for rotating around the central axis
5093                                         for (i = 0;i < 6;i++)
5094                                         {
5095                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5096                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5097 #if 0
5098                                                 Debug_PolygonBegin(NULL, 0);
5099                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5100                                                 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);
5101                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5102                                                 Debug_PolygonEnd();
5103 #endif
5104                                                 l = VectorDistance2(v1, v2);
5105                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5106                                                 if (v1[2] != v2[2])
5107                                                         l += (1.0f / 1024.0f);
5108                                                 if (shortest[0].length2 > l || i == 0)
5109                                                 {
5110                                                         shortest[1] = shortest[0];
5111                                                         shortest[0].length2 = l;
5112                                                         shortest[0].v1 = v1;
5113                                                         shortest[0].v2 = v2;
5114                                                 }
5115                                                 else if (shortest[1].length2 > l || i == 1)
5116                                                 {
5117                                                         shortest[1].length2 = l;
5118                                                         shortest[1].v1 = v1;
5119                                                         shortest[1].v2 = v2;
5120                                                 }
5121                                         }
5122                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5123                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5124 #if 0
5125                                         Debug_PolygonBegin(NULL, 0);
5126                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5127                                         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);
5128                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5129                                         Debug_PolygonEnd();
5130 #endif
5131                                         // this calculates the right vector from the shortest edge
5132                                         // and the up vector from the edge midpoints
5133                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5134                                         VectorNormalize(right);
5135                                         VectorSubtract(end, start, up);
5136                                         VectorNormalize(up);
5137                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5138                                         //VectorSubtract(rsurface.modelorg, center, forward);
5139                                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5140                                         VectorNegate(forward, forward);
5141                                         VectorReflect(forward, 0, up, forward);
5142                                         VectorNormalize(forward);
5143                                         CrossProduct(up, forward, newright);
5144                                         VectorNormalize(newright);
5145 #if 0
5146                                         Debug_PolygonBegin(NULL, 0);
5147                                         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);
5148                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5149                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
5150                                         Debug_PolygonEnd();
5151 #endif
5152 #if 0
5153                                         Debug_PolygonBegin(NULL, 0);
5154                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5155                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5156                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
5157                                         Debug_PolygonEnd();
5158 #endif
5159                                         // rotate the quad around the up axis vector, this is made
5160                                         // especially easy by the fact we know the quad is flat,
5161                                         // so we only have to subtract the center position and
5162                                         // measure distance along the right vector, and then
5163                                         // multiply that by the newright vector and add back the
5164                                         // center position
5165                                         // we also need to subtract the old position to undo the
5166                                         // displacement from the center, which we do with a
5167                                         // DotProduct, the subtraction/addition of center is also
5168                                         // optimized into DotProducts here
5169                                         l = DotProduct(right, center);
5170                                         for (i = 0;i < 4;i++)
5171                                         {
5172                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5173                                                 f = DotProduct(right, v1) - l;
5174                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5175                                         }
5176                                 }
5177                                 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);
5178                                 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);
5179                         }
5180                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5181                         rsurface.vertex3f_bufferobject = 0;
5182                         rsurface.vertex3f_bufferoffset = 0;
5183                         rsurface.svector3f = rsurface.array_deformedsvector3f;
5184                         rsurface.svector3f_bufferobject = 0;
5185                         rsurface.svector3f_bufferoffset = 0;
5186                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
5187                         rsurface.tvector3f_bufferobject = 0;
5188                         rsurface.tvector3f_bufferoffset = 0;
5189                         rsurface.normal3f = rsurface.array_deformednormal3f;
5190                         rsurface.normal3f_bufferobject = 0;
5191                         rsurface.normal3f_bufferoffset = 0;
5192                         break;
5193                 case Q3DEFORM_NORMAL:
5194                         // deform the normals to make reflections wavey
5195                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5196                         {
5197                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5198                                 for (j = 0;j < surface->num_vertices;j++)
5199                                 {
5200                                         float vertex[3];
5201                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
5202                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5203                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
5204                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5205                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5206                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5207                                         VectorNormalize(normal);
5208                                 }
5209                                 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);
5210                         }
5211                         rsurface.svector3f = rsurface.array_deformedsvector3f;
5212                         rsurface.svector3f_bufferobject = 0;
5213                         rsurface.svector3f_bufferoffset = 0;
5214                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
5215                         rsurface.tvector3f_bufferobject = 0;
5216                         rsurface.tvector3f_bufferoffset = 0;
5217                         rsurface.normal3f = rsurface.array_deformednormal3f;
5218                         rsurface.normal3f_bufferobject = 0;
5219                         rsurface.normal3f_bufferoffset = 0;
5220                         break;
5221                 case Q3DEFORM_WAVE:
5222                         // deform vertex array to make wavey water and flags and such
5223                         waveparms[0] = deform->waveparms[0];
5224                         waveparms[1] = deform->waveparms[1];
5225                         waveparms[2] = deform->waveparms[2];
5226                         waveparms[3] = deform->waveparms[3];
5227                         // this is how a divisor of vertex influence on deformation
5228                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5229                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5230                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5231                         {
5232                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5233                                 for (j = 0;j < surface->num_vertices;j++)
5234                                 {
5235                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
5236                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
5237                                         // if the wavefunc depends on time, evaluate it per-vertex
5238                                         if (waveparms[3])
5239                                         {
5240                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5241                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5242                                         }
5243                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
5244                                 }
5245                         }
5246                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5247                         rsurface.vertex3f_bufferobject = 0;
5248                         rsurface.vertex3f_bufferoffset = 0;
5249                         break;
5250                 case Q3DEFORM_BULGE:
5251                         // deform vertex array to make the surface have moving bulges
5252                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5253                         {
5254                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5255                                 for (j = 0;j < surface->num_vertices;j++)
5256                                 {
5257                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
5258                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5259                                 }
5260                         }
5261                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5262                         rsurface.vertex3f_bufferobject = 0;
5263                         rsurface.vertex3f_bufferoffset = 0;
5264                         break;
5265                 case Q3DEFORM_MOVE:
5266                         // deform vertex array
5267                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
5268                         VectorScale(deform->parms, scale, waveparms);
5269                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5270                         {
5271                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5272                                 for (j = 0;j < surface->num_vertices;j++)
5273                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5274                         }
5275                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5276                         rsurface.vertex3f_bufferobject = 0;
5277                         rsurface.vertex3f_bufferoffset = 0;
5278                         break;
5279                 }
5280         }
5281         // generate texcoords based on the chosen texcoord source
5282         switch(rsurface.texture->tcgen.tcgen)
5283         {
5284         default:
5285         case Q3TCGEN_TEXTURE:
5286                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
5287                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
5288                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
5289                 break;
5290         case Q3TCGEN_LIGHTMAP:
5291                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
5292                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
5293                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
5294                 break;
5295         case Q3TCGEN_VECTOR:
5296                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5297                 {
5298                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5299                         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)
5300                         {
5301                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
5302                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
5303                         }
5304                 }
5305                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
5306                 rsurface.texcoordtexture2f_bufferobject  = 0;
5307                 rsurface.texcoordtexture2f_bufferoffset  = 0;
5308                 break;
5309         case Q3TCGEN_ENVIRONMENT:
5310                 // make environment reflections using a spheremap
5311                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5312                 {
5313                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5314                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
5315                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
5316                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
5317                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
5318                         {
5319                                 float l, d, eyedir[3];
5320                                 VectorSubtract(rsurface.modelorg, vertex, eyedir);
5321                                 l = 0.5f / VectorLength(eyedir);
5322                                 d = DotProduct(normal, eyedir)*2;
5323                                 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
5324                                 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
5325                         }
5326                 }
5327                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
5328                 rsurface.texcoordtexture2f_bufferobject  = 0;
5329                 rsurface.texcoordtexture2f_bufferoffset  = 0;
5330                 break;
5331         }
5332         // the only tcmod that needs software vertex processing is turbulent, so
5333         // check for it here and apply the changes if needed
5334         // and we only support that as the first one
5335         // (handling a mixture of turbulent and other tcmods would be problematic
5336         //  without punting it entirely to a software path)
5337         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
5338         {
5339                 amplitude = rsurface.texture->tcmods[0].parms[1];
5340                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
5341                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5342                 {
5343                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5344                         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)
5345                         {
5346                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5347                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5348                         }
5349                 }
5350                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
5351                 rsurface.texcoordtexture2f_bufferobject  = 0;
5352                 rsurface.texcoordtexture2f_bufferoffset  = 0;
5353         }
5354         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
5355         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5356         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5357         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5358 }
5359
5360 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5361 {
5362         int i, j;
5363         const msurface_t *surface = texturesurfacelist[0];
5364         const msurface_t *surface2;
5365         int firstvertex;
5366         int endvertex;
5367         int numvertices;
5368         int numtriangles;
5369         // TODO: lock all array ranges before render, rather than on each surface
5370         if (texturenumsurfaces == 1)
5371         {
5372                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5373                 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);
5374         }
5375         else if (r_batchmode.integer == 2)
5376         {
5377                 #define MAXBATCHTRIANGLES 4096
5378                 int batchtriangles = 0;
5379                 int batchelements[MAXBATCHTRIANGLES*3];
5380                 for (i = 0;i < texturenumsurfaces;i = j)
5381                 {
5382                         surface = texturesurfacelist[i];
5383                         j = i + 1;
5384                         if (surface->num_triangles > MAXBATCHTRIANGLES)
5385                         {
5386                                 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);
5387                                 continue;
5388                         }
5389                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5390                         batchtriangles = surface->num_triangles;
5391                         firstvertex = surface->num_firstvertex;
5392                         endvertex = surface->num_firstvertex + surface->num_vertices;
5393                         for (;j < texturenumsurfaces;j++)
5394                         {
5395                                 surface2 = texturesurfacelist[j];
5396                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5397                                         break;
5398                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5399                                 batchtriangles += surface2->num_triangles;
5400                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
5401                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5402                         }
5403                         surface2 = texturesurfacelist[j-1];
5404                         numvertices = endvertex - firstvertex;
5405                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5406                 }
5407         }
5408         else if (r_batchmode.integer == 1)
5409         {
5410                 for (i = 0;i < texturenumsurfaces;i = j)
5411                 {
5412                         surface = texturesurfacelist[i];
5413                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5414                                 if (texturesurfacelist[j] != surface2)
5415                                         break;
5416                         surface2 = texturesurfacelist[j-1];
5417                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5418                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5419                         GL_LockArrays(surface->num_firstvertex, numvertices);
5420                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5421                 }
5422         }
5423         else
5424         {
5425                 for (i = 0;i < texturenumsurfaces;i++)
5426                 {
5427                         surface = texturesurfacelist[i];
5428                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5429                         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);
5430                 }
5431         }
5432 }
5433
5434 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5435 {
5436         int i, planeindex, vertexindex;
5437         float d, bestd;
5438         vec3_t vert;
5439         const float *v;
5440         r_waterstate_waterplane_t *p, *bestp;
5441         msurface_t *surface;
5442         if (r_waterstate.renderingscene)
5443                 return;
5444         for (i = 0;i < texturenumsurfaces;i++)
5445         {
5446                 surface = texturesurfacelist[i];
5447                 if (lightmaptexunit >= 0)
5448                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5449                 if (deluxemaptexunit >= 0)
5450                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5451                 // pick the closest matching water plane
5452                 bestd = 0;
5453                 bestp = NULL;
5454                 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5455                 {
5456                         d = 0;
5457                         for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5458                         {
5459                                 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5460                                 d += fabs(PlaneDiff(vert, &p->plane));
5461                         }
5462                         if (bestd > d || !bestp)
5463                         {
5464                                 bestd = d;
5465                                 bestp = p;
5466                         }
5467                 }
5468                 if (bestp)
5469                 {
5470                         if (refractiontexunit >= 0)
5471                                 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5472                         if (reflectiontexunit >= 0)
5473                                 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5474                 }
5475                 else
5476                 {
5477                         if (refractiontexunit >= 0)
5478                                 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5479                         if (reflectiontexunit >= 0)
5480                                 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5481                 }
5482                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5483                 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);
5484         }
5485 }
5486
5487 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5488 {
5489         int i;
5490         int j;
5491         const msurface_t *surface = texturesurfacelist[0];
5492         const msurface_t *surface2;
5493         int firstvertex;
5494         int endvertex;
5495         int numvertices;
5496         int numtriangles;
5497         // TODO: lock all array ranges before render, rather than on each surface
5498         if (texturenumsurfaces == 1)
5499         {
5500                 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5501                 if (deluxemaptexunit >= 0)
5502                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5503                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5504                 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);
5505         }
5506         else if (r_batchmode.integer == 2)
5507         {
5508                 #define MAXBATCHTRIANGLES 4096
5509                 int batchtriangles = 0;
5510                 int batchelements[MAXBATCHTRIANGLES*3];
5511                 for (i = 0;i < texturenumsurfaces;i = j)
5512                 {
5513                         surface = texturesurfacelist[i];
5514                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5515                         if (deluxemaptexunit >= 0)
5516                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5517                         j = i + 1;
5518                         if (surface->num_triangles > MAXBATCHTRIANGLES)
5519                         {
5520                                 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);
5521                                 continue;
5522                         }
5523                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5524                         batchtriangles = surface->num_triangles;
5525                         firstvertex = surface->num_firstvertex;
5526                         endvertex = surface->num_firstvertex + surface->num_vertices;
5527                         for (;j < texturenumsurfaces;j++)
5528                         {
5529                                 surface2 = texturesurfacelist[j];
5530                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5531                                         break;
5532                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5533                                 batchtriangles += surface2->num_triangles;
5534                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
5535                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5536                         }
5537                         surface2 = texturesurfacelist[j-1];
5538                         numvertices = endvertex - firstvertex;
5539                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5540                 }
5541         }
5542         else if (r_batchmode.integer == 1)
5543         {
5544 #if 0
5545                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5546                 for (i = 0;i < texturenumsurfaces;i = j)
5547                 {
5548                         surface = texturesurfacelist[i];
5549                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5550                                 if (texturesurfacelist[j] != surface2)
5551                                         break;
5552                         Con_Printf(" %i", j - i);
5553                 }
5554                 Con_Printf("\n");
5555                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5556 #endif
5557                 for (i = 0;i < texturenumsurfaces;i = j)
5558                 {
5559                         surface = texturesurfacelist[i];
5560                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5561                         if (deluxemaptexunit >= 0)
5562                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5563                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5564                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5565                                         break;
5566 #if 0
5567                         Con_Printf(" %i", j - i);
5568 #endif
5569                         surface2 = texturesurfacelist[j-1];
5570                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5571                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5572                         GL_LockArrays(surface->num_firstvertex, numvertices);
5573                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5574                 }
5575 #if 0
5576                 Con_Printf("\n");
5577 #endif
5578         }
5579         else
5580         {
5581                 for (i = 0;i < texturenumsurfaces;i++)
5582                 {
5583                         surface = texturesurfacelist[i];
5584                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5585                         if (deluxemaptexunit >= 0)
5586                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5587                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5588                         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);
5589                 }
5590         }
5591 }
5592
5593 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5594 {
5595         int j;
5596         int texturesurfaceindex;
5597         if (r_showsurfaces.integer == 2)
5598         {
5599                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5600                 {
5601                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5602                         for (j = 0;j < surface->num_triangles;j++)
5603                         {
5604                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
5605                                 GL_Color(f, f, f, 1);
5606                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5607                         }
5608                 }
5609         }
5610         else
5611         {
5612                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5613                 {
5614                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5615                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
5616                         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);
5617                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5618                         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);
5619                 }
5620         }
5621 }
5622
5623 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5624 {
5625         int texturesurfaceindex;
5626         int i;
5627         float f;
5628         float *v, *c, *c2;
5629         if (rsurface.lightmapcolor4f)
5630         {
5631                 // generate color arrays for the surfaces in this list
5632                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5633                 {
5634                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5635                         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)
5636                         {
5637                                 f = FogPoint_Model(v);
5638                                 c2[0] = c[0] * f;
5639                                 c2[1] = c[1] * f;
5640                                 c2[2] = c[2] * f;
5641                                 c2[3] = c[3];
5642                         }
5643                 }
5644         }
5645         else
5646         {
5647                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5648                 {
5649                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5650                         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)
5651                         {
5652                                 f = FogPoint_Model(v);
5653                                 c2[0] = f;
5654                                 c2[1] = f;
5655                                 c2[2] = f;
5656                                 c2[3] = 1;
5657                         }
5658                 }
5659         }
5660         rsurface.lightmapcolor4f = rsurface.array_color4f;
5661         rsurface.lightmapcolor4f_bufferobject = 0;
5662         rsurface.lightmapcolor4f_bufferoffset = 0;
5663 }
5664
5665 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5666 {
5667         int texturesurfaceindex;
5668         int i;
5669         float *c, *c2;
5670         if (!rsurface.lightmapcolor4f)
5671                 return;
5672         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5673         {
5674                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5675                 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)
5676                 {
5677                         c2[0] = c[0] * r;
5678                         c2[1] = c[1] * g;
5679                         c2[2] = c[2] * b;
5680                         c2[3] = c[3] * a;
5681                 }
5682         }
5683         rsurface.lightmapcolor4f = rsurface.array_color4f;
5684         rsurface.lightmapcolor4f_bufferobject = 0;
5685         rsurface.lightmapcolor4f_bufferoffset = 0;
5686 }
5687
5688 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5689 {
5690         // TODO: optimize
5691         rsurface.lightmapcolor4f = NULL;
5692         rsurface.lightmapcolor4f_bufferobject = 0;
5693         rsurface.lightmapcolor4f_bufferoffset = 0;
5694         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5695         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5696         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5697         GL_Color(r, g, b, a);
5698         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5699 }
5700
5701 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5702 {
5703         // TODO: optimize applyfog && applycolor case
5704         // just apply fog if necessary, and tint the fog color array if necessary
5705         rsurface.lightmapcolor4f = NULL;
5706         rsurface.lightmapcolor4f_bufferobject = 0;
5707         rsurface.lightmapcolor4f_bufferoffset = 0;
5708         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5709         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5710         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5711         GL_Color(r, g, b, a);
5712         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5713 }
5714
5715 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5716 {
5717         int texturesurfaceindex;
5718         int i;
5719         float *c;
5720         // TODO: optimize
5721         if (texturesurfacelist[0]->lightmapinfo)
5722         {
5723                 // generate color arrays for the surfaces in this list
5724                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5725                 {
5726                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5727                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5728                         {
5729                                 if (surface->lightmapinfo->samples)
5730                                 {
5731                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5732                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5733                                         VectorScale(lm, scale, c);
5734                                         if (surface->lightmapinfo->styles[1] != 255)
5735                                         {
5736                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5737                                                 lm += size3;
5738                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5739                                                 VectorMA(c, scale, lm, c);
5740                                                 if (surface->lightmapinfo->styles[2] != 255)
5741                                                 {
5742                                                         lm += size3;
5743                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5744                                                         VectorMA(c, scale, lm, c);
5745                                                         if (surface->lightmapinfo->styles[3] != 255)
5746                                                         {
5747                                                                 lm += size3;
5748                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5749                                                                 VectorMA(c, scale, lm, c);
5750                                                         }
5751                                                 }
5752                                         }
5753                                 }
5754                                 else
5755                                         VectorClear(c);
5756                                 c[3] = 1;
5757                         }
5758                 }
5759                 rsurface.lightmapcolor4f = rsurface.array_color4f;
5760                 rsurface.lightmapcolor4f_bufferobject = 0;
5761                 rsurface.lightmapcolor4f_bufferoffset = 0;
5762         }
5763         else
5764         {
5765                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5766                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5767                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5768         }
5769         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5770         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5771         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5772         GL_Color(r, g, b, a);
5773         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5774 }
5775
5776 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5777 {
5778         int texturesurfaceindex;
5779         int i;
5780         float f;
5781         float *v, *c, *c2;
5782         vec3_t ambientcolor;
5783         vec3_t diffusecolor;
5784         vec3_t lightdir;
5785         // TODO: optimize
5786         // model lighting
5787         VectorCopy(rsurface.modellight_lightdir, lightdir);
5788         f = 0.5f * r_refdef.lightmapintensity;
5789         ambientcolor[0] = rsurface.modellight_ambient[0] * r * f;
5790         ambientcolor[1] = rsurface.modellight_ambient[1] * g * f;
5791         ambientcolor[2] = rsurface.modellight_ambient[2] * b * f;
5792         diffusecolor[0] = rsurface.modellight_diffuse[0] * r * f;
5793         diffusecolor[1] = rsurface.modellight_diffuse[1] * g * f;
5794         diffusecolor[2] = rsurface.modellight_diffuse[2] * b * f;
5795         if (VectorLength2(diffusecolor) > 0)
5796         {
5797                 // generate color arrays for the surfaces in this list
5798                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5799                 {
5800                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5801                         int numverts = surface->num_vertices;
5802                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5803                         c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5804                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5805                         // q3-style directional shading
5806                         for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5807                         {
5808                                 if ((f = DotProduct(c2, lightdir)) > 0)
5809                                         VectorMA(ambientcolor, f, diffusecolor, c);
5810                                 else
5811                                         VectorCopy(ambientcolor, c);
5812                                 c[3] = a;
5813                         }
5814                 }
5815                 r = 1;
5816                 g = 1;
5817                 b = 1;
5818                 a = 1;
5819                 applycolor = false;
5820                 rsurface.lightmapcolor4f = rsurface.array_color4f;
5821                 rsurface.lightmapcolor4f_bufferobject = 0;
5822                 rsurface.lightmapcolor4f_bufferoffset = 0;
5823         }
5824         else
5825         {
5826                 r = ambientcolor[0];
5827                 g = ambientcolor[1];
5828                 b = ambientcolor[2];
5829                 rsurface.lightmapcolor4f = NULL;
5830                 rsurface.lightmapcolor4f_bufferobject = 0;
5831                 rsurface.lightmapcolor4f_bufferoffset = 0;
5832         }
5833         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5834         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5835         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5836         GL_Color(r, g, b, a);
5837         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5838 }
5839
5840 void RSurf_SetupDepthAndCulling(void)
5841 {
5842         // submodels are biased to avoid z-fighting with world surfaces that they
5843         // may be exactly overlapping (avoids z-fighting artifacts on certain
5844         // doors and things in Quake maps)
5845         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5846         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
5847         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5848         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
5849 }
5850
5851 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5852 {
5853         // transparent sky would be ridiculous
5854         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5855                 return;
5856         R_SetupGenericShader(false);
5857         if (skyrendernow)
5858         {
5859                 skyrendernow = false;
5860                 // we have to force off the water clipping plane while rendering sky
5861                 R_SetupView(false);
5862                 R_Sky();
5863                 R_SetupView(true);
5864                 // restore entity matrix
5865                 R_Mesh_Matrix(&rsurface.matrix);
5866         }
5867         RSurf_SetupDepthAndCulling();
5868         GL_DepthMask(true);
5869         // LordHavoc: HalfLife maps have freaky skypolys so don't use
5870         // skymasking on them, and Quake3 never did sky masking (unlike
5871         // software Quake and software Quake2), so disable the sky masking
5872         // in Quake3 maps as it causes problems with q3map2 sky tricks,
5873         // and skymasking also looks very bad when noclipping outside the
5874         // level, so don't use it then either.
5875         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
5876         {
5877                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
5878                 R_Mesh_ColorPointer(NULL, 0, 0);
5879                 R_Mesh_ResetTextureState();
5880                 if (skyrendermasked)
5881                 {
5882                         R_SetupDepthOrShadowShader();
5883                         // depth-only (masking)
5884                         GL_ColorMask(0,0,0,0);
5885                         // just to make sure that braindead drivers don't draw
5886                         // anything despite that colormask...
5887                         GL_BlendFunc(GL_ZERO, GL_ONE);
5888                 }
5889                 else
5890                 {
5891                         R_SetupGenericShader(false);
5892                         // fog sky
5893                         GL_BlendFunc(GL_ONE, GL_ZERO);
5894                 }
5895                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5896                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5897                 if (skyrendermasked)
5898                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5899         }
5900         R_Mesh_ResetTextureState();
5901         GL_Color(1, 1, 1, 1);
5902 }
5903
5904 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
5905 {
5906         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5907                 return;
5908
5909         R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5910         R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5911         R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
5912         R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
5913         R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
5914         if (rsurface.texture->backgroundcurrentskinframe)
5915         {
5916                 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
5917                 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
5918                 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
5919                 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
5920         }
5921         if(rsurface.texture->colormapping)
5922         {
5923                 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
5924                 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5925         }
5926         R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
5927         if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
5928                 R_Mesh_ColorPointer(NULL, 0, 0);
5929         else
5930                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5931
5932         if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5933         {
5934                 // render background
5935                 GL_BlendFunc(GL_ONE, GL_ZERO);
5936                 GL_DepthMask(true);
5937                 GL_AlphaTest(false);
5938
5939                 GL_Color(1, 1, 1, 1);
5940                 R_Mesh_ColorPointer(NULL, 0, 0);
5941
5942                 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5943                 if (r_glsl_permutation)
5944                 {
5945                         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5946                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5947                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5948                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5949                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5950                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5951                         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);
5952                 }
5953                 GL_LockArrays(0, 0);
5954
5955                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5956                 GL_DepthMask(false);
5957                 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
5958                         R_Mesh_ColorPointer(NULL, 0, 0);
5959                 else
5960                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5961                 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
5962                 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
5963         }
5964
5965         R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5966         if (!r_glsl_permutation)
5967                 return;
5968
5969         RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5970         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5971         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5972         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5973         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5974         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5975
5976         if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5977         {
5978                 GL_BlendFunc(GL_ONE, GL_ZERO);
5979                 GL_DepthMask(true);
5980                 GL_AlphaTest(false);
5981         }
5982         else
5983         {
5984                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5985                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5986                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5987         }
5988
5989         if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5990         {
5991                 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5992                         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);
5993                 else
5994                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
5995         }
5996         else
5997         {
5998                 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5999                         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);
6000                 else
6001                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6002         }
6003         GL_LockArrays(0, 0);
6004 }
6005
6006 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6007 {
6008         // OpenGL 1.3 path - anything not completely ancient
6009         int texturesurfaceindex;
6010         qboolean applycolor;
6011         qboolean applyfog;
6012         rmeshstate_t m;
6013         int layerindex;
6014         const texturelayer_t *layer;
6015         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6016
6017         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6018         {
6019                 vec4_t layercolor;
6020                 int layertexrgbscale;
6021                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6022                 {
6023                         if (layerindex == 0)
6024                                 GL_AlphaTest(true);
6025                         else
6026                         {
6027                                 GL_AlphaTest(false);
6028                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6029                         }
6030                 }
6031                 GL_DepthMask(layer->depthmask && writedepth);
6032                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6033                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
6034                 {
6035                         layertexrgbscale = 4;
6036                         VectorScale(layer->color, 0.25f, layercolor);
6037                 }
6038                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
6039                 {
6040                         layertexrgbscale = 2;
6041                         VectorScale(layer->color, 0.5f, layercolor);
6042                 }
6043                 else
6044                 {
6045                         layertexrgbscale = 1;
6046                         VectorScale(layer->color, 1.0f, layercolor);
6047                 }
6048                 layercolor[3] = layer->color[3];
6049                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6050                 R_Mesh_ColorPointer(NULL, 0, 0);
6051                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6052                 switch (layer->type)
6053                 {
6054                 case TEXTURELAYERTYPE_LITTEXTURE:
6055                         memset(&m, 0, sizeof(m));
6056                         m.tex[0] = R_GetTexture(r_texture_white);
6057                         m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6058                         m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6059                         m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6060                         m.tex[1] = R_GetTexture(layer->texture);
6061                         m.texmatrix[1] = layer->texmatrix;
6062                         m.texrgbscale[1] = layertexrgbscale;
6063                         m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
6064                         m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
6065                         m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
6066                         R_Mesh_TextureState(&m);
6067                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6068                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6069                         else if (rsurface.uselightmaptexture)
6070                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6071                         else
6072                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6073                         break;
6074                 case TEXTURELAYERTYPE_TEXTURE:
6075                         memset(&m, 0, sizeof(m));
6076                         m.tex[0] = R_GetTexture(layer->texture);
6077                         m.texmatrix[0] = layer->texmatrix;
6078                         m.texrgbscale[0] = layertexrgbscale;
6079                         m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6080                         m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6081                         m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6082                         R_Mesh_TextureState(&m);
6083                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6084                         break;
6085                 case TEXTURELAYERTYPE_FOG:
6086                         memset(&m, 0, sizeof(m));
6087                         m.texrgbscale[0] = layertexrgbscale;
6088                         if (layer->texture)
6089                         {
6090                                 m.tex[0] = R_GetTexture(layer->texture);
6091                                 m.texmatrix[0] = layer->texmatrix;
6092                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6093                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6094                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6095                         }
6096                         R_Mesh_TextureState(&m);
6097                         // generate a color array for the fog pass
6098                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6099                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6100                         {
6101                                 int i;
6102                                 float f, *v, *c;
6103                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6104                                 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)
6105                                 {
6106                                         f = 1 - FogPoint_Model(v);
6107                                         c[0] = layercolor[0];
6108                                         c[1] = layercolor[1];
6109                                         c[2] = layercolor[2];
6110                                         c[3] = f * layercolor[3];
6111                                 }
6112                         }
6113                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6114                         break;
6115                 default:
6116                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6117                 }
6118                 GL_LockArrays(0, 0);
6119         }
6120         CHECKGLERROR
6121         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6122         {
6123                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6124                 GL_AlphaTest(false);
6125         }
6126 }
6127
6128 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6129 {
6130         // OpenGL 1.1 - crusty old voodoo path
6131         int texturesurfaceindex;
6132         qboolean applyfog;
6133         rmeshstate_t m;
6134         int layerindex;
6135         const texturelayer_t *layer;
6136         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6137
6138         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6139         {
6140                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6141                 {
6142                         if (layerindex == 0)
6143                                 GL_AlphaTest(true);
6144                         else
6145                         {
6146                                 GL_AlphaTest(false);
6147                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6148                         }
6149                 }
6150                 GL_DepthMask(layer->depthmask && writedepth);
6151                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6152                 R_Mesh_ColorPointer(NULL, 0, 0);
6153                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6154                 switch (layer->type)
6155                 {
6156                 case TEXTURELAYERTYPE_LITTEXTURE:
6157                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
6158                         {
6159                                 // two-pass lit texture with 2x rgbscale
6160                                 // first the lightmap pass
6161                                 memset(&m, 0, sizeof(m));
6162                                 m.tex[0] = R_GetTexture(r_texture_white);
6163                                 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6164                                 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6165                                 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6166                                 R_Mesh_TextureState(&m);
6167                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6168                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6169                                 else if (rsurface.uselightmaptexture)
6170                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6171                                 else
6172                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6173                                 GL_LockArrays(0, 0);
6174                                 // then apply the texture to it
6175                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6176                                 memset(&m, 0, sizeof(m));
6177                                 m.tex[0] = R_GetTexture(layer->texture);
6178                                 m.texmatrix[0] = layer->texmatrix;
6179                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6180                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6181                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6182                                 R_Mesh_TextureState(&m);
6183                                 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);
6184                         }
6185                         else
6186                         {
6187                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6188                                 memset(&m, 0, sizeof(m));
6189                                 m.tex[0] = R_GetTexture(layer->texture);
6190                                 m.texmatrix[0] = layer->texmatrix;
6191                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6192                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6193                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6194                                 R_Mesh_TextureState(&m);
6195                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6196                                         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);
6197                                 else
6198                                         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);
6199                         }
6200                         break;
6201                 case TEXTURELAYERTYPE_TEXTURE:
6202                         // singletexture unlit texture with transparency support
6203                         memset(&m, 0, sizeof(m));
6204                         m.tex[0] = R_GetTexture(layer->texture);
6205                         m.texmatrix[0] = layer->texmatrix;
6206                         m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6207                         m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6208                         m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6209                         R_Mesh_TextureState(&m);
6210                         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);
6211                         break;
6212                 case TEXTURELAYERTYPE_FOG:
6213                         // singletexture fogging
6214                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6215                         if (layer->texture)
6216                         {
6217                                 memset(&m, 0, sizeof(m));
6218                                 m.tex[0] = R_GetTexture(layer->texture);
6219                                 m.texmatrix[0] = layer->texmatrix;
6220                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6221                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6222                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6223                                 R_Mesh_TextureState(&m);
6224                         }
6225                         else
6226                                 R_Mesh_ResetTextureState();
6227                         // generate a color array for the fog pass
6228                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6229                         {
6230                                 int i;
6231                                 float f, *v, *c;
6232                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6233                                 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)
6234                                 {
6235                                         f = 1 - FogPoint_Model(v);
6236                                         c[0] = layer->color[0];
6237                                         c[1] = layer->color[1];
6238                                         c[2] = layer->color[2];
6239                                         c[3] = f * layer->color[3];
6240                                 }
6241                         }
6242                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6243                         break;
6244                 default:
6245                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6246                 }
6247                 GL_LockArrays(0, 0);
6248         }
6249         CHECKGLERROR
6250         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6251         {
6252                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6253                 GL_AlphaTest(false);
6254         }
6255 }
6256
6257 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6258 {
6259         CHECKGLERROR
6260         RSurf_SetupDepthAndCulling();
6261         if (r_glsl.integer && gl_support_fragment_shader)
6262                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6263         else if (gl_combine.integer && r_textureunits.integer >= 2)
6264                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6265         else
6266                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6267         CHECKGLERROR
6268 }
6269
6270 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6271 {
6272         int i, j;
6273         int texturenumsurfaces, endsurface;
6274         texture_t *texture;
6275         msurface_t *surface;
6276         msurface_t *texturesurfacelist[1024];
6277
6278         // if the model is static it doesn't matter what value we give for
6279         // wantnormals and wanttangents, so this logic uses only rules applicable
6280         // to a model, knowing that they are meaningless otherwise
6281         if (ent == r_refdef.scene.worldentity)
6282                 RSurf_ActiveWorldEntity();
6283         else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6284                 RSurf_ActiveModelEntity(ent, false, false);
6285         else
6286                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6287
6288         for (i = 0;i < numsurfaces;i = j)
6289         {
6290                 j = i + 1;
6291                 surface = rsurface.modelsurfaces + surfacelist[i];
6292                 texture = surface->texture;
6293                 R_UpdateTextureInfo(ent, texture);
6294                 rsurface.texture = texture->currentframe;
6295                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6296                 // scan ahead until we find a different texture
6297                 endsurface = min(i + 1024, numsurfaces);
6298                 texturenumsurfaces = 0;
6299                 texturesurfacelist[texturenumsurfaces++] = surface;
6300                 for (;j < endsurface;j++)
6301                 {
6302                         surface = rsurface.modelsurfaces + surfacelist[j];
6303                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6304                                 break;
6305                         texturesurfacelist[texturenumsurfaces++] = surface;
6306                 }
6307                 // render the range of surfaces
6308                 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6309         }
6310         GL_AlphaTest(false);
6311 }
6312
6313 static void R_ProcessTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
6314 {
6315         CHECKGLERROR
6316         if (depthonly)
6317         {
6318                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6319                         return;
6320                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6321                         return;
6322                 RSurf_SetupDepthAndCulling();
6323                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6324                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6325         }
6326         else if (r_showsurfaces.integer)
6327         {
6328                 RSurf_SetupDepthAndCulling();
6329                 GL_DepthTest(true);
6330                 GL_BlendFunc(GL_ONE, GL_ZERO);
6331                 GL_DepthMask(true);
6332                 GL_AlphaTest(false);
6333                 R_Mesh_ColorPointer(NULL, 0, 0);
6334                 R_Mesh_ResetTextureState();
6335                 R_SetupGenericShader(false);
6336                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6337                 if (!r_refdef.view.showdebug)
6338                 {
6339                         GL_Color(0, 0, 0, 1);
6340                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6341                 }
6342                 else
6343                         RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6344         }
6345         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6346                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6347         else if (!rsurface.texture->currentnumlayers)
6348                 return;
6349         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) && queueentity)
6350         {
6351                 // transparent surfaces get pushed off into the transparent queue
6352                 int surfacelistindex;
6353                 const msurface_t *surface;
6354                 vec3_t tempcenter, center;
6355                 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6356                 {
6357                         surface = texturesurfacelist[surfacelistindex];
6358                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6359                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6360                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6361                         Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6362                         R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6363                 }
6364         }
6365         else
6366         {
6367                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6368                 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6369         }
6370         CHECKGLERROR
6371 }
6372
6373 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
6374 {
6375         int i, j;
6376         texture_t *texture;
6377         // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
6378         if (addwaterplanes)
6379         {
6380                 for (i = 0;i < numsurfaces;i++)
6381                         if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
6382                                 R_Water_AddWaterPlane(surfacelist[i]);
6383                 return;
6384         }
6385         // break the surface list down into batches by texture and use of lightmapping
6386         for (i = 0;i < numsurfaces;i = j)
6387         {
6388                 j = i + 1;
6389                 // texture is the base texture pointer, rsurface.texture is the
6390                 // current frame/skin the texture is directing us to use (for example
6391                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6392                 // use skin 1 instead)
6393                 texture = surfacelist[i]->texture;
6394                 rsurface.texture = texture->currentframe;
6395                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6396                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6397                 {
6398                         // if this texture is not the kind we want, skip ahead to the next one
6399                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6400                                 ;
6401                         continue;
6402                 }
6403                 // simply scan ahead until we find a different texture or lightmap state
6404                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6405                         ;
6406                 // render the range of surfaces
6407                 R_ProcessTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
6408         }
6409 }
6410
6411 float locboxvertex3f[6*4*3] =
6412 {
6413         1,0,1, 1,0,0, 1,1,0, 1,1,1,
6414         0,1,1, 0,1,0, 0,0,0, 0,0,1,
6415         1,1,1, 1,1,0, 0,1,0, 0,1,1,
6416         0,0,1, 0,0,0, 1,0,0, 1,0,1,
6417         0,0,1, 1,0,1, 1,1,1, 0,1,1,
6418         1,0,0, 0,0,0, 0,1,0, 1,1,0
6419 };
6420
6421 unsigned short locboxelements[6*2*3] =
6422 {
6423          0, 1, 2, 0, 2, 3,
6424          4, 5, 6, 4, 6, 7,
6425          8, 9,10, 8,10,11,
6426         12,13,14, 12,14,15,
6427         16,17,18, 16,18,19,
6428         20,21,22, 20,22,23
6429 };
6430
6431 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6432 {
6433         int i, j;
6434         cl_locnode_t *loc = (cl_locnode_t *)ent;
6435         vec3_t mins, size;
6436         float vertex3f[6*4*3];
6437         CHECKGLERROR
6438         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6439         GL_DepthMask(false);
6440         GL_DepthRange(0, 1);
6441         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6442         GL_DepthTest(true);
6443         GL_CullFace(GL_NONE);
6444         R_Mesh_Matrix(&identitymatrix);
6445
6446         R_Mesh_VertexPointer(vertex3f, 0, 0);
6447         R_Mesh_ColorPointer(NULL, 0, 0);
6448         R_Mesh_ResetTextureState();
6449         R_SetupGenericShader(false);
6450
6451         i = surfacelist[0];
6452         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6453                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6454                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6455                         surfacelist[0] < 0 ? 0.5f : 0.125f);
6456
6457         if (VectorCompare(loc->mins, loc->maxs))
6458         {
6459                 VectorSet(size, 2, 2, 2);
6460                 VectorMA(loc->mins, -0.5f, size, mins);
6461         }
6462         else
6463         {
6464                 VectorCopy(loc->mins, mins);
6465                 VectorSubtract(loc->maxs, loc->mins, size);
6466         }
6467
6468         for (i = 0;i < 6*4*3;)
6469                 for (j = 0;j < 3;j++, i++)
6470                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6471
6472         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
6473 }
6474
6475 void R_DrawLocs(void)
6476 {
6477         int index;
6478         cl_locnode_t *loc, *nearestloc;
6479         vec3_t center;
6480         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6481         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6482         {
6483                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6484                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6485         }
6486 }
6487
6488 void R_DrawDebugModel(entity_render_t *ent)
6489 {
6490         int i, j, k, l, flagsmask;
6491         const int *elements;
6492         q3mbrush_t *brush;
6493         msurface_t *surface;
6494         dp_model_t *model = ent->model;
6495         vec3_t v;
6496
6497         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
6498
6499         R_Mesh_ColorPointer(NULL, 0, 0);
6500         R_Mesh_ResetTextureState();
6501         R_SetupGenericShader(false);
6502         GL_DepthRange(0, 1);
6503         GL_DepthTest(!r_showdisabledepthtest.integer);
6504         GL_DepthMask(false);
6505         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6506
6507         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6508         {
6509                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6510                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6511                 {
6512                         if (brush->colbrushf && brush->colbrushf->numtriangles)
6513                         {
6514                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6515                                 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);
6516                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
6517                         }
6518                 }
6519                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6520                 {
6521                         if (surface->num_collisiontriangles)
6522                         {
6523                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 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, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
6526                         }
6527                 }
6528         }
6529
6530         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6531
6532         if (r_showtris.integer || r_shownormals.integer)
6533         {
6534                 if (r_showdisabledepthtest.integer)
6535                 {
6536                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6537                         GL_DepthMask(false);
6538                 }
6539                 else
6540                 {
6541                         GL_BlendFunc(GL_ONE, GL_ZERO);
6542                         GL_DepthMask(true);
6543                 }
6544                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6545                 {
6546                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
6547                                 continue;
6548                         rsurface.texture = surface->texture->currentframe;
6549                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6550                         {
6551                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6552                                 if (r_showtris.value > 0)
6553                                 {
6554                                         if (!rsurface.texture->currentlayers->depthmask)
6555                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
6556                                         else if (ent == r_refdef.scene.worldentity)
6557                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
6558                                         else
6559                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
6560                                         elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6561                                         CHECKGLERROR
6562                                         qglBegin(GL_LINES);
6563                                         for (k = 0;k < surface->num_triangles;k++, elements += 3)
6564                                         {
6565 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6566                                                 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6567                                                 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6568                                                 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6569                                         }
6570                                         qglEnd();
6571                                         CHECKGLERROR
6572                                 }
6573                                 if (r_shownormals.value > 0)
6574                                 {
6575                                         qglBegin(GL_LINES);
6576                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6577                                         {
6578                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
6579                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
6580                                                 qglVertex3f(v[0], v[1], v[2]);
6581                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
6582                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6583                                                 qglVertex3f(v[0], v[1], v[2]);
6584                                         }
6585                                         qglEnd();
6586                                         CHECKGLERROR
6587                                         qglBegin(GL_LINES);
6588                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6589                                         {
6590                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
6591                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
6592                                                 qglVertex3f(v[0], v[1], v[2]);
6593                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
6594                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6595                                                 qglVertex3f(v[0], v[1], v[2]);
6596                                         }
6597                                         qglEnd();
6598                                         CHECKGLERROR
6599                                         qglBegin(GL_LINES);
6600                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6601                                         {
6602                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
6603                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
6604                                                 qglVertex3f(v[0], v[1], v[2]);
6605                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
6606                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6607                                                 qglVertex3f(v[0], v[1], v[2]);
6608                                         }
6609                                         qglEnd();
6610                                         CHECKGLERROR
6611                                 }
6612                         }
6613                 }
6614                 rsurface.texture = NULL;
6615         }
6616 }
6617
6618 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6619 int r_maxsurfacelist = 0;
6620 msurface_t **r_surfacelist = NULL;
6621 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6622 {
6623         int i, j, endj, f, flagsmask;
6624         texture_t *t;
6625         dp_model_t *model = r_refdef.scene.worldmodel;
6626         msurface_t *surfaces;
6627         unsigned char *update;
6628         int numsurfacelist = 0;
6629         if (model == NULL)
6630                 return;
6631
6632         if (r_maxsurfacelist < model->num_surfaces)
6633         {
6634                 r_maxsurfacelist = model->num_surfaces;
6635                 if (r_surfacelist)
6636                         Mem_Free(r_surfacelist);
6637                 r_surfacelist = Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
6638         }
6639
6640         RSurf_ActiveWorldEntity();
6641
6642         surfaces = model->data_surfaces;
6643         update = model->brushq1.lightmapupdateflags;
6644
6645         // update light styles on this submodel
6646         if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6647         {
6648                 model_brush_lightstyleinfo_t *style;
6649                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6650                 {
6651                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
6652                         {
6653                                 int *list = style->surfacelist;
6654                                 style->value = r_refdef.scene.lightstylevalue[style->style];
6655                                 for (j = 0;j < style->numsurfaces;j++)
6656                                         update[list[j]] = true;
6657                         }
6658                 }
6659         }
6660
6661         R_UpdateAllTextureInfo(r_refdef.scene.worldentity);
6662         flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL);
6663
6664         if (debug)
6665         {
6666                 R_DrawDebugModel(r_refdef.scene.worldentity);
6667                 return;
6668         }
6669
6670         f = 0;
6671         t = NULL;
6672         rsurface.uselightmaptexture = false;
6673         rsurface.texture = NULL;
6674         rsurface.rtlight = NULL;
6675         numsurfacelist = 0;
6676         // add visible surfaces to draw list
6677         j = model->firstmodelsurface;
6678         endj = j + model->nummodelsurfaces;
6679         if (update)
6680         {
6681                 for (;j < endj;j++)
6682                 {
6683                         if (r_refdef.viewcache.world_surfacevisible[j])
6684                         {
6685                                 r_surfacelist[numsurfacelist++] = surfaces + j;
6686                                 // update lightmap if needed
6687                                 if (update[j])
6688                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
6689                         }
6690                 }
6691         }
6692         else
6693                 for (;j < endj;j++)
6694                         if (r_refdef.viewcache.world_surfacevisible[j])
6695                                 r_surfacelist[numsurfacelist++] = surfaces + j;
6696         // don't do anything if there were no surfaces
6697         if (!numsurfacelist)
6698                 return;
6699         R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6700         GL_AlphaTest(false);
6701
6702         // add to stats if desired
6703         if (r_speeds.integer && !skysurfaces && !depthonly && !addwaterplanes)
6704         {
6705                 r_refdef.stats.world_surfaces += numsurfacelist;
6706                 for (j = 0;j < numsurfacelist;j++)
6707                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
6708         }
6709 }
6710
6711 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6712 {
6713         int i, j, endj, f, flagsmask;
6714         texture_t *t;
6715         dp_model_t *model = ent->model;
6716         msurface_t *surfaces;
6717         unsigned char *update;
6718         int numsurfacelist = 0;
6719         if (model == NULL)
6720                 return;
6721
6722         if (r_maxsurfacelist < model->num_surfaces)
6723         {
6724                 r_maxsurfacelist = model->num_surfaces;
6725                 if (r_surfacelist)
6726                         Mem_Free(r_surfacelist);
6727                 r_surfacelist = Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
6728         }
6729
6730         // if the model is static it doesn't matter what value we give for
6731         // wantnormals and wanttangents, so this logic uses only rules applicable
6732         // to a model, knowing that they are meaningless otherwise
6733         if (ent == r_refdef.scene.worldentity)
6734                 RSurf_ActiveWorldEntity();
6735         else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6736                 RSurf_ActiveModelEntity(ent, false, false);
6737         else
6738                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6739
6740         surfaces = model->data_surfaces;
6741         update = model->brushq1.lightmapupdateflags;
6742
6743         // update light styles
6744         if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6745         {
6746                 model_brush_lightstyleinfo_t *style;
6747                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6748                 {
6749                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
6750                         {
6751                                 int *list = style->surfacelist;
6752                                 style->value = r_refdef.scene.lightstylevalue[style->style];
6753                                 for (j = 0;j < style->numsurfaces;j++)
6754                                         update[list[j]] = true;
6755                         }
6756                 }
6757         }
6758
6759         R_UpdateAllTextureInfo(ent);
6760         flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL);
6761
6762         if (debug)
6763         {
6764                 R_DrawDebugModel(ent);
6765                 return;
6766         }
6767
6768         f = 0;
6769         t = NULL;
6770         rsurface.uselightmaptexture = false;
6771         rsurface.texture = NULL;
6772         rsurface.rtlight = NULL;
6773         numsurfacelist = 0;
6774         // add visible surfaces to draw list
6775         j = model->firstmodelsurface;
6776         endj = j + model->nummodelsurfaces;
6777         for (;j < endj;j++)
6778                 r_surfacelist[numsurfacelist++] = surfaces + j;
6779         // don't do anything if there were no surfaces
6780         if (!numsurfacelist)
6781                 return;
6782         // update lightmaps if needed
6783         if (update)
6784                 for (j = model->firstmodelsurface;j < endj;j++)
6785                         if (update[j])
6786                                 R_BuildLightMap(ent, surfaces + j);
6787         R_QueueSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6788         GL_AlphaTest(false);
6789
6790         // add to stats if desired
6791         if (r_speeds.integer && !skysurfaces && !depthonly && !addwaterplanes)
6792         {
6793                 r_refdef.stats.entities++;
6794                 r_refdef.stats.entities_surfaces += numsurfacelist;
6795                 for (j = 0;j < numsurfacelist;j++)
6796                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
6797         }
6798 }