]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
ignore GL_EXT_texture3D extension if it reports a bogus GL_MAX_3D_TEXTURE_SIZE
[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                         t = t->anim_frames[ent->frame != 0][(t->anim_total[ent->frame != 0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[ent->frame != 0]) : 0];
2173                 texture->currentframe = t;
2174         }
2175
2176         t->currentmaterialflags = t->basematerialflags;
2177         t->currentalpha = ent->alpha;
2178         if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2179                 t->currentalpha *= r_wateralpha.value;
2180         if (!(ent->flags & RENDER_LIGHT))
2181                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2182         if (ent->effects & EF_ADDITIVE)
2183                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2184         else if (t->currentalpha < 1)
2185                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2186         if (ent->effects & EF_NODEPTHTEST)
2187                 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2188         if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2189                 t->currenttexmatrix = r_waterscrollmatrix;
2190         else
2191                 t->currenttexmatrix = identitymatrix;
2192
2193         t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2194         t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2195         t->glosstexture = r_texture_white;
2196         t->specularpower = 8;
2197         t->specularscale = 0;
2198         if (r_shadow_gloss.integer > 0)
2199         {
2200                 if (t->skin.gloss)
2201                 {
2202                         if (r_shadow_glossintensity.value > 0)
2203                         {
2204                                 t->glosstexture = t->skin.gloss;
2205                                 t->specularscale = r_shadow_glossintensity.value;
2206                         }
2207                 }
2208                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2209                         t->specularscale = r_shadow_gloss2intensity.value;
2210         }
2211
2212         t->currentnumlayers = 0;
2213         if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2214         {
2215                 if (gl_lightmaps.integer)
2216                         R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2217                 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2218                 {
2219                         int blendfunc1, blendfunc2, depthmask;
2220                         if (t->currentmaterialflags & MATERIALFLAG_ADD)
2221                         {
2222                                 blendfunc1 = GL_SRC_ALPHA;
2223                                 blendfunc2 = GL_ONE;
2224                         }
2225                         else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2226                         {
2227                                 blendfunc1 = GL_SRC_ALPHA;
2228                                 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2229                         }
2230                         else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2231                         {
2232                                 blendfunc1 = t->customblendfunc[0];
2233                                 blendfunc2 = t->customblendfunc[1];
2234                         }
2235                         else
2236                         {
2237                                 blendfunc1 = GL_ONE;
2238                                 blendfunc2 = GL_ZERO;
2239                         }
2240                         depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2241                         if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2242                         {
2243                                 rtexture_t *currentbasetexture;
2244                                 int layerflags = 0;
2245                                 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2246                                         layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2247                                 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2248                                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2249                                 {
2250                                         // fullbright is not affected by r_refdef.lightmapintensity
2251                                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2252                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2253                                                 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);
2254                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2255                                                 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);
2256                                 }
2257                                 else
2258                                 {
2259                                         float colorscale;
2260                                         colorscale = 2;
2261                                         // q3bsp has no lightmap updates, so the lightstylevalue that
2262                                         // would normally be baked into the lightmap must be
2263                                         // applied to the color
2264                                         if (ent->model->type == mod_brushq3)
2265                                                 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2266                                         colorscale *= r_refdef.lightmapintensity;
2267                                         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);
2268                                         if (r_ambient.value >= (1.0f/64.0f))
2269                                                 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);
2270                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2271                                         {
2272                                                 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);
2273                                                 if (r_ambient.value >= (1.0f/64.0f))
2274                                                         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);
2275                                         }
2276                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2277                                         {
2278                                                 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);
2279                                                 if (r_ambient.value >= (1.0f/64.0f))
2280                                                         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);
2281                                         }
2282                                 }
2283                                 if (t->skin.glow != NULL)
2284                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2285                                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2286                                 {
2287                                         // if this is opaque use alpha blend which will darken the earlier
2288                                         // passes cheaply.
2289                                         //
2290                                         // if this is an alpha blended material, all the earlier passes
2291                                         // were darkened by fog already, so we only need to add the fog
2292                                         // color ontop through the fog mask texture
2293                                         //
2294                                         // if this is an additive blended material, all the earlier passes
2295                                         // were darkened by fog already, and we should not add fog color
2296                                         // (because the background was not darkened, there is no fog color
2297                                         // that was lost behind it).
2298                                         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);
2299                                 }
2300                         }
2301                 }
2302         }
2303 }
2304
2305 void R_UpdateAllTextureInfo(entity_render_t *ent)
2306 {
2307         int i;
2308         if (ent->model)
2309                 for (i = 0;i < ent->model->num_textures;i++)
2310                         R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2311 }
2312
2313 int rsurface_array_size = 0;
2314 float *rsurface_array_modelvertex3f = NULL;
2315 float *rsurface_array_modelsvector3f = NULL;
2316 float *rsurface_array_modeltvector3f = NULL;
2317 float *rsurface_array_modelnormal3f = NULL;
2318 float *rsurface_array_deformedvertex3f = NULL;
2319 float *rsurface_array_deformedsvector3f = NULL;
2320 float *rsurface_array_deformedtvector3f = NULL;
2321 float *rsurface_array_deformednormal3f = NULL;
2322 float *rsurface_array_color4f = NULL;
2323 float *rsurface_array_texcoord3f = NULL;
2324
2325 void R_Mesh_ResizeArrays(int newvertices)
2326 {
2327         float *base;
2328         if (rsurface_array_size >= newvertices)
2329                 return;
2330         if (rsurface_array_modelvertex3f)
2331                 Mem_Free(rsurface_array_modelvertex3f);
2332         rsurface_array_size = (newvertices + 1023) & ~1023;
2333         base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2334         rsurface_array_modelvertex3f     = base + rsurface_array_size * 0;
2335         rsurface_array_modelsvector3f    = base + rsurface_array_size * 3;
2336         rsurface_array_modeltvector3f    = base + rsurface_array_size * 6;
2337         rsurface_array_modelnormal3f     = base + rsurface_array_size * 9;
2338         rsurface_array_deformedvertex3f  = base + rsurface_array_size * 12;
2339         rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2340         rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2341         rsurface_array_deformednormal3f  = base + rsurface_array_size * 21;
2342         rsurface_array_texcoord3f        = base + rsurface_array_size * 24;
2343         rsurface_array_color4f           = base + rsurface_array_size * 27;
2344 }
2345
2346 float *rsurface_modelvertex3f;
2347 float *rsurface_modelsvector3f;
2348 float *rsurface_modeltvector3f;
2349 float *rsurface_modelnormal3f;
2350 float *rsurface_vertex3f;
2351 float *rsurface_svector3f;
2352 float *rsurface_tvector3f;
2353 float *rsurface_normal3f;
2354 float *rsurface_lightmapcolor4f;
2355 vec3_t rsurface_modelorg;
2356 qboolean rsurface_generatedvertex;
2357 const entity_render_t *rsurface_entity;
2358 const model_t *rsurface_model;
2359 texture_t *rsurface_texture;
2360 rtexture_t *rsurface_lightmaptexture;
2361 rsurfmode_t rsurface_mode;
2362 texture_t *rsurface_glsl_texture;
2363 qboolean rsurface_glsl_uselightmap;
2364
2365 void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2366 {
2367         Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2368         rsurface_entity = ent;
2369         rsurface_model = ent->model;
2370         if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2371                 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2372         R_Mesh_Matrix(&ent->matrix);
2373         Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2374         if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && (rsurface_model->surfmesh.data_morphvertex3f || rsurface_model->surfmesh.data_vertexweightindex4i))
2375         {
2376                 if (wanttangents)
2377                 {
2378                         rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2379                         rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2380                         rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2381                         rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2382                         Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2383                 }
2384                 else if (wantnormals)
2385                 {
2386                         rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2387                         rsurface_modelsvector3f = NULL;
2388                         rsurface_modeltvector3f = NULL;
2389                         rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2390                         Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2391                 }
2392                 else
2393                 {
2394                         rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2395                         rsurface_modelsvector3f = NULL;
2396                         rsurface_modeltvector3f = NULL;
2397                         rsurface_modelnormal3f = NULL;
2398                         Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2399                 }
2400                 rsurface_generatedvertex = true;
2401         }
2402         else
2403         {
2404                 rsurface_modelvertex3f  = rsurface_model->surfmesh.data_vertex3f;
2405                 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2406                 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2407                 rsurface_modelnormal3f  = rsurface_model->surfmesh.data_normal3f;
2408                 rsurface_generatedvertex = false;
2409         }
2410         rsurface_vertex3f  = rsurface_modelvertex3f;
2411         rsurface_svector3f = rsurface_modelsvector3f;
2412         rsurface_tvector3f = rsurface_modeltvector3f;
2413         rsurface_normal3f  = rsurface_modelnormal3f;
2414         rsurface_mode = RSURFMODE_NONE;
2415         rsurface_lightmaptexture = NULL;
2416         rsurface_texture = NULL;
2417         rsurface_glsl_texture = NULL;
2418         rsurface_glsl_uselightmap = false;
2419 }
2420
2421 void RSurf_CleanUp(void)
2422 {
2423         CHECKGLERROR
2424         if (rsurface_mode == RSURFMODE_GLSL)
2425         {
2426                 qglUseProgramObjectARB(0);CHECKGLERROR
2427         }
2428         GL_AlphaTest(false);
2429         rsurface_mode = RSURFMODE_NONE;
2430         rsurface_lightmaptexture = NULL;
2431         rsurface_texture = NULL;
2432         rsurface_glsl_texture = NULL;
2433         rsurface_glsl_uselightmap = false;
2434 }
2435
2436 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2437 {
2438         if (rsurface_generatedvertex)
2439         {
2440                 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2441                         generatetangents = true;
2442                 if (generatetangents)
2443                         generatenormals = true;
2444                 if (generatenormals && !rsurface_modelnormal3f)
2445                 {
2446                         rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2447                         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);
2448                 }
2449                 if (generatetangents && !rsurface_modelsvector3f)
2450                 {
2451                         rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2452                         rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2453                         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);
2454                 }
2455         }
2456         if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2457         {
2458                 int texturesurfaceindex;
2459                 float center[3], forward[3], right[3], up[3], v[4][3];
2460                 matrix4x4_t matrix1, imatrix1;
2461                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
2462                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
2463                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
2464                 // make deformed versions of only the vertices used by the specified surfaces
2465                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2466                 {
2467                         int i, j;
2468                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2469                         // a single autosprite surface can contain multiple sprites...
2470                         for (j = 0;j < surface->num_vertices - 3;j += 4)
2471                         {
2472                                 VectorClear(center);
2473                                 for (i = 0;i < 4;i++)
2474                                         VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2475                                 VectorScale(center, 0.25f, center);
2476                                 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2477                                 {
2478                                         forward[0] = rsurface_modelorg[0] - center[0];
2479                                         forward[1] = rsurface_modelorg[1] - center[1];
2480                                         forward[2] = 0;
2481                                         VectorNormalize(forward);
2482                                         right[0] = forward[1];
2483                                         right[1] = -forward[0];
2484                                         right[2] = 0;
2485                                         VectorSet(up, 0, 0, 1);
2486                                 }
2487                                 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2488                                 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);
2489                                 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2490                                 for (i = 0;i < 4;i++)
2491                                         Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2492                                 for (i = 0;i < 4;i++)
2493                                         VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_modelvertex3f + (surface->num_firstvertex+i+j) * 3);
2494                         }
2495                         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);
2496                         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);
2497                 }
2498                 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2499                 rsurface_svector3f = rsurface_array_deformedsvector3f;
2500                 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2501                 rsurface_normal3f = rsurface_array_deformednormal3f;
2502         }
2503         R_Mesh_VertexPointer(rsurface_vertex3f);
2504 }
2505
2506 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
2507 {
2508         int texturesurfaceindex;
2509         const msurface_t *surface = texturesurfacelist[0];
2510         int firstvertex = surface->num_firstvertex;
2511         int endvertex = surface->num_firstvertex + surface->num_vertices;
2512         if (texturenumsurfaces == 1)
2513         {
2514                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2515                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2516         }
2517         else if (r_batchmode.integer == 2)
2518         {
2519                 #define MAXBATCHTRIANGLES 4096
2520                 int batchtriangles = 0;
2521                 int batchelements[MAXBATCHTRIANGLES*3];
2522                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2523                 {
2524                         surface = texturesurfacelist[texturesurfaceindex];
2525                         if (surface->num_triangles >= 256 || (batchtriangles == 0 && texturesurfaceindex + 1 >= texturenumsurfaces))
2526                         {
2527                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2528                                 continue;
2529                         }
2530                         if (batchtriangles + surface->num_triangles > MAXBATCHTRIANGLES)
2531                         {
2532                                 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2533                                 batchtriangles = 0;
2534                                 firstvertex = surface->num_firstvertex;
2535                                 endvertex = surface->num_firstvertex + surface->num_vertices;
2536                         }
2537                         else
2538                         {
2539                                 firstvertex = min(firstvertex, surface->num_firstvertex);
2540                                 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2541                         }
2542                         memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
2543                         batchtriangles += surface->num_triangles;
2544                 }
2545                 if (batchtriangles)
2546                         R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2547         }
2548         else if (r_batchmode.integer == 1)
2549         {
2550                 int firsttriangle = 0;
2551                 int endtriangle = -1;
2552                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2553                 {
2554                         surface = texturesurfacelist[texturesurfaceindex];
2555                         if (surface->num_firsttriangle != endtriangle)
2556                         {
2557                                 if (endtriangle > firsttriangle)
2558                                 {
2559                                         GL_LockArrays(firstvertex, endvertex - firstvertex);
2560                                         R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2561                                 }
2562                                 firstvertex = surface->num_firstvertex;
2563                                 endvertex = surface->num_firstvertex + surface->num_vertices;
2564                                 firsttriangle = surface->num_firsttriangle;
2565                         }
2566                         else
2567                         {
2568                                 firstvertex = min(firstvertex, surface->num_firstvertex);
2569                                 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2570                         }
2571                         endtriangle = surface->num_firsttriangle + surface->num_triangles;
2572                 }
2573                 if (endtriangle > firsttriangle)
2574                 {
2575                         GL_LockArrays(firstvertex, endvertex - firstvertex);
2576                         R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2577                 }
2578         }
2579         else
2580         {
2581                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2582                 {
2583                         surface = texturesurfacelist[texturesurfaceindex];
2584                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2585                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2586                 }
2587         }
2588 }
2589
2590 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2591 {
2592         int texturesurfaceindex;
2593         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2594         {
2595                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2596                 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2597                 GL_Color((k & 15) * (1.0f / 16.0f), ((k >> 4) & 15) * (1.0f / 16.0f), ((k >> 8) & 15) * (1.0f / 16.0f), 0.2f);
2598                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2599                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2600         }
2601 }
2602
2603 static void RSurf_DrawBatch_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2604 {
2605         int texturesurfaceindex;
2606         int i;
2607         float f;
2608         float *v, *c, *c2;
2609         // TODO: optimize
2610         if (lightmode >= 2)
2611         {
2612                 // model lighting
2613                 vec3_t ambientcolor;
2614                 vec3_t diffusecolor;
2615                 vec3_t lightdir;
2616                 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2617                 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2618                 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2619                 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2620                 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2621                 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2622                 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2623                 if (VectorLength2(diffusecolor) > 0)
2624                 {
2625                         // generate color arrays for the surfaces in this list
2626                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2627                         {
2628                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2629                                 int numverts = surface->num_vertices;
2630                                 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2631                                 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2632                                 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2633                                 // q3-style directional shading
2634                                 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2635                                 {
2636                                         if ((f = DotProduct(c2, lightdir)) > 0)
2637                                                 VectorMA(ambientcolor, f, diffusecolor, c);
2638                                         else
2639                                                 VectorCopy(ambientcolor, c);
2640                                         c[3] = a;
2641                                 }
2642                         }
2643                         r = 1;
2644                         g = 1;
2645                         b = 1;
2646                         a = 1;
2647                         applycolor = false;
2648                         rsurface_lightmapcolor4f = rsurface_array_color4f;
2649                 }
2650                 else
2651                 {
2652                         r = ambientcolor[0];
2653                         g = ambientcolor[1];
2654                         b = ambientcolor[2];
2655                         rsurface_lightmapcolor4f = NULL;
2656                 }
2657         }
2658         else if (lightmode >= 1 || !rsurface_lightmaptexture)
2659         {
2660                 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
2661                 {
2662                         // generate color arrays for the surfaces in this list
2663                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2664                         {
2665                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2666                                 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2667                                 {
2668                                         if (surface->lightmapinfo->samples)
2669                                         {
2670                                                 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2671                                                 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2672                                                 VectorScale(lm, scale, c);
2673                                                 if (surface->lightmapinfo->styles[1] != 255)
2674                                                 {
2675                                                         int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2676                                                         lm += size3;
2677                                                         scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2678                                                         VectorMA(c, scale, lm, c);
2679                                                         if (surface->lightmapinfo->styles[2] != 255)
2680                                                         {
2681                                                                 lm += size3;
2682                                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2683                                                                 VectorMA(c, scale, lm, c);
2684                                                                 if (surface->lightmapinfo->styles[3] != 255)
2685                                                                 {
2686                                                                         lm += size3;
2687                                                                         scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2688                                                                         VectorMA(c, scale, lm, c);
2689                                                                 }
2690                                                         }
2691                                                 }
2692                                         }
2693                                         else
2694                                                 VectorClear(c);
2695                                         c[3] = 1;
2696                                 }
2697                         }
2698                         rsurface_lightmapcolor4f = rsurface_array_color4f;
2699                 }
2700                 else
2701                         rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2702         }
2703         else
2704         {
2705                 // just lightmap it
2706                 rsurface_lightmapcolor4f = NULL;
2707         }
2708         if (applyfog)
2709         {
2710                 if (rsurface_lightmapcolor4f)
2711                 {
2712                         // generate color arrays for the surfaces in this list
2713                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2714                         {
2715                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2716                                 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)
2717                                 {
2718                                         f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2719                                         c2[0] = c[0] * f;
2720                                         c2[1] = c[1] * f;
2721                                         c2[2] = c[2] * f;
2722                                         c2[3] = c[3];
2723                                 }
2724                         }
2725                 }
2726                 else
2727                 {
2728                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2729                         {
2730                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2731                                 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)
2732                                 {
2733                                         f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2734                                         c2[0] = f;
2735                                         c2[1] = f;
2736                                         c2[2] = f;
2737                                         c2[3] = 1;
2738                                 }
2739                         }
2740                 }
2741                 rsurface_lightmapcolor4f = rsurface_array_color4f;
2742         }
2743         if (applycolor && rsurface_lightmapcolor4f)
2744         {
2745                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2746                 {
2747                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2748                         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)
2749                         {
2750                                 c2[0] = c[0] * r;
2751                                 c2[1] = c[1] * g;
2752                                 c2[2] = c[2] * b;
2753                                 c2[3] = c[3] * a;
2754                         }
2755                 }
2756                 rsurface_lightmapcolor4f = rsurface_array_color4f;
2757         }
2758         R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2759         GL_Color(r, g, b, a);
2760         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2761 }
2762
2763 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2764 {
2765         if (rsurface_mode != RSURFMODE_SHOWSURFACES)
2766         {
2767                 rsurface_mode = RSURFMODE_SHOWSURFACES;
2768                 GL_DepthMask(true);
2769                 GL_BlendFunc(GL_ONE, GL_ZERO);
2770                 R_Mesh_ColorPointer(NULL);
2771                 R_Mesh_ResetTextureState();
2772         }
2773         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2774         RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
2775 }
2776
2777 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
2778 {
2779         // transparent sky would be ridiculous
2780         if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2781                 return;
2782         if (rsurface_mode != RSURFMODE_SKY)
2783         {
2784                 if (rsurface_mode == RSURFMODE_GLSL)
2785                 {
2786                         qglUseProgramObjectARB(0);CHECKGLERROR
2787                 }
2788                 rsurface_mode = RSURFMODE_SKY;
2789         }
2790         if (skyrendernow)
2791         {
2792                 skyrendernow = false;
2793                 R_Sky();
2794                 // restore entity matrix
2795                 R_Mesh_Matrix(&rsurface_entity->matrix);
2796         }
2797         GL_DepthMask(true);
2798         // LordHavoc: HalfLife maps have freaky skypolys so don't use
2799         // skymasking on them, and Quake3 never did sky masking (unlike
2800         // software Quake and software Quake2), so disable the sky masking
2801         // in Quake3 maps as it causes problems with q3map2 sky tricks,
2802         // and skymasking also looks very bad when noclipping outside the
2803         // level, so don't use it then either.
2804         if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
2805         {
2806                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
2807                 R_Mesh_ColorPointer(NULL);
2808                 R_Mesh_ResetTextureState();
2809                 if (skyrendermasked)
2810                 {
2811                         // depth-only (masking)
2812                         GL_ColorMask(0,0,0,0);
2813                         // just to make sure that braindead drivers don't draw
2814                         // anything despite that colormask...
2815                         GL_BlendFunc(GL_ZERO, GL_ONE);
2816                 }
2817                 else
2818                 {
2819                         // fog sky
2820                         GL_BlendFunc(GL_ONE, GL_ZERO);
2821                 }
2822                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2823                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2824                 if (skyrendermasked)
2825                         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2826         }
2827 }
2828
2829 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
2830 {
2831         int lightmode;
2832         // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
2833         lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
2834         if (rsurface_mode != RSURFMODE_GLSL)
2835         {
2836                 rsurface_mode = RSURFMODE_GLSL;
2837                 rsurface_glsl_texture = NULL;
2838                 rsurface_glsl_uselightmap = false;
2839                 R_Mesh_ResetTextureState();
2840         }
2841         if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != (rsurface_lightmaptexture != NULL))
2842         {
2843                 rsurface_glsl_texture = rsurface_texture;
2844                 rsurface_glsl_uselightmap = rsurface_lightmaptexture != NULL;
2845                 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
2846                 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
2847                 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
2848                 R_SetupSurfaceShader(vec3_origin, lightmode == 2);
2849                 //permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, false);
2850                 //if (r_glsl_deluxemapping.integer)
2851                 //      permutation_deluxemapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, true);
2852                 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
2853                 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
2854                 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2855         }
2856         if (!r_glsl_permutation)
2857                 return;
2858         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
2859         R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2860         R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2861         R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2862         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2863         {
2864                 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2865                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2866                         R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2867                 R_Mesh_ColorPointer(NULL);
2868         }
2869         else if (rsurface_lightmaptexture)
2870         {
2871                 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
2872                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2873                         R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
2874                 R_Mesh_ColorPointer(NULL);
2875         }
2876         else
2877         {
2878                 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2879                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2880                         R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2881                 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
2882         }
2883         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2884 }
2885
2886 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
2887 {
2888         // OpenGL 1.3 path - anything not completely ancient
2889         int texturesurfaceindex;
2890         int lightmode;
2891         qboolean applycolor;
2892         qboolean applyfog;
2893         rmeshstate_t m;
2894         int layerindex;
2895         const texturelayer_t *layer;
2896         CHECKGLERROR
2897         // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
2898         lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
2899         if (rsurface_mode != RSURFMODE_MULTIPASS)
2900                 rsurface_mode = RSURFMODE_MULTIPASS;
2901         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
2902         for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
2903         {
2904                 vec4_t layercolor;
2905                 int layertexrgbscale;
2906                 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2907                 {
2908                         if (layerindex == 0)
2909                                 GL_AlphaTest(true);
2910                         else
2911                         {
2912                                 GL_AlphaTest(false);
2913                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
2914                         }
2915                 }
2916                 GL_DepthMask(layer->depthmask);
2917                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2918                 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2919                 {
2920                         layertexrgbscale = 4;
2921                         VectorScale(layer->color, 0.25f, layercolor);
2922                 }
2923                 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2924                 {
2925                         layertexrgbscale = 2;
2926                         VectorScale(layer->color, 0.5f, layercolor);
2927                 }
2928                 else
2929                 {
2930                         layertexrgbscale = 1;
2931                         VectorScale(layer->color, 1.0f, layercolor);
2932                 }
2933                 layercolor[3] = layer->color[3];
2934                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2935                 R_Mesh_ColorPointer(NULL);
2936                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2937                 switch (layer->type)
2938                 {
2939                 case TEXTURELAYERTYPE_LITTEXTURE:
2940                         memset(&m, 0, sizeof(m));
2941                         if (lightmode >= 1 || !rsurface_lightmaptexture)
2942                                 m.tex[0] = R_GetTexture(r_texture_white);
2943                         else
2944                                 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
2945                         m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
2946                         m.tex[1] = R_GetTexture(layer->texture);
2947                         m.texmatrix[1] = layer->texmatrix;
2948                         m.texrgbscale[1] = layertexrgbscale;
2949                         m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
2950                         R_Mesh_TextureState(&m);
2951                         RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode, applycolor, applyfog);
2952                         break;
2953                 case TEXTURELAYERTYPE_TEXTURE:
2954                         memset(&m, 0, sizeof(m));
2955                         m.tex[0] = R_GetTexture(layer->texture);
2956                         m.texmatrix[0] = layer->texmatrix;
2957                         m.texrgbscale[0] = layertexrgbscale;
2958                         m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
2959                         R_Mesh_TextureState(&m);
2960                         RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2961                         break;
2962                 case TEXTURELAYERTYPE_FOG:
2963                         memset(&m, 0, sizeof(m));
2964                         m.texrgbscale[0] = layertexrgbscale;
2965                         if (layer->texture)
2966                         {
2967                                 m.tex[0] = R_GetTexture(layer->texture);
2968                                 m.texmatrix[0] = layer->texmatrix;
2969                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
2970                         }
2971                         R_Mesh_TextureState(&m);
2972                         // generate a color array for the fog pass
2973                         R_Mesh_ColorPointer(rsurface_array_color4f);
2974                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2975                         {
2976                                 int i;
2977                                 float f, *v, *c;
2978                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2979                                 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)
2980                                 {
2981                                         f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2982                                         c[0] = layercolor[0];
2983                                         c[1] = layercolor[1];
2984                                         c[2] = layercolor[2];
2985                                         c[3] = f * layercolor[3];
2986                                 }
2987                         }
2988                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2989                         break;
2990                 default:
2991                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2992                 }
2993                 GL_LockArrays(0, 0);
2994         }
2995         CHECKGLERROR
2996         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2997         {
2998                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2999                 GL_AlphaTest(false);
3000         }
3001 }
3002
3003 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3004 {
3005         // OpenGL 1.1 - crusty old voodoo path
3006         int texturesurfaceindex;
3007         int lightmode;
3008         qboolean applyfog;
3009         rmeshstate_t m;
3010         int layerindex;
3011         const texturelayer_t *layer;
3012         CHECKGLERROR
3013         // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3014         lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3015         if (rsurface_mode != RSURFMODE_MULTIPASS)
3016                 rsurface_mode = RSURFMODE_MULTIPASS;
3017         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3018         for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3019         {
3020                 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3021                 {
3022                         if (layerindex == 0)
3023                                 GL_AlphaTest(true);
3024                         else
3025                         {
3026                                 GL_AlphaTest(false);
3027                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3028                         }
3029                 }
3030                 GL_DepthMask(layer->depthmask);
3031                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3032                 R_Mesh_ColorPointer(NULL);
3033                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3034                 switch (layer->type)
3035                 {
3036                 case TEXTURELAYERTYPE_LITTEXTURE:
3037                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3038                         {
3039                                 // two-pass lit texture with 2x rgbscale
3040                                 // first the lightmap pass
3041                                 memset(&m, 0, sizeof(m));
3042                                 if (lightmode >= 1 || !rsurface_lightmaptexture)
3043                                         m.tex[0] = R_GetTexture(r_texture_white);
3044                                 else
3045                                         m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3046                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3047                                 R_Mesh_TextureState(&m);
3048                                 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, lightmode, false, false);
3049                                 GL_LockArrays(0, 0);
3050                                 // then apply the texture to it
3051                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3052                                 memset(&m, 0, sizeof(m));
3053                                 m.tex[0] = R_GetTexture(layer->texture);
3054                                 m.texmatrix[0] = layer->texmatrix;
3055                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3056                                 R_Mesh_TextureState(&m);
3057                                 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);
3058                         }
3059                         else
3060                         {
3061                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3062                                 memset(&m, 0, sizeof(m));
3063                                 m.tex[0] = R_GetTexture(layer->texture);
3064                                 m.texmatrix[0] = layer->texmatrix;
3065                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3066                                 R_Mesh_TextureState(&m);
3067                                 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);
3068                         }
3069                         break;
3070                 case TEXTURELAYERTYPE_TEXTURE:
3071                         // singletexture unlit texture with transparency support
3072                         memset(&m, 0, sizeof(m));
3073                         m.tex[0] = R_GetTexture(layer->texture);
3074                         m.texmatrix[0] = layer->texmatrix;
3075                         m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3076                         R_Mesh_TextureState(&m);
3077                         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);
3078                         break;
3079                 case TEXTURELAYERTYPE_FOG:
3080                         // singletexture fogging
3081                         R_Mesh_ColorPointer(rsurface_array_color4f);
3082                         if (layer->texture)
3083                         {
3084                                 memset(&m, 0, sizeof(m));
3085                                 m.tex[0] = R_GetTexture(layer->texture);
3086                                 m.texmatrix[0] = layer->texmatrix;
3087                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3088                                 R_Mesh_TextureState(&m);
3089                         }
3090                         else
3091                                 R_Mesh_ResetTextureState();
3092                         // generate a color array for the fog pass
3093                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3094                         {
3095                                 int i;
3096                                 float f, *v, *c;
3097                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3098                                 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)
3099                                 {
3100                                         f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3101                                         c[0] = layer->color[0];
3102                                         c[1] = layer->color[1];
3103                                         c[2] = layer->color[2];
3104                                         c[3] = f * layer->color[3];
3105                                 }
3106                         }
3107                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3108                         break;
3109                 default:
3110                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3111                 }
3112                 GL_LockArrays(0, 0);
3113         }
3114         CHECKGLERROR
3115         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3116         {
3117                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3118                 GL_AlphaTest(false);
3119         }
3120 }
3121
3122 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3123 {
3124         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3125                 return;
3126         r_shadow_rtlight = NULL;
3127         r_refdef.stats.entities_surfaces += texturenumsurfaces;
3128         CHECKGLERROR
3129         GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3130         if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3131         {
3132                 qglDisable(GL_CULL_FACE);CHECKGLERROR
3133         }
3134         if (r_showsurfaces.integer)
3135                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3136         else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3137                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3138         else if (rsurface_texture->currentnumlayers)
3139         {
3140                 if (r_glsl.integer && gl_support_fragment_shader)
3141                         R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3142                 else if (gl_combine.integer && r_textureunits.integer >= 2)
3143                         R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3144                 else
3145                         R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3146         }
3147         CHECKGLERROR
3148         GL_LockArrays(0, 0);
3149         if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3150         {
3151                 qglEnable(GL_CULL_FACE);CHECKGLERROR
3152         }
3153 }
3154
3155 #define BATCHSIZE 256
3156 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3157 {
3158         int surfacelistindex;
3159         int batchcount;
3160         texture_t *t;
3161         msurface_t *texturesurfacelist[BATCHSIZE];
3162         // if the model is static it doesn't matter what value we give for
3163         // wantnormals and wanttangents, so this logic uses only rules applicable
3164         // to a model, knowing that they are meaningless otherwise
3165         if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3166                 RSurf_ActiveEntity(ent, false, false);
3167         else
3168                 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3169         batchcount = 0;
3170         t = NULL;
3171         for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3172         {
3173                 msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
3174
3175                 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3176                 {
3177                         if (batchcount > 0)
3178                                 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3179                         batchcount = 0;
3180                         t = surface->texture;
3181                         rsurface_lightmaptexture = surface->lightmaptexture;
3182                         R_UpdateTextureInfo(ent, t);
3183                         rsurface_texture = t->currentframe;
3184                 }
3185                 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3186                         continue; // transparent sky is too difficult
3187
3188                 texturesurfacelist[batchcount++] = surface;
3189         }
3190         if (batchcount > 0)
3191                 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3192         RSurf_CleanUp();
3193 }
3194
3195 void R_QueueTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3196 {
3197         int texturesurfaceindex;
3198         vec3_t tempcenter, center;
3199         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3200         {
3201                 // drawing sky transparently would be too difficult
3202                 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY))
3203                 {
3204                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3205                         {
3206                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3207                                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3208                                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3209                                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3210                                 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3211                                 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);
3212                         }
3213                 }
3214         }
3215         else
3216                 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3217 }
3218
3219 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3220 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3221 {
3222         int i, j, f, flagsmask;
3223         int counttriangles = 0;
3224         texture_t *t;
3225         model_t *model = ent->model;
3226         const int maxsurfacelist = 1024;
3227         int numsurfacelist = 0;
3228         msurface_t *surfacelist[1024];
3229         if (model == NULL)
3230                 return;
3231
3232         // if the model is static it doesn't matter what value we give for
3233         // wantnormals and wanttangents, so this logic uses only rules applicable
3234         // to a model, knowing that they are meaningless otherwise
3235         if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3236                 RSurf_ActiveEntity(ent, false, false);
3237         else
3238                 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3239
3240         // update light styles
3241         if (!skysurfaces && model->brushq1.light_styleupdatechains)
3242         {
3243                 msurface_t *surface, **surfacechain;
3244                 for (i = 0;i < model->brushq1.light_styles;i++)
3245                 {
3246                         if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3247                         {
3248                                 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3249                                 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3250                                         for (;(surface = *surfacechain);surfacechain++)
3251                                                 surface->cached_dlight = true;
3252                         }
3253                 }
3254         }
3255
3256         R_UpdateAllTextureInfo(ent);
3257         flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3258         f = 0;
3259         t = NULL;
3260         rsurface_lightmaptexture = NULL;
3261         rsurface_texture = NULL;
3262         numsurfacelist = 0;
3263         if (ent == r_refdef.worldentity)
3264         {
3265                 msurface_t *surface;
3266                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3267                 {
3268                         if (!r_viewcache.world_surfacevisible[j])
3269                                 continue;
3270                         if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3271                         {
3272                                 if (numsurfacelist)
3273                                 {
3274                                         R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3275                                         numsurfacelist = 0;
3276                                 }
3277                                 t = surface->texture;
3278                                 rsurface_lightmaptexture = surface->lightmaptexture;
3279                                 rsurface_texture = t->currentframe;
3280                                 f = rsurface_texture->currentmaterialflags & flagsmask;
3281                         }
3282                         if (f && surface->num_triangles)
3283                         {
3284                                 // if lightmap parameters changed, rebuild lightmap texture
3285                                 if (surface->cached_dlight)
3286                                         R_BuildLightMap(ent, surface);
3287                                 // add face to draw list
3288                                 surfacelist[numsurfacelist++] = surface;
3289                                 counttriangles += surface->num_triangles;
3290                                 if (numsurfacelist >= maxsurfacelist)
3291                                 {
3292                                         R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3293                                         numsurfacelist = 0;
3294                                 }
3295                         }
3296                 }
3297         }
3298         else
3299         {
3300                 msurface_t *surface;
3301                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3302                 {
3303                         if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3304                         {
3305                                 if (numsurfacelist)
3306                                 {
3307                                         R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3308                                         numsurfacelist = 0;
3309                                 }
3310                                 t = surface->texture;
3311                                 rsurface_lightmaptexture = surface->lightmaptexture;
3312                                 rsurface_texture = t->currentframe;
3313                                 f = rsurface_texture->currentmaterialflags & flagsmask;
3314                         }
3315                         if (f && surface->num_triangles)
3316                         {
3317                                 // if lightmap parameters changed, rebuild lightmap texture
3318                                 if (surface->cached_dlight)
3319                                         R_BuildLightMap(ent, surface);
3320                                 // add face to draw list
3321                                 surfacelist[numsurfacelist++] = surface;
3322                                 counttriangles += surface->num_triangles;
3323                                 if (numsurfacelist >= maxsurfacelist)
3324                                 {
3325                                         R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3326                                         numsurfacelist = 0;
3327                                 }
3328                         }
3329                 }
3330         }
3331         if (numsurfacelist)
3332                 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3333         r_refdef.stats.entities_triangles += counttriangles;
3334         RSurf_CleanUp();
3335
3336         if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3337         {
3338                 int i;
3339                 const msurface_t *surface;
3340                 q3mbrush_t *brush;
3341                 CHECKGLERROR
3342                 R_Mesh_Matrix(&ent->matrix);
3343                 R_Mesh_ColorPointer(NULL);
3344                 R_Mesh_ResetTextureState();
3345                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3346                 GL_DepthMask(false);
3347                 GL_DepthTest(!r_showdisabledepthtest.integer);
3348                 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3349                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3350                         if (brush->colbrushf && brush->colbrushf->numtriangles)
3351                                 R_DrawCollisionBrush(brush->colbrushf);
3352                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3353                         if (surface->num_collisiontriangles)
3354                                 R_DrawCollisionSurface(ent, surface);
3355                 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
3356         }
3357
3358         if (r_showtris.integer || r_shownormals.integer)
3359         {
3360                 int k, l;
3361                 msurface_t *surface;
3362                 const int *elements;
3363                 vec3_t v;
3364                 CHECKGLERROR
3365                 GL_DepthTest(true);
3366                 GL_DepthMask(true);
3367                 if (r_showdisabledepthtest.integer)
3368                 {
3369                         qglDepthFunc(GL_ALWAYS);CHECKGLERROR
3370                 }
3371                 GL_BlendFunc(GL_ONE, GL_ZERO);
3372                 R_Mesh_ColorPointer(NULL);
3373                 R_Mesh_ResetTextureState();
3374                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3375                 {
3376                         if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
3377                                 continue;
3378                         rsurface_texture = surface->texture->currentframe;
3379                         if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3380                         {
3381                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3382                                 if (r_showtris.integer)
3383                                 {
3384                                         if (!rsurface_texture->currentlayers->depthmask)
3385                                                 GL_Color(r_showtris.value, 0, 0, 1);
3386                                         else if (ent == r_refdef.worldentity)
3387                                                 GL_Color(r_showtris.value, r_showtris.value, r_showtris.value, 1);
3388                                         else
3389                                                 GL_Color(0, r_showtris.value, 0, 1);
3390                                         elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3391                                         CHECKGLERROR
3392                                         qglBegin(GL_LINES);
3393                                         for (k = 0;k < surface->num_triangles;k++, elements += 3)
3394                                         {
3395                                                 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3396                                                 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3397                                                 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3398                                         }
3399                                         qglEnd();
3400                                         CHECKGLERROR
3401                                 }
3402                                 if (r_shownormals.integer)
3403                                 {
3404                                         GL_Color(r_shownormals.value, 0, 0, 1);
3405                                         qglBegin(GL_LINES);
3406                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3407                                         {
3408                                                 VectorCopy(rsurface_vertex3f + l * 3, v);
3409                                                 qglVertex3f(v[0], v[1], v[2]);
3410                                                 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3411                                                 qglVertex3f(v[0], v[1], v[2]);
3412                                         }
3413                                         qglEnd();
3414                                         CHECKGLERROR
3415                                         GL_Color(0, 0, r_shownormals.value, 1);
3416                                         qglBegin(GL_LINES);
3417                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3418                                         {
3419                                                 VectorCopy(rsurface_vertex3f + l * 3, v);
3420                                                 qglVertex3f(v[0], v[1], v[2]);
3421                                                 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3422                                                 qglVertex3f(v[0], v[1], v[2]);
3423                                         }
3424                                         qglEnd();
3425                                         CHECKGLERROR
3426                                         GL_Color(0, r_shownormals.value, 0, 1);
3427                                         qglBegin(GL_LINES);
3428                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3429                                         {
3430                                                 VectorCopy(rsurface_vertex3f + l * 3, v);
3431                                                 qglVertex3f(v[0], v[1], v[2]);
3432                                                 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3433                                                 qglVertex3f(v[0], v[1], v[2]);
3434                                         }
3435                                         qglEnd();
3436                                         CHECKGLERROR
3437                                 }
3438                         }
3439                 }
3440                 rsurface_texture = NULL;
3441                 if (r_showdisabledepthtest.integer)
3442                 {
3443                         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3444                 }
3445         }
3446 }
3447