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