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