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