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