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