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