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