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