0cd996a46ed577e4f14b557cdaddf3d4c0d8aa3b
[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
26 mempool_t *r_main_mempool;
27 rtexturepool_t *r_main_texturepool;
28
29 //
30 // screen size info
31 //
32 r_refdef_t r_refdef;
33 r_view_t r_view;
34 r_viewcache_t r_viewcache;
35
36 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
37 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "shows surfaces as different colors"};
38 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
39 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
40 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"};
41 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"};
42 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
43 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"};
44 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"};
45 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"};
46 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
47 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
48 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
49 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
50 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
51 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
52 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
53 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
54 cvar_t r_q1bsp_skymasking = {0, "r_qb1sp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
55
56 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
57 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
58 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
59 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
60 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
61 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
62 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
63
64 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)"};
65
66 cvar_t r_glsl = {0, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
67 cvar_t r_glsl_offsetmapping = {0, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
68 cvar_t r_glsl_offsetmapping_reliefmapping = {0, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
69 cvar_t r_glsl_offsetmapping_scale = {0, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
70 cvar_t r_glsl_deluxemapping = {0, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
71
72 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
73 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
74 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
75
76 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
77 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
78 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
79 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
80 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
81
82 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"};
83
84 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"};
85
86 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
87
88 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"}; // used for testing renderer code changes, otherwise does nothing
89 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
90
91 rtexture_t *r_bloom_texture_screen;
92 rtexture_t *r_bloom_texture_bloom;
93 rtexture_t *r_texture_blanknormalmap;
94 rtexture_t *r_texture_white;
95 rtexture_t *r_texture_black;
96 rtexture_t *r_texture_notexture;
97 rtexture_t *r_texture_whitecube;
98 rtexture_t *r_texture_normalizationcube;
99 rtexture_t *r_texture_fogattenuation;
100 //rtexture_t *r_texture_fogintensity;
101
102 // information about each possible shader permutation
103 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
104 // currently selected permutation
105 r_glsl_permutation_t *r_glsl_permutation;
106
107 // temporary variable used by a macro
108 int fogtableindex;
109
110 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
111 {
112         int i;
113         for (i = 0;i < verts;i++)
114         {
115                 out[0] = in[0] * r;
116                 out[1] = in[1] * g;
117                 out[2] = in[2] * b;
118                 out[3] = in[3];
119                 in += 4;
120                 out += 4;
121         }
122 }
123
124 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
125 {
126         int i;
127         for (i = 0;i < verts;i++)
128         {
129                 out[0] = r;
130                 out[1] = g;
131                 out[2] = b;
132                 out[3] = a;
133                 out += 4;
134         }
135 }
136
137 // FIXME: move this to client?
138 void FOG_clear(void)
139 {
140         if (gamemode == GAME_NEHAHRA)
141         {
142                 Cvar_Set("gl_fogenable", "0");
143                 Cvar_Set("gl_fogdensity", "0.2");
144                 Cvar_Set("gl_fogred", "0.3");
145                 Cvar_Set("gl_foggreen", "0.3");
146                 Cvar_Set("gl_fogblue", "0.3");
147         }
148         r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
149 }
150
151 // FIXME: move this to client?
152 void FOG_registercvars(void)
153 {
154         int x;
155         double r, alpha;
156
157         if (gamemode == GAME_NEHAHRA)
158         {
159                 Cvar_RegisterVariable (&gl_fogenable);
160                 Cvar_RegisterVariable (&gl_fogdensity);
161                 Cvar_RegisterVariable (&gl_fogred);
162                 Cvar_RegisterVariable (&gl_foggreen);
163                 Cvar_RegisterVariable (&gl_fogblue);
164                 Cvar_RegisterVariable (&gl_fogstart);
165                 Cvar_RegisterVariable (&gl_fogend);
166         }
167
168         r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
169         for (x = 0;x < FOGTABLEWIDTH;x++)
170         {
171                 alpha = exp(r / ((double)x*(double)x));
172                 if (x == FOGTABLEWIDTH - 1)
173                         alpha = 1;
174                 r_refdef.fogtable[x] = bound(0, alpha, 1);
175         }
176 }
177
178 static void R_BuildBlankTextures(void)
179 {
180         unsigned char data[4];
181         data[0] = 128; // normal X
182         data[1] = 128; // normal Y
183         data[2] = 255; // normal Z
184         data[3] = 128; // height
185         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
186         data[0] = 255;
187         data[1] = 255;
188         data[2] = 255;
189         data[3] = 255;
190         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
191         data[0] = 0;
192         data[1] = 0;
193         data[2] = 0;
194         data[3] = 255;
195         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
196 }
197
198 static void R_BuildNoTexture(void)
199 {
200         int x, y;
201         unsigned char pix[16][16][4];
202         // this makes a light grey/dark grey checkerboard texture
203         for (y = 0;y < 16;y++)
204         {
205                 for (x = 0;x < 16;x++)
206                 {
207                         if ((y < 8) ^ (x < 8))
208                         {
209                                 pix[y][x][0] = 128;
210                                 pix[y][x][1] = 128;
211                                 pix[y][x][2] = 128;
212                                 pix[y][x][3] = 255;
213                         }
214                         else
215                         {
216                                 pix[y][x][0] = 64;
217                                 pix[y][x][1] = 64;
218                                 pix[y][x][2] = 64;
219                                 pix[y][x][3] = 255;
220                         }
221                 }
222         }
223         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
224 }
225
226 static void R_BuildWhiteCube(void)
227 {
228         unsigned char data[6*1*1*4];
229         data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
230         data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
231         data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
232         data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
233         data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
234         data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
235         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
236 }
237
238 static void R_BuildNormalizationCube(void)
239 {
240         int x, y, side;
241         vec3_t v;
242         vec_t s, t, intensity;
243 #define NORMSIZE 64
244         unsigned char data[6][NORMSIZE][NORMSIZE][4];
245         for (side = 0;side < 6;side++)
246         {
247                 for (y = 0;y < NORMSIZE;y++)
248                 {
249                         for (x = 0;x < NORMSIZE;x++)
250                         {
251                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
252                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
253                                 switch(side)
254                                 {
255                                 default:
256                                 case 0:
257                                         v[0] = 1;
258                                         v[1] = -t;
259                                         v[2] = -s;
260                                         break;
261                                 case 1:
262                                         v[0] = -1;
263                                         v[1] = -t;
264                                         v[2] = s;
265                                         break;
266                                 case 2:
267                                         v[0] = s;
268                                         v[1] = 1;
269                                         v[2] = t;
270                                         break;
271                                 case 3:
272                                         v[0] = s;
273                                         v[1] = -1;
274                                         v[2] = -t;
275                                         break;
276                                 case 4:
277                                         v[0] = s;
278                                         v[1] = -t;
279                                         v[2] = 1;
280                                         break;
281                                 case 5:
282                                         v[0] = -s;
283                                         v[1] = -t;
284                                         v[2] = -1;
285                                         break;
286                                 }
287                                 intensity = 127.0f / sqrt(DotProduct(v, v));
288                                 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
289                                 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
290                                 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
291                                 data[side][y][x][3] = 255;
292                         }
293                 }
294         }
295         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
296 }
297
298 static void R_BuildFogTexture(void)
299 {
300         int x, b;
301         double r, alpha;
302 #define FOGWIDTH 64
303         unsigned char data1[FOGWIDTH][4];
304         //unsigned char data2[FOGWIDTH][4];
305         r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
306         for (x = 0;x < FOGWIDTH;x++)
307         {
308                 alpha = exp(r / ((double)x*(double)x));
309                 if (x == FOGWIDTH - 1)
310                         alpha = 1;
311                 b = (int)(256.0 * alpha);
312                 b = bound(0, b, 255);
313                 data1[x][0] = 255 - b;
314                 data1[x][1] = 255 - b;
315                 data1[x][2] = 255 - b;
316                 data1[x][3] = 255;
317                 //data2[x][0] = b;
318                 //data2[x][1] = b;
319                 //data2[x][2] = b;
320                 //data2[x][3] = 255;
321         }
322         r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
323         //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
324 }
325
326 static const char *builtinshaderstring =
327 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
328 "// written by Forest 'LordHavoc' Hale\n"
329 "\n"
330 "// common definitions between vertex shader and fragment shader:\n"
331 "\n"
332 "varying vec2 TexCoord;\n"
333 "varying vec2 TexCoordLightmap;\n"
334 "\n"
335 "varying vec3 CubeVector;\n"
336 "varying vec3 LightVector;\n"
337 "varying vec3 EyeVector;\n"
338 "#ifdef USEFOG\n"
339 "varying vec3 EyeVectorModelSpace;\n"
340 "#endif\n"
341 "\n"
342 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
343 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
344 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
345 "\n"
346 "\n"
347 "\n"
348 "\n"
349 "// vertex shader specific:\n"
350 "#ifdef VERTEX_SHADER\n"
351 "\n"
352 "uniform vec3 LightPosition;\n"
353 "uniform vec3 EyePosition;\n"
354 "uniform vec3 LightDir;\n"
355 "\n"
356 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
357 "\n"
358 "void main(void)\n"
359 "{\n"
360 "       gl_FrontColor = gl_Color;\n"
361 "       // copy the surface texcoord\n"
362 "       TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
363 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
364 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
365 "#endif\n"
366 "\n"
367 "#ifdef MODE_LIGHTSOURCE\n"
368 "       // transform vertex position into light attenuation/cubemap space\n"
369 "       // (-1 to +1 across the light box)\n"
370 "       CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
371 "\n"
372 "       // transform unnormalized light direction into tangent space\n"
373 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
374 "       //  normalize it per pixel)\n"
375 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
376 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
377 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
378 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
379 "#endif\n"
380 "\n"
381 "#ifdef MODE_LIGHTDIRECTION\n"
382 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
383 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
384 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
385 "#endif\n"
386 "\n"
387 "       // transform unnormalized eye direction into tangent space\n"
388 "#ifndef USEFOG\n"
389 "       vec3 EyeVectorModelSpace;\n"
390 "#endif\n"
391 "       EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
392 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
393 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
394 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
395 "\n"
396 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
397 "       VectorS = gl_MultiTexCoord1.xyz;\n"
398 "       VectorT = gl_MultiTexCoord2.xyz;\n"
399 "       VectorR = gl_MultiTexCoord3.xyz;\n"
400 "#endif\n"
401 "\n"
402 "       // transform vertex to camera space, using ftransform to match non-VS\n"
403 "       // rendering\n"
404 "       gl_Position = ftransform();\n"
405 "}\n"
406 "\n"
407 "#endif // VERTEX_SHADER\n"
408 "\n"
409 "\n"
410 "\n"
411 "\n"
412 "// fragment shader specific:\n"
413 "#ifdef FRAGMENT_SHADER\n"
414 "\n"
415 "uniform sampler2D Texture_Normal;\n"
416 "uniform sampler2D Texture_Color;\n"
417 "uniform sampler2D Texture_Gloss;\n"
418 "uniform samplerCube Texture_Cube;\n"
419 "uniform sampler2D Texture_FogMask;\n"
420 "uniform sampler2D Texture_Pants;\n"
421 "uniform sampler2D Texture_Shirt;\n"
422 "uniform sampler2D Texture_Lightmap;\n"
423 "uniform sampler2D Texture_Deluxemap;\n"
424 "uniform sampler2D Texture_Glow;\n"
425 "\n"
426 "uniform vec3 LightColor;\n"
427 "uniform vec3 AmbientColor;\n"
428 "uniform vec3 DiffuseColor;\n"
429 "uniform vec3 SpecularColor;\n"
430 "uniform vec3 Color_Pants;\n"
431 "uniform vec3 Color_Shirt;\n"
432 "uniform vec3 FogColor;\n"
433 "\n"
434 "uniform float OffsetMapping_Scale;\n"
435 "uniform float OffsetMapping_Bias;\n"
436 "uniform float FogRangeRecip;\n"
437 "\n"
438 "uniform float AmbientScale;\n"
439 "uniform float DiffuseScale;\n"
440 "uniform float SpecularScale;\n"
441 "uniform float SpecularPower;\n"
442 "\n"
443 "void main(void)\n"
444 "{\n"
445 "       // apply offsetmapping\n"
446 "#ifdef USEOFFSETMAPPING\n"
447 "       vec2 TexCoordOffset = TexCoord;\n"
448 "#define TexCoord TexCoordOffset\n"
449 "\n"
450 "       vec3 eyedir = vec3(normalize(EyeVector));\n"
451 "       float depthbias = 1.0 - eyedir.z; // should this be a -?\n"
452 "       depthbias = 1.0 - depthbias * depthbias;\n"
453 "\n"
454 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
455 "       // 14 sample relief mapping: linear search and then binary search\n"
456 "       vec3 OffsetVector = vec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
457 "       vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + OffsetVector;\n"
458 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
459 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
460 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
461 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
462 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
463 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
464 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
465 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
466 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
467 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
468 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
469 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
470 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
471 "       if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
472 "       TexCoord = RT.xy;\n"
473 "#else\n"
474 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
475 "       vec2 OffsetVector = vec2((EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333));\n"
476 "       //TexCoord += OffsetVector * 3.0;\n"
477 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
478 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
479 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
480 "#endif\n"
481 "#endif\n"
482 "\n"
483 "       // combine the diffuse textures (base, pants, shirt)\n"
484 "       vec4 color = vec4(texture2D(Texture_Color, TexCoord));\n"
485 "#ifdef USECOLORMAPPING\n"
486 "       color.rgb += vec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + vec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
487 "#endif\n"
488 "\n"
489 "\n"
490 "\n"
491 "\n"
492 "#ifdef MODE_LIGHTSOURCE\n"
493 "       // light source\n"
494 "\n"
495 "       // get the surface normal and light normal\n"
496 "       vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
497 "       vec3 diffusenormal = vec3(normalize(LightVector));\n"
498 "\n"
499 "       // calculate directional shading\n"
500 "       color.rgb *= (AmbientScale + DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
501 "#ifdef USESPECULAR\n"
502 "       vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
503 "       color.rgb += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
504 "#endif\n"
505 "\n"
506 "#ifdef USECUBEFILTER\n"
507 "       // apply light cubemap filter\n"
508 "       //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
509 "       color.rgb *= vec3(textureCube(Texture_Cube, CubeVector));\n"
510 "#endif\n"
511 "\n"
512 "       // apply light color\n"
513 "       color.rgb *= LightColor;\n"
514 "\n"
515 "       // apply attenuation\n"
516 "       //\n"
517 "       // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
518 "       // center and sharp falloff at the edge, this is about the most efficient\n"
519 "       // we can get away with as far as providing illumination.\n"
520 "       //\n"
521 "       // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
522 "       // provide significant illumination, large = slow = pain.\n"
523 "       color.rgb *= max(1.0 - dot(CubeVector, CubeVector), 0.0);\n"
524 "\n"
525 "\n"
526 "\n"
527 "\n"
528 "#elif defined(MODE_LIGHTDIRECTION)\n"
529 "       // directional model lighting\n"
530 "\n"
531 "       // get the surface normal and light normal\n"
532 "       vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
533 "       vec3 diffusenormal = vec3(normalize(LightVector));\n"
534 "\n"
535 "       // calculate directional shading\n"
536 "       color.rgb *= AmbientColor + DiffuseColor * max(dot(surfacenormal, diffusenormal), 0.0);\n"
537 "#ifdef USESPECULAR\n"
538 "       vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
539 "       color.rgb += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
540 "#endif\n"
541 "\n"
542 "\n"
543 "\n"
544 "\n"
545 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE)\n"
546 "       // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
547 "\n"
548 "       // get the surface normal and light normal\n"
549 "       vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
550 "       vec3 diffusenormal_modelspace = vec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5;\n"
551 "       vec3 diffusenormal = normalize(vec3(dot(diffusenormal_modelspace, VectorS), dot(diffusenormal_modelspace, VectorT), dot(diffusenormal_modelspace, VectorR)));\n"
552 "\n"
553 "       // calculate directional shading\n"
554 "       vec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
555 "#ifdef USESPECULAR\n"
556 "       vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
557 "       tempcolor += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
558 "#endif\n"
559 "\n"
560 "       // apply lightmap color\n"
561 "       color.rgb = tempcolor * vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * vec3(AmbientScale);\n"
562 "\n"
563 "\n"
564 "\n"
565 "\n"
566 "#elif defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
567 "       // deluxemap lightmapping using light vectors in tangentspace\n"
568 "\n"
569 "       // get the surface normal and light normal\n"
570 "       vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
571 "       vec3 diffusenormal = normalize(vec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5);\n"
572 "\n"
573 "       // calculate directional shading\n"
574 "       vec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
575 "#ifdef USESPECULAR\n"
576 "       vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
577 "       tempcolor += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
578 "#endif\n"
579 "\n"
580 "       // apply lightmap color\n"
581 "       color.rgb = tempcolor * vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * vec3(AmbientScale);\n"
582 "\n"
583 "\n"
584 "\n"
585 "\n"
586 "#else // MODE none (lightmap)\n"
587 "       // apply lightmap color\n"
588 "       color.rgb *= vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + vec3(AmbientScale);\n"
589 "#endif // MODE\n"
590 "\n"
591 "       color *= gl_Color;\n"
592 "\n"
593 "#ifdef USEGLOW\n"
594 "       color.rgb += vec3(texture2D(Texture_Glow, TexCoord));\n"
595 "#endif\n"
596 "\n"
597 "#ifdef USEFOG\n"
598 "       // apply fog\n"
599 "       float fog = texture2D(Texture_FogMask, vec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0)).x;\n"
600 "       color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
601 "#endif\n"
602 "\n"
603 "       gl_FragColor = color;\n"
604 "}\n"
605 "\n"
606 "#endif // FRAGMENT_SHADER\n"
607 ;
608
609 void R_GLSL_CompilePermutation(int permutation)
610 {
611         r_glsl_permutation_t *p = r_glsl_permutations + permutation;
612         int vertstrings_count;
613         int fragstrings_count;
614         char *shaderstring;
615         const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
616         const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
617         char permutationname[256];
618         if (p->compiled)
619                 return;
620         p->compiled = true;
621         vertstrings_list[0] = "#define VERTEX_SHADER\n";
622         fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
623         vertstrings_count = 1;
624         fragstrings_count = 1;
625         permutationname[0] = 0;
626         if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
627         {
628                 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTSOURCE\n";
629                 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTSOURCE\n";
630                 strlcat(permutationname, " lightsource", sizeof(permutationname));
631         }
632         if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE)
633         {
634                 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
635                 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
636                 strlcat(permutationname, " lightdirectionmap_modelspace", sizeof(permutationname));
637         }
638         if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)
639         {
640                 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
641                 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
642                 strlcat(permutationname, " lightdirectionmap_tangentspace", sizeof(permutationname));
643         }
644         if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
645         {
646                 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
647                 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
648                 strlcat(permutationname, " lightdirection", sizeof(permutationname));
649         }
650         if (permutation & SHADERPERMUTATION_GLOW)
651         {
652                 vertstrings_list[vertstrings_count++] = "#define USEGLOW\n";
653                 fragstrings_list[fragstrings_count++] = "#define USEGLOW\n";
654                 strlcat(permutationname, " glow", sizeof(permutationname));
655         }
656         if (permutation & SHADERPERMUTATION_COLORMAPPING)
657         {
658                 vertstrings_list[vertstrings_count++] = "#define USECOLORMAPPING\n";
659                 fragstrings_list[fragstrings_count++] = "#define USECOLORMAPPING\n";
660                 strlcat(permutationname, " colormapping", sizeof(permutationname));
661         }
662         if (permutation & SHADERPERMUTATION_SPECULAR)
663         {
664                 vertstrings_list[vertstrings_count++] = "#define USESPECULAR\n";
665                 fragstrings_list[fragstrings_count++] = "#define USESPECULAR\n";
666                 strlcat(permutationname, " specular", sizeof(permutationname));
667         }
668         if (permutation & SHADERPERMUTATION_FOG)
669         {
670                 vertstrings_list[vertstrings_count++] = "#define USEFOG\n";
671                 fragstrings_list[fragstrings_count++] = "#define USEFOG\n";
672                 strlcat(permutationname, " fog", sizeof(permutationname));
673         }
674         if (permutation & SHADERPERMUTATION_CUBEFILTER)
675         {
676                 vertstrings_list[vertstrings_count++] = "#define USECUBEFILTER\n";
677                 fragstrings_list[fragstrings_count++] = "#define USECUBEFILTER\n";
678                 strlcat(permutationname, " cubefilter", sizeof(permutationname));
679         }
680         if (permutation & SHADERPERMUTATION_OFFSETMAPPING)
681         {
682                 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING\n";
683                 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING\n";
684                 strlcat(permutationname, " offsetmapping", sizeof(permutationname));
685         }
686         if (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING)
687         {
688                 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
689                 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
690                 strlcat(permutationname, " OFFSETMAPPING_RELIEFMAPPING", sizeof(permutationname));
691         }
692         shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
693         if (shaderstring)
694         {
695                 Con_DPrintf("GLSL shader text loaded from disk\n");
696                 vertstrings_list[vertstrings_count++] = shaderstring;
697                 fragstrings_list[fragstrings_count++] = shaderstring;
698         }
699         else
700         {
701                 vertstrings_list[vertstrings_count++] = builtinshaderstring;
702                 fragstrings_list[fragstrings_count++] = builtinshaderstring;
703         }
704         p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
705         if (p->program)
706         {
707                 CHECKGLERROR
708                 qglUseProgramObjectARB(p->program);CHECKGLERROR
709                 p->loc_Texture_Normal      = qglGetUniformLocationARB(p->program, "Texture_Normal");
710                 p->loc_Texture_Color       = qglGetUniformLocationARB(p->program, "Texture_Color");
711                 p->loc_Texture_Gloss       = qglGetUniformLocationARB(p->program, "Texture_Gloss");
712                 p->loc_Texture_Cube        = qglGetUniformLocationARB(p->program, "Texture_Cube");
713                 p->loc_Texture_FogMask     = qglGetUniformLocationARB(p->program, "Texture_FogMask");
714                 p->loc_Texture_Pants       = qglGetUniformLocationARB(p->program, "Texture_Pants");
715                 p->loc_Texture_Shirt       = qglGetUniformLocationARB(p->program, "Texture_Shirt");
716                 p->loc_Texture_Lightmap    = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
717                 p->loc_Texture_Deluxemap   = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
718                 p->loc_Texture_Glow        = qglGetUniformLocationARB(p->program, "Texture_Glow");
719                 p->loc_FogColor            = qglGetUniformLocationARB(p->program, "FogColor");
720                 p->loc_LightPosition       = qglGetUniformLocationARB(p->program, "LightPosition");
721                 p->loc_EyePosition         = qglGetUniformLocationARB(p->program, "EyePosition");
722                 p->loc_LightColor          = qglGetUniformLocationARB(p->program, "LightColor");
723                 p->loc_Color_Pants         = qglGetUniformLocationARB(p->program, "Color_Pants");
724                 p->loc_Color_Shirt         = qglGetUniformLocationARB(p->program, "Color_Shirt");
725                 p->loc_FogRangeRecip       = qglGetUniformLocationARB(p->program, "FogRangeRecip");
726                 p->loc_AmbientScale        = qglGetUniformLocationARB(p->program, "AmbientScale");
727                 p->loc_DiffuseScale        = qglGetUniformLocationARB(p->program, "DiffuseScale");
728                 p->loc_SpecularPower       = qglGetUniformLocationARB(p->program, "SpecularPower");
729                 p->loc_SpecularScale       = qglGetUniformLocationARB(p->program, "SpecularScale");
730                 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
731                 p->loc_AmbientColor        = qglGetUniformLocationARB(p->program, "AmbientColor");
732                 p->loc_DiffuseColor        = qglGetUniformLocationARB(p->program, "DiffuseColor");
733                 p->loc_SpecularColor       = qglGetUniformLocationARB(p->program, "SpecularColor");
734                 p->loc_LightDir            = qglGetUniformLocationARB(p->program, "LightDir");
735                 if (p->loc_Texture_Normal >= 0)    qglUniform1iARB(p->loc_Texture_Normal, 0);
736                 if (p->loc_Texture_Color >= 0)     qglUniform1iARB(p->loc_Texture_Color, 1);
737                 if (p->loc_Texture_Gloss >= 0)     qglUniform1iARB(p->loc_Texture_Gloss, 2);
738                 if (p->loc_Texture_Cube >= 0)      qglUniform1iARB(p->loc_Texture_Cube, 3);
739                 if (p->loc_Texture_FogMask >= 0)   qglUniform1iARB(p->loc_Texture_FogMask, 4);
740                 if (p->loc_Texture_Pants >= 0)     qglUniform1iARB(p->loc_Texture_Pants, 5);
741                 if (p->loc_Texture_Shirt >= 0)     qglUniform1iARB(p->loc_Texture_Shirt, 6);
742                 if (p->loc_Texture_Lightmap >= 0)  qglUniform1iARB(p->loc_Texture_Lightmap, 7);
743                 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
744                 if (p->loc_Texture_Glow >= 0)      qglUniform1iARB(p->loc_Texture_Glow, 9);
745                 CHECKGLERROR
746                 qglUseProgramObjectARB(0);CHECKGLERROR
747         }
748         else
749                 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
750         if (shaderstring)
751                 Mem_Free(shaderstring);
752 }
753
754 void R_GLSL_Restart_f(void)
755 {
756         int i;
757         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
758                 if (r_glsl_permutations[i].program)
759                         GL_Backend_FreeProgram(r_glsl_permutations[i].program);
760         memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
761 }
762
763 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting)
764 {
765         // select a permutation of the lighting shader appropriate to this
766         // combination of texture, entity, light source, and fogging, only use the
767         // minimum features necessary to avoid wasting rendering time in the
768         // fragment shader on features that are not being used
769         int permutation = 0;
770         float specularscale = rsurface_texture->specularscale;
771         r_glsl_permutation = NULL;
772         if (r_shadow_rtlight)
773         {
774                 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
775                 specularscale *= r_shadow_rtlight->specularscale;
776                 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
777                         permutation |= SHADERPERMUTATION_CUBEFILTER;
778         }
779         else
780         {
781                 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
782                 {
783                         if (modellighting)
784                                 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
785                         else
786                         {
787                                 if (r_glsl_deluxemapping.integer >= 1 && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && rsurface_lightmaptexture)
788                                 {
789                                         if (r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
790                                                 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
791                                         else
792                                                 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
793                                 }
794                                 else if (r_glsl_deluxemapping.integer >= 2) // fake mode
795                                         permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
796                         }
797                 }
798                 if (rsurface_texture->skin.glow)
799                         permutation |= SHADERPERMUTATION_GLOW;
800         }
801         if (specularscale > 0)
802                 permutation |= SHADERPERMUTATION_SPECULAR;
803         if (r_refdef.fogenabled)
804                 permutation |= SHADERPERMUTATION_FOG;
805         if (rsurface_texture->colormapping)
806                 permutation |= SHADERPERMUTATION_COLORMAPPING;
807         if (r_glsl_offsetmapping.integer)
808         {
809                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
810                 if (r_glsl_offsetmapping_reliefmapping.integer)
811                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
812         }
813         if (!r_glsl_permutations[permutation].program)
814         {
815                 if (!r_glsl_permutations[permutation].compiled)
816                         R_GLSL_CompilePermutation(permutation);
817                 if (!r_glsl_permutations[permutation].program)
818                 {
819                         // remove features until we find a valid permutation
820                         int i;
821                         for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
822                         {
823                                 // reduce i more quickly whenever it would not remove any bits
824                                 if (permutation < i)
825                                         continue;
826                                 permutation &= i;
827                                 if (!r_glsl_permutations[permutation].compiled)
828                                         R_GLSL_CompilePermutation(permutation);
829                                 if (r_glsl_permutations[permutation].program)
830                                         break;
831                                 if (!i)
832                                         return 0; // utterly failed
833                         }
834                 }
835         }
836         r_glsl_permutation = r_glsl_permutations + permutation;
837         CHECKGLERROR
838         qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
839         R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
840         if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
841         {
842                 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
843                 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, r_shadow_entitylightorigin[0], r_shadow_entitylightorigin[1], r_shadow_entitylightorigin[2]);
844                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
845                 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
846                 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
847                 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
848         }
849         else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
850         {
851                 if (r_glsl_permutation->loc_AmbientColor >= 0)
852                         qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0], rsurface_entity->modellight_ambient[1], rsurface_entity->modellight_ambient[2]);
853                 if (r_glsl_permutation->loc_DiffuseColor >= 0)
854                         qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0], rsurface_entity->modellight_diffuse[1], rsurface_entity->modellight_diffuse[2]);
855                 if (r_glsl_permutation->loc_SpecularColor >= 0)
856                         qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface_entity->modellight_diffuse[0] * rsurface_texture->specularscale, rsurface_entity->modellight_diffuse[1] * rsurface_texture->specularscale, rsurface_entity->modellight_diffuse[2] * rsurface_texture->specularscale);
857                 if (r_glsl_permutation->loc_LightDir >= 0)
858                         qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
859         }
860         else
861         {
862                 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
863                 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
864                 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
865         }
866         if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->skin.nmap));
867         if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
868         if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
869         //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
870         if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
871         if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->skin.pants));
872         if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->skin.shirt));
873         //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
874         //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
875         if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->skin.glow));
876         if (r_glsl_permutation->loc_FogColor >= 0)
877         {
878                 // additive passes are only darkened by fog, not tinted
879                 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
880                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
881                 else
882                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
883         }
884         if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
885         if (r_glsl_permutation->loc_Color_Pants >= 0)
886         {
887                 if (rsurface_texture->skin.pants)
888                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
889                 else
890                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
891         }
892         if (r_glsl_permutation->loc_Color_Shirt >= 0)
893         {
894                 if (rsurface_texture->skin.shirt)
895                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
896                 else
897                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
898         }
899         if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
900         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
901         if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
902         CHECKGLERROR
903         return permutation;
904 }
905
906 void R_SwitchSurfaceShader(int permutation)
907 {
908         if (r_glsl_permutation != r_glsl_permutations + permutation)
909         {
910                 r_glsl_permutation = r_glsl_permutations + permutation;
911                 CHECKGLERROR
912                 qglUseProgramObjectARB(r_glsl_permutation->program);
913                 CHECKGLERROR
914         }
915 }
916
917 void gl_main_start(void)
918 {
919         r_main_texturepool = R_AllocTexturePool();
920         r_bloom_texture_screen = NULL;
921         r_bloom_texture_bloom = NULL;
922         R_BuildBlankTextures();
923         R_BuildNoTexture();
924         if (gl_texturecubemap)
925         {
926                 R_BuildWhiteCube();
927                 R_BuildNormalizationCube();
928         }
929         R_BuildFogTexture();
930         memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
931 }
932
933 void gl_main_shutdown(void)
934 {
935         R_FreeTexturePool(&r_main_texturepool);
936         r_bloom_texture_screen = NULL;
937         r_bloom_texture_bloom = NULL;
938         r_texture_blanknormalmap = NULL;
939         r_texture_white = NULL;
940         r_texture_black = NULL;
941         r_texture_whitecube = NULL;
942         r_texture_normalizationcube = NULL;
943         R_GLSL_Restart_f();
944 }
945
946 extern void CL_ParseEntityLump(char *entitystring);
947 void gl_main_newmap(void)
948 {
949         // FIXME: move this code to client
950         int l;
951         char *entities, entname[MAX_QPATH];
952         if (cl.worldmodel)
953         {
954                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
955                 l = (int)strlen(entname) - 4;
956                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
957                 {
958                         strcpy(entname + l, ".ent");
959                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
960                         {
961                                 CL_ParseEntityLump(entities);
962                                 Mem_Free(entities);
963                                 return;
964                         }
965                 }
966                 if (cl.worldmodel->brush.entities)
967                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
968         }
969 }
970
971 void GL_Main_Init(void)
972 {
973         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
974
975         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
976         FOG_registercvars(); // FIXME: move this fog stuff to client?
977         Cvar_RegisterVariable(&r_nearclip);
978         Cvar_RegisterVariable(&r_showsurfaces);
979         Cvar_RegisterVariable(&r_showtris);
980         Cvar_RegisterVariable(&r_shownormals);
981         Cvar_RegisterVariable(&r_showlighting);
982         Cvar_RegisterVariable(&r_showshadowvolumes);
983         Cvar_RegisterVariable(&r_showcollisionbrushes);
984         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
985         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
986         Cvar_RegisterVariable(&r_showdisabledepthtest);
987         Cvar_RegisterVariable(&r_drawportals);
988         Cvar_RegisterVariable(&r_drawentities);
989         Cvar_RegisterVariable(&r_drawviewmodel);
990         Cvar_RegisterVariable(&r_speeds);
991         Cvar_RegisterVariable(&r_fullbrights);
992         Cvar_RegisterVariable(&r_wateralpha);
993         Cvar_RegisterVariable(&r_dynamic);
994         Cvar_RegisterVariable(&r_fullbright);
995         Cvar_RegisterVariable(&r_q1bsp_skymasking);
996         Cvar_RegisterVariable(&r_textureunits);
997         Cvar_RegisterVariable(&r_glsl);
998         Cvar_RegisterVariable(&r_glsl_offsetmapping);
999         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1000         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1001         Cvar_RegisterVariable(&r_glsl_deluxemapping);
1002         Cvar_RegisterVariable(&r_lerpsprites);
1003         Cvar_RegisterVariable(&r_lerpmodels);
1004         Cvar_RegisterVariable(&r_waterscroll);
1005         Cvar_RegisterVariable(&r_bloom);
1006         Cvar_RegisterVariable(&r_bloom_intensity);
1007         Cvar_RegisterVariable(&r_bloom_blur);
1008         Cvar_RegisterVariable(&r_bloom_resolution);
1009         Cvar_RegisterVariable(&r_bloom_power);
1010         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1011         Cvar_RegisterVariable(&developer_texturelogging);
1012         Cvar_RegisterVariable(&gl_lightmaps);
1013         Cvar_RegisterVariable(&r_test);
1014         Cvar_RegisterVariable(&r_batchmode);
1015         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1016                 Cvar_SetValue("r_fullbrights", 0);
1017         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1018 }
1019
1020 extern void R_Textures_Init(void);
1021 extern void GL_Draw_Init(void);
1022 extern void GL_Main_Init(void);
1023 extern void R_Shadow_Init(void);
1024 extern void R_Sky_Init(void);
1025 extern void GL_Surf_Init(void);
1026 extern void R_Light_Init(void);
1027 extern void R_Particles_Init(void);
1028 extern void R_Explosion_Init(void);
1029 extern void gl_backend_init(void);
1030 extern void Sbar_Init(void);
1031 extern void R_LightningBeams_Init(void);
1032 extern void Mod_RenderInit(void);
1033
1034 void Render_Init(void)
1035 {
1036         gl_backend_init();
1037         R_Textures_Init();
1038         GL_Main_Init();
1039         GL_Draw_Init();
1040         R_Shadow_Init();
1041         R_Sky_Init();
1042         GL_Surf_Init();
1043         Sbar_Init();
1044         R_Light_Init();
1045         R_Particles_Init();
1046         R_Explosion_Init();
1047         R_LightningBeams_Init();
1048         Mod_RenderInit();
1049 }
1050
1051 /*
1052 ===============
1053 GL_Init
1054 ===============
1055 */
1056 extern char *ENGINE_EXTENSIONS;
1057 void GL_Init (void)
1058 {
1059         VID_CheckExtensions();
1060
1061         // LordHavoc: report supported extensions
1062         Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1063
1064         // clear to black (loading plaque will be seen over this)
1065         CHECKGLERROR
1066         qglClearColor(0,0,0,1);CHECKGLERROR
1067         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1068 }
1069
1070 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1071 {
1072         int i;
1073         mplane_t *p;
1074         for (i = 0;i < 4;i++)
1075         {
1076                 p = r_view.frustum + i;
1077                 switch(p->signbits)
1078                 {
1079                 default:
1080                 case 0:
1081                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1082                                 return true;
1083                         break;
1084                 case 1:
1085                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1086                                 return true;
1087                         break;
1088                 case 2:
1089                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1090                                 return true;
1091                         break;
1092                 case 3:
1093                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1094                                 return true;
1095                         break;
1096                 case 4:
1097                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1098                                 return true;
1099                         break;
1100                 case 5:
1101                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1102                                 return true;
1103                         break;
1104                 case 6:
1105                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1106                                 return true;
1107                         break;
1108                 case 7:
1109                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1110                                 return true;
1111                         break;
1112                 }
1113         }
1114         return false;
1115 }
1116
1117 //==================================================================================
1118
1119 static void R_UpdateEntityLighting(entity_render_t *ent)
1120 {
1121         vec3_t tempdiffusenormal;
1122         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));
1123         VectorClear(ent->modellight_diffuse);
1124         VectorClear(ent->modellight_lightdir);
1125         if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1126                 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1127         else // highly rare
1128                 VectorSet(ent->modellight_ambient, 1, 1, 1);
1129         Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1130         VectorNormalize(ent->modellight_lightdir);
1131         ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1132         ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1133         ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1134         ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1135         ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1136         ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1137 }
1138
1139 static void R_View_UpdateEntityVisible (void)
1140 {
1141         int i, renderimask;
1142         entity_render_t *ent;
1143
1144         if (!r_drawentities.integer)
1145                 return;
1146
1147         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1148         if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1149         {
1150                 // worldmodel can check visibility
1151                 for (i = 0;i < r_refdef.numentities;i++)
1152                 {
1153                         ent = r_refdef.entities[i];
1154                         r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_viewcache.world_leafvisible, ent->mins, ent->maxs));
1155                 }
1156         }
1157         else
1158         {
1159                 // no worldmodel or it can't check visibility
1160                 for (i = 0;i < r_refdef.numentities;i++)
1161                 {
1162                         ent = r_refdef.entities[i];
1163                         r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST);
1164                 }
1165         }
1166 }
1167
1168 // only used if skyrendermasked, and normally returns false
1169 int R_DrawBrushModelsSky (void)
1170 {
1171         int i, sky;
1172         entity_render_t *ent;
1173
1174         if (!r_drawentities.integer)
1175                 return false;
1176
1177         sky = false;
1178         for (i = 0;i < r_refdef.numentities;i++)
1179         {
1180                 if (!r_viewcache.entityvisible[i])
1181                         continue;
1182                 ent = r_refdef.entities[i];
1183                 if (!ent->model || !ent->model->DrawSky)
1184                         continue;
1185                 ent->model->DrawSky(ent);
1186                 sky = true;
1187         }
1188         return sky;
1189 }
1190
1191 void R_DrawNoModel(entity_render_t *ent);
1192 void R_DrawModels(void)
1193 {
1194         int i;
1195         entity_render_t *ent;
1196
1197         if (!r_drawentities.integer)
1198                 return;
1199
1200         for (i = 0;i < r_refdef.numentities;i++)
1201         {
1202                 if (!r_viewcache.entityvisible[i])
1203                         continue;
1204                 ent = r_refdef.entities[i];
1205                 r_refdef.stats.entities++;
1206                 if (ent->model && ent->model->Draw != NULL)
1207                         ent->model->Draw(ent);
1208                 else
1209                         R_DrawNoModel(ent);
1210         }
1211 }
1212
1213 static void R_View_SetFrustum(void)
1214 {
1215         // break apart the view matrix into vectors for various purposes
1216         Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1217         VectorNegate(r_view.left, r_view.right);
1218
1219 #if 0
1220         r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1221         r_view.frustum[0].normal[1] = 0 - 0;
1222         r_view.frustum[0].normal[2] = -1 - 0;
1223         r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1224         r_view.frustum[1].normal[1] = 0 + 0;
1225         r_view.frustum[1].normal[2] = -1 + 0;
1226         r_view.frustum[2].normal[0] = 0 - 0;
1227         r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1228         r_view.frustum[2].normal[2] = -1 - 0;
1229         r_view.frustum[3].normal[0] = 0 + 0;
1230         r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1231         r_view.frustum[3].normal[2] = -1 + 0;
1232 #endif
1233
1234 #if 0
1235         zNear = r_refdef.nearclip;
1236         nudge = 1.0 - 1.0 / (1<<23);
1237         r_view.frustum[4].normal[0] = 0 - 0;
1238         r_view.frustum[4].normal[1] = 0 - 0;
1239         r_view.frustum[4].normal[2] = -1 - -nudge;
1240         r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1241         r_view.frustum[5].normal[0] = 0 + 0;
1242         r_view.frustum[5].normal[1] = 0 + 0;
1243         r_view.frustum[5].normal[2] = -1 + -nudge;
1244         r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1245 #endif
1246
1247
1248
1249 #if 0
1250         r_view.frustum[0].normal[0] = m[3] - m[0];
1251         r_view.frustum[0].normal[1] = m[7] - m[4];
1252         r_view.frustum[0].normal[2] = m[11] - m[8];
1253         r_view.frustum[0].dist = m[15] - m[12];
1254
1255         r_view.frustum[1].normal[0] = m[3] + m[0];
1256         r_view.frustum[1].normal[1] = m[7] + m[4];
1257         r_view.frustum[1].normal[2] = m[11] + m[8];
1258         r_view.frustum[1].dist = m[15] + m[12];
1259
1260         r_view.frustum[2].normal[0] = m[3] - m[1];
1261         r_view.frustum[2].normal[1] = m[7] - m[5];
1262         r_view.frustum[2].normal[2] = m[11] - m[9];
1263         r_view.frustum[2].dist = m[15] - m[13];
1264
1265         r_view.frustum[3].normal[0] = m[3] + m[1];
1266         r_view.frustum[3].normal[1] = m[7] + m[5];
1267         r_view.frustum[3].normal[2] = m[11] + m[9];
1268         r_view.frustum[3].dist = m[15] + m[13];
1269
1270         r_view.frustum[4].normal[0] = m[3] - m[2];
1271         r_view.frustum[4].normal[1] = m[7] - m[6];
1272         r_view.frustum[4].normal[2] = m[11] - m[10];
1273         r_view.frustum[4].dist = m[15] - m[14];
1274
1275         r_view.frustum[5].normal[0] = m[3] + m[2];
1276         r_view.frustum[5].normal[1] = m[7] + m[6];
1277         r_view.frustum[5].normal[2] = m[11] + m[10];
1278         r_view.frustum[5].dist = m[15] + m[14];
1279 #endif
1280
1281
1282
1283         VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_x, r_view.left, r_view.frustum[0].normal);
1284         VectorMAM(1, r_view.forward, 1.0 /  r_view.frustum_x, r_view.left, r_view.frustum[1].normal);
1285         VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_y, r_view.up, r_view.frustum[2].normal);
1286         VectorMAM(1, r_view.forward, 1.0 /  r_view.frustum_y, r_view.up, r_view.frustum[3].normal);
1287         VectorCopy(r_view.forward, r_view.frustum[4].normal);
1288         VectorNormalize(r_view.frustum[0].normal);
1289         VectorNormalize(r_view.frustum[1].normal);
1290         VectorNormalize(r_view.frustum[2].normal);
1291         VectorNormalize(r_view.frustum[3].normal);
1292         r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1293         r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1294         r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1295         r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1296         r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1297         PlaneClassify(&r_view.frustum[0]);
1298         PlaneClassify(&r_view.frustum[1]);
1299         PlaneClassify(&r_view.frustum[2]);
1300         PlaneClassify(&r_view.frustum[3]);
1301         PlaneClassify(&r_view.frustum[4]);
1302
1303         // LordHavoc: note to all quake engine coders, Quake had a special case
1304         // for 90 degrees which assumed a square view (wrong), so I removed it,
1305         // Quake2 has it disabled as well.
1306
1307         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1308         //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1309         //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1310         //PlaneClassify(&frustum[0]);
1311
1312         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1313         //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1314         //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1315         //PlaneClassify(&frustum[1]);
1316
1317         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1318         //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1319         //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1320         //PlaneClassify(&frustum[2]);
1321
1322         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1323         //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1324         //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1325         //PlaneClassify(&frustum[3]);
1326
1327         // nearclip plane
1328         //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1329         //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1330         //PlaneClassify(&frustum[4]);
1331 }
1332
1333 void R_View_Update(void)
1334 {
1335         // GL is weird because it's bottom to top, r_view.y is top to bottom
1336         qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1337         GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1338         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1339         R_View_SetFrustum();
1340         R_View_WorldVisibility();
1341         R_View_UpdateEntityVisible();
1342 }
1343
1344 static void R_BlendView(void)
1345 {
1346         int screenwidth, screenheight;
1347         qboolean dobloom;
1348         qboolean doblend;
1349         float vertex3f[12];
1350         float texcoord2f[3][8];
1351
1352         // set the (poorly named) screenwidth and screenheight variables to
1353         // a power of 2 at least as large as the screen, these will define the
1354         // size of the texture to allocate
1355         for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1356         for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1357
1358         doblend = r_refdef.viewblend[3] >= 0.01f;
1359         dobloom = r_bloom.integer && screenwidth <= gl_max_texture_size && screenheight <= gl_max_texture_size && r_bloom_resolution.value >= 32 && r_bloom_power.integer >= 1 && r_bloom_power.integer < 100 && r_bloom_blur.value >= 0 && r_bloom_blur.value < 512;
1360
1361         if (!dobloom && !doblend)
1362                 return;
1363
1364         GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1365         GL_DepthMask(true);
1366         GL_DepthTest(false);
1367         R_Mesh_Matrix(&identitymatrix);
1368         // vertex coordinates for a quad that covers the screen exactly
1369         vertex3f[0] = 0;vertex3f[1] = 0;vertex3f[2] = 0;
1370         vertex3f[3] = 1;vertex3f[4] = 0;vertex3f[5] = 0;
1371         vertex3f[6] = 1;vertex3f[7] = 1;vertex3f[8] = 0;
1372         vertex3f[9] = 0;vertex3f[10] = 1;vertex3f[11] = 0;
1373         R_Mesh_VertexPointer(vertex3f);
1374         R_Mesh_ColorPointer(NULL);
1375         R_Mesh_ResetTextureState();
1376         if (dobloom)
1377         {
1378                 int bloomwidth, bloomheight, x, range;
1379                 float xoffset, yoffset, r;
1380                 r_refdef.stats.bloom++;
1381                 // allocate textures as needed
1382                 if (!r_bloom_texture_screen)
1383                         r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1384                 if (!r_bloom_texture_bloom)
1385                         r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1386                 // set bloomwidth and bloomheight to the bloom resolution that will be
1387                 // used (often less than the screen resolution for faster rendering)
1388                 bloomwidth = min(r_view.width, r_bloom_resolution.integer);
1389                 bloomheight = min(r_view.height, bloomwidth * r_view.height / r_view.width);
1390                 // set up a texcoord array for the full resolution screen image
1391                 // (we have to keep this around to copy back during final render)
1392                 texcoord2f[0][0] = 0;
1393                 texcoord2f[0][1] = (float)r_view.height / (float)screenheight;
1394                 texcoord2f[0][2] = (float)r_view.width / (float)screenwidth;
1395                 texcoord2f[0][3] = (float)r_view.height / (float)screenheight;
1396                 texcoord2f[0][4] = (float)r_view.width / (float)screenwidth;
1397                 texcoord2f[0][5] = 0;
1398                 texcoord2f[0][6] = 0;
1399                 texcoord2f[0][7] = 0;
1400                 // set up a texcoord array for the reduced resolution bloom image
1401                 // (which will be additive blended over the screen image)
1402                 texcoord2f[1][0] = 0;
1403                 texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1404                 texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1405                 texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1406                 texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1407                 texcoord2f[1][5] = 0;
1408                 texcoord2f[1][6] = 0;
1409                 texcoord2f[1][7] = 0;
1410                 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1411                 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1412                 // copy view into the full resolution screen image texture
1413                 GL_ActiveTexture(0);
1414                 CHECKGLERROR
1415                 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
1416                 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1417                 // now scale it down to the bloom size and raise to a power of itself
1418                 // to darken it (this leaves the really bright stuff bright, and
1419                 // everything else becomes very dark)
1420                 // TODO: optimize with multitexture or GLSL
1421                 CHECKGLERROR
1422                 qglViewport(r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1423                 GL_BlendFunc(GL_ONE, GL_ZERO);
1424                 GL_Color(1, 1, 1, 1);
1425                 R_Mesh_Draw(0, 4, 2, polygonelements);
1426                 r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1427                 // render multiple times with a multiply blendfunc to raise to a power
1428                 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1429                 for (x = 1;x < r_bloom_power.integer;x++)
1430                 {
1431                         R_Mesh_Draw(0, 4, 2, polygonelements);
1432                         r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1433                 }
1434                 // we now have a darkened bloom image in the framebuffer, copy it into
1435                 // the bloom image texture for more processing
1436                 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1437                 R_Mesh_TexCoordPointer(0, 2, texcoord2f[2]);
1438                 GL_ActiveTexture(0);
1439                 CHECKGLERROR
1440                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1441                 r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
1442                 // blend on at multiple vertical offsets to achieve a vertical blur
1443                 // TODO: do offset blends using GLSL
1444                 range = r_bloom_blur.integer * bloomwidth / 320;
1445                 GL_BlendFunc(GL_ONE, GL_ZERO);
1446                 for (x = -range;x <= range;x++)
1447                 {
1448                         xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1449                         yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1450                         // compute a texcoord array with the specified x and y offset
1451                         texcoord2f[2][0] = xoffset+0;
1452                         texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1453                         texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1454                         texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1455                         texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1456                         texcoord2f[2][5] = yoffset+0;
1457                         texcoord2f[2][6] = xoffset+0;
1458                         texcoord2f[2][7] = yoffset+0;
1459                         // this r value looks like a 'dot' particle, fading sharply to
1460                         // black at the edges
1461                         // (probably not realistic but looks good enough)
1462                         r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1463                         if (r < 0.01f)
1464                                 continue;
1465                         GL_Color(r, r, r, 1);
1466                         R_Mesh_Draw(0, 4, 2, polygonelements);
1467                         r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1468                         GL_BlendFunc(GL_ONE, GL_ONE);
1469                 }
1470                 // copy the vertically blurred bloom view to a texture
1471                 GL_ActiveTexture(0);
1472                 CHECKGLERROR
1473                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1474                 r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
1475                 // blend the vertically blurred image at multiple offsets horizontally
1476                 // to finish the blur effect
1477                 // TODO: do offset blends using GLSL
1478                 range = r_bloom_blur.integer * bloomwidth / 320;
1479                 GL_BlendFunc(GL_ONE, GL_ZERO);
1480                 for (x = -range;x <= range;x++)
1481                 {
1482                         xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1483                         yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1484                         // compute a texcoord array with the specified x and y offset
1485                         texcoord2f[2][0] = xoffset+0;
1486                         texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1487                         texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1488                         texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1489                         texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1490                         texcoord2f[2][5] = yoffset+0;
1491                         texcoord2f[2][6] = xoffset+0;
1492                         texcoord2f[2][7] = yoffset+0;
1493                         // this r value looks like a 'dot' particle, fading sharply to
1494                         // black at the edges
1495                         // (probably not realistic but looks good enough)
1496                         r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1497                         if (r < 0.01f)
1498                                 continue;
1499                         GL_Color(r, r, r, 1);
1500                         R_Mesh_Draw(0, 4, 2, polygonelements);
1501                         r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1502                         GL_BlendFunc(GL_ONE, GL_ONE);
1503                 }
1504                 // copy the blurred bloom view to a texture
1505                 GL_ActiveTexture(0);
1506                 CHECKGLERROR
1507                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1508                 r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
1509                 // go back to full view area
1510                 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1511                 // put the original screen image back in place and blend the bloom
1512                 // texture on it
1513                 GL_Color(1,1,1,1);
1514                 GL_BlendFunc(GL_ONE, GL_ZERO);
1515                 // do both in one pass if possible
1516                 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1517                 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1518                 if (r_textureunits.integer >= 2 && gl_combine.integer)
1519                 {
1520                         R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
1521                         R_Mesh_TexBind(1, R_GetTexture(r_bloom_texture_bloom));
1522                         R_Mesh_TexCoordPointer(1, 2, texcoord2f[1]);
1523                 }
1524                 else
1525                 {
1526                         R_Mesh_Draw(0, 4, 2, polygonelements);
1527                         r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1528                         // now blend on the bloom texture
1529                         GL_BlendFunc(GL_ONE, GL_ONE);
1530                         R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1531                         R_Mesh_TexCoordPointer(0, 2, texcoord2f[1]);
1532                 }
1533                 R_Mesh_Draw(0, 4, 2, polygonelements);
1534                 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1535         }
1536         if (doblend)
1537         {
1538                 // apply a color tint to the whole view
1539                 R_Mesh_ResetTextureState();
1540                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1541                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1542                 R_Mesh_Draw(0, 4, 2, polygonelements);
1543         }
1544 }
1545
1546 void R_RenderScene(void);
1547
1548 matrix4x4_t r_waterscrollmatrix;
1549
1550 void R_UpdateVariables(void)
1551 {
1552         int i;
1553
1554         R_Textures_Frame();
1555
1556         r_refdef.farclip = 4096;
1557         if (r_refdef.worldmodel)
1558                 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1559         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
1560
1561         r_refdef.polygonfactor = 0;
1562         r_refdef.polygonoffset = 0;
1563         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
1564         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
1565
1566         r_refdef.rtworld = r_shadow_realtime_world.integer;
1567         r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1568         r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1569         r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1570         r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1571         if (r_showsurfaces.integer)
1572         {
1573                 r_refdef.rtworld = false;
1574                 r_refdef.rtworldshadows = false;
1575                 r_refdef.rtdlight = false;
1576                 r_refdef.rtdlightshadows = false;
1577                 r_refdef.lightmapintensity = 0;
1578         }
1579
1580         if (gamemode == GAME_NEHAHRA)
1581         {
1582                 if (gl_fogenable.integer)
1583                 {
1584                         r_refdef.oldgl_fogenable = true;
1585                         r_refdef.fog_density = gl_fogdensity.value;
1586                         r_refdef.fog_red = gl_fogred.value;
1587                         r_refdef.fog_green = gl_foggreen.value;
1588                         r_refdef.fog_blue = gl_fogblue.value;
1589                 }
1590                 else if (r_refdef.oldgl_fogenable)
1591                 {
1592                         r_refdef.oldgl_fogenable = false;
1593                         r_refdef.fog_density = 0;
1594                         r_refdef.fog_red = 0;
1595                         r_refdef.fog_green = 0;
1596                         r_refdef.fog_blue = 0;
1597                 }
1598         }
1599         if (r_refdef.fog_density)
1600         {
1601                 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red  , 1.0f);
1602                 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
1603                 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
1604         }
1605         if (r_refdef.fog_density)
1606         {
1607                 r_refdef.fogenabled = true;
1608                 // this is the point where the fog reaches 0.9986 alpha, which we
1609                 // consider a good enough cutoff point for the texture
1610                 // (0.9986 * 256 == 255.6)
1611                 r_refdef.fogrange = 400 / r_refdef.fog_density;
1612                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
1613                 r_refdef.fogtabledistmultiplier = FOGTABLEWIDTH * r_refdef.fograngerecip;
1614                 // fog color was already set
1615         }
1616         else
1617                 r_refdef.fogenabled = false;
1618
1619         // update some cached entity properties...
1620         for (i = 0;i < r_refdef.numentities;i++)
1621         {
1622                 entity_render_t *ent = r_refdef.entities[i];
1623                 // some of the renderer still relies on origin...
1624                 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1625                 // some of the renderer still relies on scale...
1626                 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1627                 R_UpdateEntityLighting(ent);
1628         }
1629 }
1630
1631 /*
1632 ================
1633 R_RenderView
1634 ================
1635 */
1636 void R_RenderView(void)
1637 {
1638         if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1639                 return; //Host_Error ("R_RenderView: NULL worldmodel");
1640
1641         CHECKGLERROR
1642         GL_ScissorTest(true);
1643         GL_DepthMask(true);
1644         if (r_timereport_active)
1645                 R_TimeReport("setup");
1646
1647         R_View_Update();
1648         if (r_timereport_active)
1649                 R_TimeReport("visibility");
1650
1651         R_ClearScreen();
1652         if (r_timereport_active)
1653                 R_TimeReport("clear");
1654
1655         R_RenderScene();
1656
1657         R_BlendView();
1658         if (r_timereport_active)
1659                 R_TimeReport("blendview");
1660
1661         GL_Scissor(0, 0, vid.width, vid.height);
1662         GL_ScissorTest(false);
1663         CHECKGLERROR
1664 }
1665
1666 //[515]: csqc
1667 void CSQC_R_ClearScreen (void)
1668 {
1669         if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1670                 return; //Host_Error ("R_RenderView: NULL worldmodel");
1671
1672         CHECKGLERROR
1673         GL_ScissorTest(true);
1674         GL_DepthMask(true);
1675         if (r_timereport_active)
1676                 R_TimeReport("setup");
1677
1678         R_View_Update();
1679         if (r_timereport_active)
1680                 R_TimeReport("visibility");
1681
1682         R_ClearScreen();
1683         if (r_timereport_active)
1684                 R_TimeReport("clear");
1685         CHECKGLERROR
1686 }
1687
1688 //[515]: csqc
1689 void CSQC_R_RenderScene (void)
1690 {
1691         R_RenderScene();
1692
1693         R_BlendView();
1694         if (r_timereport_active)
1695                 R_TimeReport("blendview");
1696
1697         GL_Scissor(0, 0, vid.width, vid.height);
1698         GL_ScissorTest(false);
1699         CHECKGLERROR
1700 }
1701
1702 extern void R_DrawLightningBeams (void);
1703 extern void VM_AddPolygonsToMeshQueue (void);
1704 extern void R_DrawPortals (void);
1705 void R_RenderScene(void)
1706 {
1707         // don't let sound skip if going slow
1708         if (r_refdef.extraupdate)
1709                 S_ExtraUpdate ();
1710
1711         CHECKGLERROR
1712         if (gl_support_fragment_shader)
1713         {
1714                 qglUseProgramObjectARB(0);CHECKGLERROR
1715         }
1716         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1717         qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1718         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1719
1720         R_MeshQueue_BeginScene();
1721
1722         if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1723                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1724         else
1725                 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1726
1727         GL_SetupView_Orientation_FromEntity(&r_view.matrix);
1728
1729         R_Shadow_UpdateWorldLightSelection();
1730
1731         R_SkyStartFrame();
1732
1733         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);
1734
1735         if (cl.csqc_vidvars.drawworld)
1736         {
1737                 // don't let sound skip if going slow
1738                 if (r_refdef.extraupdate)
1739                         S_ExtraUpdate ();
1740
1741                 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1742                 {
1743                         r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1744                         if (r_timereport_active)
1745                                 R_TimeReport("worldsky");
1746                 }
1747
1748                 if (R_DrawBrushModelsSky() && r_timereport_active)
1749                         R_TimeReport("bmodelsky");
1750
1751                 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1752                 {
1753                         r_refdef.worldmodel->Draw(r_refdef.worldentity);
1754                         if (r_timereport_active)
1755                                 R_TimeReport("world");
1756                 }
1757         }
1758
1759         // don't let sound skip if going slow
1760         if (r_refdef.extraupdate)
1761                 S_ExtraUpdate ();
1762
1763         R_DrawModels();
1764         if (r_timereport_active)
1765                 R_TimeReport("models");
1766
1767         // don't let sound skip if going slow
1768         if (r_refdef.extraupdate)
1769                 S_ExtraUpdate ();
1770
1771         R_ShadowVolumeLighting(false);
1772         if (r_timereport_active)
1773                 R_TimeReport("rtlights");
1774
1775         // don't let sound skip if going slow
1776         if (r_refdef.extraupdate)
1777                 S_ExtraUpdate ();
1778
1779         if (cl.csqc_vidvars.drawworld)
1780         {
1781                 R_DrawLightningBeams();
1782                 if (r_timereport_active)
1783                         R_TimeReport("lightning");
1784
1785                 R_DrawParticles();
1786                 if (r_timereport_active)
1787                         R_TimeReport("particles");
1788
1789                 R_DrawExplosions();
1790                 if (r_timereport_active)
1791                         R_TimeReport("explosions");
1792         }
1793
1794         if (gl_support_fragment_shader)
1795         {
1796                 qglUseProgramObjectARB(0);CHECKGLERROR
1797         }
1798         VM_AddPolygonsToMeshQueue();
1799
1800         if (r_drawportals.integer)
1801         {
1802                 R_DrawPortals();
1803                 if (r_timereport_active)
1804                         R_TimeReport("portals");
1805         }
1806
1807         if (gl_support_fragment_shader)
1808         {
1809                 qglUseProgramObjectARB(0);CHECKGLERROR
1810         }
1811         R_MeshQueue_RenderTransparent();
1812         if (r_timereport_active)
1813                 R_TimeReport("drawtrans");
1814
1815         if (gl_support_fragment_shader)
1816         {
1817                 qglUseProgramObjectARB(0);CHECKGLERROR
1818         }
1819
1820         if (cl.csqc_vidvars.drawworld)
1821         {
1822                 R_DrawCoronas();
1823                 if (r_timereport_active)
1824                         R_TimeReport("coronas");
1825         }
1826
1827         // don't let sound skip if going slow
1828         if (r_refdef.extraupdate)
1829                 S_ExtraUpdate ();
1830
1831         CHECKGLERROR
1832         if (gl_support_fragment_shader)
1833         {
1834                 qglUseProgramObjectARB(0);CHECKGLERROR
1835         }
1836         qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1837         qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1838 }
1839
1840 /*
1841 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1842 {
1843         int i;
1844         float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1845         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1846         GL_DepthMask(false);
1847         GL_DepthTest(true);
1848         R_Mesh_Matrix(&identitymatrix);
1849
1850         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1851         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1852         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1853         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1854         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1855         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1856         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1857         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1858         R_FillColors(color, 8, cr, cg, cb, ca);
1859         if (r_refdef.fogenabled)
1860         {
1861                 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1862                 {
1863                         f2 = VERTEXFOGTABLE(VectorDistance(v, r_view.origin));
1864                         f1 = 1 - f2;
1865                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
1866                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
1867                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
1868                 }
1869         }
1870         R_Mesh_VertexPointer(vertex3f);
1871         R_Mesh_ColorPointer(color);
1872         R_Mesh_ResetTextureState();
1873         R_Mesh_Draw(8, 12);
1874 }
1875 */
1876
1877 int nomodelelements[24] =
1878 {
1879         5, 2, 0,
1880         5, 1, 2,
1881         5, 0, 3,
1882         5, 3, 1,
1883         0, 2, 4,
1884         2, 1, 4,
1885         3, 0, 4,
1886         1, 3, 4
1887 };
1888
1889 float nomodelvertex3f[6*3] =
1890 {
1891         -16,   0,   0,
1892          16,   0,   0,
1893           0, -16,   0,
1894           0,  16,   0,
1895           0,   0, -16,
1896           0,   0,  16
1897 };
1898
1899 float nomodelcolor4f[6*4] =
1900 {
1901         0.0f, 0.0f, 0.5f, 1.0f,
1902         0.0f, 0.0f, 0.5f, 1.0f,
1903         0.0f, 0.5f, 0.0f, 1.0f,
1904         0.0f, 0.5f, 0.0f, 1.0f,
1905         0.5f, 0.0f, 0.0f, 1.0f,
1906         0.5f, 0.0f, 0.0f, 1.0f
1907 };
1908
1909 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
1910 {
1911         int i;
1912         float f1, f2, *c;
1913         float color4f[6*4];
1914         // this is only called once per entity so numsurfaces is always 1, and
1915         // surfacelist is always {0}, so this code does not handle batches
1916         R_Mesh_Matrix(&ent->matrix);
1917
1918         if (ent->flags & EF_ADDITIVE)
1919         {
1920                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1921                 GL_DepthMask(false);
1922         }
1923         else if (ent->alpha < 1)
1924         {
1925                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1926                 GL_DepthMask(false);
1927         }
1928         else
1929         {
1930                 GL_BlendFunc(GL_ONE, GL_ZERO);
1931                 GL_DepthMask(true);
1932         }
1933         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1934         R_Mesh_VertexPointer(nomodelvertex3f);
1935         if (r_refdef.fogenabled)
1936         {
1937                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1938                 R_Mesh_ColorPointer(color4f);
1939                 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_view.origin));
1940                 f1 = 1 - f2;
1941                 for (i = 0, c = color4f;i < 6;i++, c += 4)
1942                 {
1943                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
1944                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
1945                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
1946                         c[3] *= ent->alpha;
1947                 }
1948         }
1949         else if (ent->alpha != 1)
1950         {
1951                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1952                 R_Mesh_ColorPointer(color4f);
1953                 for (i = 0, c = color4f;i < 6;i++, c += 4)
1954                         c[3] *= ent->alpha;
1955         }
1956         else
1957                 R_Mesh_ColorPointer(nomodelcolor4f);
1958         R_Mesh_ResetTextureState();
1959         R_Mesh_Draw(0, 6, 8, nomodelelements);
1960 }
1961
1962 void R_DrawNoModel(entity_render_t *ent)
1963 {
1964         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1965                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
1966         //else
1967         //      R_DrawNoModelCallback(ent, 0);
1968 }
1969
1970 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1971 {
1972         vec3_t right1, right2, diff, normal;
1973
1974         VectorSubtract (org2, org1, normal);
1975
1976         // calculate 'right' vector for start
1977         VectorSubtract (r_view.origin, org1, diff);
1978         CrossProduct (normal, diff, right1);
1979         VectorNormalize (right1);
1980
1981         // calculate 'right' vector for end
1982         VectorSubtract (r_view.origin, org2, diff);
1983         CrossProduct (normal, diff, right2);
1984         VectorNormalize (right2);
1985
1986         vert[ 0] = org1[0] + width * right1[0];
1987         vert[ 1] = org1[1] + width * right1[1];
1988         vert[ 2] = org1[2] + width * right1[2];
1989         vert[ 3] = org1[0] - width * right1[0];
1990         vert[ 4] = org1[1] - width * right1[1];
1991         vert[ 5] = org1[2] - width * right1[2];
1992         vert[ 6] = org2[0] - width * right2[0];
1993         vert[ 7] = org2[1] - width * right2[1];
1994         vert[ 8] = org2[2] - width * right2[2];
1995         vert[ 9] = org2[0] + width * right2[0];
1996         vert[10] = org2[1] + width * right2[1];
1997         vert[11] = org2[2] + width * right2[2];
1998 }
1999
2000 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2001
2002 void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_t *fogtexture, int depthdisable, 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)
2003 {
2004         float fog = 0.0f, ifog;
2005         float vertex3f[12];
2006
2007         if (r_refdef.fogenabled)
2008                 fog = VERTEXFOGTABLE(VectorDistance(origin, r_view.origin));
2009         ifog = 1 - fog;
2010
2011         R_Mesh_Matrix(&identitymatrix);
2012         GL_BlendFunc(blendfunc1, blendfunc2);
2013         GL_DepthMask(false);
2014         GL_DepthTest(!depthdisable);
2015
2016         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2017         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2018         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2019         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2020         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2021         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2022         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2023         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2024         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2025         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2026         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2027         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2028
2029         R_Mesh_VertexPointer(vertex3f);
2030         R_Mesh_ColorPointer(NULL);
2031         R_Mesh_ResetTextureState();
2032         R_Mesh_TexBind(0, R_GetTexture(texture));
2033         R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2034         GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2035         R_Mesh_Draw(0, 4, 2, polygonelements);
2036
2037         if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2038         {
2039                 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2040                 GL_BlendFunc(blendfunc1, GL_ONE);
2041                 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
2042                 R_Mesh_Draw(0, 4, 2, polygonelements);
2043         }
2044 }
2045
2046 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2047 {
2048         int i;
2049         float *vertex3f;
2050         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2051                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2052                         break;
2053         if (i == mesh->numvertices)
2054         {
2055                 if (mesh->numvertices < mesh->maxvertices)
2056                 {
2057                         VectorCopy(v, vertex3f);
2058                         mesh->numvertices++;
2059                 }
2060                 return mesh->numvertices;
2061         }
2062         else
2063                 return i;
2064 }
2065
2066 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2067 {
2068         int i;
2069         int *e, element[3];
2070         element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2071         element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2072         e = mesh->element3i + mesh->numtriangles * 3;
2073         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2074         {
2075                 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2076                 if (mesh->numtriangles < mesh->maxtriangles)
2077                 {
2078                         *e++ = element[0];
2079                         *e++ = element[1];
2080                         *e++ = element[2];
2081                         mesh->numtriangles++;
2082                 }
2083                 element[1] = element[2];
2084         }
2085 }
2086
2087 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2088 {
2089         int planenum, planenum2;
2090         int w;
2091         int tempnumpoints;
2092         mplane_t *plane, *plane2;
2093         float temppoints[2][256*3];
2094         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2095         {
2096                 w = 0;
2097                 tempnumpoints = 4;
2098                 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2099                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2100                 {
2101                         if (planenum2 == planenum)
2102                                 continue;
2103                         PolygonF_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, 1.0/32.0, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
2104                         w = !w;
2105                 }
2106                 if (tempnumpoints < 3)
2107                         continue;
2108                 // generate elements forming a triangle fan for this polygon
2109                 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2110         }
2111 }
2112
2113 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2114 {
2115         int i;
2116         R_Mesh_VertexPointer(brush->points->v);
2117         i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2118         GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2119         GL_LockArrays(0, brush->numpoints);
2120         R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2121         GL_LockArrays(0, 0);
2122 }
2123
2124 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2125 {
2126         int i;
2127         if (!surface->num_collisiontriangles)
2128                 return;
2129         R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2130         i = (int)(((size_t)surface) / sizeof(msurface_t));
2131         GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2132         GL_LockArrays(0, surface->num_collisionvertices);
2133         R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2134         GL_LockArrays(0, 0);
2135 }
2136
2137 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)
2138 {
2139         texturelayer_t *layer;
2140         layer = t->currentlayers + t->currentnumlayers++;
2141         layer->type = type;
2142         layer->depthmask = depthmask;
2143         layer->blendfunc1 = blendfunc1;
2144         layer->blendfunc2 = blendfunc2;
2145         layer->texture = texture;
2146         layer->texmatrix = *matrix;
2147         layer->color[0] = r;
2148         layer->color[1] = g;
2149         layer->color[2] = b;
2150         layer->color[3] = a;
2151 }
2152
2153 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2154 {
2155         // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2156         //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2157
2158         {
2159                 texture_t *texture = t;
2160                 model_t *model = ent->model;
2161                 int s = ent->skinnum;
2162                 if ((unsigned int)s >= (unsigned int)model->numskins)
2163                         s = 0;
2164                 if (model->skinscenes)
2165                 {
2166                         if (model->skinscenes[s].framecount > 1)
2167                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2168                         else
2169                                 s = model->skinscenes[s].firstframe;
2170                 }
2171                 if (s > 0)
2172                         t = t + s * model->num_surfaces;
2173                 if (t->animated)
2174                 {
2175                         // use an alternate animation if the entity's frame is not 0,
2176                         // and only if the texture has an alternate animation
2177                         if (ent->frame != 0 && t->anim_total[1])
2178                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
2179                         else
2180                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
2181                 }
2182                 texture->currentframe = t;
2183         }
2184
2185         t->currentmaterialflags = t->basematerialflags;
2186         t->currentalpha = ent->alpha;
2187         if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2188                 t->currentalpha *= r_wateralpha.value;
2189         if (!(ent->flags & RENDER_LIGHT))
2190                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2191         if (ent->effects & EF_ADDITIVE)
2192                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2193         else if (t->currentalpha < 1)
2194                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2195         if (ent->effects & EF_NODEPTHTEST)
2196                 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2197         if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2198                 t->currenttexmatrix = r_waterscrollmatrix;
2199         else
2200                 t->currenttexmatrix = identitymatrix;
2201
2202         t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2203         t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2204         t->glosstexture = r_texture_white;
2205         t->specularpower = 8;
2206         t->specularscale = 0;
2207         if (r_shadow_gloss.integer > 0)
2208         {
2209                 if (t->skin.gloss)
2210                 {
2211                         if (r_shadow_glossintensity.value > 0)
2212                         {
2213                                 t->glosstexture = t->skin.gloss;
2214                                 t->specularscale = r_shadow_glossintensity.value;
2215                         }
2216                 }
2217                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2218                         t->specularscale = r_shadow_gloss2intensity.value;
2219         }
2220
2221         t->currentnumlayers = 0;
2222         if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2223         {
2224                 if (gl_lightmaps.integer)
2225                         R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2226                 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2227                 {
2228                         int blendfunc1, blendfunc2, depthmask;
2229                         if (t->currentmaterialflags & MATERIALFLAG_ADD)
2230                         {
2231                                 blendfunc1 = GL_SRC_ALPHA;
2232                                 blendfunc2 = GL_ONE;
2233                         }
2234                         else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2235                         {
2236                                 blendfunc1 = GL_SRC_ALPHA;
2237                                 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2238                         }
2239                         else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2240                         {
2241                                 blendfunc1 = t->customblendfunc[0];
2242                                 blendfunc2 = t->customblendfunc[1];
2243                         }
2244                         else
2245                         {
2246                                 blendfunc1 = GL_ONE;
2247                                 blendfunc2 = GL_ZERO;
2248                         }
2249                         depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2250                         if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2251                         {
2252                                 rtexture_t *currentbasetexture;
2253                                 int layerflags = 0;
2254                                 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2255                                         layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2256                                 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2257                                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2258                                 {
2259                                         // fullbright is not affected by r_refdef.lightmapintensity
2260                                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2261                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2262                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.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);
2263                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2264                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.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);
2265                                 }
2266                                 else
2267                                 {
2268                                         float colorscale;
2269                                         colorscale = 2;
2270                                         // q3bsp has no lightmap updates, so the lightstylevalue that
2271                                         // would normally be baked into the lightmap must be
2272                                         // applied to the color
2273                                         if (ent->model->type == mod_brushq3)
2274                                                 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2275                                         colorscale *= r_refdef.lightmapintensity;
2276                                         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);
2277                                         if (r_ambient.value >= (1.0f/64.0f))
2278                                                 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);
2279                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2280                                         {
2281                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->skin.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);
2282                                                 if (r_ambient.value >= (1.0f/64.0f))
2283                                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.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);
2284                                         }
2285                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2286                                         {
2287                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->skin.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);
2288                                                 if (r_ambient.value >= (1.0f/64.0f))
2289                                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.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);
2290                                         }
2291                                 }
2292                                 if (t->skin.glow != NULL)
2293                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2294                                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2295                                 {
2296                                         // if this is opaque use alpha blend which will darken the earlier
2297                                         // passes cheaply.
2298                                         //
2299                                         // if this is an alpha blended material, all the earlier passes
2300                                         // were darkened by fog already, so we only need to add the fog
2301                                         // color ontop through the fog mask texture
2302                                         //
2303                                         // if this is an additive blended material, all the earlier passes
2304                                         // were darkened by fog already, and we should not add fog color
2305                                         // (because the background was not darkened, there is no fog color
2306                                         // that was lost behind it).
2307                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->skin.fog, &identitymatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha);
2308                                 }
2309                         }
2310                 }
2311         }
2312 }
2313
2314 void R_UpdateAllTextureInfo(entity_render_t *ent)
2315 {
2316         int i;
2317         if (ent->model)
2318                 for (i = 0;i < ent->model->num_textures;i++)
2319                         R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2320 }
2321
2322 int rsurface_array_size = 0;
2323 float *rsurface_array_modelvertex3f = NULL;
2324 float *rsurface_array_modelsvector3f = NULL;
2325 float *rsurface_array_modeltvector3f = NULL;
2326 float *rsurface_array_modelnormal3f = NULL;
2327 float *rsurface_array_deformedvertex3f = NULL;
2328 float *rsurface_array_deformedsvector3f = NULL;
2329 float *rsurface_array_deformedtvector3f = NULL;
2330 float *rsurface_array_deformednormal3f = NULL;
2331 float *rsurface_array_color4f = NULL;
2332 float *rsurface_array_texcoord3f = NULL;
2333
2334 void R_Mesh_ResizeArrays(int newvertices)
2335 {
2336         float *base;
2337         if (rsurface_array_size >= newvertices)
2338                 return;
2339         if (rsurface_array_modelvertex3f)
2340                 Mem_Free(rsurface_array_modelvertex3f);
2341         rsurface_array_size = (newvertices + 1023) & ~1023;
2342         base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2343         rsurface_array_modelvertex3f     = base + rsurface_array_size * 0;
2344         rsurface_array_modelsvector3f    = base + rsurface_array_size * 3;
2345         rsurface_array_modeltvector3f    = base + rsurface_array_size * 6;
2346         rsurface_array_modelnormal3f     = base + rsurface_array_size * 9;
2347         rsurface_array_deformedvertex3f  = base + rsurface_array_size * 12;
2348         rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2349         rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2350         rsurface_array_deformednormal3f  = base + rsurface_array_size * 21;
2351         rsurface_array_texcoord3f        = base + rsurface_array_size * 24;
2352         rsurface_array_color4f           = base + rsurface_array_size * 27;
2353 }
2354
2355 float *rsurface_modelvertex3f;
2356 float *rsurface_modelsvector3f;
2357 float *rsurface_modeltvector3f;
2358 float *rsurface_modelnormal3f;
2359 float *rsurface_vertex3f;
2360 float *rsurface_svector3f;
2361 float *rsurface_tvector3f;
2362 float *rsurface_normal3f;
2363 float *rsurface_lightmapcolor4f;
2364 vec3_t rsurface_modelorg;
2365 qboolean rsurface_generatedvertex;
2366 const entity_render_t *rsurface_entity;
2367 const model_t *rsurface_model;
2368 texture_t *rsurface_texture;
2369 rtexture_t *rsurface_lightmaptexture;
2370 rsurfmode_t rsurface_mode;
2371 texture_t *rsurface_glsl_texture;
2372 qboolean rsurface_glsl_uselightmap;
2373
2374 void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2375 {
2376         Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2377         rsurface_entity = ent;
2378         rsurface_model = ent->model;
2379         if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2380                 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2381         R_Mesh_Matrix(&ent->matrix);
2382         Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2383         if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && rsurface_model->surfmesh.isanimated)
2384         {
2385                 if (wanttangents)
2386                 {
2387                         rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2388                         rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2389                         rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2390                         rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2391                         Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2392                 }
2393                 else if (wantnormals)
2394                 {
2395                         rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2396                         rsurface_modelsvector3f = NULL;
2397                         rsurface_modeltvector3f = NULL;
2398                         rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2399                         Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2400                 }
2401                 else
2402                 {
2403                         rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2404                         rsurface_modelsvector3f = NULL;
2405                         rsurface_modeltvector3f = NULL;
2406                         rsurface_modelnormal3f = NULL;
2407                         Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2408                 }
2409                 rsurface_generatedvertex = true;
2410         }
2411         else
2412         {
2413                 rsurface_modelvertex3f  = rsurface_model->surfmesh.data_vertex3f;
2414                 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2415                 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2416                 rsurface_modelnormal3f  = rsurface_model->surfmesh.data_normal3f;
2417                 rsurface_generatedvertex = false;
2418         }
2419         rsurface_vertex3f  = rsurface_modelvertex3f;
2420         rsurface_svector3f = rsurface_modelsvector3f;
2421         rsurface_tvector3f = rsurface_modeltvector3f;
2422         rsurface_normal3f  = rsurface_modelnormal3f;
2423         rsurface_mode = RSURFMODE_NONE;
2424         rsurface_lightmaptexture = NULL;
2425         rsurface_texture = NULL;
2426         rsurface_glsl_texture = NULL;
2427         rsurface_glsl_uselightmap = false;
2428 }
2429
2430 void RSurf_CleanUp(void)
2431 {
2432         CHECKGLERROR
2433         if (rsurface_mode == RSURFMODE_GLSL)
2434         {
2435                 qglUseProgramObjectARB(0);CHECKGLERROR
2436         }
2437         GL_AlphaTest(false);
2438         rsurface_mode = RSURFMODE_NONE;
2439         rsurface_lightmaptexture = NULL;
2440         rsurface_texture = NULL;
2441         rsurface_glsl_texture = NULL;
2442         rsurface_glsl_uselightmap = false;
2443 }
2444
2445 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2446 {
2447         if (rsurface_generatedvertex)
2448         {
2449                 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2450                         generatetangents = true;
2451                 if (generatetangents)
2452                         generatenormals = true;
2453                 if (generatenormals && !rsurface_modelnormal3f)
2454                 {
2455                         rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2456                         Mod_BuildNormals(0, rsurface_model->surfmesh.num_vertices, rsurface_model->surfmesh.num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_element3i, rsurface_array_modelnormal3f, r_smoothnormals_areaweighting.integer);
2457                 }
2458                 if (generatetangents && !rsurface_modelsvector3f)
2459                 {
2460                         rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2461                         rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2462                         Mod_BuildTextureVectorsFromNormals(0, rsurface_model->surfmesh.num_vertices, rsurface_model->surfmesh.num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_modelnormal3f, rsurface_model->surfmesh.data_element3i, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f, r_smoothnormals_areaweighting.integer);
2463                 }
2464         }
2465         if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2466         {
2467                 int texturesurfaceindex;
2468                 float center[3], forward[3], right[3], up[3], v[4][3];
2469                 matrix4x4_t matrix1, imatrix1;
2470                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
2471                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
2472                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
2473                 // make deformed versions of only the vertices used by the specified surfaces
2474                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2475                 {
2476                         int i, j;
2477                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2478                         // a single autosprite surface can contain multiple sprites...
2479                         for (j = 0;j < surface->num_vertices - 3;j += 4)
2480                         {
2481                                 VectorClear(center);
2482                                 for (i = 0;i < 4;i++)
2483                                         VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2484                                 VectorScale(center, 0.25f, center);
2485                                 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2486                                 {
2487                                         forward[0] = rsurface_modelorg[0] - center[0];
2488                                         forward[1] = rsurface_modelorg[1] - center[1];
2489                                         forward[2] = 0;
2490                                         VectorNormalize(forward);
2491                                         right[0] = forward[1];
2492                                         right[1] = -forward[0];
2493                                         right[2] = 0;
2494                                         VectorSet(up, 0, 0, 1);
2495                                 }
2496                                 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2497                                 Matrix4x4_FromVectors(&matrix1, (rsurface_normal3f + 3 * surface->num_firstvertex) + j*3, (rsurface_svector3f + 3 * surface->num_firstvertex) + j*3, (rsurface_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
2498                                 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2499                                 for (i = 0;i < 4;i++)
2500                                         Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2501                                 for (i = 0;i < 4;i++)
2502                                         VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_modelvertex3f + (surface->num_firstvertex+i+j) * 3);
2503                         }
2504                         Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_deformednormal3f, r_smoothnormals_areaweighting.integer);
2505                         Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_array_deformednormal3f, rsurface_model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_deformedsvector3f, rsurface_array_deformedtvector3f, r_smoothnormals_areaweighting.integer);
2506                 }
2507                 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2508                 rsurface_svector3f = rsurface_array_deformedsvector3f;
2509                 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2510                 rsurface_normal3f = rsurface_array_deformednormal3f;
2511         }
2512         R_Mesh_VertexPointer(rsurface_vertex3f);
2513 }
2514
2515 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
2516 {
2517         int texturesurfaceindex;
2518         const msurface_t *surface = texturesurfacelist[0];
2519         int firstvertex = surface->num_firstvertex;
2520         int endvertex = surface->num_firstvertex + surface->num_vertices;
2521         if (texturenumsurfaces == 1)
2522         {
2523                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2524                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2525         }
2526         else if (r_batchmode.integer == 2)
2527         {
2528                 #define MAXBATCHTRIANGLES 4096
2529                 int batchtriangles = 0;
2530                 int batchelements[MAXBATCHTRIANGLES*3];
2531                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2532                 {
2533                         surface = texturesurfacelist[texturesurfaceindex];
2534                         if (surface->num_triangles >= 256 || (batchtriangles == 0 && texturesurfaceindex + 1 >= texturenumsurfaces))
2535                         {
2536                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2537                                 continue;
2538                         }
2539                         if (batchtriangles + surface->num_triangles > MAXBATCHTRIANGLES)
2540                         {
2541                                 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2542                                 batchtriangles = 0;
2543                                 firstvertex = surface->num_firstvertex;
2544                                 endvertex = surface->num_firstvertex + surface->num_vertices;
2545                         }
2546                         else
2547                         {
2548                                 firstvertex = min(firstvertex, surface->num_firstvertex);
2549                                 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2550                         }
2551                         memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
2552                         batchtriangles += surface->num_triangles;
2553                 }
2554                 if (batchtriangles)
2555                         R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2556         }
2557         else if (r_batchmode.integer == 1)
2558         {
2559                 int firsttriangle = 0;
2560                 int endtriangle = -1;
2561                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2562                 {
2563                         surface = texturesurfacelist[texturesurfaceindex];
2564                         if (surface->num_firsttriangle != endtriangle)
2565                         {
2566                                 if (endtriangle > firsttriangle)
2567                                 {
2568                                         GL_LockArrays(firstvertex, endvertex - firstvertex);
2569                                         R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2570                                 }
2571                                 firstvertex = surface->num_firstvertex;
2572                                 endvertex = surface->num_firstvertex + surface->num_vertices;
2573                                 firsttriangle = surface->num_firsttriangle;
2574                         }
2575                         else
2576                         {
2577                                 firstvertex = min(firstvertex, surface->num_firstvertex);
2578                                 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2579                         }
2580                         endtriangle = surface->num_firsttriangle + surface->num_triangles;
2581                 }
2582                 if (endtriangle > firsttriangle)
2583                 {
2584                         GL_LockArrays(firstvertex, endvertex - firstvertex);
2585                         R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2586                 }
2587         }
2588         else
2589         {
2590                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2591                 {
2592                         surface = texturesurfacelist[texturesurfaceindex];
2593                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2594                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2595                 }
2596         }
2597 }
2598
2599 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2600 {
2601         int texturesurfaceindex;
2602         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2603         {
2604                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2605                 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2606                 GL_Color((k & 15) * (1.0f / 16.0f), ((k >> 4) & 15) * (1.0f / 16.0f), ((k >> 8) & 15) * (1.0f / 16.0f), 0.2f);
2607                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2608                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2609         }
2610 }
2611
2612 static void RSurf_DrawBatch_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2613 {
2614         int texturesurfaceindex;
2615         int i;
2616         float f;
2617         float *v, *c, *c2;
2618         // TODO: optimize
2619         if (lightmode >= 2)
2620         {
2621                 // model lighting
2622                 vec3_t ambientcolor;
2623                 vec3_t diffusecolor;
2624                 vec3_t lightdir;
2625                 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2626                 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2627                 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2628                 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2629                 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2630                 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2631                 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2632                 if (VectorLength2(diffusecolor) > 0)
2633                 {
2634                         // generate color arrays for the surfaces in this list
2635                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2636                         {
2637                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2638                                 int numverts = surface->num_vertices;
2639                                 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2640                                 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2641                                 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2642                                 // q3-style directional shading
2643                                 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2644                                 {
2645                                         if ((f = DotProduct(c2, lightdir)) > 0)
2646                                                 VectorMA(ambientcolor, f, diffusecolor, c);
2647                                         else
2648                                                 VectorCopy(ambientcolor, c);
2649                                         c[3] = a;
2650                                 }
2651                         }
2652                         r = 1;
2653                         g = 1;
2654                         b = 1;
2655                         a = 1;
2656                         applycolor = false;
2657                         rsurface_lightmapcolor4f = rsurface_array_color4f;
2658                 }
2659                 else
2660                 {
2661                         r = ambientcolor[0];
2662                         g = ambientcolor[1];
2663                         b = ambientcolor[2];
2664                         rsurface_lightmapcolor4f = NULL;
2665                 }
2666         }
2667         else if (lightmode >= 1 || !rsurface_lightmaptexture)
2668         {
2669                 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
2670                 {
2671                         // generate color arrays for the surfaces in this list
2672                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2673                         {
2674                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2675                                 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2676                                 {
2677                                         if (surface->lightmapinfo->samples)
2678                                         {
2679                                                 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2680                                                 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2681                                                 VectorScale(lm, scale, c);
2682                                                 if (surface->lightmapinfo->styles[1] != 255)
2683                                                 {
2684                                                         int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2685                                                         lm += size3;
2686                                                         scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2687                                                         VectorMA(c, scale, lm, c);
2688                                                         if (surface->lightmapinfo->styles[2] != 255)
2689                                                         {
2690                                                                 lm += size3;
2691                                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2692                                                                 VectorMA(c, scale, lm, c);
2693                                                                 if (surface->lightmapinfo->styles[3] != 255)
2694                                                                 {
2695                                                                         lm += size3;
2696                                                                         scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2697                                                                         VectorMA(c, scale, lm, c);
2698                                                                 }
2699                                                         }
2700                                                 }
2701                                         }
2702                                         else
2703                                                 VectorClear(c);
2704                                         c[3] = 1;
2705                                 }
2706                         }
2707                         rsurface_lightmapcolor4f = rsurface_array_color4f;
2708                 }
2709                 else
2710                         rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2711         }
2712         else
2713         {
2714                 // just lightmap it
2715                 rsurface_lightmapcolor4f = NULL;
2716         }
2717         if (applyfog)
2718         {
2719                 if (rsurface_lightmapcolor4f)
2720                 {
2721                         // generate color arrays for the surfaces in this list
2722                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2723                         {
2724                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2725                                 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)
2726                                 {
2727                                         f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2728                                         c2[0] = c[0] * f;
2729                                         c2[1] = c[1] * f;
2730                                         c2[2] = c[2] * f;
2731                                         c2[3] = c[3];
2732                                 }
2733                         }
2734                 }
2735                 else
2736                 {
2737                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2738                         {
2739                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2740                                 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)
2741                                 {
2742                                         f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2743                                         c2[0] = f;
2744                                         c2[1] = f;
2745                                         c2[2] = f;
2746                                         c2[3] = 1;
2747                                 }
2748                         }
2749                 }
2750                 rsurface_lightmapcolor4f = rsurface_array_color4f;
2751         }
2752         if (applycolor && rsurface_lightmapcolor4f)
2753         {
2754                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2755                 {
2756                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2757                         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)
2758                         {
2759                                 c2[0] = c[0] * r;
2760                                 c2[1] = c[1] * g;
2761                                 c2[2] = c[2] * b;
2762                                 c2[3] = c[3] * a;
2763                         }
2764                 }
2765                 rsurface_lightmapcolor4f = rsurface_array_color4f;
2766         }
2767         R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2768         GL_Color(r, g, b, a);
2769         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2770 }
2771
2772 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2773 {
2774         if (rsurface_mode != RSURFMODE_SHOWSURFACES)
2775         {
2776                 rsurface_mode = RSURFMODE_SHOWSURFACES;
2777                 GL_DepthMask(true);
2778                 GL_BlendFunc(GL_ONE, GL_ZERO);
2779                 R_Mesh_ColorPointer(NULL);
2780                 R_Mesh_ResetTextureState();
2781         }
2782         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2783         RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
2784 }
2785
2786 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
2787 {
2788         // transparent sky would be ridiculous
2789         if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2790                 return;
2791         if (rsurface_mode != RSURFMODE_SKY)
2792         {
2793                 if (rsurface_mode == RSURFMODE_GLSL)
2794                 {
2795                         qglUseProgramObjectARB(0);CHECKGLERROR
2796                 }
2797                 rsurface_mode = RSURFMODE_SKY;
2798         }
2799         if (skyrendernow)
2800         {
2801                 skyrendernow = false;
2802                 R_Sky();
2803                 // restore entity matrix
2804                 R_Mesh_Matrix(&rsurface_entity->matrix);
2805         }
2806         GL_DepthMask(true);
2807         // LordHavoc: HalfLife maps have freaky skypolys so don't use
2808         // skymasking on them, and Quake3 never did sky masking (unlike
2809         // software Quake and software Quake2), so disable the sky masking
2810         // in Quake3 maps as it causes problems with q3map2 sky tricks,
2811         // and skymasking also looks very bad when noclipping outside the
2812         // level, so don't use it then either.
2813         if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
2814         {
2815                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
2816                 R_Mesh_ColorPointer(NULL);
2817                 R_Mesh_ResetTextureState();
2818                 if (skyrendermasked)
2819                 {
2820                         // depth-only (masking)
2821                         GL_ColorMask(0,0,0,0);
2822                         // just to make sure that braindead drivers don't draw
2823                         // anything despite that colormask...
2824                         GL_BlendFunc(GL_ZERO, GL_ONE);
2825                 }
2826                 else
2827                 {
2828                         // fog sky
2829                         GL_BlendFunc(GL_ONE, GL_ZERO);
2830                 }
2831                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2832                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2833                 if (skyrendermasked)
2834                         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2835         }
2836 }
2837
2838 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
2839 {
2840         int lightmode;
2841         // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
2842         lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
2843         if (rsurface_mode != RSURFMODE_GLSL)
2844         {
2845                 rsurface_mode = RSURFMODE_GLSL;
2846                 rsurface_glsl_texture = NULL;
2847                 rsurface_glsl_uselightmap = false;
2848                 R_Mesh_ResetTextureState();
2849         }
2850         if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != (rsurface_lightmaptexture != NULL))
2851         {
2852                 rsurface_glsl_texture = rsurface_texture;
2853                 rsurface_glsl_uselightmap = rsurface_lightmaptexture != NULL;
2854                 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
2855                 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
2856                 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
2857                 R_SetupSurfaceShader(vec3_origin, lightmode == 2);
2858                 //permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, false);
2859                 //if (r_glsl_deluxemapping.integer)
2860                 //      permutation_deluxemapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, true);
2861                 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
2862                 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
2863                 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2864         }
2865         if (!r_glsl_permutation)
2866                 return;
2867         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
2868         R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2869         R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2870         R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2871         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2872         {
2873                 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2874                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2875                         R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2876                 R_Mesh_ColorPointer(NULL);
2877         }
2878         else if (rsurface_lightmaptexture)
2879         {
2880                 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
2881                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2882                         R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
2883                 R_Mesh_ColorPointer(NULL);
2884         }
2885         else
2886         {
2887                 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2888                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2889                         R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2890                 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
2891         }
2892         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2893 }
2894
2895 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
2896 {
2897         // OpenGL 1.3 path - anything not completely ancient
2898         int texturesurfaceindex;
2899         int lightmode;
2900         qboolean applycolor;
2901         qboolean applyfog;
2902         rmeshstate_t m;
2903         int layerindex;
2904         const texturelayer_t *layer;
2905         CHECKGLERROR
2906         // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
2907         lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
2908         if (rsurface_mode != RSURFMODE_MULTIPASS)
2909                 rsurface_mode = RSURFMODE_MULTIPASS;
2910         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
2911         for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
2912         {
2913                 vec4_t layercolor;
2914                 int layertexrgbscale;
2915                 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2916                 {
2917                         if (layerindex == 0)
2918                                 GL_AlphaTest(true);
2919                         else
2920                         {
2921                                 GL_AlphaTest(false);
2922                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
2923                         }
2924                 }
2925                 GL_DepthMask(layer->depthmask);
2926                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2927                 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2928                 {
2929                         layertexrgbscale = 4;
2930                         VectorScale(layer->color, 0.25f, layercolor);
2931                 }
2932                 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2933                 {
2934                         layertexrgbscale = 2;
2935                         VectorScale(layer->color, 0.5f, layercolor);
2936                 }
2937                 else
2938                 {
2939                         layertexrgbscale = 1;
2940                         VectorScale(layer->color, 1.0f, layercolor);
2941                 }
2942                 layercolor[3] = layer->color[3];
2943                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2944                 R_Mesh_ColorPointer(NULL);
2945                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2946                 switch (layer->type)
2947                 {
2948                 case TEXTURELAYERTYPE_LITTEXTURE:
2949                         memset(&m, 0, sizeof(m));
2950                         if (lightmode >= 1 || !rsurface_lightmaptexture)
2951                                 m.tex[0] = R_GetTexture(r_texture_white);
2952                         else
2953                                 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
2954                         m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
2955                         m.tex[1] = R_GetTexture(layer->texture);
2956                         m.texmatrix[1] = layer->texmatrix;
2957                         m.texrgbscale[1] = layertexrgbscale;
2958                         m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
2959                         R_Mesh_TextureState(&m);
2960                         RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode, applycolor, applyfog);
2961                         break;
2962                 case TEXTURELAYERTYPE_TEXTURE:
2963                         memset(&m, 0, sizeof(m));
2964                         m.tex[0] = R_GetTexture(layer->texture);
2965                         m.texmatrix[0] = layer->texmatrix;
2966                         m.texrgbscale[0] = layertexrgbscale;
2967                         m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
2968                         R_Mesh_TextureState(&m);
2969                         RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2970                         break;
2971                 case TEXTURELAYERTYPE_FOG:
2972                         memset(&m, 0, sizeof(m));
2973                         m.texrgbscale[0] = layertexrgbscale;
2974                         if (layer->texture)
2975                         {
2976                                 m.tex[0] = R_GetTexture(layer->texture);
2977                                 m.texmatrix[0] = layer->texmatrix;
2978                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
2979                         }
2980                         R_Mesh_TextureState(&m);
2981                         // generate a color array for the fog pass
2982                         R_Mesh_ColorPointer(rsurface_array_color4f);
2983                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2984                         {
2985                                 int i;
2986                                 float f, *v, *c;
2987                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2988                                 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)
2989                                 {
2990                                         f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2991                                         c[0] = layercolor[0];
2992                                         c[1] = layercolor[1];
2993                                         c[2] = layercolor[2];
2994                                         c[3] = f * layercolor[3];
2995                                 }
2996                         }
2997                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2998                         break;
2999                 default:
3000                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3001                 }
3002                 GL_LockArrays(0, 0);
3003         }
3004         CHECKGLERROR
3005         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3006         {
3007                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3008                 GL_AlphaTest(false);
3009         }
3010 }
3011
3012 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3013 {
3014         // OpenGL 1.1 - crusty old voodoo path
3015         int texturesurfaceindex;
3016         int lightmode;
3017         qboolean applyfog;
3018         rmeshstate_t m;
3019         int layerindex;
3020         const texturelayer_t *layer;
3021         CHECKGLERROR
3022         // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3023         lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3024         if (rsurface_mode != RSURFMODE_MULTIPASS)
3025                 rsurface_mode = RSURFMODE_MULTIPASS;
3026         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3027         for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3028         {
3029                 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3030                 {
3031                         if (layerindex == 0)
3032                                 GL_AlphaTest(true);
3033                         else
3034                         {
3035                                 GL_AlphaTest(false);
3036                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3037                         }
3038                 }
3039                 GL_DepthMask(layer->depthmask);
3040                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3041                 R_Mesh_ColorPointer(NULL);
3042                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3043                 switch (layer->type)
3044                 {
3045                 case TEXTURELAYERTYPE_LITTEXTURE:
3046                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3047                         {
3048                                 // two-pass lit texture with 2x rgbscale
3049                                 // first the lightmap pass
3050                                 memset(&m, 0, sizeof(m));
3051                                 if (lightmode >= 1 || !rsurface_lightmaptexture)
3052                                         m.tex[0] = R_GetTexture(r_texture_white);
3053                                 else
3054                                         m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3055                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3056                                 R_Mesh_TextureState(&m);
3057                                 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, lightmode, false, false);
3058                                 GL_LockArrays(0, 0);
3059                                 // then apply the texture to it
3060                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3061                                 memset(&m, 0, sizeof(m));
3062                                 m.tex[0] = R_GetTexture(layer->texture);
3063                                 m.texmatrix[0] = layer->texmatrix;
3064                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3065                                 R_Mesh_TextureState(&m);
3066                                 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], 0, layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
3067                         }
3068                         else
3069                         {
3070                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3071                                 memset(&m, 0, sizeof(m));
3072                                 m.tex[0] = R_GetTexture(layer->texture);
3073                                 m.texmatrix[0] = layer->texmatrix;
3074                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3075                                 R_Mesh_TextureState(&m);
3076                                 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], lightmode == 2 ? 2 : 1, layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
3077                         }
3078                         break;
3079                 case TEXTURELAYERTYPE_TEXTURE:
3080                         // singletexture unlit texture with transparency support
3081                         memset(&m, 0, sizeof(m));
3082                         m.tex[0] = R_GetTexture(layer->texture);
3083                         m.texmatrix[0] = layer->texmatrix;
3084                         m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3085                         R_Mesh_TextureState(&m);
3086                         RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], 0, layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
3087                         break;
3088                 case TEXTURELAYERTYPE_FOG:
3089                         // singletexture fogging
3090                         R_Mesh_ColorPointer(rsurface_array_color4f);
3091                         if (layer->texture)
3092                         {
3093                                 memset(&m, 0, sizeof(m));
3094                                 m.tex[0] = R_GetTexture(layer->texture);
3095                                 m.texmatrix[0] = layer->texmatrix;
3096                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3097                                 R_Mesh_TextureState(&m);
3098                         }
3099                         else
3100                                 R_Mesh_ResetTextureState();
3101                         // generate a color array for the fog pass
3102                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3103                         {
3104                                 int i;
3105                                 float f, *v, *c;
3106                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3107                                 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)
3108                                 {
3109                                         f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3110                                         c[0] = layer->color[0];
3111                                         c[1] = layer->color[1];
3112                                         c[2] = layer->color[2];
3113                                         c[3] = f * layer->color[3];
3114                                 }
3115                         }
3116                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3117                         break;
3118                 default:
3119                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3120                 }
3121                 GL_LockArrays(0, 0);
3122         }
3123         CHECKGLERROR
3124         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3125         {
3126                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3127                 GL_AlphaTest(false);
3128         }
3129 }
3130
3131 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3132 {
3133         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3134                 return;
3135         r_shadow_rtlight = NULL;
3136         r_refdef.stats.entities_surfaces += texturenumsurfaces;
3137         CHECKGLERROR
3138         GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3139         if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3140         {
3141                 qglDisable(GL_CULL_FACE);CHECKGLERROR
3142         }
3143         if (r_showsurfaces.integer)
3144                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3145         else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3146                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3147         else if (rsurface_texture->currentnumlayers)
3148         {
3149                 if (r_glsl.integer && gl_support_fragment_shader)
3150                         R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3151                 else if (gl_combine.integer && r_textureunits.integer >= 2)
3152                         R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3153                 else
3154                         R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3155         }
3156         CHECKGLERROR
3157         GL_LockArrays(0, 0);
3158         if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3159         {
3160                 qglEnable(GL_CULL_FACE);CHECKGLERROR
3161         }
3162 }
3163
3164 #define BATCHSIZE 256
3165 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3166 {
3167         int surfacelistindex;
3168         int batchcount;
3169         texture_t *t;
3170         msurface_t *texturesurfacelist[BATCHSIZE];
3171         // if the model is static it doesn't matter what value we give for
3172         // wantnormals and wanttangents, so this logic uses only rules applicable
3173         // to a model, knowing that they are meaningless otherwise
3174         if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3175                 RSurf_ActiveEntity(ent, false, false);
3176         else
3177                 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3178         batchcount = 0;
3179         t = NULL;
3180         for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3181         {
3182                 msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
3183
3184                 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3185                 {
3186                         if (batchcount > 0)
3187                                 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3188                         batchcount = 0;
3189                         t = surface->texture;
3190                         rsurface_lightmaptexture = surface->lightmaptexture;
3191                         R_UpdateTextureInfo(ent, t);
3192                         rsurface_texture = t->currentframe;
3193                 }
3194                 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3195                         continue; // transparent sky is too difficult
3196
3197                 texturesurfacelist[batchcount++] = surface;
3198         }
3199         if (batchcount > 0)
3200                 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3201         RSurf_CleanUp();
3202 }
3203
3204 void R_QueueTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3205 {
3206         int texturesurfaceindex;
3207         vec3_t tempcenter, center;
3208         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3209         {
3210                 // drawing sky transparently would be too difficult
3211                 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY))
3212                 {
3213                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3214                         {
3215                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3216                                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3217                                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3218                                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3219                                 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3220                                 R_MeshQueue_AddTransparent(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, rsurface_entity, surface - rsurface_model->data_surfaces, r_shadow_rtlight);
3221                         }
3222                 }
3223         }
3224         else
3225                 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3226 }
3227
3228 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3229 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3230 {
3231         int i, j, f, flagsmask;
3232         int counttriangles = 0;
3233         texture_t *t;
3234         model_t *model = ent->model;
3235         const int maxsurfacelist = 1024;
3236         int numsurfacelist = 0;
3237         msurface_t *surfacelist[1024];
3238         if (model == NULL)
3239                 return;
3240
3241         // if the model is static it doesn't matter what value we give for
3242         // wantnormals and wanttangents, so this logic uses only rules applicable
3243         // to a model, knowing that they are meaningless otherwise
3244         if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3245                 RSurf_ActiveEntity(ent, false, false);
3246         else
3247                 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3248
3249         // update light styles
3250         if (!skysurfaces && model->brushq1.light_styleupdatechains)
3251         {
3252                 msurface_t *surface, **surfacechain;
3253                 for (i = 0;i < model->brushq1.light_styles;i++)
3254                 {
3255                         if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3256                         {
3257                                 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3258                                 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3259                                         for (;(surface = *surfacechain);surfacechain++)
3260                                                 surface->cached_dlight = true;
3261                         }
3262                 }
3263         }
3264
3265         R_UpdateAllTextureInfo(ent);
3266         flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3267         f = 0;
3268         t = NULL;
3269         rsurface_lightmaptexture = NULL;
3270         rsurface_texture = NULL;
3271         numsurfacelist = 0;
3272         if (ent == r_refdef.worldentity)
3273         {
3274                 msurface_t *surface;
3275                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3276                 {
3277                         if (!r_viewcache.world_surfacevisible[j])
3278                                 continue;
3279                         if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3280                         {
3281                                 if (numsurfacelist)
3282                                 {
3283                                         R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3284                                         numsurfacelist = 0;
3285                                 }
3286                                 t = surface->texture;
3287                                 rsurface_lightmaptexture = surface->lightmaptexture;
3288                                 rsurface_texture = t->currentframe;
3289                                 f = rsurface_texture->currentmaterialflags & flagsmask;
3290                         }
3291                         if (f && surface->num_triangles)
3292                         {
3293                                 // if lightmap parameters changed, rebuild lightmap texture
3294                                 if (surface->cached_dlight)
3295                                         R_BuildLightMap(ent, surface);
3296                                 // add face to draw list
3297                                 surfacelist[numsurfacelist++] = surface;
3298                                 counttriangles += surface->num_triangles;
3299                                 if (numsurfacelist >= maxsurfacelist)
3300                                 {
3301                                         R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3302                                         numsurfacelist = 0;
3303                                 }
3304                         }
3305                 }
3306         }
3307         else
3308         {
3309                 msurface_t *surface;
3310                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3311                 {
3312                         if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3313                         {
3314                                 if (numsurfacelist)
3315                                 {
3316                                         R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3317                                         numsurfacelist = 0;
3318                                 }
3319                                 t = surface->texture;
3320                                 rsurface_lightmaptexture = surface->lightmaptexture;
3321                                 rsurface_texture = t->currentframe;
3322                                 f = rsurface_texture->currentmaterialflags & flagsmask;
3323                         }
3324                         if (f && surface->num_triangles)
3325                         {
3326                                 // if lightmap parameters changed, rebuild lightmap texture
3327                                 if (surface->cached_dlight)
3328                                         R_BuildLightMap(ent, surface);
3329                                 // add face to draw list
3330                                 surfacelist[numsurfacelist++] = surface;
3331                                 counttriangles += surface->num_triangles;
3332                                 if (numsurfacelist >= maxsurfacelist)
3333                                 {
3334                                         R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3335                                         numsurfacelist = 0;
3336                                 }
3337                         }
3338                 }
3339         }
3340         if (numsurfacelist)
3341                 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3342         r_refdef.stats.entities_triangles += counttriangles;
3343         RSurf_CleanUp();
3344
3345         if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3346         {
3347                 int i;
3348                 const msurface_t *surface;
3349                 q3mbrush_t *brush;
3350                 CHECKGLERROR
3351                 R_Mesh_Matrix(&ent->matrix);
3352                 R_Mesh_ColorPointer(NULL);
3353                 R_Mesh_ResetTextureState();
3354                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3355                 GL_DepthMask(false);
3356                 GL_DepthTest(!r_showdisabledepthtest.integer);
3357                 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3358                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3359                         if (brush->colbrushf && brush->colbrushf->numtriangles)
3360                                 R_DrawCollisionBrush(brush->colbrushf);
3361                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3362                         if (surface->num_collisiontriangles)
3363                                 R_DrawCollisionSurface(ent, surface);
3364                 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
3365         }
3366
3367         if (r_showtris.integer || r_shownormals.integer)
3368         {
3369                 int k, l;
3370                 msurface_t *surface;
3371                 const int *elements;
3372                 vec3_t v;
3373                 CHECKGLERROR
3374                 GL_DepthTest(true);
3375                 GL_DepthMask(true);
3376                 if (r_showdisabledepthtest.integer)
3377                 {
3378                         qglDepthFunc(GL_ALWAYS);CHECKGLERROR
3379                 }
3380                 GL_BlendFunc(GL_ONE, GL_ZERO);
3381                 R_Mesh_ColorPointer(NULL);
3382                 R_Mesh_ResetTextureState();
3383                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3384                 {
3385                         if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
3386                                 continue;
3387                         rsurface_texture = surface->texture->currentframe;
3388                         if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3389                         {
3390                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3391                                 if (r_showtris.integer)
3392                                 {
3393                                         if (!rsurface_texture->currentlayers->depthmask)
3394                                                 GL_Color(r_showtris.value, 0, 0, 1);
3395                                         else if (ent == r_refdef.worldentity)
3396                                                 GL_Color(r_showtris.value, r_showtris.value, r_showtris.value, 1);
3397                                         else
3398                                                 GL_Color(0, r_showtris.value, 0, 1);
3399                                         elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3400                                         CHECKGLERROR
3401                                         qglBegin(GL_LINES);
3402                                         for (k = 0;k < surface->num_triangles;k++, elements += 3)
3403                                         {
3404                                                 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3405                                                 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3406                                                 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3407                                         }
3408                                         qglEnd();
3409                                         CHECKGLERROR
3410                                 }
3411                                 if (r_shownormals.integer)
3412                                 {
3413                                         GL_Color(r_shownormals.value, 0, 0, 1);
3414                                         qglBegin(GL_LINES);
3415                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3416                                         {
3417                                                 VectorCopy(rsurface_vertex3f + l * 3, v);
3418                                                 qglVertex3f(v[0], v[1], v[2]);
3419                                                 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3420                                                 qglVertex3f(v[0], v[1], v[2]);
3421                                         }
3422                                         qglEnd();
3423                                         CHECKGLERROR
3424                                         GL_Color(0, 0, r_shownormals.value, 1);
3425                                         qglBegin(GL_LINES);
3426                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3427                                         {
3428                                                 VectorCopy(rsurface_vertex3f + l * 3, v);
3429                                                 qglVertex3f(v[0], v[1], v[2]);
3430                                                 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3431                                                 qglVertex3f(v[0], v[1], v[2]);
3432                                         }
3433                                         qglEnd();
3434                                         CHECKGLERROR
3435                                         GL_Color(0, r_shownormals.value, 0, 1);
3436                                         qglBegin(GL_LINES);
3437                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3438                                         {
3439                                                 VectorCopy(rsurface_vertex3f + l * 3, v);
3440                                                 qglVertex3f(v[0], v[1], v[2]);
3441                                                 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3442                                                 qglVertex3f(v[0], v[1], v[2]);
3443                                         }
3444                                         qglEnd();
3445                                         CHECKGLERROR
3446                                 }
3447                         }
3448                 }
3449                 rsurface_texture = NULL;
3450                 if (r_showdisabledepthtest.integer)
3451                 {
3452                         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3453                 }
3454         }
3455 }
3456