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