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