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