]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
da1bd813df1c7fb12b6f90f81dc3f5bf4dfe1110
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "r_shadow.h"
24 #include "polygon.h"
25 #include "image.h"
26
27 mempool_t *r_main_mempool;
28 rtexturepool_t *r_main_texturepool;
29
30 //
31 // screen size info
32 //
33 r_refdef_t r_refdef;
34 r_view_t r_view;
35 r_viewcache_t r_viewcache;
36
37 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "1", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
38 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
39 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
40 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
41 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
42 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
43 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
44 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
45 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
46 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
47 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
48 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
49 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
50 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
51 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
52 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
53 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
54 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
55 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
56 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
57 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
58 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
59 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
60 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
61 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
62 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
63 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
64 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
65 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "2", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
66
67 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
68 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
69 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
70 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
71 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
72 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
73 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
74
75 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
76
77 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
78 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
79 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
80 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
81 cvar_t r_glsl_water = {CVAR_SAVE, "r_glsl_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
82 cvar_t r_glsl_water_clippingplanebias = {CVAR_SAVE, "r_glsl_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
83 cvar_t r_glsl_water_resolutionmultiplier = {CVAR_SAVE, "r_glsl_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
84 cvar_t r_glsl_water_refractcolor_r = {CVAR_SAVE, "r_glsl_water_refractcolor_r", "1", "water color tint for refraction"};
85 cvar_t r_glsl_water_refractcolor_g = {CVAR_SAVE, "r_glsl_water_refractcolor_g", "1", "water color tint for refraction"};
86 cvar_t r_glsl_water_refractcolor_b = {CVAR_SAVE, "r_glsl_water_refractcolor_b", "1", "water color tint for refraction"};
87 cvar_t r_glsl_water_reflectcolor_r = {CVAR_SAVE, "r_glsl_water_reflectcolor_r", "1", "water color tint for reflection"};
88 cvar_t r_glsl_water_reflectcolor_g = {CVAR_SAVE, "r_glsl_water_reflectcolor_g", "1", "water color tint for reflection"};
89 cvar_t r_glsl_water_reflectcolor_b = {CVAR_SAVE, "r_glsl_water_reflectcolor_b", "1", "water color tint for reflection"};
90 cvar_t r_glsl_water_refractdistort = {CVAR_SAVE, "r_glsl_water_refractdistort", "0.01", "how much water refractions shimmer"};
91 cvar_t r_glsl_water_reflectdistort = {CVAR_SAVE, "r_glsl_water_reflectdistort", "0.01", "how much water reflections shimmer"};
92 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
93 cvar_t r_glsl_contrastboost = {CVAR_SAVE, "r_glsl_contrastboost", "1", "by how much to multiply the contrast in dark areas (1 is no change)"};
94
95 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
96 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
97 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
98
99 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
100 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
101 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
102 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
103 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
104 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
105 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
106
107 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
108 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
109 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
110 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
111
112 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
113
114 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
115
116 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
117
118 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
119 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
120
121 extern qboolean v_flipped_state;
122
123 typedef struct r_glsl_bloomshader_s
124 {
125         int program;
126         int loc_Texture_Bloom;
127 }
128 r_glsl_bloomshader_t;
129
130 static struct r_bloomstate_s
131 {
132         qboolean enabled;
133         qboolean hdr;
134
135         int bloomwidth, bloomheight;
136
137         int screentexturewidth, screentextureheight;
138         rtexture_t *texture_screen;
139
140         int bloomtexturewidth, bloomtextureheight;
141         rtexture_t *texture_bloom;
142
143         r_glsl_bloomshader_t *shader;
144
145         // arrays for rendering the screen passes
146         float screentexcoord2f[8];
147         float bloomtexcoord2f[8];
148         float offsettexcoord2f[8];
149 }
150 r_bloomstate;
151
152 typedef struct r_waterstate_waterplane_s
153 {
154         rtexture_t *texture_refraction;
155         rtexture_t *texture_reflection;
156         mplane_t plane;
157         int materialflags; // combined flags of all water surfaces on this plane
158         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_DrawModelsDebug(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->DrawDebug != NULL)
2107                         ent->model->DrawDebug(ent);
2108         }
2109 }
2110
2111 static void R_DrawModelsAddWaterPlanes(void)
2112 {
2113         int i;
2114         entity_render_t *ent;
2115
2116         if (!r_drawentities.integer)
2117                 return;
2118
2119         for (i = 0;i < r_refdef.numentities;i++)
2120         {
2121                 if (!r_viewcache.entityvisible[i])
2122                         continue;
2123                 ent = r_refdef.entities[i];
2124                 r_refdef.stats.entities++;
2125                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2126                         ent->model->DrawAddWaterPlanes(ent);
2127         }
2128 }
2129
2130 static void R_View_SetFrustum(void)
2131 {
2132         int i;
2133         double slopex, slopey;
2134
2135         // break apart the view matrix into vectors for various purposes
2136         Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
2137         VectorNegate(r_view.left, r_view.right);
2138
2139 #if 0
2140         r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
2141         r_view.frustum[0].normal[1] = 0 - 0;
2142         r_view.frustum[0].normal[2] = -1 - 0;
2143         r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
2144         r_view.frustum[1].normal[1] = 0 + 0;
2145         r_view.frustum[1].normal[2] = -1 + 0;
2146         r_view.frustum[2].normal[0] = 0 - 0;
2147         r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
2148         r_view.frustum[2].normal[2] = -1 - 0;
2149         r_view.frustum[3].normal[0] = 0 + 0;
2150         r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
2151         r_view.frustum[3].normal[2] = -1 + 0;
2152 #endif
2153
2154 #if 0
2155         zNear = r_refdef.nearclip;
2156         nudge = 1.0 - 1.0 / (1<<23);
2157         r_view.frustum[4].normal[0] = 0 - 0;
2158         r_view.frustum[4].normal[1] = 0 - 0;
2159         r_view.frustum[4].normal[2] = -1 - -nudge;
2160         r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
2161         r_view.frustum[5].normal[0] = 0 + 0;
2162         r_view.frustum[5].normal[1] = 0 + 0;
2163         r_view.frustum[5].normal[2] = -1 + -nudge;
2164         r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
2165 #endif
2166
2167
2168
2169 #if 0
2170         r_view.frustum[0].normal[0] = m[3] - m[0];
2171         r_view.frustum[0].normal[1] = m[7] - m[4];
2172         r_view.frustum[0].normal[2] = m[11] - m[8];
2173         r_view.frustum[0].dist = m[15] - m[12];
2174
2175         r_view.frustum[1].normal[0] = m[3] + m[0];
2176         r_view.frustum[1].normal[1] = m[7] + m[4];
2177         r_view.frustum[1].normal[2] = m[11] + m[8];
2178         r_view.frustum[1].dist = m[15] + m[12];
2179
2180         r_view.frustum[2].normal[0] = m[3] - m[1];
2181         r_view.frustum[2].normal[1] = m[7] - m[5];
2182         r_view.frustum[2].normal[2] = m[11] - m[9];
2183         r_view.frustum[2].dist = m[15] - m[13];
2184
2185         r_view.frustum[3].normal[0] = m[3] + m[1];
2186         r_view.frustum[3].normal[1] = m[7] + m[5];
2187         r_view.frustum[3].normal[2] = m[11] + m[9];
2188         r_view.frustum[3].dist = m[15] + m[13];
2189
2190         r_view.frustum[4].normal[0] = m[3] - m[2];
2191         r_view.frustum[4].normal[1] = m[7] - m[6];
2192         r_view.frustum[4].normal[2] = m[11] - m[10];
2193         r_view.frustum[4].dist = m[15] - m[14];
2194
2195         r_view.frustum[5].normal[0] = m[3] + m[2];
2196         r_view.frustum[5].normal[1] = m[7] + m[6];
2197         r_view.frustum[5].normal[2] = m[11] + m[10];
2198         r_view.frustum[5].dist = m[15] + m[14];
2199 #endif
2200
2201
2202
2203         if (r_view.useperspective)
2204         {
2205                 slopex = 1.0 / r_view.frustum_x;
2206                 slopey = 1.0 / r_view.frustum_y;
2207                 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
2208                 VectorMA(r_view.forward,  slopex, r_view.left, r_view.frustum[1].normal);
2209                 VectorMA(r_view.forward, -slopey, r_view.up  , r_view.frustum[2].normal);
2210                 VectorMA(r_view.forward,  slopey, r_view.up  , r_view.frustum[3].normal);
2211                 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2212
2213                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2214                 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
2215                 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward,  1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
2216                 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left,  1024 * slopey, r_view.up, r_view.frustumcorner[2]);
2217                 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward,  1024 * slopex, r_view.left,  1024 * slopey, r_view.up, r_view.frustumcorner[3]);
2218
2219                 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
2220                 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
2221                 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
2222                 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
2223                 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2224         }
2225         else
2226         {
2227                 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
2228                 VectorScale(r_view.left,  r_view.ortho_x, r_view.frustum[1].normal);
2229                 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
2230                 VectorScale(r_view.up,  r_view.ortho_y, r_view.frustum[3].normal);
2231                 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2232                 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
2233                 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
2234                 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
2235                 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
2236                 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2237         }
2238         r_view.numfrustumplanes = 5;
2239
2240         if (r_view.useclipplane)
2241         {
2242                 r_view.numfrustumplanes = 6;
2243                 r_view.frustum[5] = r_view.clipplane;
2244         }
2245
2246         for (i = 0;i < r_view.numfrustumplanes;i++)
2247                 PlaneClassify(r_view.frustum + i);
2248
2249         // LordHavoc: note to all quake engine coders, Quake had a special case
2250         // for 90 degrees which assumed a square view (wrong), so I removed it,
2251         // Quake2 has it disabled as well.
2252
2253         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2254         //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2255         //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2256         //PlaneClassify(&frustum[0]);
2257
2258         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2259         //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2260         //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2261         //PlaneClassify(&frustum[1]);
2262
2263         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2264         //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2265         //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2266         //PlaneClassify(&frustum[2]);
2267
2268         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2269         //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2270         //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2271         //PlaneClassify(&frustum[3]);
2272
2273         // nearclip plane
2274         //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2275         //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2276         //PlaneClassify(&frustum[4]);
2277 }
2278
2279 void R_View_Update(void)
2280 {
2281         R_View_SetFrustum();
2282         R_View_WorldVisibility(r_view.useclipplane);
2283         R_View_UpdateEntityVisible();
2284 }
2285
2286 void R_SetupView(void)
2287 {
2288         if (!r_view.useperspective)
2289                 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);
2290         else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2291                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2292         else
2293                 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2294
2295         GL_SetupView_Orientation_FromEntity(&r_view.matrix);
2296
2297         if (r_view.useclipplane)
2298         {
2299                 // LordHavoc: couldn't figure out how to make this approach the
2300                 vec_t dist = r_view.clipplane.dist - r_glsl_water_clippingplanebias.value;
2301                 vec_t viewdist = DotProduct(r_view.origin, r_view.clipplane.normal);
2302                 if (viewdist < r_view.clipplane.dist + r_glsl_water_clippingplanebias.value)
2303                         dist = r_view.clipplane.dist;
2304                 GL_SetupView_ApplyCustomNearClipPlane(r_view.clipplane.normal[0], r_view.clipplane.normal[1], r_view.clipplane.normal[2], dist);
2305         }
2306 }
2307
2308 void R_ResetViewRendering2D(void)
2309 {
2310         if (gl_support_fragment_shader)
2311         {
2312                 qglUseProgramObjectARB(0);CHECKGLERROR
2313         }
2314
2315         DrawQ_Finish();
2316
2317         // GL is weird because it's bottom to top, r_view.y is top to bottom
2318         qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2319         GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2320         GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2321         GL_Color(1, 1, 1, 1);
2322         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2323         GL_BlendFunc(GL_ONE, GL_ZERO);
2324         GL_AlphaTest(false);
2325         GL_ScissorTest(false);
2326         GL_DepthMask(false);
2327         GL_DepthRange(0, 1);
2328         GL_DepthTest(false);
2329         R_Mesh_Matrix(&identitymatrix);
2330         R_Mesh_ResetTextureState();
2331         GL_PolygonOffset(0, 0);
2332         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2333         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2334         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2335         qglStencilMask(~0);CHECKGLERROR
2336         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2337         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2338         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2339 }
2340
2341 void R_ResetViewRendering3D(void)
2342 {
2343         if (gl_support_fragment_shader)
2344         {
2345                 qglUseProgramObjectARB(0);CHECKGLERROR
2346         }
2347
2348         DrawQ_Finish();
2349
2350         // GL is weird because it's bottom to top, r_view.y is top to bottom
2351         qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2352         R_SetupView();
2353         GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2354         GL_Color(1, 1, 1, 1);
2355         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2356         GL_BlendFunc(GL_ONE, GL_ZERO);
2357         GL_AlphaTest(false);
2358         GL_ScissorTest(true);
2359         GL_DepthMask(true);
2360         GL_DepthRange(0, 1);
2361         GL_DepthTest(true);
2362         R_Mesh_Matrix(&identitymatrix);
2363         R_Mesh_ResetTextureState();
2364         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2365         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2366         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2367         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2368         qglStencilMask(~0);CHECKGLERROR
2369         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2370         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2371         GL_CullFace(r_view.cullface_back);
2372 }
2373
2374 /*
2375         R_Bloom_SetupShader(
2376 "// bloom shader\n"
2377 "// written by Forest 'LordHavoc' Hale\n"
2378 "\n"
2379 "// common definitions between vertex shader and fragment shader:\n"
2380 "\n"
2381 "#ifdef __GLSL_CG_DATA_TYPES\n"
2382 "#define myhalf half\n"
2383 "#define myhvec2 hvec2\n"
2384 "#define myhvec3 hvec3\n"
2385 "#define myhvec4 hvec4\n"
2386 "#else\n"
2387 "#define myhalf float\n"
2388 "#define myhvec2 vec2\n"
2389 "#define myhvec3 vec3\n"
2390 "#define myhvec4 vec4\n"
2391 "#endif\n"
2392 "\n"
2393 "varying vec2 ScreenTexCoord;\n"
2394 "varying vec2 BloomTexCoord;\n"
2395 "\n"
2396 "\n"
2397 "\n"
2398 "\n"
2399 "// vertex shader specific:\n"
2400 "#ifdef VERTEX_SHADER\n"
2401 "\n"
2402 "void main(void)\n"
2403 "{\n"
2404 "       ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2405 "       BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2406 "       // transform vertex to camera space, using ftransform to match non-VS\n"
2407 "       // rendering\n"
2408 "       gl_Position = ftransform();\n"
2409 "}\n"
2410 "\n"
2411 "#endif // VERTEX_SHADER\n"
2412 "\n"
2413 "\n"
2414 "\n"
2415 "\n"
2416 "// fragment shader specific:\n"
2417 "#ifdef FRAGMENT_SHADER\n"
2418 "\n"
2419 "void main(void)\n"
2420 "{\n"
2421 "       int x, y;
2422 "       myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2423 "       for (x = -BLUR_X;x <= BLUR_X;x++)
2424 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2425 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2426 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2427 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2428
2429 "       gl_FragColor = vec4(color);\n"
2430 "}\n"
2431 "\n"
2432 "#endif // FRAGMENT_SHADER\n"
2433 */
2434
2435 void R_RenderScene(qboolean addwaterplanes);
2436
2437 static void R_Water_StartFrame(void)
2438 {
2439         int i;
2440         int waterwidth, waterheight, texturewidth, textureheight;
2441         r_waterstate_waterplane_t *p;
2442
2443         // set waterwidth and waterheight to the water resolution that will be
2444         // used (often less than the screen resolution for faster rendering)
2445         waterwidth = (int)bound(1, r_view.width * r_glsl_water_resolutionmultiplier.value, r_view.width);
2446         waterheight = (int)bound(1, r_view.height * r_glsl_water_resolutionmultiplier.value, r_view.height);
2447
2448         // calculate desired texture sizes
2449         // can't use water if the card does not support the texture size
2450         if (!r_glsl_water.integer || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2451                 texturewidth = textureheight = waterwidth = waterheight = 0;
2452         else if (gl_support_arb_texture_non_power_of_two)
2453         {
2454                 texturewidth = waterwidth;
2455                 textureheight = waterheight;
2456         }
2457         else
2458         {
2459                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
2460                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
2461         }
2462
2463         // allocate textures as needed
2464         if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2465         {
2466                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2467                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2468                 {
2469                         if (p->texture_refraction)
2470                                 R_FreeTexture(p->texture_refraction);
2471                         p->texture_refraction = NULL;
2472                         if (p->texture_reflection)
2473                                 R_FreeTexture(p->texture_reflection);
2474                         p->texture_reflection = NULL;
2475                 }
2476                 memset(&r_waterstate, 0, sizeof(r_waterstate));
2477                 r_waterstate.waterwidth = waterwidth;
2478                 r_waterstate.waterheight = waterheight;
2479                 r_waterstate.texturewidth = texturewidth;
2480                 r_waterstate.textureheight = textureheight;
2481         }
2482
2483         if (r_waterstate.waterwidth)
2484         {
2485                 r_waterstate.enabled = true;
2486
2487                 // set up variables that will be used in shader setup
2488                 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2489                 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2490                 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2491                 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2492         }
2493
2494         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2495         r_waterstate.numwaterplanes = 0;
2496 }
2497
2498 static void R_Water_AddWaterPlane(msurface_t *surface)
2499 {
2500         int triangleindex, planeindex;
2501         const int *e;
2502         vec_t f;
2503         vec3_t vert[3];
2504         vec3_t normal;
2505         vec3_t center;
2506         r_waterstate_waterplane_t *p;
2507         // just use the first triangle with a valid normal for any decisions
2508         VectorClear(normal);
2509         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2510         {
2511                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2512                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2513                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2514                 TriangleNormal(vert[0], vert[1], vert[2], normal);
2515                 if (VectorLength2(normal) >= 0.001)
2516                         break;
2517         }
2518         // now find the center of this surface
2519         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles*3;triangleindex++, e++)
2520         {
2521                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2522                 VectorAdd(center, vert[0], center);
2523         }
2524         f = 1.0 / surface->num_triangles*3;
2525         VectorScale(center, f, center);
2526
2527         // find a matching plane if there is one
2528         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2529                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2530                         break;
2531         if (planeindex >= r_waterstate.maxwaterplanes)
2532                 return; // nothing we can do, out of planes
2533
2534         // if this triangle does not fit any known plane rendered this frame, add one
2535         if (planeindex >= r_waterstate.numwaterplanes)
2536         {
2537                 // store the new plane
2538                 r_waterstate.numwaterplanes++;
2539                 VectorCopy(normal, p->plane.normal);
2540                 VectorNormalize(p->plane.normal);
2541                 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2542                 PlaneClassify(&p->plane);
2543                 // flip the plane if it does not face the viewer
2544                 if (PlaneDiff(r_view.origin, &p->plane) < 0)
2545                 {
2546                         VectorNegate(p->plane.normal, p->plane.normal);
2547                         p->plane.dist *= -1;
2548                         PlaneClassify(&p->plane);
2549                 }
2550                 // clear materialflags and pvs
2551                 p->materialflags = 0;
2552                 p->pvsvalid = false;
2553         }
2554         // merge this surface's materialflags into the waterplane
2555         p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2556         // merge this surface's PVS into the waterplane
2557         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION) && r_refdef.worldmodel && r_refdef.worldmodel->brush.FatPVS)
2558         {
2559                 r_refdef.worldmodel->brush.FatPVS(r_refdef.worldmodel, r_view.origin, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2560                 p->pvsvalid = true;
2561         }
2562 }
2563
2564 static void R_Water_ProcessPlanes(void)
2565 {
2566         r_view_t originalview;
2567         int planeindex;
2568         r_waterstate_waterplane_t *p;
2569
2570         // make sure enough textures are allocated
2571         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2572         {
2573                 if (p->materialflags & MATERIALFLAG_WATERSHADER)
2574                 {
2575                         if (!p->texture_refraction)
2576                                 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);
2577                         if (!p->texture_refraction)
2578                                 goto error;
2579                 }
2580
2581                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2582                 {
2583                         if (!p->texture_reflection)
2584                                 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);
2585                         if (!p->texture_reflection)
2586                                 goto error;
2587                 }
2588         }
2589
2590         // render views
2591         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2592         {
2593                 originalview = r_view;
2594                 r_view.showdebug = false;
2595                 r_view.width = r_waterstate.waterwidth;
2596                 r_view.height = r_waterstate.waterheight;
2597                 r_view.useclipplane = true;
2598                 r_waterstate.renderingscene = true;
2599
2600                 // render the normal view scene and copy into texture
2601                 // (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)
2602                 if (p->materialflags & MATERIALFLAG_WATERSHADER)
2603                 {
2604                         r_view.clipplane = p->plane;
2605                         VectorNegate(r_view.clipplane.normal, r_view.clipplane.normal);
2606                         r_view.clipplane.dist = -r_view.clipplane.dist;
2607                         PlaneClassify(&r_view.clipplane);
2608
2609                         R_RenderScene(false);
2610
2611                         // copy view into the screen texture
2612                         R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
2613                         GL_ActiveTexture(0);
2614                         CHECKGLERROR
2615                         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
2616                 }
2617
2618                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2619                 {
2620                         // render reflected scene and copy into texture
2621                         Matrix4x4_Reflect(&r_view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2622                         r_view.clipplane = p->plane;
2623                         // reverse the cullface settings for this render
2624                         r_view.cullface_front = GL_FRONT;
2625                         r_view.cullface_back = GL_BACK;
2626                         if (r_refdef.worldmodel && r_refdef.worldmodel->brush.num_pvsclusterbytes)
2627                         {
2628                                 r_view.usecustompvs = true;
2629                                 if (p->pvsvalid)
2630                                         memcpy(r_viewcache.world_pvsbits, p->pvsbits, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2631                                 else
2632                                         memset(r_viewcache.world_pvsbits, 0xFF, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2633                         }
2634
2635                         R_ResetViewRendering3D();
2636                         R_ClearScreen();
2637
2638                         R_RenderScene(false);
2639
2640                         R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
2641                         GL_ActiveTexture(0);
2642                         CHECKGLERROR
2643                         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
2644
2645                         R_ResetViewRendering3D();
2646                         R_ClearScreen();
2647                 }
2648
2649                 r_view = originalview;
2650                 r_waterstate.renderingscene = false;
2651         }
2652         return;
2653 error:
2654         r_view = originalview;
2655         r_waterstate.renderingscene = false;
2656         Cvar_SetValueQuick(&r_glsl_water, 0);
2657         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_glsl_water.\n");
2658         return;
2659 }
2660
2661 void R_Bloom_StartFrame(void)
2662 {
2663         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2664
2665         // set bloomwidth and bloomheight to the bloom resolution that will be
2666         // used (often less than the screen resolution for faster rendering)
2667         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2668         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2669         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2670
2671         // calculate desired texture sizes
2672         if (gl_support_arb_texture_non_power_of_two)
2673         {
2674                 screentexturewidth = r_view.width;
2675                 screentextureheight = r_view.height;
2676                 bloomtexturewidth = r_bloomstate.bloomwidth;
2677                 bloomtextureheight = r_bloomstate.bloomheight;
2678         }
2679         else
2680         {
2681                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
2682                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
2683                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
2684                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
2685         }
2686
2687         if (r_hdr.integer)
2688         {
2689                 screentexturewidth = screentextureheight = 0;
2690         }
2691         else if (r_bloom.integer)
2692         {
2693         }
2694         else
2695         {
2696                 screentexturewidth = screentextureheight = 0;
2697                 bloomtexturewidth = bloomtextureheight = 0;
2698         }
2699
2700         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)
2701         {
2702                 // can't use bloom if the parameters are too weird
2703                 // can't use bloom if the card does not support the texture size
2704                 if (r_bloomstate.texture_screen)
2705                         R_FreeTexture(r_bloomstate.texture_screen);
2706                 if (r_bloomstate.texture_bloom)
2707                         R_FreeTexture(r_bloomstate.texture_bloom);
2708                 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2709                 return;
2710         }
2711
2712         r_bloomstate.enabled = true;
2713         r_bloomstate.hdr = r_hdr.integer != 0;
2714
2715         // allocate textures as needed
2716         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2717         {
2718                 if (r_bloomstate.texture_screen)
2719                         R_FreeTexture(r_bloomstate.texture_screen);
2720                 r_bloomstate.texture_screen = NULL;
2721                 r_bloomstate.screentexturewidth = screentexturewidth;
2722                 r_bloomstate.screentextureheight = screentextureheight;
2723                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2724                         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);
2725         }
2726         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2727         {
2728                 if (r_bloomstate.texture_bloom)
2729                         R_FreeTexture(r_bloomstate.texture_bloom);
2730                 r_bloomstate.texture_bloom = NULL;
2731                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2732                 r_bloomstate.bloomtextureheight = bloomtextureheight;
2733                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2734                         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);
2735         }
2736
2737         // set up a texcoord array for the full resolution screen image
2738         // (we have to keep this around to copy back during final render)
2739         r_bloomstate.screentexcoord2f[0] = 0;
2740         r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2741         r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2742         r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2743         r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2744         r_bloomstate.screentexcoord2f[5] = 0;
2745         r_bloomstate.screentexcoord2f[6] = 0;
2746         r_bloomstate.screentexcoord2f[7] = 0;
2747
2748         // set up a texcoord array for the reduced resolution bloom image
2749         // (which will be additive blended over the screen image)
2750         r_bloomstate.bloomtexcoord2f[0] = 0;
2751         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2752         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2753         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2754         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2755         r_bloomstate.bloomtexcoord2f[5] = 0;
2756         r_bloomstate.bloomtexcoord2f[6] = 0;
2757         r_bloomstate.bloomtexcoord2f[7] = 0;
2758 }
2759
2760 void R_Bloom_CopyScreenTexture(float colorscale)
2761 {
2762         r_refdef.stats.bloom++;
2763
2764         R_ResetViewRendering2D();
2765         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2766         R_Mesh_ColorPointer(NULL, 0, 0);
2767         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2768         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2769
2770         // copy view into the screen texture
2771         GL_ActiveTexture(0);
2772         CHECKGLERROR
2773         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
2774         r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2775
2776         // now scale it down to the bloom texture size
2777         CHECKGLERROR
2778         qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2779         GL_BlendFunc(GL_ONE, GL_ZERO);
2780         GL_Color(colorscale, colorscale, colorscale, 1);
2781         // TODO: optimize with multitexture or GLSL
2782         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2783         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2784
2785         // we now have a bloom image in the framebuffer
2786         // copy it into the bloom image texture for later processing
2787         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2788         GL_ActiveTexture(0);
2789         CHECKGLERROR
2790         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
2791         r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2792 }
2793
2794 void R_Bloom_CopyHDRTexture(void)
2795 {
2796         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2797         GL_ActiveTexture(0);
2798         CHECKGLERROR
2799         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
2800         r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2801 }
2802
2803 void R_Bloom_MakeTexture(void)
2804 {
2805         int x, range, dir;
2806         float xoffset, yoffset, r, brighten;
2807
2808         r_refdef.stats.bloom++;
2809
2810         R_ResetViewRendering2D();
2811         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2812         R_Mesh_ColorPointer(NULL, 0, 0);
2813
2814         // we have a bloom image in the framebuffer
2815         CHECKGLERROR
2816         qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2817
2818         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
2819         {
2820                 x *= 2;
2821                 r = bound(0, r_bloom_colorexponent.value / x, 1);
2822                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2823                 GL_Color(r, r, r, 1);
2824                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2825                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2826                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2827                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2828
2829                 // copy the vertically blurred bloom view to a texture
2830                 GL_ActiveTexture(0);
2831                 CHECKGLERROR
2832                 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
2833                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2834         }
2835
2836         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2837         brighten = r_bloom_brighten.value;
2838         if (r_hdr.integer)
2839                 brighten *= r_hdr_range.value;
2840         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2841         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2842
2843         for (dir = 0;dir < 2;dir++)
2844         {
2845                 // blend on at multiple vertical offsets to achieve a vertical blur
2846                 // TODO: do offset blends using GLSL
2847                 GL_BlendFunc(GL_ONE, GL_ZERO);
2848                 for (x = -range;x <= range;x++)
2849                 {
2850                         if (!dir){xoffset = 0;yoffset = x;}
2851                         else {xoffset = x;yoffset = 0;}
2852                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
2853                         yoffset /= (float)r_bloomstate.bloomtextureheight;
2854                         // compute a texcoord array with the specified x and y offset
2855                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2856                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2857                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2858                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2859                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2860                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2861                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2862                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2863                         // this r value looks like a 'dot' particle, fading sharply to
2864                         // black at the edges
2865                         // (probably not realistic but looks good enough)
2866                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2867                         //r = (dir ? 1.0f : brighten)/(range*2+1);
2868                         r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2869                         GL_Color(r, r, r, 1);
2870                         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2871                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2872                         GL_BlendFunc(GL_ONE, GL_ONE);
2873                 }
2874
2875                 // copy the vertically blurred bloom view to a texture
2876                 GL_ActiveTexture(0);
2877                 CHECKGLERROR
2878                 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
2879                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2880         }
2881
2882         // apply subtract last
2883         // (just like it would be in a GLSL shader)
2884         if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
2885         {
2886                 GL_BlendFunc(GL_ONE, GL_ZERO);
2887                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2888                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2889                 GL_Color(1, 1, 1, 1);
2890                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2891                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2892
2893                 GL_BlendFunc(GL_ONE, GL_ONE);
2894                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2895                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2896                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2897                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
2898                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2899                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2900                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2901
2902                 // copy the darkened bloom view to a texture
2903                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2904                 GL_ActiveTexture(0);
2905                 CHECKGLERROR
2906                 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
2907                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2908         }
2909 }
2910
2911 void R_HDR_RenderBloomTexture(void)
2912 {
2913         int oldwidth, oldheight;
2914
2915         oldwidth = r_view.width;
2916         oldheight = r_view.height;
2917         r_view.width = r_bloomstate.bloomwidth;
2918         r_view.height = r_bloomstate.bloomheight;
2919
2920         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
2921         // TODO: add exposure compensation features
2922         // TODO: add fp16 framebuffer support
2923
2924         r_view.showdebug = false;
2925         r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
2926         if (r_hdr.integer)
2927                 r_view.colorscale /= r_hdr_range.value;
2928         r_waterstate.numwaterplanes = 0;
2929         R_RenderScene(r_waterstate.enabled);
2930         r_view.showdebug = true;
2931
2932         R_ResetViewRendering2D();
2933
2934         R_Bloom_CopyHDRTexture();
2935         R_Bloom_MakeTexture();
2936
2937         R_ResetViewRendering3D();
2938
2939         R_ClearScreen();
2940         if (r_timereport_active)
2941                 R_TimeReport("clear");
2942
2943
2944         // restore the view settings
2945         r_view.width = oldwidth;
2946         r_view.height = oldheight;
2947 }
2948
2949 static void R_BlendView(void)
2950 {
2951         if (r_bloomstate.enabled && r_bloomstate.hdr)
2952         {
2953                 // render high dynamic range bloom effect
2954                 // the bloom texture was made earlier this render, so we just need to
2955                 // blend it onto the screen...
2956                 R_ResetViewRendering2D();
2957                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2958                 R_Mesh_ColorPointer(NULL, 0, 0);
2959                 GL_Color(1, 1, 1, 1);
2960                 GL_BlendFunc(GL_ONE, GL_ONE);
2961                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2962                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2963                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2964                 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2965         }
2966         else if (r_bloomstate.enabled)
2967         {
2968                 // render simple bloom effect
2969                 // copy the screen and shrink it and darken it for the bloom process
2970                 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2971                 // make the bloom texture
2972                 R_Bloom_MakeTexture();
2973                 // put the original screen image back in place and blend the bloom
2974                 // texture on it
2975                 R_ResetViewRendering2D();
2976                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2977                 R_Mesh_ColorPointer(NULL, 0, 0);
2978                 GL_Color(1, 1, 1, 1);
2979                 GL_BlendFunc(GL_ONE, GL_ZERO);
2980                 // do both in one pass if possible
2981                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2982                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2983                 if (r_textureunits.integer >= 2 && gl_combine.integer)
2984                 {
2985                         R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2986                         R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2987                         R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
2988                 }
2989                 else
2990                 {
2991                         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2992                         r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2993                         // now blend on the bloom texture
2994                         GL_BlendFunc(GL_ONE, GL_ONE);
2995                         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2996                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2997                 }
2998                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2999                 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3000         }
3001         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3002         {
3003                 // apply a color tint to the whole view
3004                 R_ResetViewRendering2D();
3005                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3006                 R_Mesh_ColorPointer(NULL, 0, 0);
3007                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3008                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3009                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3010         }
3011 }
3012
3013 void R_RenderScene(qboolean addwaterplanes);
3014
3015 matrix4x4_t r_waterscrollmatrix;
3016
3017 void R_UpdateVariables(void)
3018 {
3019         R_Textures_Frame();
3020
3021         r_refdef.farclip = 4096;
3022         if (r_refdef.worldmodel)
3023                 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
3024         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3025
3026         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3027                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3028         r_refdef.polygonfactor = 0;
3029         r_refdef.polygonoffset = 0;
3030         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3031         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3032
3033         r_refdef.rtworld = r_shadow_realtime_world.integer;
3034         r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3035         r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3036         r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3037         r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3038         if (r_showsurfaces.integer)
3039         {
3040                 r_refdef.rtworld = false;
3041                 r_refdef.rtworldshadows = false;
3042                 r_refdef.rtdlight = false;
3043                 r_refdef.rtdlightshadows = false;
3044                 r_refdef.lightmapintensity = 0;
3045         }
3046
3047         if (gamemode == GAME_NEHAHRA)
3048         {
3049                 if (gl_fogenable.integer)
3050                 {
3051                         r_refdef.oldgl_fogenable = true;
3052                         r_refdef.fog_density = gl_fogdensity.value;
3053                         r_refdef.fog_red = gl_fogred.value;
3054                         r_refdef.fog_green = gl_foggreen.value;
3055                         r_refdef.fog_blue = gl_fogblue.value;
3056                 }
3057                 else if (r_refdef.oldgl_fogenable)
3058                 {
3059                         r_refdef.oldgl_fogenable = false;
3060                         r_refdef.fog_density = 0;
3061                         r_refdef.fog_red = 0;
3062                         r_refdef.fog_green = 0;
3063                         r_refdef.fog_blue = 0;
3064                 }
3065         }
3066         if (r_refdef.fog_density)
3067         {
3068                 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red  , 1.0f);
3069                 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
3070                 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
3071         }
3072         if (r_refdef.fog_density)
3073         {
3074                 r_refdef.fogenabled = true;
3075                 // this is the point where the fog reaches 0.9986 alpha, which we
3076                 // consider a good enough cutoff point for the texture
3077                 // (0.9986 * 256 == 255.6)
3078                 r_refdef.fogrange = 400 / r_refdef.fog_density;
3079                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3080                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3081                 // fog color was already set
3082         }
3083         else
3084                 r_refdef.fogenabled = false;
3085 }
3086
3087 /*
3088 ================
3089 R_RenderView
3090 ================
3091 */
3092 void R_RenderView(void)
3093 {
3094         if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
3095                 return; //Host_Error ("R_RenderView: NULL worldmodel");
3096
3097         R_Shadow_UpdateWorldLightSelection();
3098
3099         R_Bloom_StartFrame();
3100         R_Water_StartFrame();
3101
3102         CHECKGLERROR
3103         if (r_timereport_active)
3104                 R_TimeReport("setup");
3105
3106         R_ResetViewRendering3D();
3107
3108         R_ClearScreen();
3109         if (r_timereport_active)
3110                 R_TimeReport("clear");
3111
3112         r_view.showdebug = true;
3113
3114         // this produces a bloom texture to be used in R_BlendView() later
3115         if (r_hdr.integer)
3116                 R_HDR_RenderBloomTexture();
3117
3118         r_view.colorscale = r_hdr_scenebrightness.value;
3119         r_waterstate.numwaterplanes = 0;
3120         R_RenderScene(r_waterstate.enabled);
3121
3122         R_BlendView();
3123         if (r_timereport_active)
3124                 R_TimeReport("blendview");
3125
3126         GL_Scissor(0, 0, vid.width, vid.height);
3127         GL_ScissorTest(false);
3128         CHECKGLERROR
3129 }
3130
3131 extern void R_DrawLightningBeams (void);
3132 extern void VM_CL_AddPolygonsToMeshQueue (void);
3133 extern void R_DrawPortals (void);
3134 extern cvar_t cl_locs_show;
3135 static void R_DrawLocs(void);
3136 static void R_DrawEntityBBoxes(void);
3137 void R_RenderScene(qboolean addwaterplanes)
3138 {
3139         if (addwaterplanes)
3140         {
3141                 R_ResetViewRendering3D();
3142
3143                 R_View_Update();
3144                 if (r_timereport_active)
3145                         R_TimeReport("watervisibility");
3146
3147                 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawAddWaterPlanes)
3148                 {
3149                         r_refdef.worldmodel->DrawAddWaterPlanes(r_refdef.worldentity);
3150                         if (r_timereport_active)
3151                                 R_TimeReport("waterworld");
3152                 }
3153
3154                 // don't let sound skip if going slow
3155                 if (r_refdef.extraupdate)
3156                         S_ExtraUpdate ();
3157
3158                 R_DrawModelsAddWaterPlanes();
3159                 if (r_timereport_active)
3160                         R_TimeReport("watermodels");
3161
3162                 R_Water_ProcessPlanes();
3163                 if (r_timereport_active)
3164                         R_TimeReport("waterscenes");
3165         }
3166
3167         R_ResetViewRendering3D();
3168
3169         // don't let sound skip if going slow
3170         if (r_refdef.extraupdate)
3171                 S_ExtraUpdate ();
3172
3173         R_MeshQueue_BeginScene();
3174
3175         R_SkyStartFrame();
3176
3177         R_View_Update();
3178         if (r_timereport_active)
3179                 R_TimeReport("visibility");
3180
3181         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);
3182
3183         if (cl.csqc_vidvars.drawworld)
3184         {
3185                 // don't let sound skip if going slow
3186                 if (r_refdef.extraupdate)
3187                         S_ExtraUpdate ();
3188
3189                 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
3190                 {
3191                         r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
3192                         if (r_timereport_active)
3193                                 R_TimeReport("worldsky");
3194                 }
3195
3196                 if (R_DrawBrushModelsSky() && r_timereport_active)
3197                         R_TimeReport("bmodelsky");
3198         }
3199
3200         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
3201         {
3202                 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
3203                 if (r_timereport_active)
3204                         R_TimeReport("worlddepth");
3205         }
3206         if (r_depthfirst.integer >= 2)
3207         {
3208                 R_DrawModelsDepth();
3209                 if (r_timereport_active)
3210                         R_TimeReport("modeldepth");
3211         }
3212
3213         if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
3214         {
3215                 r_refdef.worldmodel->Draw(r_refdef.worldentity);
3216                 if (r_timereport_active)
3217                         R_TimeReport("world");
3218         }
3219
3220         // don't let sound skip if going slow
3221         if (r_refdef.extraupdate)
3222                 S_ExtraUpdate ();
3223
3224         R_DrawModels();
3225         if (r_timereport_active)
3226                 R_TimeReport("models");
3227
3228         // don't let sound skip if going slow
3229         if (r_refdef.extraupdate)
3230                 S_ExtraUpdate ();
3231
3232         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3233         {
3234                 R_DrawModelShadows();
3235
3236                 R_ResetViewRendering3D();
3237
3238                 // don't let sound skip if going slow
3239                 if (r_refdef.extraupdate)
3240                         S_ExtraUpdate ();
3241         }
3242
3243         R_ShadowVolumeLighting(false);
3244         if (r_timereport_active)
3245                 R_TimeReport("rtlights");
3246
3247         // don't let sound skip if going slow
3248         if (r_refdef.extraupdate)
3249                 S_ExtraUpdate ();
3250
3251         if (cl.csqc_vidvars.drawworld)
3252         {
3253                 R_DrawLightningBeams();
3254                 if (r_timereport_active)
3255                         R_TimeReport("lightning");
3256
3257                 R_DrawParticles();
3258                 if (r_timereport_active)
3259                         R_TimeReport("particles");
3260
3261                 R_DrawExplosions();
3262                 if (r_timereport_active)
3263                         R_TimeReport("explosions");
3264         }
3265
3266         if (gl_support_fragment_shader)
3267         {
3268                 qglUseProgramObjectARB(0);CHECKGLERROR
3269         }
3270         VM_CL_AddPolygonsToMeshQueue();
3271
3272         if (r_view.showdebug)
3273         {
3274                 if (cl_locs_show.integer)
3275                 {
3276                         R_DrawLocs();
3277                         if (r_timereport_active)
3278                                 R_TimeReport("showlocs");
3279                 }
3280
3281                 if (r_drawportals.integer)
3282                 {
3283                         R_DrawPortals();
3284                         if (r_timereport_active)
3285                                 R_TimeReport("portals");
3286                 }
3287
3288                 if (r_showbboxes.value > 0)
3289                 {
3290                         R_DrawEntityBBoxes();
3291                         if (r_timereport_active)
3292                                 R_TimeReport("bboxes");
3293                 }
3294         }
3295
3296         if (gl_support_fragment_shader)
3297         {
3298                 qglUseProgramObjectARB(0);CHECKGLERROR
3299         }
3300         R_MeshQueue_RenderTransparent();
3301         if (r_timereport_active)
3302                 R_TimeReport("drawtrans");
3303
3304         if (gl_support_fragment_shader)
3305         {
3306                 qglUseProgramObjectARB(0);CHECKGLERROR
3307         }
3308
3309         if (r_view.showdebug && r_refdef.worldmodel && r_refdef.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3310         {
3311                 r_refdef.worldmodel->DrawDebug(r_refdef.worldentity);
3312                 if (r_timereport_active)
3313                         R_TimeReport("worlddebug");
3314                 R_DrawModelsDebug();
3315                 if (r_timereport_active)
3316                         R_TimeReport("modeldebug");
3317         }
3318
3319         if (gl_support_fragment_shader)
3320         {
3321                 qglUseProgramObjectARB(0);CHECKGLERROR
3322         }
3323
3324         if (cl.csqc_vidvars.drawworld)
3325         {
3326                 R_DrawCoronas();
3327                 if (r_timereport_active)
3328                         R_TimeReport("coronas");
3329         }
3330
3331         // don't let sound skip if going slow
3332         if (r_refdef.extraupdate)
3333                 S_ExtraUpdate ();
3334
3335         R_ResetViewRendering2D();
3336 }
3337
3338 static const int bboxelements[36] =
3339 {
3340         5, 1, 3, 5, 3, 7,
3341         6, 2, 0, 6, 0, 4,
3342         7, 3, 2, 7, 2, 6,
3343         4, 0, 1, 4, 1, 5,
3344         4, 5, 7, 4, 7, 6,
3345         1, 0, 2, 1, 2, 3,
3346 };
3347
3348 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3349 {
3350         int i;
3351         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3352         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3353         GL_DepthMask(false);
3354         GL_DepthRange(0, 1);
3355         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3356         R_Mesh_Matrix(&identitymatrix);
3357         R_Mesh_ResetTextureState();
3358
3359         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3360         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3361         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3362         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3363         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3364         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3365         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3366         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3367         R_FillColors(color4f, 8, cr, cg, cb, ca);
3368         if (r_refdef.fogenabled)
3369         {
3370                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3371                 {
3372                         f1 = FogPoint_World(v);
3373                         f2 = 1 - f1;
3374                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3375                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3376                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3377                 }
3378         }
3379         R_Mesh_VertexPointer(vertex3f, 0, 0);
3380         R_Mesh_ColorPointer(color4f, 0, 0);
3381         R_Mesh_ResetTextureState();
3382         R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3383 }
3384
3385 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3386 {
3387         int i;
3388         float color[4];
3389         prvm_edict_t *edict;
3390         // this function draws bounding boxes of server entities
3391         if (!sv.active)
3392                 return;
3393         SV_VM_Begin();
3394         for (i = 0;i < numsurfaces;i++)
3395         {
3396                 edict = PRVM_EDICT_NUM(surfacelist[i]);
3397                 switch ((int)edict->fields.server->solid)
3398                 {
3399                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
3400                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
3401                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
3402                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3403                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
3404                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
3405                 }
3406                 color[3] *= r_showbboxes.value;
3407                 color[3] = bound(0, color[3], 1);
3408                 GL_DepthTest(!r_showdisabledepthtest.integer);
3409                 GL_CullFace(r_view.cullface_front);
3410                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3411         }
3412         SV_VM_End();
3413 }
3414
3415 static void R_DrawEntityBBoxes(void)
3416 {
3417         int i;
3418         prvm_edict_t *edict;
3419         vec3_t center;
3420         // this function draws bounding boxes of server entities
3421         if (!sv.active)
3422                 return;
3423         SV_VM_Begin();
3424         for (i = 0;i < prog->num_edicts;i++)
3425         {
3426                 edict = PRVM_EDICT_NUM(i);
3427                 if (edict->priv.server->free)
3428                         continue;
3429                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3430                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3431         }
3432         SV_VM_End();
3433 }
3434
3435 int nomodelelements[24] =
3436 {
3437         5, 2, 0,
3438         5, 1, 2,
3439         5, 0, 3,
3440         5, 3, 1,
3441         0, 2, 4,
3442         2, 1, 4,
3443         3, 0, 4,
3444         1, 3, 4
3445 };
3446
3447 float nomodelvertex3f[6*3] =
3448 {
3449         -16,   0,   0,
3450          16,   0,   0,
3451           0, -16,   0,
3452           0,  16,   0,
3453           0,   0, -16,
3454           0,   0,  16
3455 };
3456
3457 float nomodelcolor4f[6*4] =
3458 {
3459         0.0f, 0.0f, 0.5f, 1.0f,
3460         0.0f, 0.0f, 0.5f, 1.0f,
3461         0.0f, 0.5f, 0.0f, 1.0f,
3462         0.0f, 0.5f, 0.0f, 1.0f,
3463         0.5f, 0.0f, 0.0f, 1.0f,
3464         0.5f, 0.0f, 0.0f, 1.0f
3465 };
3466
3467 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3468 {
3469         int i;
3470         float f1, f2, *c;
3471         float color4f[6*4];
3472         // this is only called once per entity so numsurfaces is always 1, and
3473         // surfacelist is always {0}, so this code does not handle batches
3474         R_Mesh_Matrix(&ent->matrix);
3475
3476         if (ent->flags & EF_ADDITIVE)
3477         {
3478                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3479                 GL_DepthMask(false);
3480         }
3481         else if (ent->alpha < 1)
3482         {
3483                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3484                 GL_DepthMask(false);
3485         }
3486         else
3487         {
3488                 GL_BlendFunc(GL_ONE, GL_ZERO);
3489                 GL_DepthMask(true);
3490         }
3491         GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3492         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3493         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3494         GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_view.cullface_back);
3495         R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3496         if (r_refdef.fogenabled)
3497         {
3498                 vec3_t org;
3499                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3500                 R_Mesh_ColorPointer(color4f, 0, 0);
3501                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3502                 f1 = FogPoint_World(org);
3503                 f2 = 1 - f1;
3504                 for (i = 0, c = color4f;i < 6;i++, c += 4)
3505                 {
3506                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3507                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3508                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3509                         c[3] *= ent->alpha;
3510                 }
3511         }
3512         else if (ent->alpha != 1)
3513         {
3514                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3515                 R_Mesh_ColorPointer(color4f, 0, 0);
3516                 for (i = 0, c = color4f;i < 6;i++, c += 4)
3517                         c[3] *= ent->alpha;
3518         }
3519         else
3520                 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3521         R_Mesh_ResetTextureState();
3522         R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3523 }
3524
3525 void R_DrawNoModel(entity_render_t *ent)
3526 {
3527         vec3_t org;
3528         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3529         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3530                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3531         //else
3532         //      R_DrawNoModelCallback(ent, 0);
3533 }
3534
3535 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3536 {
3537         vec3_t right1, right2, diff, normal;
3538
3539         VectorSubtract (org2, org1, normal);
3540
3541         // calculate 'right' vector for start
3542         VectorSubtract (r_view.origin, org1, diff);
3543         CrossProduct (normal, diff, right1);
3544         VectorNormalize (right1);
3545
3546         // calculate 'right' vector for end
3547         VectorSubtract (r_view.origin, org2, diff);
3548         CrossProduct (normal, diff, right2);
3549         VectorNormalize (right2);
3550
3551         vert[ 0] = org1[0] + width * right1[0];
3552         vert[ 1] = org1[1] + width * right1[1];
3553         vert[ 2] = org1[2] + width * right1[2];
3554         vert[ 3] = org1[0] - width * right1[0];
3555         vert[ 4] = org1[1] - width * right1[1];
3556         vert[ 5] = org1[2] - width * right1[2];
3557         vert[ 6] = org2[0] - width * right2[0];
3558         vert[ 7] = org2[1] - width * right2[1];
3559         vert[ 8] = org2[2] - width * right2[2];
3560         vert[ 9] = org2[0] + width * right2[0];
3561         vert[10] = org2[1] + width * right2[1];
3562         vert[11] = org2[2] + width * right2[2];
3563 }
3564
3565 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3566
3567 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)
3568 {
3569         float fog = 1.0f;
3570         float vertex3f[12];
3571
3572         if (r_refdef.fogenabled)
3573                 fog = FogPoint_World(origin);
3574
3575         R_Mesh_Matrix(&identitymatrix);
3576         GL_BlendFunc(blendfunc1, blendfunc2);
3577
3578         if(v_flipped_state)
3579         {
3580                 scalex1 = -scalex1;
3581                 scalex2 = -scalex2;
3582                 GL_CullFace(r_view.cullface_front);
3583         }
3584         else
3585                 GL_CullFace(r_view.cullface_back);
3586
3587         GL_DepthMask(false);
3588         GL_DepthRange(0, depthshort ? 0.0625 : 1);
3589         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3590         GL_DepthTest(!depthdisable);
3591
3592         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3593         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3594         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3595         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3596         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3597         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3598         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3599         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3600         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3601         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3602         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3603         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3604
3605         R_Mesh_VertexPointer(vertex3f, 0, 0);
3606         R_Mesh_ColorPointer(NULL, 0, 0);
3607         R_Mesh_ResetTextureState();
3608         R_Mesh_TexBind(0, R_GetTexture(texture));
3609         R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3610         // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3611         GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3612         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3613
3614         if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3615         {
3616                 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3617                 GL_BlendFunc(blendfunc1, GL_ONE);
3618                 fog = 1 - fog;
3619                 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);
3620                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3621         }
3622 }
3623
3624 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3625 {
3626         int i;
3627         float *vertex3f;
3628         float v[3];
3629         VectorSet(v, x, y, z);
3630         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3631                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3632                         break;
3633         if (i == mesh->numvertices)
3634         {
3635                 if (mesh->numvertices < mesh->maxvertices)
3636                 {
3637                         VectorCopy(v, vertex3f);
3638                         mesh->numvertices++;
3639                 }
3640                 return mesh->numvertices;
3641         }
3642         else
3643                 return i;
3644 }
3645
3646 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3647 {
3648         int i;
3649         int *e, element[3];
3650         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3651         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3652         e = mesh->element3i + mesh->numtriangles * 3;
3653         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3654         {
3655                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3656                 if (mesh->numtriangles < mesh->maxtriangles)
3657                 {
3658                         *e++ = element[0];
3659                         *e++ = element[1];
3660                         *e++ = element[2];
3661                         mesh->numtriangles++;
3662                 }
3663                 element[1] = element[2];
3664         }
3665 }
3666
3667 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3668 {
3669         int i;
3670         int *e, element[3];
3671         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3672         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3673         e = mesh->element3i + mesh->numtriangles * 3;
3674         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3675         {
3676                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3677                 if (mesh->numtriangles < mesh->maxtriangles)
3678                 {
3679                         *e++ = element[0];
3680                         *e++ = element[1];
3681                         *e++ = element[2];
3682                         mesh->numtriangles++;
3683                 }
3684                 element[1] = element[2];
3685         }
3686 }
3687
3688 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3689 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3690 {
3691         int planenum, planenum2;
3692         int w;
3693         int tempnumpoints;
3694         mplane_t *plane, *plane2;
3695         double maxdist;
3696         double temppoints[2][256*3];
3697         // figure out how large a bounding box we need to properly compute this brush
3698         maxdist = 0;
3699         for (w = 0;w < numplanes;w++)
3700                 maxdist = max(maxdist, planes[w].dist);
3701         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3702         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3703         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3704         {
3705                 w = 0;
3706                 tempnumpoints = 4;
3707                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3708                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3709                 {
3710                         if (planenum2 == planenum)
3711                                 continue;
3712                         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);
3713                         w = !w;
3714                 }
3715                 if (tempnumpoints < 3)
3716                         continue;
3717                 // generate elements forming a triangle fan for this polygon
3718                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3719         }
3720 }
3721
3722 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)
3723 {
3724         texturelayer_t *layer;
3725         layer = t->currentlayers + t->currentnumlayers++;
3726         layer->type = type;
3727         layer->depthmask = depthmask;
3728         layer->blendfunc1 = blendfunc1;
3729         layer->blendfunc2 = blendfunc2;
3730         layer->texture = texture;
3731         layer->texmatrix = *matrix;
3732         layer->color[0] = r * r_view.colorscale;
3733         layer->color[1] = g * r_view.colorscale;
3734         layer->color[2] = b * r_view.colorscale;
3735         layer->color[3] = a;
3736 }
3737
3738 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3739 {
3740         double index, f;
3741         index = parms[2] + r_refdef.time * parms[3];
3742         index -= floor(index);
3743         switch (func)
3744         {
3745         default:
3746         case Q3WAVEFUNC_NONE:
3747         case Q3WAVEFUNC_NOISE:
3748         case Q3WAVEFUNC_COUNT:
3749                 f = 0;
3750                 break;
3751         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3752         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3753         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3754         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3755         case Q3WAVEFUNC_TRIANGLE:
3756                 index *= 4;
3757                 f = index - floor(index);
3758                 if (index < 1)
3759                         f = f;
3760                 else if (index < 2)
3761                         f = 1 - f;
3762                 else if (index < 3)
3763                         f = -f;
3764                 else
3765                         f = -(1 - f);
3766                 break;
3767         }
3768         return (float)(parms[0] + parms[1] * f);
3769 }
3770
3771 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3772 {
3773         int i;
3774         model_t *model = ent->model;
3775         float f;
3776         float tcmat[12];
3777         q3shaderinfo_layer_tcmod_t *tcmod;
3778
3779         // switch to an alternate material if this is a q1bsp animated material
3780         {
3781                 texture_t *texture = t;
3782                 int s = ent->skinnum;
3783                 if ((unsigned int)s >= (unsigned int)model->numskins)
3784                         s = 0;
3785                 if (model->skinscenes)
3786                 {
3787                         if (model->skinscenes[s].framecount > 1)
3788                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3789                         else
3790                                 s = model->skinscenes[s].firstframe;
3791                 }
3792                 if (s > 0)
3793                         t = t + s * model->num_surfaces;
3794                 if (t->animated)
3795                 {
3796                         // use an alternate animation if the entity's frame is not 0,
3797                         // and only if the texture has an alternate animation
3798                         if (ent->frame2 != 0 && t->anim_total[1])
3799                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3800                         else
3801                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3802                 }
3803                 texture->currentframe = t;
3804         }
3805
3806         // update currentskinframe to be a qw skin or animation frame
3807         if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
3808         {
3809                 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
3810                 {
3811                         strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
3812                         Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
3813                         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);
3814                 }
3815                 t->currentskinframe = r_qwskincache_skinframe[i];
3816                 if (t->currentskinframe == NULL)
3817                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3818         }
3819         else if (t->numskinframes >= 2)
3820                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3821         if (t->backgroundnumskinframes >= 2)
3822                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3823
3824         t->currentmaterialflags = t->basematerialflags;
3825         t->currentalpha = ent->alpha;
3826         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3827         {
3828                 t->currentalpha *= r_wateralpha.value;
3829                 // if rendering refraction/reflection, disable transparency
3830                 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
3831                         t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
3832         }
3833         if (!(ent->flags & RENDER_LIGHT))
3834                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3835         if (ent->effects & EF_ADDITIVE)
3836                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3837         else if (t->currentalpha < 1)
3838                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3839         if (ent->effects & EF_DOUBLESIDED)
3840                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3841         if (ent->effects & EF_NODEPTHTEST)
3842                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3843         if (ent->flags & RENDER_VIEWMODEL)
3844                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3845         if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3846                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3847         if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
3848                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_CUSTOMBLEND);
3849
3850         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
3851         {
3852                 matrix4x4_t matrix;
3853                 switch(tcmod->tcmod)
3854                 {
3855                 case Q3TCMOD_COUNT:
3856                 case Q3TCMOD_NONE:
3857                         if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3858                                 matrix = r_waterscrollmatrix;
3859                         else
3860                                 matrix = identitymatrix;
3861                         break;
3862                 case Q3TCMOD_ENTITYTRANSLATE:
3863                         // this is used in Q3 to allow the gamecode to control texcoord
3864                         // scrolling on the entity, which is not supported in darkplaces yet.
3865                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
3866                         break;
3867                 case Q3TCMOD_ROTATE:
3868                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
3869                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
3870                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
3871                         break;
3872                 case Q3TCMOD_SCALE:
3873                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
3874                         break;
3875                 case Q3TCMOD_SCROLL:
3876                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
3877                         break;
3878                 case Q3TCMOD_STRETCH:
3879                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
3880                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
3881                         break;
3882                 case Q3TCMOD_TRANSFORM:
3883                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
3884                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
3885                         VectorSet(tcmat +  6, 0                   , 0                , 1);
3886                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
3887                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
3888                         break;
3889                 case Q3TCMOD_TURBULENT:
3890                         // this is handled in the RSurf_PrepareVertices function
3891                         matrix = identitymatrix;
3892                         break;
3893                 }
3894                 // either replace or concatenate the transformation
3895                 if (i < 1)
3896                         t->currenttexmatrix = matrix;
3897                 else
3898                 {
3899                         matrix4x4_t temp = t->currenttexmatrix;
3900                         Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
3901                 }
3902         }
3903
3904         t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
3905         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3906         t->glosstexture = r_texture_black;
3907         t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
3908         t->backgroundglosstexture = r_texture_black;
3909         t->specularpower = r_shadow_glossexponent.value;
3910         // TODO: store reference values for these in the texture?
3911         t->specularscale = 0;
3912         if (r_shadow_gloss.integer > 0)
3913         {
3914                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
3915                 {
3916                         if (r_shadow_glossintensity.value > 0)
3917                         {
3918                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
3919                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
3920                                 t->specularscale = r_shadow_glossintensity.value;
3921                         }
3922                 }
3923                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
3924                 {
3925                         t->glosstexture = r_texture_white;
3926                         t->backgroundglosstexture = r_texture_white;
3927                         t->specularscale = r_shadow_gloss2intensity.value;
3928                 }
3929         }
3930
3931         // lightmaps mode looks bad with dlights using actual texturing, so turn
3932         // off the colormap and glossmap, but leave the normalmap on as it still
3933         // accurately represents the shading involved
3934         if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
3935         {
3936                 t->basetexture = r_texture_white;
3937                 t->specularscale = 0;
3938         }
3939
3940         t->currentpolygonfactor = r_refdef.polygonfactor + t->basepolygonfactor;
3941         t->currentpolygonoffset = r_refdef.polygonoffset + t->basepolygonoffset;
3942         // submodels are biased to avoid z-fighting with world surfaces that they
3943         // may be exactly overlapping (avoids z-fighting artifacts on certain
3944         // doors and things in Quake maps)
3945         if (ent->model->brush.submodel)
3946         {
3947                 t->currentpolygonfactor += r_polygonoffset_submodel_factor.value;
3948                 t->currentpolygonoffset += r_polygonoffset_submodel_offset.value;
3949         }
3950
3951         VectorClear(t->dlightcolor);
3952         t->currentnumlayers = 0;
3953         if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
3954         {
3955                 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
3956                 {
3957                         int blendfunc1, blendfunc2, depthmask;
3958                         if (t->currentmaterialflags & MATERIALFLAG_ADD)
3959                         {
3960                                 blendfunc1 = GL_SRC_ALPHA;
3961                                 blendfunc2 = GL_ONE;
3962                         }
3963                         else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
3964                         {
3965                                 blendfunc1 = GL_SRC_ALPHA;
3966                                 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
3967                         }
3968                         else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
3969                         {
3970                                 blendfunc1 = t->customblendfunc[0];
3971                                 blendfunc2 = t->customblendfunc[1];
3972                         }
3973                         else
3974                         {
3975                                 blendfunc1 = GL_ONE;
3976                                 blendfunc2 = GL_ZERO;
3977                         }
3978                         depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
3979                         if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
3980                         {
3981                                 rtexture_t *currentbasetexture;
3982                                 int layerflags = 0;
3983                                 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
3984                                         layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
3985                                 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3986                                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3987                                 {
3988                                         // fullbright is not affected by r_refdef.lightmapintensity
3989                                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
3990                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3991                                                 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);
3992                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3993                                                 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);
3994                                 }
3995                                 else
3996                                 {
3997                                         float colorscale;
3998                                         // set the color tint used for lights affecting this surface
3999                                         VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
4000                                         colorscale = 2;
4001                                         // q3bsp has no lightmap updates, so the lightstylevalue that
4002                                         // would normally be baked into the lightmap must be
4003                                         // applied to the color
4004                                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4005                                         if (ent->model->type == mod_brushq3)
4006                                                 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
4007                                         colorscale *= r_refdef.lightmapintensity;
4008                                         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);
4009                                         if (r_ambient.value >= (1.0f/64.0f))
4010                                                 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);
4011                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4012                                         {
4013                                                 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);
4014                                                 if (r_ambient.value >= (1.0f/64.0f))
4015                                                         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);
4016                                         }
4017                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4018                                         {
4019                                                 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);
4020                                                 if (r_ambient.value >= (1.0f/64.0f))
4021                                                         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);
4022                                         }
4023                                 }
4024                                 if (t->currentskinframe->glow != NULL)
4025                                         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);
4026                                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4027                                 {
4028                                         // if this is opaque use alpha blend which will darken the earlier
4029                                         // passes cheaply.
4030                                         //
4031                                         // if this is an alpha blended material, all the earlier passes
4032                                         // were darkened by fog already, so we only need to add the fog
4033                                         // color ontop through the fog mask texture
4034                                         //
4035                                         // if this is an additive blended material, all the earlier passes
4036                                         // were darkened by fog already, and we should not add fog color
4037                                         // (because the background was not darkened, there is no fog color
4038                                         // that was lost behind it).
4039                                         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);
4040                                 }
4041                         }
4042                 }
4043         }
4044 }
4045
4046 void R_UpdateAllTextureInfo(entity_render_t *ent)
4047 {
4048         int i;
4049         if (ent->model)
4050                 for (i = 0;i < ent->model->num_texturesperskin;i++)
4051                         R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4052 }
4053
4054 rsurfacestate_t rsurface;
4055
4056 void R_Mesh_ResizeArrays(int newvertices)
4057 {
4058         float *base;
4059         if (rsurface.array_size >= newvertices)
4060                 return;
4061         if (rsurface.array_modelvertex3f)
4062                 Mem_Free(rsurface.array_modelvertex3f);
4063         rsurface.array_size = (newvertices + 1023) & ~1023;
4064         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4065         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
4066         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
4067         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
4068         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
4069         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
4070         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4071         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4072         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
4073         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
4074         rsurface.array_color4f           = base + rsurface.array_size * 27;
4075         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4076 }
4077
4078 void RSurf_CleanUp(void)
4079 {
4080         CHECKGLERROR
4081         if (rsurface.mode == RSURFMODE_GLSL)
4082         {
4083                 qglUseProgramObjectARB(0);CHECKGLERROR
4084         }
4085         GL_AlphaTest(false);
4086         rsurface.mode = RSURFMODE_NONE;
4087         rsurface.uselightmaptexture = false;
4088         rsurface.texture = NULL;
4089 }
4090
4091 void RSurf_ActiveWorldEntity(void)
4092 {
4093         model_t *model = r_refdef.worldmodel;
4094         RSurf_CleanUp();
4095         if (rsurface.array_size < model->surfmesh.num_vertices)
4096                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4097         rsurface.matrix = identitymatrix;
4098         rsurface.inversematrix = identitymatrix;
4099         R_Mesh_Matrix(&identitymatrix);
4100         VectorCopy(r_view.origin, rsurface.modelorg);
4101         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4102         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4103         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4104         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4105         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4106         rsurface.frameblend[0].frame = 0;
4107         rsurface.frameblend[0].lerp = 1;
4108         rsurface.frameblend[1].frame = 0;
4109         rsurface.frameblend[1].lerp = 0;
4110         rsurface.frameblend[2].frame = 0;
4111         rsurface.frameblend[2].lerp = 0;
4112         rsurface.frameblend[3].frame = 0;
4113         rsurface.frameblend[3].lerp = 0;
4114         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
4115         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4116         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4117         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4118         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4119         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4120         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4121         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4122         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4123         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
4124         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4125         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4126         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
4127         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4128         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4129         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
4130         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4131         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4132         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
4133         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4134         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4135         rsurface.modelelement3i = model->surfmesh.data_element3i;
4136         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4137         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4138         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4139         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4140         rsurface.modelsurfaces = model->data_surfaces;
4141         rsurface.generatedvertex = false;
4142         rsurface.vertex3f  = rsurface.modelvertex3f;
4143         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4144         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4145         rsurface.svector3f = rsurface.modelsvector3f;
4146         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4147         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4148         rsurface.tvector3f = rsurface.modeltvector3f;
4149         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4150         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4151         rsurface.normal3f  = rsurface.modelnormal3f;
4152         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4153         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4154         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4155 }
4156
4157 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4158 {
4159         model_t *model = ent->model;
4160         RSurf_CleanUp();
4161         if (rsurface.array_size < model->surfmesh.num_vertices)
4162                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4163         rsurface.matrix = ent->matrix;
4164         rsurface.inversematrix = ent->inversematrix;
4165         R_Mesh_Matrix(&rsurface.matrix);
4166         Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
4167         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
4168         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4169         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4170         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4171         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4172         rsurface.frameblend[0] = ent->frameblend[0];
4173         rsurface.frameblend[1] = ent->frameblend[1];
4174         rsurface.frameblend[2] = ent->frameblend[2];
4175         rsurface.frameblend[3] = ent->frameblend[3];
4176         if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4177         {
4178                 if (wanttangents)
4179                 {
4180                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4181                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4182                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4183                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4184                         Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4185                 }
4186                 else if (wantnormals)
4187                 {
4188                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4189                         rsurface.modelsvector3f = NULL;
4190                         rsurface.modeltvector3f = NULL;
4191                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4192                         Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4193                 }
4194                 else
4195                 {
4196                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4197                         rsurface.modelsvector3f = NULL;
4198                         rsurface.modeltvector3f = NULL;
4199                         rsurface.modelnormal3f = NULL;
4200                         Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4201                 }
4202                 rsurface.modelvertex3f_bufferobject = 0;
4203                 rsurface.modelvertex3f_bufferoffset = 0;
4204                 rsurface.modelsvector3f_bufferobject = 0;
4205                 rsurface.modelsvector3f_bufferoffset = 0;
4206                 rsurface.modeltvector3f_bufferobject = 0;
4207                 rsurface.modeltvector3f_bufferoffset = 0;
4208                 rsurface.modelnormal3f_bufferobject = 0;
4209                 rsurface.modelnormal3f_bufferoffset = 0;
4210                 rsurface.generatedvertex = true;
4211         }
4212         else
4213         {
4214                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
4215                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4216                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4217                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4218                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4219                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4220                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4221                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4222                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4223                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
4224                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4225                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4226                 rsurface.generatedvertex = false;
4227         }
4228         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
4229         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4230         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4231         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
4232         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4233         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4234         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
4235         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4236         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4237         rsurface.modelelement3i = model->surfmesh.data_element3i;
4238         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4239         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4240         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4241         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4242         rsurface.modelsurfaces = model->data_surfaces;
4243         rsurface.vertex3f  = rsurface.modelvertex3f;
4244         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4245         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4246         rsurface.svector3f = rsurface.modelsvector3f;
4247         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4248         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4249         rsurface.tvector3f = rsurface.modeltvector3f;
4250         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4251         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4252         rsurface.normal3f  = rsurface.modelnormal3f;
4253         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4254         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4255         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4256 }
4257
4258 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4259 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4260 {
4261         int deformindex;
4262         int texturesurfaceindex;
4263         int i, j;
4264         float amplitude;
4265         float animpos;
4266         float scale;
4267         const float *v1, *in_tc;
4268         float *out_tc;
4269         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4270         float waveparms[4];
4271         q3shaderinfo_deform_t *deform;
4272         // 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
4273         if (rsurface.generatedvertex)
4274         {
4275                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4276                         generatenormals = true;
4277                 for (i = 0;i < Q3MAXDEFORMS;i++)
4278                 {
4279                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4280                         {
4281                                 generatetangents = true;
4282                                 generatenormals = true;
4283                         }
4284                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4285                                 generatenormals = true;
4286                 }
4287                 if (generatenormals && !rsurface.modelnormal3f)
4288                 {
4289                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4290                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4291                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4292                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4293                 }
4294                 if (generatetangents && !rsurface.modelsvector3f)
4295                 {
4296                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4297                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4298                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4299                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4300                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4301                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4302                         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);
4303                 }
4304         }
4305         rsurface.vertex3f  = rsurface.modelvertex3f;
4306         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4307         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4308         rsurface.svector3f = rsurface.modelsvector3f;
4309         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4310         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4311         rsurface.tvector3f = rsurface.modeltvector3f;
4312         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4313         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4314         rsurface.normal3f  = rsurface.modelnormal3f;
4315         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4316         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4317         // if vertices are deformed (sprite flares and things in maps, possibly
4318         // water waves, bulges and other deformations), generate them into
4319         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4320         // (may be static model data or generated data for an animated model, or
4321         //  the previous deform pass)
4322         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4323         {
4324                 switch (deform->deform)
4325                 {
4326                 default:
4327                 case Q3DEFORM_PROJECTIONSHADOW:
4328                 case Q3DEFORM_TEXT0:
4329                 case Q3DEFORM_TEXT1:
4330                 case Q3DEFORM_TEXT2:
4331                 case Q3DEFORM_TEXT3:
4332                 case Q3DEFORM_TEXT4:
4333                 case Q3DEFORM_TEXT5:
4334                 case Q3DEFORM_TEXT6:
4335                 case Q3DEFORM_TEXT7:
4336                 case Q3DEFORM_NONE:
4337                         break;
4338                 case Q3DEFORM_AUTOSPRITE:
4339                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4340                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4341                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4342                         VectorNormalize(newforward);
4343                         VectorNormalize(newright);
4344                         VectorNormalize(newup);
4345                         // make deformed versions of only the model vertices used by the specified surfaces
4346                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4347                         {
4348                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4349                                 // a single autosprite surface can contain multiple sprites...
4350                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
4351                                 {
4352                                         VectorClear(center);
4353                                         for (i = 0;i < 4;i++)
4354                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4355                                         VectorScale(center, 0.25f, center);
4356                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
4357                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4358                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4359                                         for (i = 0;i < 4;i++)
4360                                         {
4361                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4362                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4363                                         }
4364                                 }
4365                                 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);
4366                                 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);
4367                         }
4368                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
4369                         rsurface.vertex3f_bufferobject = 0;
4370                         rsurface.vertex3f_bufferoffset = 0;
4371                         rsurface.svector3f = rsurface.array_deformedsvector3f;
4372                         rsurface.svector3f_bufferobject = 0;
4373                         rsurface.svector3f_bufferoffset = 0;
4374                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
4375                         rsurface.tvector3f_bufferobject = 0;
4376                         rsurface.tvector3f_bufferoffset = 0;
4377                         rsurface.normal3f = rsurface.array_deformednormal3f;
4378                         rsurface.normal3f_bufferobject = 0;
4379                         rsurface.normal3f_bufferoffset = 0;
4380                         break;
4381                 case Q3DEFORM_AUTOSPRITE2:
4382                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4383                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4384                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4385                         VectorNormalize(newforward);
4386                         VectorNormalize(newright);
4387                         VectorNormalize(newup);
4388                         // make deformed versions of only the model vertices used by the specified surfaces
4389                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4390                         {
4391                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4392                                 const float *v1, *v2;
4393                                 vec3_t start, end;
4394                                 float f, l;
4395                                 struct
4396                                 {
4397                                         float length2;
4398                                         const float *v1;
4399                                         const float *v2;
4400                                 }
4401                                 shortest[2];
4402                                 memset(shortest, 0, sizeof(shortest));
4403                                 // a single autosprite surface can contain multiple sprites...
4404                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
4405                                 {
4406                                         VectorClear(center);
4407                                         for (i = 0;i < 4;i++)
4408                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4409                                         VectorScale(center, 0.25f, center);
4410                                         // find the two shortest edges, then use them to define the
4411                                         // axis vectors for rotating around the central axis
4412                                         for (i = 0;i < 6;i++)
4413                                         {
4414                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4415                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4416 #if 0
4417                                                 Debug_PolygonBegin(NULL, 0, false, 0);
4418                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4419                                                 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);
4420                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4421                                                 Debug_PolygonEnd();
4422 #endif
4423                                                 l = VectorDistance2(v1, v2);
4424                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4425                                                 if (v1[2] != v2[2])
4426                                                         l += (1.0f / 1024.0f);
4427                                                 if (shortest[0].length2 > l || i == 0)
4428                                                 {
4429                                                         shortest[1] = shortest[0];
4430                                                         shortest[0].length2 = l;
4431                                                         shortest[0].v1 = v1;
4432                                                         shortest[0].v2 = v2;
4433                                                 }
4434                                                 else if (shortest[1].length2 > l || i == 1)
4435                                                 {
4436                                                         shortest[1].length2 = l;
4437                                                         shortest[1].v1 = v1;
4438                                                         shortest[1].v2 = v2;
4439                                                 }
4440                                         }
4441                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4442                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4443 #if 0
4444                                         Debug_PolygonBegin(NULL, 0, false, 0);
4445                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4446                                         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);
4447                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4448                                         Debug_PolygonEnd();
4449 #endif
4450                                         // this calculates the right vector from the shortest edge
4451                                         // and the up vector from the edge midpoints
4452                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4453                                         VectorNormalize(right);
4454                                         VectorSubtract(end, start, up);
4455                                         VectorNormalize(up);
4456                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4457                                         //VectorSubtract(rsurface.modelorg, center, forward);
4458                                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
4459                                         VectorNegate(forward, forward);
4460                                         VectorReflect(forward, 0, up, forward);
4461                                         VectorNormalize(forward);
4462                                         CrossProduct(up, forward, newright);
4463                                         VectorNormalize(newright);
4464 #if 0
4465                                         Debug_PolygonBegin(NULL, 0, false, 0);
4466                                         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);
4467                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4468                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
4469                                         Debug_PolygonEnd();
4470 #endif
4471 #if 0
4472                                         Debug_PolygonBegin(NULL, 0, false, 0);
4473                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4474                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4475                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
4476                                         Debug_PolygonEnd();
4477 #endif
4478                                         // rotate the quad around the up axis vector, this is made
4479                                         // especially easy by the fact we know the quad is flat,
4480                                         // so we only have to subtract the center position and
4481                                         // measure distance along the right vector, and then
4482                                         // multiply that by the newright vector and add back the
4483                                         // center position
4484                                         // we also need to subtract the old position to undo the
4485                                         // displacement from the center, which we do with a
4486                                         // DotProduct, the subtraction/addition of center is also
4487                                         // optimized into DotProducts here
4488                                         l = DotProduct(right, center);
4489                                         for (i = 0;i < 4;i++)
4490                                         {
4491                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4492                                                 f = DotProduct(right, v1) - l;
4493                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4494                                         }
4495                                 }
4496                                 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);
4497                                 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);
4498                         }
4499                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
4500                         rsurface.vertex3f_bufferobject = 0;
4501                         rsurface.vertex3f_bufferoffset = 0;
4502                         rsurface.svector3f = rsurface.array_deformedsvector3f;
4503                         rsurface.svector3f_bufferobject = 0;
4504                         rsurface.svector3f_bufferoffset = 0;
4505                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
4506                         rsurface.tvector3f_bufferobject = 0;
4507                         rsurface.tvector3f_bufferoffset = 0;
4508                         rsurface.normal3f = rsurface.array_deformednormal3f;
4509                         rsurface.normal3f_bufferobject = 0;
4510                         rsurface.normal3f_bufferoffset = 0;
4511                         break;
4512                 case Q3DEFORM_NORMAL:
4513                         // deform the normals to make reflections wavey
4514                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4515                         {
4516                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4517                                 for (j = 0;j < surface->num_vertices;j++)
4518                                 {
4519                                         float vertex[3];
4520                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
4521                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4522                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
4523                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4524                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4525                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4526                                         VectorNormalize(normal);
4527                                 }
4528                                 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);
4529                         }
4530                         rsurface.svector3f = rsurface.array_deformedsvector3f;
4531                         rsurface.svector3f_bufferobject = 0;
4532                         rsurface.svector3f_bufferoffset = 0;
4533                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
4534                         rsurface.tvector3f_bufferobject = 0;
4535                         rsurface.tvector3f_bufferoffset = 0;
4536                         rsurface.normal3f = rsurface.array_deformednormal3f;
4537                         rsurface.normal3f_bufferobject = 0;
4538                         rsurface.normal3f_bufferoffset = 0;
4539                         break;
4540                 case Q3DEFORM_WAVE:
4541                         // deform vertex array to make wavey water and flags and such
4542                         waveparms[0] = deform->waveparms[0];
4543                         waveparms[1] = deform->waveparms[1];
4544                         waveparms[2] = deform->waveparms[2];
4545                         waveparms[3] = deform->waveparms[3];
4546                         // this is how a divisor of vertex influence on deformation
4547                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4548                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4549                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4550                         {
4551                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4552                                 for (j = 0;j < surface->num_vertices;j++)
4553                                 {
4554                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
4555                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
4556                                         // if the wavefunc depends on time, evaluate it per-vertex
4557                                         if (waveparms[3])
4558                                         {
4559                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4560                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4561                                         }
4562                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
4563                                 }
4564                         }
4565                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
4566                         rsurface.vertex3f_bufferobject = 0;
4567                         rsurface.vertex3f_bufferoffset = 0;
4568                         break;
4569                 case Q3DEFORM_BULGE:
4570                         // deform vertex array to make the surface have moving bulges
4571                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4572                         {
4573                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4574                                 for (j = 0;j < surface->num_vertices;j++)
4575                                 {
4576                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4577                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4578                                 }
4579                         }
4580                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
4581                         rsurface.vertex3f_bufferobject = 0;
4582                         rsurface.vertex3f_bufferoffset = 0;
4583                         break;
4584                 case Q3DEFORM_MOVE:
4585                         // deform vertex array
4586                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4587                         VectorScale(deform->parms, scale, waveparms);
4588                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4589                         {
4590                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4591                                 for (j = 0;j < surface->num_vertices;j++)
4592                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4593                         }
4594                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
4595                         rsurface.vertex3f_bufferobject = 0;
4596                         rsurface.vertex3f_bufferoffset = 0;
4597                         break;
4598                 }
4599         }
4600         // generate texcoords based on the chosen texcoord source
4601         switch(rsurface.texture->tcgen.tcgen)
4602         {
4603         default:
4604         case Q3TCGEN_TEXTURE:
4605                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
4606                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
4607                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
4608                 break;
4609         case Q3TCGEN_LIGHTMAP:
4610                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
4611                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
4612                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
4613                 break;
4614         case Q3TCGEN_VECTOR:
4615                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4616                 {
4617                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4618                         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)
4619                         {
4620                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4621                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4622                         }
4623                 }
4624                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
4625                 rsurface.texcoordtexture2f_bufferobject  = 0;
4626                 rsurface.texcoordtexture2f_bufferoffset  = 0;
4627                 break;
4628         case Q3TCGEN_ENVIRONMENT:
4629                 // make environment reflections using a spheremap
4630                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4631                 {
4632                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4633                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4634                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4635                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4636                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4637                         {
4638                                 float l, d, eyedir[3];
4639                                 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4640                                 l = 0.5f / VectorLength(eyedir);
4641                                 d = DotProduct(normal, eyedir)*2;
4642                                 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4643                                 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4644                         }
4645                 }
4646                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
4647                 rsurface.texcoordtexture2f_bufferobject  = 0;
4648                 rsurface.texcoordtexture2f_bufferoffset  = 0;
4649                 break;
4650         }
4651         // the only tcmod that needs software vertex processing is turbulent, so
4652         // check for it here and apply the changes if needed
4653         // and we only support that as the first one
4654         // (handling a mixture of turbulent and other tcmods would be problematic
4655         //  without punting it entirely to a software path)
4656         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4657         {
4658                 amplitude = rsurface.texture->tcmods[0].parms[1];
4659                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4660                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4661                 {
4662                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4663                         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)
4664                         {
4665                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4666                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4667                         }
4668                 }
4669                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
4670                 rsurface.texcoordtexture2f_bufferobject  = 0;
4671                 rsurface.texcoordtexture2f_bufferoffset  = 0;
4672         }
4673         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
4674         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4675         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4676         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4677 }
4678
4679 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4680 {
4681         int i, j;
4682         const msurface_t *surface = texturesurfacelist[0];
4683         const msurface_t *surface2;
4684         int firstvertex;
4685         int endvertex;
4686         int numvertices;
4687         int numtriangles;
4688         // TODO: lock all array ranges before render, rather than on each surface
4689         if (texturenumsurfaces == 1)
4690         {
4691                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4692                 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));
4693         }
4694         else if (r_batchmode.integer == 2)
4695         {
4696                 #define MAXBATCHTRIANGLES 4096
4697                 int batchtriangles = 0;
4698                 int batchelements[MAXBATCHTRIANGLES*3];
4699                 for (i = 0;i < texturenumsurfaces;i = j)
4700                 {
4701                         surface = texturesurfacelist[i];
4702                         j = i + 1;
4703                         if (surface->num_triangles > MAXBATCHTRIANGLES)
4704                         {
4705                                 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));
4706                                 continue;
4707                         }
4708                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4709                         batchtriangles = surface->num_triangles;
4710                         firstvertex = surface->num_firstvertex;
4711                         endvertex = surface->num_firstvertex + surface->num_vertices;
4712                         for (;j < texturenumsurfaces;j++)
4713                         {
4714                                 surface2 = texturesurfacelist[j];
4715                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4716                                         break;
4717                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4718                                 batchtriangles += surface2->num_triangles;
4719                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
4720                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4721                         }
4722                         surface2 = texturesurfacelist[j-1];
4723                         numvertices = endvertex - firstvertex;
4724                         R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4725                 }
4726         }
4727         else if (r_batchmode.integer == 1)
4728         {
4729                 for (i = 0;i < texturenumsurfaces;i = j)
4730                 {
4731                         surface = texturesurfacelist[i];
4732                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4733                                 if (texturesurfacelist[j] != surface2)
4734                                         break;
4735                         surface2 = texturesurfacelist[j-1];
4736                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4737                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4738                         GL_LockArrays(surface->num_firstvertex, numvertices);
4739                         R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4740                 }
4741         }
4742         else
4743         {
4744                 for (i = 0;i < texturenumsurfaces;i++)
4745                 {
4746                         surface = texturesurfacelist[i];
4747                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4748                         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));
4749                 }
4750         }
4751 }
4752
4753 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
4754 {
4755         int i, planeindex, vertexindex;
4756         float d, bestd;
4757         vec3_t vert;
4758         const float *v;
4759         r_waterstate_waterplane_t *p, *bestp;
4760         msurface_t *surface;
4761         if (r_waterstate.renderingscene)
4762                 return;
4763         for (i = 0;i < texturenumsurfaces;i++)
4764         {
4765                 surface = texturesurfacelist[i];
4766                 if (lightmaptexunit >= 0)
4767                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4768                 if (deluxemaptexunit >= 0)
4769                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4770                 // pick the closest matching water plane
4771                 bestd = 0;
4772                 bestp = NULL;
4773                 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4774                 {
4775                         d = 0;
4776                         for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
4777                         {
4778                                 Matrix4x4_Transform(&rsurface.matrix, v, vert);
4779                                 d += fabs(PlaneDiff(vert, &p->plane));
4780                         }
4781                         if (bestd > d || !bestp)
4782                         {
4783                                 bestd = d;
4784                                 bestp = p;
4785                         }
4786                 }
4787                 if (bestp)
4788                 {
4789                         if (refractiontexunit >= 0)
4790                                 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
4791                         if (reflectiontexunit >= 0)
4792                                 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
4793                 }
4794                 else
4795                 {
4796                         if (refractiontexunit >= 0)
4797                                 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
4798                         if (reflectiontexunit >= 0)
4799                                 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
4800                 }
4801                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4802                 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));
4803         }
4804 }
4805
4806 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
4807 {
4808         int i;
4809         int j;
4810         const msurface_t *surface = texturesurfacelist[0];
4811         const msurface_t *surface2;
4812         int firstvertex;
4813         int endvertex;
4814         int numvertices;
4815         int numtriangles;
4816         // TODO: lock all array ranges before render, rather than on each surface
4817         if (texturenumsurfaces == 1)
4818         {
4819                 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4820                 if (deluxemaptexunit >= 0)
4821                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4822                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4823                 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));
4824         }
4825         else if (r_batchmode.integer == 2)
4826         {
4827                 #define MAXBATCHTRIANGLES 4096
4828                 int batchtriangles = 0;
4829                 int batchelements[MAXBATCHTRIANGLES*3];
4830                 for (i = 0;i < texturenumsurfaces;i = j)
4831                 {
4832                         surface = texturesurfacelist[i];
4833                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4834                         if (deluxemaptexunit >= 0)
4835                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4836                         j = i + 1;
4837                         if (surface->num_triangles > MAXBATCHTRIANGLES)
4838                         {
4839                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4840                                 continue;
4841                         }
4842                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4843                         batchtriangles = surface->num_triangles;
4844                         firstvertex = surface->num_firstvertex;
4845                         endvertex = surface->num_firstvertex + surface->num_vertices;
4846                         for (;j < texturenumsurfaces;j++)
4847                         {
4848                                 surface2 = texturesurfacelist[j];
4849                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4850                                         break;
4851                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4852                                 batchtriangles += surface2->num_triangles;
4853                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
4854                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4855                         }
4856                         surface2 = texturesurfacelist[j-1];
4857                         numvertices = endvertex - firstvertex;
4858                         R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4859                 }
4860         }
4861         else if (r_batchmode.integer == 1)
4862         {
4863 #if 0
4864                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
4865                 for (i = 0;i < texturenumsurfaces;i = j)
4866                 {
4867                         surface = texturesurfacelist[i];
4868                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4869                                 if (texturesurfacelist[j] != surface2)
4870                                         break;
4871                         Con_Printf(" %i", j - i);
4872                 }
4873                 Con_Printf("\n");
4874                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
4875 #endif
4876                 for (i = 0;i < texturenumsurfaces;i = j)
4877                 {
4878                         surface = texturesurfacelist[i];
4879                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4880                         if (deluxemaptexunit >= 0)
4881                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4882                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4883                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
4884                                         break;
4885 #if 0
4886                         Con_Printf(" %i", j - i);
4887 #endif
4888                         surface2 = texturesurfacelist[j-1];
4889                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4890                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4891                         GL_LockArrays(surface->num_firstvertex, numvertices);
4892                         R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4893                 }
4894 #if 0
4895                 Con_Printf("\n");
4896 #endif
4897         }
4898         else
4899         {
4900                 for (i = 0;i < texturenumsurfaces;i++)
4901                 {
4902                         surface = texturesurfacelist[i];
4903                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4904                         if (deluxemaptexunit >= 0)
4905                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4906                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4907                         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));
4908                 }
4909         }
4910 }
4911
4912 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
4913 {
4914         int j;
4915         int texturesurfaceindex;
4916         if (r_showsurfaces.integer == 2)
4917         {
4918                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4919                 {
4920                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4921                         for (j = 0;j < surface->num_triangles;j++)
4922                         {
4923                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
4924                                 GL_Color(f, f, f, 1);
4925                                 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)));
4926                         }
4927                 }
4928         }
4929         else
4930         {
4931                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4932                 {
4933                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4934                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
4935                         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);
4936                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4937                         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));
4938                 }
4939         }
4940 }
4941
4942 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
4943 {
4944         int texturesurfaceindex;
4945         int i;
4946         float f;
4947         float *v, *c, *c2;
4948         if (rsurface.lightmapcolor4f)
4949         {
4950                 // generate color arrays for the surfaces in this list
4951                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4952                 {
4953                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4954                         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)
4955                         {
4956                                 f = FogPoint_Model(v);
4957                                 c2[0] = c[0] * f;
4958                                 c2[1] = c[1] * f;
4959                                 c2[2] = c[2] * f;
4960                                 c2[3] = c[3];
4961                         }
4962                 }
4963         }
4964         else
4965         {
4966                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4967                 {
4968                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4969                         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)
4970                         {
4971                                 f = FogPoint_Model(v);
4972                                 c2[0] = f;
4973                                 c2[1] = f;
4974                                 c2[2] = f;
4975                                 c2[3] = 1;
4976                         }
4977                 }
4978         }
4979         rsurface.lightmapcolor4f = rsurface.array_color4f;
4980         rsurface.lightmapcolor4f_bufferobject = 0;
4981         rsurface.lightmapcolor4f_bufferoffset = 0;
4982 }
4983
4984 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
4985 {
4986         int texturesurfaceindex;
4987         int i;
4988         float *c, *c2;
4989         if (!rsurface.lightmapcolor4f)
4990                 return;
4991         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4992         {
4993                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4994                 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)
4995                 {
4996                         c2[0] = c[0] * r;
4997                         c2[1] = c[1] * g;
4998                         c2[2] = c[2] * b;
4999                         c2[3] = c[3] * a;
5000                 }
5001         }
5002         rsurface.lightmapcolor4f = rsurface.array_color4f;
5003         rsurface.lightmapcolor4f_bufferobject = 0;
5004         rsurface.lightmapcolor4f_bufferoffset = 0;
5005 }
5006
5007 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5008 {
5009         // TODO: optimize
5010         rsurface.lightmapcolor4f = NULL;
5011         rsurface.lightmapcolor4f_bufferobject = 0;
5012         rsurface.lightmapcolor4f_bufferoffset = 0;
5013         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5014         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5015         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5016         GL_Color(r, g, b, a);
5017         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5018 }
5019
5020 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5021 {
5022         // TODO: optimize applyfog && applycolor case
5023         // just apply fog if necessary, and tint the fog color array if necessary
5024         rsurface.lightmapcolor4f = NULL;
5025         rsurface.lightmapcolor4f_bufferobject = 0;
5026         rsurface.lightmapcolor4f_bufferoffset = 0;
5027         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5028         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5029         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5030         GL_Color(r, g, b, a);
5031         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5032 }
5033
5034 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5035 {
5036         int texturesurfaceindex;
5037         int i;
5038         float *c;
5039         // TODO: optimize
5040         if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5041         {
5042                 // generate color arrays for the surfaces in this list
5043                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5044                 {
5045                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5046                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5047                         {
5048                                 if (surface->lightmapinfo->samples)
5049                                 {
5050                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5051                                         float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5052                                         VectorScale(lm, scale, c);
5053                                         if (surface->lightmapinfo->styles[1] != 255)
5054                                         {
5055                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5056                                                 lm += size3;
5057                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5058                                                 VectorMA(c, scale, lm, c);
5059                                                 if (surface->lightmapinfo->styles[2] != 255)
5060                                                 {
5061                                                         lm += size3;
5062                                                         scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5063                                                         VectorMA(c, scale, lm, c);
5064                                                         if (surface->lightmapinfo->styles[3] != 255)
5065                                                         {
5066                                                                 lm += size3;
5067                                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5068                                                                 VectorMA(c, scale, lm, c);
5069                                                         }
5070                                                 }
5071                                         }
5072                                 }
5073                                 else
5074                                         VectorClear(c);
5075                                 c[3] = 1;
5076                         }
5077                 }
5078                 rsurface.lightmapcolor4f = rsurface.array_color4f;
5079                 rsurface.lightmapcolor4f_bufferobject = 0;
5080                 rsurface.lightmapcolor4f_bufferoffset = 0;
5081         }
5082         else
5083         {
5084                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5085                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5086                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5087         }
5088         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5089         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5090         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5091         GL_Color(r, g, b, a);
5092         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5093 }
5094
5095 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5096 {
5097         int texturesurfaceindex;
5098         int i;
5099         float f;
5100         float *v, *c, *c2;
5101         vec3_t ambientcolor;
5102         vec3_t diffusecolor;
5103         vec3_t lightdir;
5104         // TODO: optimize
5105         // model lighting
5106         VectorCopy(rsurface.modellight_lightdir, lightdir);
5107         ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f;
5108         ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f;
5109         ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f;
5110         diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f;
5111         diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f;
5112         diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f;
5113         if (VectorLength2(diffusecolor) > 0)
5114         {
5115                 // generate color arrays for the surfaces in this list
5116                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5117                 {
5118                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5119                         int numverts = surface->num_vertices;
5120                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5121                         c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5122                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5123                         // q3-style directional shading
5124                         for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5125                         {
5126                                 if ((f = DotProduct(c2, lightdir)) > 0)
5127                                         VectorMA(ambientcolor, f, diffusecolor, c);
5128                                 else
5129                                         VectorCopy(ambientcolor, c);
5130                                 c[3] = a;
5131                         }
5132                 }
5133                 r = 1;
5134                 g = 1;
5135                 b = 1;
5136                 a = 1;
5137                 applycolor = false;
5138                 rsurface.lightmapcolor4f = rsurface.array_color4f;
5139                 rsurface.lightmapcolor4f_bufferobject = 0;
5140                 rsurface.lightmapcolor4f_bufferoffset = 0;
5141         }
5142         else
5143         {
5144                 r = ambientcolor[0];
5145                 g = ambientcolor[1];
5146                 b = ambientcolor[2];
5147                 rsurface.lightmapcolor4f = NULL;
5148                 rsurface.lightmapcolor4f_bufferobject = 0;
5149                 rsurface.lightmapcolor4f_bufferoffset = 0;
5150         }
5151         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5152         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5153         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5154         GL_Color(r, g, b, a);
5155         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5156 }
5157
5158 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5159 {
5160         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5161         GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5162         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5163         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5164         if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5165         {
5166                 rsurface.mode = RSURFMODE_SHOWSURFACES;
5167                 GL_DepthMask(true);
5168                 GL_BlendFunc(GL_ONE, GL_ZERO);
5169                 R_Mesh_ColorPointer(NULL, 0, 0);
5170                 R_Mesh_ResetTextureState();
5171         }
5172         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5173         RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5174 }
5175
5176 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5177 {
5178         // transparent sky would be ridiculous
5179         if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5180                 return;
5181         if (rsurface.mode != RSURFMODE_SKY)
5182         {
5183                 if (rsurface.mode == RSURFMODE_GLSL)
5184                 {
5185                         qglUseProgramObjectARB(0);CHECKGLERROR
5186                 }
5187                 rsurface.mode = RSURFMODE_SKY;
5188         }
5189         if (skyrendernow)
5190         {
5191                 skyrendernow = false;
5192                 R_Sky();
5193                 // restore entity matrix
5194                 R_Mesh_Matrix(&rsurface.matrix);
5195         }
5196         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5197         GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5198         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5199         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5200         GL_DepthMask(true);
5201         // LordHavoc: HalfLife maps have freaky skypolys so don't use
5202         // skymasking on them, and Quake3 never did sky masking (unlike
5203         // software Quake and software Quake2), so disable the sky masking
5204         // in Quake3 maps as it causes problems with q3map2 sky tricks,
5205         // and skymasking also looks very bad when noclipping outside the
5206         // level, so don't use it then either.
5207         if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
5208         {
5209                 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
5210                 R_Mesh_ColorPointer(NULL, 0, 0);
5211                 R_Mesh_ResetTextureState();
5212                 if (skyrendermasked)
5213                 {
5214                         // depth-only (masking)
5215                         GL_ColorMask(0,0,0,0);
5216                         // just to make sure that braindead drivers don't draw
5217                         // anything despite that colormask...
5218                         GL_BlendFunc(GL_ZERO, GL_ONE);
5219                 }
5220                 else
5221                 {
5222                         // fog sky
5223                         GL_BlendFunc(GL_ONE, GL_ZERO);
5224                 }
5225                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5226                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5227                 if (skyrendermasked)
5228                         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5229         }
5230 }
5231
5232 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5233 {
5234         if (rsurface.mode != RSURFMODE_GLSL)
5235         {
5236                 rsurface.mode = RSURFMODE_GLSL;
5237                 R_Mesh_ResetTextureState();
5238         }
5239
5240         R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale);
5241         if (!r_glsl_permutation)
5242                 return;
5243
5244         if (rsurface.lightmode == 2)
5245                 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5246         else
5247                 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5248         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5249         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5250         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5251         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5252         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5253
5254         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]);
5255         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5256         {
5257                 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5258                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5259                         R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5260                 R_Mesh_ColorPointer(NULL, 0, 0);
5261         }
5262         else if (rsurface.uselightmaptexture)
5263         {
5264                 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5265                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5266                         R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5267                 R_Mesh_ColorPointer(NULL, 0, 0);
5268         }
5269         else
5270         {
5271                 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5272                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5273                         R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5274                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5275         }
5276
5277         if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5278         {
5279                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5280                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1, 11, 12);
5281                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5282                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1, -1, 12);
5283                 else
5284                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5285         }
5286         else
5287         {
5288                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5289                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, 11, 12);
5290                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5291                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, -1, 12);
5292                 else
5293                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5294         }
5295         if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5296         {
5297         }
5298 }
5299
5300 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5301 {
5302         // OpenGL 1.3 path - anything not completely ancient
5303         int texturesurfaceindex;
5304         qboolean applycolor;
5305         qboolean applyfog;
5306         rmeshstate_t m;
5307         int layerindex;
5308         const texturelayer_t *layer;
5309         if (rsurface.mode != RSURFMODE_MULTIPASS)
5310                 rsurface.mode = RSURFMODE_MULTIPASS;
5311         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5312         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5313         {
5314                 vec4_t layercolor;
5315                 int layertexrgbscale;
5316                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5317                 {
5318                         if (layerindex == 0)
5319                                 GL_AlphaTest(true);
5320                         else
5321                         {
5322                                 GL_AlphaTest(false);
5323                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5324                         }
5325                 }
5326                 GL_DepthMask(layer->depthmask);
5327                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5328                 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
5329                 {
5330                         layertexrgbscale = 4;
5331                         VectorScale(layer->color, 0.25f, layercolor);
5332                 }
5333                 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
5334                 {
5335                         layertexrgbscale = 2;
5336                         VectorScale(layer->color, 0.5f, layercolor);
5337                 }
5338                 else
5339                 {
5340                         layertexrgbscale = 1;
5341                         VectorScale(layer->color, 1.0f, layercolor);
5342                 }
5343                 layercolor[3] = layer->color[3];
5344                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5345                 R_Mesh_ColorPointer(NULL, 0, 0);
5346                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5347                 switch (layer->type)
5348                 {
5349                 case TEXTURELAYERTYPE_LITTEXTURE:
5350                         memset(&m, 0, sizeof(m));
5351                         m.tex[0] = R_GetTexture(r_texture_white);
5352                         m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5353                         m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5354                         m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5355                         m.tex[1] = R_GetTexture(layer->texture);
5356                         m.texmatrix[1] = layer->texmatrix;
5357                         m.texrgbscale[1] = layertexrgbscale;
5358                         m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5359                         m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5360                         m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5361                         R_Mesh_TextureState(&m);
5362                         if (rsurface.lightmode == 2)
5363                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5364                         else if (rsurface.uselightmaptexture)
5365                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5366                         else
5367                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5368                         break;
5369                 case TEXTURELAYERTYPE_TEXTURE:
5370                         memset(&m, 0, sizeof(m));
5371                         m.tex[0] = R_GetTexture(layer->texture);
5372                         m.texmatrix[0] = layer->texmatrix;
5373                         m.texrgbscale[0] = layertexrgbscale;
5374                         m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5375                         m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5376                         m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5377                         R_Mesh_TextureState(&m);
5378                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5379                         break;
5380                 case TEXTURELAYERTYPE_FOG:
5381                         memset(&m, 0, sizeof(m));
5382                         m.texrgbscale[0] = layertexrgbscale;
5383                         if (layer->texture)
5384                         {
5385                                 m.tex[0] = R_GetTexture(layer->texture);
5386                                 m.texmatrix[0] = layer->texmatrix;
5387                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5388                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5389                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5390                         }
5391                         R_Mesh_TextureState(&m);
5392                         // generate a color array for the fog pass
5393                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5394                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5395                         {
5396                                 int i;
5397                                 float f, *v, *c;
5398                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5399                                 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)
5400                                 {
5401                                         f = 1 - FogPoint_Model(v);
5402                                         c[0] = layercolor[0];
5403                                         c[1] = layercolor[1];
5404                                         c[2] = layercolor[2];
5405                                         c[3] = f * layercolor[3];
5406                                 }
5407                         }
5408                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5409                         break;
5410                 default:
5411                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5412                 }
5413                 GL_LockArrays(0, 0);
5414         }
5415         CHECKGLERROR
5416         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5417         {
5418                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5419                 GL_AlphaTest(false);
5420         }
5421 }
5422
5423 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5424 {
5425         // OpenGL 1.1 - crusty old voodoo path
5426         int texturesurfaceindex;
5427         qboolean applyfog;
5428         rmeshstate_t m;
5429         int layerindex;
5430         const texturelayer_t *layer;
5431         if (rsurface.mode != RSURFMODE_MULTIPASS)
5432                 rsurface.mode = RSURFMODE_MULTIPASS;
5433         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5434         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5435         {
5436                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5437                 {
5438                         if (layerindex == 0)
5439                                 GL_AlphaTest(true);
5440                         else
5441                         {
5442                                 GL_AlphaTest(false);
5443                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5444                         }
5445                 }
5446                 GL_DepthMask(layer->depthmask);
5447                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5448                 R_Mesh_ColorPointer(NULL, 0, 0);
5449                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5450                 switch (layer->type)
5451                 {
5452                 case TEXTURELAYERTYPE_LITTEXTURE:
5453                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5454                         {
5455                                 // two-pass lit texture with 2x rgbscale
5456                                 // first the lightmap pass
5457                                 memset(&m, 0, sizeof(m));
5458                                 m.tex[0] = R_GetTexture(r_texture_white);
5459                                 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5460                                 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5461                                 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5462                                 R_Mesh_TextureState(&m);
5463                                 if (rsurface.lightmode == 2)
5464                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5465                                 else if (rsurface.uselightmaptexture)
5466                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5467                                 else
5468                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5469                                 GL_LockArrays(0, 0);
5470                                 // then apply the texture to it
5471                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5472                                 memset(&m, 0, sizeof(m));
5473                                 m.tex[0] = R_GetTexture(layer->texture);
5474                                 m.texmatrix[0] = layer->texmatrix;
5475                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5476                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5477                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5478                                 R_Mesh_TextureState(&m);
5479                                 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);
5480                         }
5481                         else
5482                         {
5483                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5484                                 memset(&m, 0, sizeof(m));
5485                                 m.tex[0] = R_GetTexture(layer->texture);
5486                                 m.texmatrix[0] = layer->texmatrix;
5487                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5488                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5489                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5490                                 R_Mesh_TextureState(&m);
5491                                 if (rsurface.lightmode == 2)
5492                                         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);
5493                                 else
5494                                         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);
5495                         }
5496                         break;
5497                 case TEXTURELAYERTYPE_TEXTURE:
5498                         // singletexture unlit texture with transparency support
5499                         memset(&m, 0, sizeof(m));
5500                         m.tex[0] = R_GetTexture(layer->texture);
5501                         m.texmatrix[0] = layer->texmatrix;
5502                         m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5503                         m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5504                         m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5505                         R_Mesh_TextureState(&m);
5506                         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);
5507                         break;
5508                 case TEXTURELAYERTYPE_FOG:
5509                         // singletexture fogging
5510                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5511                         if (layer->texture)
5512                         {
5513                                 memset(&m, 0, sizeof(m));
5514                                 m.tex[0] = R_GetTexture(layer->texture);
5515                                 m.texmatrix[0] = layer->texmatrix;
5516                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5517                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5518                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5519                                 R_Mesh_TextureState(&m);
5520                         }
5521                         else
5522                                 R_Mesh_ResetTextureState();
5523                         // generate a color array for the fog pass
5524                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5525                         {
5526                                 int i;
5527                                 float f, *v, *c;
5528                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5529                                 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)
5530                                 {
5531                                         f = 1 - FogPoint_Model(v);
5532                                         c[0] = layer->color[0];
5533                                         c[1] = layer->color[1];
5534                                         c[2] = layer->color[2];
5535                                         c[3] = f * layer->color[3];
5536                                 }
5537                         }
5538                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5539                         break;
5540                 default:
5541                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5542                 }
5543                 GL_LockArrays(0, 0);
5544         }
5545         CHECKGLERROR
5546         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5547         {
5548                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5549                 GL_AlphaTest(false);
5550         }
5551 }
5552
5553 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5554 {
5555         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5556                 return;
5557         rsurface.rtlight = NULL;
5558         CHECKGLERROR
5559         if (depthonly)
5560         {
5561                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5562                         return;
5563                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5564                         return;
5565                 if (rsurface.mode != RSURFMODE_MULTIPASS)
5566                         rsurface.mode = RSURFMODE_MULTIPASS;
5567                 if (r_depthfirst.integer == 3)
5568                 {
5569                         int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5570                         if (!r_view.showdebug)
5571                                 GL_Color(0, 0, 0, 1);
5572                         else
5573                                 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5574                 }
5575                 else
5576                 {
5577                         GL_ColorMask(0,0,0,0);
5578                         GL_Color(1,1,1,1);
5579                 }
5580                 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5581                 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5582                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5583                 GL_DepthTest(true);
5584                 GL_BlendFunc(GL_ONE, GL_ZERO);
5585                 GL_DepthMask(true);
5586                 GL_AlphaTest(false);
5587                 R_Mesh_ColorPointer(NULL, 0, 0);
5588                 R_Mesh_ResetTextureState();
5589                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5590                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5591                 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5592                 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5593         }
5594         else if (r_depthfirst.integer == 3)
5595                 return;
5596         else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5597         {
5598                 GL_Color(0, 0, 0, 1);
5599                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5600         }
5601         else if (r_showsurfaces.integer)
5602         {
5603                 if (rsurface.mode != RSURFMODE_MULTIPASS)
5604                         rsurface.mode = RSURFMODE_MULTIPASS;
5605                 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5606                 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5607                 GL_DepthTest(true);
5608                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5609                 GL_BlendFunc(GL_ONE, GL_ZERO);
5610                 GL_DepthMask(writedepth);
5611                 GL_Color(1,1,1,1);
5612                 GL_AlphaTest(false);
5613                 R_Mesh_ColorPointer(NULL, 0, 0);
5614                 R_Mesh_ResetTextureState();
5615                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5616                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5617                 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5618         }
5619         else if (gl_lightmaps.integer)
5620         {
5621                 rmeshstate_t m;
5622                 if (rsurface.mode != RSURFMODE_MULTIPASS)
5623                         rsurface.mode = RSURFMODE_MULTIPASS;
5624                 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5625                 GL_DepthTest(true);
5626                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5627                 GL_BlendFunc(GL_ONE, GL_ZERO);
5628                 GL_DepthMask(writedepth);
5629                 GL_Color(1,1,1,1);
5630                 GL_AlphaTest(false);
5631                 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5632                 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5633                 R_Mesh_ColorPointer(NULL, 0, 0);
5634                 memset(&m, 0, sizeof(m));
5635                 m.tex[0] = R_GetTexture(r_texture_white);
5636                 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5637                 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5638                 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5639                 R_Mesh_TextureState(&m);
5640                 RSurf_PrepareVerticesForBatch(rsurface.lightmode == 2, false, texturenumsurfaces, texturesurfacelist);
5641                 if (rsurface.lightmode == 2)
5642                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5643                 else if (rsurface.uselightmaptexture)
5644                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5645                 else
5646                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5647                 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5648         }
5649         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5650         {
5651                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5652                 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5653         }
5654         else if (rsurface.texture->currentnumlayers)
5655         {
5656                 // write depth for anything we skipped on the depth-only pass earlier
5657                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5658                         writedepth = true;
5659                 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5660                 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5661                 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5662                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5663                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5664                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5665                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5666                 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5667                 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5668                 if (r_glsl.integer && gl_support_fragment_shader)
5669                         R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
5670                 else if (gl_combine.integer && r_textureunits.integer >= 2)
5671                         R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
5672                 else
5673                         R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
5674                 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5675         }
5676         CHECKGLERROR
5677         GL_LockArrays(0, 0);
5678 }
5679
5680 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5681 {
5682         int i, j;
5683         int texturenumsurfaces, endsurface;
5684         texture_t *texture;
5685         msurface_t *surface;
5686         msurface_t *texturesurfacelist[1024];
5687
5688         // if the model is static it doesn't matter what value we give for
5689         // wantnormals and wanttangents, so this logic uses only rules applicable
5690         // to a model, knowing that they are meaningless otherwise
5691         if (ent == r_refdef.worldentity)
5692                 RSurf_ActiveWorldEntity();
5693         else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5694                 RSurf_ActiveModelEntity(ent, false, false);
5695         else
5696                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
5697
5698         for (i = 0;i < numsurfaces;i = j)
5699         {
5700                 j = i + 1;
5701                 surface = rsurface.modelsurfaces + surfacelist[i];
5702                 texture = surface->texture;
5703                 R_UpdateTextureInfo(ent, texture);
5704                 rsurface.texture = texture->currentframe;
5705                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
5706                 // scan ahead until we find a different texture
5707                 endsurface = min(i + 1024, numsurfaces);
5708                 texturenumsurfaces = 0;
5709                 texturesurfacelist[texturenumsurfaces++] = surface;
5710                 for (;j < endsurface;j++)
5711                 {
5712                         surface = rsurface.modelsurfaces + surfacelist[j];
5713                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
5714                                 break;
5715                         texturesurfacelist[texturenumsurfaces++] = surface;
5716                 }
5717                 // render the range of surfaces
5718                 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
5719         }
5720
5721         RSurf_CleanUp();
5722 }
5723
5724 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
5725 {
5726         int i, j;
5727         vec3_t tempcenter, center;
5728         texture_t *texture;
5729         // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
5730         if (addwaterplanes)
5731         {
5732                 for (i = 0;i < numsurfaces;i++)
5733                         if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5734                                 R_Water_AddWaterPlane(surfacelist[i]);
5735                 return;
5736         }
5737         // break the surface list down into batches by texture and use of lightmapping
5738         for (i = 0;i < numsurfaces;i = j)
5739         {
5740                 j = i + 1;
5741                 // texture is the base texture pointer, rsurface.texture is the
5742                 // current frame/skin the texture is directing us to use (for example
5743                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
5744                 // use skin 1 instead)
5745                 texture = surfacelist[i]->texture;
5746                 rsurface.texture = texture->currentframe;
5747                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
5748                 if (!(rsurface.texture->currentmaterialflags & flagsmask))
5749                 {
5750                         // if this texture is not the kind we want, skip ahead to the next one
5751                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
5752                                 ;
5753                         continue;
5754                 }
5755                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5756                 {
5757                         // transparent surfaces get pushed off into the transparent queue
5758                         const msurface_t *surface = surfacelist[i];
5759                         if (depthonly)
5760                                 continue;
5761                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
5762                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
5763                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
5764                         Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
5765                         R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
5766                 }
5767                 else
5768                 {
5769                         // simply scan ahead until we find a different texture or lightmap state
5770                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
5771                                 ;
5772                         // render the range of surfaces
5773                         R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
5774                 }
5775         }
5776 }
5777
5778 float locboxvertex3f[6*4*3] =
5779 {
5780         1,0,1, 1,0,0, 1,1,0, 1,1,1,
5781         0,1,1, 0,1,0, 0,0,0, 0,0,1,
5782         1,1,1, 1,1,0, 0,1,0, 0,1,1,
5783         0,0,1, 0,0,0, 1,0,0, 1,0,1,
5784         0,0,1, 1,0,1, 1,1,1, 0,1,1,
5785         1,0,0, 0,0,0, 0,1,0, 1,1,0
5786 };
5787
5788 int locboxelement3i[6*2*3] =
5789 {
5790          0, 1, 2, 0, 2, 3,
5791          4, 5, 6, 4, 6, 7,
5792          8, 9,10, 8,10,11,
5793         12,13,14, 12,14,15,
5794         16,17,18, 16,18,19,
5795         20,21,22, 20,22,23
5796 };
5797
5798 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5799 {
5800         int i, j;
5801         cl_locnode_t *loc = (cl_locnode_t *)ent;
5802         vec3_t mins, size;
5803         float vertex3f[6*4*3];
5804         CHECKGLERROR
5805         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5806         GL_DepthMask(false);
5807         GL_DepthRange(0, 1);
5808         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5809         GL_DepthTest(true);
5810         GL_CullFace(GL_NONE);
5811         R_Mesh_Matrix(&identitymatrix);
5812
5813         R_Mesh_VertexPointer(vertex3f, 0, 0);
5814         R_Mesh_ColorPointer(NULL, 0, 0);
5815         R_Mesh_ResetTextureState();
5816
5817         i = surfacelist[0];
5818         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
5819                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
5820                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
5821                         surfacelist[0] < 0 ? 0.5f : 0.125f);
5822
5823         if (VectorCompare(loc->mins, loc->maxs))
5824         {
5825                 VectorSet(size, 2, 2, 2);
5826                 VectorMA(loc->mins, -0.5f, size, mins);
5827         }
5828         else
5829         {
5830                 VectorCopy(loc->mins, mins);
5831                 VectorSubtract(loc->maxs, loc->mins, size);
5832         }
5833
5834         for (i = 0;i < 6*4*3;)
5835                 for (j = 0;j < 3;j++, i++)
5836                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
5837
5838         R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
5839 }
5840
5841 void R_DrawLocs(void)
5842 {
5843         int index;
5844         cl_locnode_t *loc, *nearestloc;
5845         vec3_t center;
5846         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
5847         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
5848         {
5849                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
5850                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
5851         }
5852 }
5853
5854 void R_DrawDebugModel(entity_render_t *ent)
5855 {
5856         int i, j, k, l, flagsmask;
5857         const int *elements;
5858         q3mbrush_t *brush;
5859         msurface_t *surface;
5860         model_t *model = ent->model;
5861         vec3_t v;
5862
5863         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
5864
5865         R_Mesh_ColorPointer(NULL, 0, 0);
5866         R_Mesh_ResetTextureState();
5867         GL_DepthRange(0, 1);
5868         GL_DepthTest(!r_showdisabledepthtest.integer);
5869         GL_DepthMask(false);
5870         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5871
5872         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
5873         {
5874                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
5875                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
5876                 {
5877                         if (brush->colbrushf && brush->colbrushf->numtriangles)
5878                         {
5879                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
5880                                 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, r_showcollisionbrushes.value);
5881                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
5882                         }
5883                 }
5884                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
5885                 {
5886                         if (surface->num_collisiontriangles)
5887                         {
5888                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
5889                                 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, r_showcollisionbrushes.value);
5890                                 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
5891                         }
5892                 }
5893         }
5894
5895         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5896
5897         if (r_showtris.integer || r_shownormals.integer)
5898         {
5899                 if (r_showdisabledepthtest.integer)
5900                 {
5901                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5902                         GL_DepthMask(false);
5903                 }
5904                 else
5905                 {
5906                         GL_BlendFunc(GL_ONE, GL_ZERO);
5907                         GL_DepthMask(true);
5908                 }
5909                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
5910                 {
5911                         if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
5912                                 continue;
5913                         rsurface.texture = surface->texture->currentframe;
5914                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
5915                         {
5916                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
5917                                 if (r_showtris.value > 0)
5918                                 {
5919                                         if (!rsurface.texture->currentlayers->depthmask)
5920                                                 GL_Color(r_view.colorscale, 0, 0, r_showtris.value);
5921                                         else if (ent == r_refdef.worldentity)
5922                                                 GL_Color(r_view.colorscale, r_view.colorscale, r_view.colorscale, r_showtris.value);
5923                                         else
5924                                                 GL_Color(0, r_view.colorscale, 0, r_showtris.value);
5925                                         elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
5926                                         CHECKGLERROR
5927                                         qglBegin(GL_LINES);
5928                                         for (k = 0;k < surface->num_triangles;k++, elements += 3)
5929                                         {
5930 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
5931                                                 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
5932                                                 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
5933                                                 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
5934                                         }
5935                                         qglEnd();
5936                                         CHECKGLERROR
5937                                 }
5938                                 if (r_shownormals.value > 0)
5939                                 {
5940                                         GL_Color(r_view.colorscale, 0, 0, r_shownormals.value);
5941                                         qglBegin(GL_LINES);
5942                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5943                                         {
5944                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
5945                                                 qglVertex3f(v[0], v[1], v[2]);
5946                                                 VectorMA(v, 8, rsurface.svector3f + l * 3, v);
5947                                                 qglVertex3f(v[0], v[1], v[2]);
5948                                         }
5949                                         qglEnd();
5950                                         CHECKGLERROR
5951                                         GL_Color(0, 0, r_view.colorscale, r_shownormals.value);
5952                                         qglBegin(GL_LINES);
5953                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5954                                         {
5955                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
5956                                                 qglVertex3f(v[0], v[1], v[2]);
5957                                                 VectorMA(v, 8, rsurface.tvector3f + l * 3, v);
5958                                                 qglVertex3f(v[0], v[1], v[2]);
5959                                         }
5960                                         qglEnd();
5961                                         CHECKGLERROR
5962                                         GL_Color(0, r_view.colorscale, 0, r_shownormals.value);
5963                                         qglBegin(GL_LINES);
5964                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5965                                         {
5966                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
5967                                                 qglVertex3f(v[0], v[1], v[2]);
5968                                                 VectorMA(v, 8, rsurface.normal3f + l * 3, v);
5969                                                 qglVertex3f(v[0], v[1], v[2]);
5970                                         }
5971                                         qglEnd();
5972                                         CHECKGLERROR
5973                                 }
5974                         }
5975                 }
5976                 rsurface.texture = NULL;
5977         }
5978 }
5979
5980 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
5981 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
5982 {
5983         int i, j, endj, f, flagsmask;
5984         int counttriangles = 0;
5985         msurface_t *surface, **surfacechain;
5986         texture_t *t;
5987         model_t *model = r_refdef.worldmodel;
5988         const int maxsurfacelist = 1024;
5989         int numsurfacelist = 0;
5990         msurface_t *surfacelist[1024];
5991         if (model == NULL)
5992                 return;
5993
5994         RSurf_ActiveWorldEntity();
5995
5996         // update light styles
5997         if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
5998         {
5999                 for (i = 0;i < model->brushq1.light_styles;i++)
6000                 {
6001                         if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6002                         {
6003                                 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6004                                 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6005                                         for (;(surface = *surfacechain);surfacechain++)
6006                                                 surface->cached_dlight = true;
6007                         }
6008                 }
6009         }
6010
6011         R_UpdateAllTextureInfo(r_refdef.worldentity);
6012         flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6013
6014         if (debug)
6015         {
6016                 R_DrawDebugModel(r_refdef.worldentity);
6017                 return;
6018         }
6019
6020         f = 0;
6021         t = NULL;
6022         rsurface.uselightmaptexture = false;
6023         rsurface.texture = NULL;
6024         numsurfacelist = 0;
6025         j = model->firstmodelsurface;
6026         endj = j + model->nummodelsurfaces;
6027         while (j < endj)
6028         {
6029                 // quickly skip over non-visible surfaces
6030                 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
6031                         ;
6032                 // quickly iterate over visible surfaces
6033                 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
6034                 {
6035                         // process this surface
6036                         surface = model->data_surfaces + j;
6037                         // if this surface fits the criteria, add it to the list
6038                         if (surface->num_triangles)
6039                         {
6040                                 // if lightmap parameters changed, rebuild lightmap texture
6041                                 if (surface->cached_dlight)
6042                                         R_BuildLightMap(r_refdef.worldentity, surface);
6043                                 // add face to draw list
6044                                 surfacelist[numsurfacelist++] = surface;
6045                                 counttriangles += surface->num_triangles;
6046                                 if (numsurfacelist >= maxsurfacelist)
6047                                 {
6048                                         R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6049                                         numsurfacelist = 0;
6050                                 }
6051                         }
6052                 }
6053         }
6054         if (numsurfacelist)
6055                 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6056         r_refdef.stats.entities_triangles += counttriangles;
6057         RSurf_CleanUp();
6058 }
6059
6060 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6061 {
6062         int i, f, flagsmask;
6063         int counttriangles = 0;
6064         msurface_t *surface, *endsurface, **surfacechain;
6065         texture_t *t;
6066         model_t *model = ent->model;
6067         const int maxsurfacelist = 1024;
6068         int numsurfacelist = 0;
6069         msurface_t *surfacelist[1024];
6070         if (model == NULL)
6071                 return;
6072
6073         // if the model is static it doesn't matter what value we give for
6074         // wantnormals and wanttangents, so this logic uses only rules applicable
6075         // to a model, knowing that they are meaningless otherwise
6076         if (ent == r_refdef.worldentity)
6077                 RSurf_ActiveWorldEntity();
6078         else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6079                 RSurf_ActiveModelEntity(ent, false, false);
6080         else
6081                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6082
6083         // update light styles
6084         if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6085         {
6086                 for (i = 0;i < model->brushq1.light_styles;i++)
6087                 {
6088                         if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6089                         {
6090                                 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6091                                 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6092                                         for (;(surface = *surfacechain);surfacechain++)
6093                                                 surface->cached_dlight = true;
6094                         }
6095                 }
6096         }
6097
6098         R_UpdateAllTextureInfo(ent);
6099         flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6100
6101         if (debug)
6102         {
6103                 R_DrawDebugModel(ent);
6104                 return;
6105         }
6106
6107         f = 0;
6108         t = NULL;
6109         rsurface.uselightmaptexture = false;
6110         rsurface.texture = NULL;
6111         numsurfacelist = 0;
6112         surface = model->data_surfaces + model->firstmodelsurface;
6113         endsurface = surface + model->nummodelsurfaces;
6114         for (;surface < endsurface;surface++)
6115         {
6116                 // if this surface fits the criteria, add it to the list
6117                 if (surface->num_triangles)
6118                 {
6119                         // if lightmap parameters changed, rebuild lightmap texture
6120                         if (surface->cached_dlight)
6121                                 R_BuildLightMap(ent, surface);
6122                         // add face to draw list
6123                         surfacelist[numsurfacelist++] = surface;
6124                         counttriangles += surface->num_triangles;
6125                         if (numsurfacelist >= maxsurfacelist)
6126                         {
6127                                 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6128                                 numsurfacelist = 0;
6129                         }
6130                 }
6131         }
6132         if (numsurfacelist)
6133                 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6134         r_refdef.stats.entities_triangles += counttriangles;
6135         RSurf_CleanUp();
6136 }