]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
added r_glsl_restart command, and modified shaderstring loading back to the old way...
[xonotic/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 "#ifdef USESPECULAR\n"
669 "       myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
670 "       color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
671 "#endif\n"
672 "\n"
673 "\n"
674 "\n"
675 "\n"
676 "#elif defined(MODE_LIGHTDIRECTIONMAP)\n"
677 "       // deluxemap lightmapping\n"
678 "\n"
679 "       // get the surface normal and light normal\n"
680 "#ifdef SURFACENORMALIZE\n"
681 "       myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
682 "       myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5);\n"
683 "#else\n"
684 "       myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
685 "       myhvec3 diffusenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap));\n"
686 "#endif\n"
687 "\n"
688 "       // calculate directional shading\n"
689 "       myhvec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
690 "#ifdef USESPECULAR\n"
691 "       myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
692 "       tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
693 "#endif\n"
694 "\n"
695 "       // apply lightmap color\n"
696 "       color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * myhvec3(AmbientScale);\n"
697 "\n"
698 "\n"
699 "\n"
700 "\n"
701 "#else // MODE none (lightmap)\n"
702 "       // apply lightmap color\n"
703 "       color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
704 "#endif // MODE\n"
705 "\n"
706 "#ifdef USEGLOW\n"
707 "       color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord));\n"
708 "#endif\n"
709 "\n"
710 "#ifdef USEFOG\n"
711 "       // apply fog\n"
712 "       myhalf fog = texture2D(Texture_FogMask, myhvec2(length(EyeVector)*FogRangeRecip, 0.0)).x;\n"
713 "       color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
714 "#endif\n"
715 "\n"
716 "       gl_FragColor = color * gl_Color;\n"
717 "}\n"
718 "#endif // !USEEASTEREGG\n"
719 "\n"
720 "#endif\n"
721 ;
722
723 void R_GLSL_CompilePermutation(int permutation)
724 {
725         r_glsl_permutation_t *p = r_glsl_permutations + permutation;
726         int vertstrings_count;
727         int fragstrings_count;
728         char *shaderstring;
729         const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
730         const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
731         char permutationname[256];
732         if (p->compiled)
733                 return;
734         p->compiled = true;
735         vertstrings_list[0] = "#define VERTEX_SHADER\n";
736         fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
737         vertstrings_count = 1;
738         fragstrings_count = 1;
739         permutationname[0] = 0;
740         if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
741         {
742                 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTSOURCE\n";
743                 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTSOURCE\n";
744                 strlcat(permutationname, " lightsource", sizeof(permutationname));
745         }
746         if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP)
747         {
748                 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP\n";
749                 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP\n";
750                 strlcat(permutationname, " lightdirectionmap", sizeof(permutationname));
751         }
752         if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
753         {
754                 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
755                 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
756                 strlcat(permutationname, " lightdirection", sizeof(permutationname));
757         }
758         if (permutation & SHADERPERMUTATION_GLOW)
759         {
760                 vertstrings_list[vertstrings_count++] = "#define USEGLOW\n";
761                 fragstrings_list[fragstrings_count++] = "#define USEGLOW\n";
762                 strlcat(permutationname, " glow", sizeof(permutationname));
763         }
764         if (permutation & SHADERPERMUTATION_COLORMAPPING)
765         {
766                 vertstrings_list[vertstrings_count++] = "#define USECOLORMAPPING\n";
767                 fragstrings_list[fragstrings_count++] = "#define USECOLORMAPPING\n";
768                 strlcat(permutationname, " colormapping", sizeof(permutationname));
769         }
770         if (permutation & SHADERPERMUTATION_SPECULAR)
771         {
772                 vertstrings_list[vertstrings_count++] = "#define USESPECULAR\n";
773                 fragstrings_list[fragstrings_count++] = "#define USESPECULAR\n";
774                 strlcat(permutationname, " specular", sizeof(permutationname));
775         }
776         if (permutation & SHADERPERMUTATION_FOG)
777         {
778                 vertstrings_list[vertstrings_count++] = "#define USEFOG\n";
779                 fragstrings_list[fragstrings_count++] = "#define USEFOG\n";
780                 strlcat(permutationname, " fog", sizeof(permutationname));
781         }
782         if (permutation & SHADERPERMUTATION_CUBEFILTER)
783         {
784                 vertstrings_list[vertstrings_count++] = "#define USECUBEFILTER\n";
785                 fragstrings_list[fragstrings_count++] = "#define USECUBEFILTER\n";
786                 strlcat(permutationname, " cubefilter", sizeof(permutationname));
787         }
788         if (permutation & SHADERPERMUTATION_OFFSETMAPPING)
789         {
790                 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING\n";
791                 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING\n";
792                 strlcat(permutationname, " offsetmapping", sizeof(permutationname));
793         }
794         if (permutation & SHADERPERMUTATION_SURFACENORMALIZE)
795         {
796                 vertstrings_list[vertstrings_count++] = "#define SURFACENORMALIZE\n";
797                 fragstrings_list[fragstrings_count++] = "#define SURFACENORMALIZE\n";
798                 strlcat(permutationname, " surfacenormalize", sizeof(permutationname));
799         }
800         if (permutation & SHADERPERMUTATION_GEFORCEFX)
801         {
802                 vertstrings_list[vertstrings_count++] = "#define GEFORCEFX\n";
803                 fragstrings_list[fragstrings_count++] = "#define GEFORCEFX\n";
804                 strlcat(permutationname, " halffloat", sizeof(permutationname));
805         }
806         shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
807         if (shaderstring)
808         {
809                 Con_DPrintf("GLSL shader text loaded from disk\n");
810                 vertstrings_list[vertstrings_count++] = shaderstring;
811                 fragstrings_list[fragstrings_count++] = shaderstring;
812         }
813         else
814         {
815                 vertstrings_list[vertstrings_count++] = builtinshaderstring;
816                 fragstrings_list[fragstrings_count++] = builtinshaderstring;
817         }
818         p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
819         if (p->program)
820         {
821                 CHECKGLERROR
822                 qglUseProgramObjectARB(p->program);
823                 p->loc_Texture_Normal      = qglGetUniformLocationARB(p->program, "Texture_Normal");
824                 p->loc_Texture_Color       = qglGetUniformLocationARB(p->program, "Texture_Color");
825                 p->loc_Texture_Gloss       = qglGetUniformLocationARB(p->program, "Texture_Gloss");
826                 p->loc_Texture_Cube        = qglGetUniformLocationARB(p->program, "Texture_Cube");
827                 p->loc_Texture_FogMask     = qglGetUniformLocationARB(p->program, "Texture_FogMask");
828                 p->loc_Texture_Pants       = qglGetUniformLocationARB(p->program, "Texture_Pants");
829                 p->loc_Texture_Shirt       = qglGetUniformLocationARB(p->program, "Texture_Shirt");
830                 p->loc_Texture_Lightmap    = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
831                 p->loc_Texture_Deluxemap   = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
832                 p->loc_Texture_Glow        = qglGetUniformLocationARB(p->program, "Texture_Glow");
833                 p->loc_FogColor            = qglGetUniformLocationARB(p->program, "FogColor");
834                 p->loc_LightPosition       = qglGetUniformLocationARB(p->program, "LightPosition");
835                 p->loc_EyePosition         = qglGetUniformLocationARB(p->program, "EyePosition");
836                 p->loc_LightColor          = qglGetUniformLocationARB(p->program, "LightColor");
837                 p->loc_Color_Pants         = qglGetUniformLocationARB(p->program, "Color_Pants");
838                 p->loc_Color_Shirt         = qglGetUniformLocationARB(p->program, "Color_Shirt");
839                 p->loc_FogRangeRecip       = qglGetUniformLocationARB(p->program, "FogRangeRecip");
840                 p->loc_AmbientScale        = qglGetUniformLocationARB(p->program, "AmbientScale");
841                 p->loc_DiffuseScale        = qglGetUniformLocationARB(p->program, "DiffuseScale");
842                 p->loc_SpecularPower       = qglGetUniformLocationARB(p->program, "SpecularPower");
843                 p->loc_SpecularScale       = qglGetUniformLocationARB(p->program, "SpecularScale");
844                 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
845                 p->loc_OffsetMapping_Bias  = qglGetUniformLocationARB(p->program, "OffsetMapping_Bias");
846                 p->loc_AmbientColor        = qglGetUniformLocationARB(p->program, "AmbientColor");
847                 p->loc_DiffuseColor        = qglGetUniformLocationARB(p->program, "DiffuseColor");
848                 p->loc_SpecularColor       = qglGetUniformLocationARB(p->program, "SpecularColor");
849                 p->loc_LightDir            = qglGetUniformLocationARB(p->program, "LightDir");
850                 if (p->loc_Texture_Normal >= 0)    qglUniform1iARB(p->loc_Texture_Normal, 0);
851                 if (p->loc_Texture_Color >= 0)     qglUniform1iARB(p->loc_Texture_Color, 1);
852                 if (p->loc_Texture_Gloss >= 0)     qglUniform1iARB(p->loc_Texture_Gloss, 2);
853                 if (p->loc_Texture_Cube >= 0)      qglUniform1iARB(p->loc_Texture_Cube, 3);
854                 if (p->loc_Texture_FogMask >= 0)   qglUniform1iARB(p->loc_Texture_FogMask, 4);
855                 if (p->loc_Texture_Pants >= 0)     qglUniform1iARB(p->loc_Texture_Pants, 5);
856                 if (p->loc_Texture_Shirt >= 0)     qglUniform1iARB(p->loc_Texture_Shirt, 6);
857                 if (p->loc_Texture_Lightmap >= 0)  qglUniform1iARB(p->loc_Texture_Lightmap, 7);
858                 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
859                 if (p->loc_Texture_Glow >= 0)      qglUniform1iARB(p->loc_Texture_Glow, 9);
860                 qglUseProgramObjectARB(0);
861                 CHECKGLERROR
862         }
863         else
864                 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
865         if (shaderstring)
866                 Mem_Free(shaderstring);
867 }
868
869 void R_GLSL_Restart_f(void)
870 {
871         int i;
872         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
873                 if (r_glsl_permutations[i].program)
874                         GL_Backend_FreeProgram(r_glsl_permutations[i].program);
875         memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
876 }
877
878 void R_SetupSurfaceShader(const entity_render_t *ent, const texture_t *texture, const vec3_t modelorg, const vec3_t lightcolorbase, qboolean modellighting)
879 {
880         // select a permutation of the lighting shader appropriate to this
881         // combination of texture, entity, light source, and fogging, only use the
882         // minimum features necessary to avoid wasting rendering time in the
883         // fragment shader on features that are not being used
884         int permutation = 0;
885         float specularscale = texture->specularscale;
886         r_glsl_permutation = NULL;
887         if (r_shadow_rtlight)
888         {
889                 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
890                 specularscale *= r_shadow_rtlight->specularscale;
891                 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
892                         permutation |= SHADERPERMUTATION_CUBEFILTER;
893         }
894         else if (modellighting)
895         {
896                 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
897                 if (texture->skin.glow)
898                         permutation |= SHADERPERMUTATION_GLOW;
899         }
900         else if (r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
901         {
902                 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP;
903                 if (texture->skin.glow)
904                         permutation |= SHADERPERMUTATION_GLOW;
905         }
906         else
907         {
908                 if (texture->skin.glow)
909                         permutation |= SHADERPERMUTATION_GLOW;
910         }
911         if (specularscale > 0)
912                 permutation |= SHADERPERMUTATION_SPECULAR;
913         if (fogenabled)
914                 permutation |= SHADERPERMUTATION_FOG;
915         if (texture->colormapping)
916                 permutation |= SHADERPERMUTATION_COLORMAPPING;
917         if (r_glsl_offsetmapping.integer)
918                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
919         if (r_glsl_surfacenormalize.integer)
920                 permutation |= SHADERPERMUTATION_SURFACENORMALIZE;
921         if (r_glsl_usehalffloat.integer)
922                 permutation |= SHADERPERMUTATION_GEFORCEFX;
923         if (!r_glsl_permutations[permutation].program)
924         {
925                 if (!r_glsl_permutations[permutation].compiled)
926                         R_GLSL_CompilePermutation(permutation);
927                 if (!r_glsl_permutations[permutation].program)
928                 {
929                         // remove features until we find a valid permutation
930                         int i;
931                         for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
932                         {
933                                 // reduce i more quickly whenever it would not remove any bits
934                                 if (permutation < i)
935                                         continue;
936                                 permutation &= i;
937                                 if (!r_glsl_permutations[permutation].compiled)
938                                         R_GLSL_CompilePermutation(permutation);
939                                 if (r_glsl_permutations[permutation].program)
940                                         break;
941                                 if (!i)
942                                         return; // utterly failed
943                         }
944                 }
945         }
946         r_glsl_permutation = r_glsl_permutations + permutation;
947         CHECKGLERROR
948         qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
949         R_Mesh_TexMatrix(0, &texture->currenttexmatrix);
950         if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
951         {
952                 R_Mesh_TexMatrix(3, &r_shadow_entitytolight);
953                 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
954                 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]);
955                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
956                 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
957                 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
958                 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
959         }
960         else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
961         {
962                 if (texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
963                 {
964                         if (r_glsl_permutation->loc_AmbientColor >= 0)
965                                 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, 1, 1, 1);
966                         if (r_glsl_permutation->loc_DiffuseColor >= 0)
967                                 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, 0, 0, 0);
968                         if (r_glsl_permutation->loc_SpecularColor >= 0)
969                                 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, 0, 0, 0);
970                         if (r_glsl_permutation->loc_LightDir >= 0)
971                                 qglUniform3fARB(r_glsl_permutation->loc_LightDir, 0, 0, -1);
972                 }
973                 else
974                 {
975                         if (r_glsl_permutation->loc_AmbientColor >= 0)
976                                 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, ent->modellight_ambient[0], ent->modellight_ambient[1], ent->modellight_ambient[2]);
977                         if (r_glsl_permutation->loc_DiffuseColor >= 0)
978                                 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, ent->modellight_diffuse[0], ent->modellight_diffuse[1], ent->modellight_diffuse[2]);
979                         if (r_glsl_permutation->loc_SpecularColor >= 0)
980                                 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, ent->modellight_diffuse[0] * texture->specularscale, ent->modellight_diffuse[1] * texture->specularscale, ent->modellight_diffuse[2] * texture->specularscale);
981                         if (r_glsl_permutation->loc_LightDir >= 0)
982                                 qglUniform3fARB(r_glsl_permutation->loc_LightDir, ent->modellight_lightdir[0], ent->modellight_lightdir[1], ent->modellight_lightdir[2]);
983                 }
984         }
985         else
986         {
987                 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
988                 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_lightmapintensity * 2.0f);
989                 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale * 2.0f);
990         }
991         if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(texture->skin.nmap));
992         if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(texture->basetexture));
993         if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(texture->glosstexture));
994         if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
995         if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(texture->skin.pants));
996         if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(texture->skin.shirt));
997         if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(texture->skin.glow));
998         if (r_glsl_permutation->loc_FogColor >= 0)
999         {
1000                 // additive passes are only darkened by fog, not tinted
1001                 if (r_shadow_rtlight || (texture->currentmaterialflags & MATERIALFLAG_ADD))
1002                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1003                 else
1004                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogcolor[0], fogcolor[1], fogcolor[2]);
1005         }
1006         if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, modelorg[0], modelorg[1], modelorg[2]);
1007         if (r_glsl_permutation->loc_Color_Pants >= 0)
1008         {
1009                 if (texture->skin.pants)
1010                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2]);
1011                 else
1012                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1013         }
1014         if (r_glsl_permutation->loc_Color_Shirt >= 0)
1015         {
1016                 if (texture->skin.shirt)
1017                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2]);
1018                 else
1019                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1020         }
1021         if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, fograngerecip);
1022         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, texture->specularpower);
1023         if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1024         if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Bias, r_glsl_offsetmapping_bias.value);
1025         CHECKGLERROR
1026 }
1027
1028 void gl_main_start(void)
1029 {
1030         // use half float math where available (speed gain on NVIDIA GFFX and GF6)
1031         if (gl_support_half_float)
1032                 Cvar_SetValue("r_glsl_usehalffloat", 1);
1033         r_main_texturepool = R_AllocTexturePool();
1034         r_bloom_texture_screen = NULL;
1035         r_bloom_texture_bloom = NULL;
1036         R_BuildBlankTextures();
1037         R_BuildNoTexture();
1038         if (gl_texturecubemap)
1039         {
1040                 R_BuildWhiteCube();
1041                 R_BuildNormalizationCube();
1042         }
1043         R_BuildFogTexture();
1044         memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1045 }
1046
1047 void gl_main_shutdown(void)
1048 {
1049         R_FreeTexturePool(&r_main_texturepool);
1050         r_bloom_texture_screen = NULL;
1051         r_bloom_texture_bloom = NULL;
1052         r_texture_blanknormalmap = NULL;
1053         r_texture_white = NULL;
1054         r_texture_black = NULL;
1055         r_texture_whitecube = NULL;
1056         r_texture_normalizationcube = NULL;
1057         R_GLSL_Restart_f();
1058 }
1059
1060 extern void CL_ParseEntityLump(char *entitystring);
1061 void gl_main_newmap(void)
1062 {
1063         // FIXME: move this code to client
1064         int l;
1065         char *entities, entname[MAX_QPATH];
1066         r_framecount = 1;
1067         if (cl.worldmodel)
1068         {
1069                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1070                 l = (int)strlen(entname) - 4;
1071                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1072                 {
1073                         strcpy(entname + l, ".ent");
1074                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1075                         {
1076                                 CL_ParseEntityLump(entities);
1077                                 Mem_Free(entities);
1078                                 return;
1079                         }
1080                 }
1081                 if (cl.worldmodel->brush.entities)
1082                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
1083         }
1084 }
1085
1086 void GL_Main_Init(void)
1087 {
1088         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1089
1090         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
1091         FOG_registercvars(); // FIXME: move this fog stuff to client?
1092         Cvar_RegisterVariable(&r_nearclip);
1093         Cvar_RegisterVariable(&r_showtris);
1094         Cvar_RegisterVariable(&r_showtris_polygonoffset);
1095         Cvar_RegisterVariable(&r_shownormals);
1096         Cvar_RegisterVariable(&r_showlighting);
1097         Cvar_RegisterVariable(&r_showshadowvolumes);
1098         Cvar_RegisterVariable(&r_showcollisionbrushes);
1099         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1100         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1101         Cvar_RegisterVariable(&r_showdisabledepthtest);
1102         Cvar_RegisterVariable(&r_drawentities);
1103         Cvar_RegisterVariable(&r_drawviewmodel);
1104         Cvar_RegisterVariable(&r_speeds);
1105         Cvar_RegisterVariable(&r_fullbrights);
1106         Cvar_RegisterVariable(&r_wateralpha);
1107         Cvar_RegisterVariable(&r_dynamic);
1108         Cvar_RegisterVariable(&r_fullbright);
1109         Cvar_RegisterVariable(&r_textureunits);
1110         Cvar_RegisterVariable(&r_glsl);
1111         Cvar_RegisterVariable(&r_glsl_offsetmapping);
1112         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1113         Cvar_RegisterVariable(&r_glsl_offsetmapping_bias);
1114         Cvar_RegisterVariable(&r_glsl_usehalffloat);
1115         Cvar_RegisterVariable(&r_glsl_surfacenormalize);
1116         Cvar_RegisterVariable(&r_lerpsprites);
1117         Cvar_RegisterVariable(&r_lerpmodels);
1118         Cvar_RegisterVariable(&r_waterscroll);
1119         Cvar_RegisterVariable(&r_bloom);
1120         Cvar_RegisterVariable(&r_bloom_intensity);
1121         Cvar_RegisterVariable(&r_bloom_blur);
1122         Cvar_RegisterVariable(&r_bloom_resolution);
1123         Cvar_RegisterVariable(&r_bloom_power);
1124         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1125         Cvar_RegisterVariable(&developer_texturelogging);
1126         Cvar_RegisterVariable(&gl_lightmaps);
1127         Cvar_RegisterVariable(&r_test);
1128         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1129                 Cvar_SetValue("r_fullbrights", 0);
1130         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1131 }
1132
1133 static vec3_t r_farclip_origin;
1134 static vec3_t r_farclip_direction;
1135 static vec_t r_farclip_directiondist;
1136 static vec_t r_farclip_meshfarclip;
1137 static int r_farclip_directionbit0;
1138 static int r_farclip_directionbit1;
1139 static int r_farclip_directionbit2;
1140
1141 // enlarge farclip to accomodate box
1142 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
1143 {
1144         float d;
1145         d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
1146           + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
1147           + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
1148         if (r_farclip_meshfarclip < d)
1149                 r_farclip_meshfarclip = d;
1150 }
1151
1152 // return farclip value
1153 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
1154 {
1155         int i;
1156
1157         VectorCopy(origin, r_farclip_origin);
1158         VectorCopy(direction, r_farclip_direction);
1159         r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
1160         r_farclip_directionbit0 = r_farclip_direction[0] < 0;
1161         r_farclip_directionbit1 = r_farclip_direction[1] < 0;
1162         r_farclip_directionbit2 = r_farclip_direction[2] < 0;
1163         r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
1164
1165         if (r_refdef.worldmodel)
1166                 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1167         for (i = 0;i < r_refdef.numentities;i++)
1168                 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
1169
1170         return r_farclip_meshfarclip - r_farclip_directiondist;
1171 }
1172
1173 extern void R_Textures_Init(void);
1174 extern void GL_Draw_Init(void);
1175 extern void GL_Main_Init(void);
1176 extern void R_Shadow_Init(void);
1177 extern void R_Sky_Init(void);
1178 extern void GL_Surf_Init(void);
1179 extern void R_Crosshairs_Init(void);
1180 extern void R_Light_Init(void);
1181 extern void R_Particles_Init(void);
1182 extern void R_Explosion_Init(void);
1183 extern void gl_backend_init(void);
1184 extern void Sbar_Init(void);
1185 extern void R_LightningBeams_Init(void);
1186 extern void Mod_RenderInit(void);
1187
1188 void Render_Init(void)
1189 {
1190         gl_backend_init();
1191         R_Textures_Init();
1192         R_MeshQueue_Init();
1193         GL_Main_Init();
1194         GL_Draw_Init();
1195         R_Shadow_Init();
1196         R_Sky_Init();
1197         GL_Surf_Init();
1198         R_Crosshairs_Init();
1199         R_Light_Init();
1200         R_Particles_Init();
1201         R_Explosion_Init();
1202         Sbar_Init();
1203         R_LightningBeams_Init();
1204         Mod_RenderInit();
1205 }
1206
1207 /*
1208 ===============
1209 GL_Init
1210 ===============
1211 */
1212 extern char *ENGINE_EXTENSIONS;
1213 void GL_Init (void)
1214 {
1215         VID_CheckExtensions();
1216
1217         // LordHavoc: report supported extensions
1218         Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1219
1220         // clear to black (loading plaque will be seen over this)
1221         qglClearColor(0,0,0,1);
1222         qglClear(GL_COLOR_BUFFER_BIT);
1223 }
1224
1225 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1226 {
1227         int i;
1228         mplane_t *p;
1229         for (i = 0;i < 4;i++)
1230         {
1231                 p = frustum + i;
1232                 switch(p->signbits)
1233                 {
1234                 default:
1235                 case 0:
1236                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1237                                 return true;
1238                         break;
1239                 case 1:
1240                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1241                                 return true;
1242                         break;
1243                 case 2:
1244                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1245                                 return true;
1246                         break;
1247                 case 3:
1248                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1249                                 return true;
1250                         break;
1251                 case 4:
1252                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1253                                 return true;
1254                         break;
1255                 case 5:
1256                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1257                                 return true;
1258                         break;
1259                 case 6:
1260                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1261                                 return true;
1262                         break;
1263                 case 7:
1264                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1265                                 return true;
1266                         break;
1267                 }
1268         }
1269         return false;
1270 }
1271
1272 //==================================================================================
1273
1274 static void R_UpdateEntityLighting(entity_render_t *ent)
1275 {
1276         vec3_t tempdiffusenormal;
1277         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));
1278         VectorClear(ent->modellight_diffuse);
1279         VectorClear(ent->modellight_lightdir);
1280         if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1281                 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1282         else // highly rare
1283                 VectorSet(ent->modellight_ambient, 1, 1, 1);
1284         Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1285         VectorNormalize(ent->modellight_lightdir);
1286         ent->modellight_ambient[0] *= ent->colormod[0] * r_lightmapintensity;
1287         ent->modellight_ambient[1] *= ent->colormod[1] * r_lightmapintensity;
1288         ent->modellight_ambient[2] *= ent->colormod[2] * r_lightmapintensity;
1289         ent->modellight_diffuse[0] *= ent->colormod[0] * r_lightmapintensity;
1290         ent->modellight_diffuse[1] *= ent->colormod[1] * r_lightmapintensity;
1291         ent->modellight_diffuse[2] *= ent->colormod[2] * r_lightmapintensity;
1292 }
1293
1294 static void R_MarkEntities (void)
1295 {
1296         int i, renderimask;
1297         entity_render_t *ent;
1298
1299         if (!r_drawentities.integer)
1300                 return;
1301
1302         r_refdef.worldentity->visframe = r_framecount;
1303         renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1304         if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1305         {
1306                 // worldmodel can check visibility
1307                 for (i = 0;i < r_refdef.numentities;i++)
1308                 {
1309                         ent = r_refdef.entities[i];
1310                         // some of the renderer still relies on origin...
1311                         Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1312                         // some of the renderer still relies on scale...
1313                         ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1314                         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)))
1315                         {
1316                                 ent->visframe = r_framecount;
1317                                 R_UpdateEntityLighting(ent);
1318                         }
1319                 }
1320         }
1321         else
1322         {
1323                 // no worldmodel or it can't check visibility
1324                 for (i = 0;i < r_refdef.numentities;i++)
1325                 {
1326                         ent = r_refdef.entities[i];
1327                         // some of the renderer still relies on origin...
1328                         Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1329                         // some of the renderer still relies on scale...
1330                         ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1331                         if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
1332                         {
1333                                 ent->visframe = r_framecount;
1334                                 R_UpdateEntityLighting(ent);
1335                         }
1336                 }
1337         }
1338 }
1339
1340 // only used if skyrendermasked, and normally returns false
1341 int R_DrawBrushModelsSky (void)
1342 {
1343         int i, sky;
1344         entity_render_t *ent;
1345
1346         if (!r_drawentities.integer)
1347                 return false;
1348
1349         sky = false;
1350         for (i = 0;i < r_refdef.numentities;i++)
1351         {
1352                 ent = r_refdef.entities[i];
1353                 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
1354                 {
1355                         ent->model->DrawSky(ent);
1356                         sky = true;
1357                 }
1358         }
1359         return sky;
1360 }
1361
1362 void R_DrawNoModel(entity_render_t *ent);
1363 void R_DrawModels(void)
1364 {
1365         int i;
1366         entity_render_t *ent;
1367
1368         if (!r_drawentities.integer)
1369                 return;
1370
1371         for (i = 0;i < r_refdef.numentities;i++)
1372         {
1373                 ent = r_refdef.entities[i];
1374                 if (ent->visframe == r_framecount)
1375                 {
1376                         renderstats.entities++;
1377                         if (ent->model && ent->model->Draw != NULL)
1378                                 ent->model->Draw(ent);
1379                         else
1380                                 R_DrawNoModel(ent);
1381                 }
1382         }
1383 }
1384
1385 static void R_SetFrustum(void)
1386 {
1387         // break apart the view matrix into vectors for various purposes
1388         Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
1389         VectorNegate(r_viewleft, r_viewright);
1390
1391 #if 0
1392         frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
1393         frustum[0].normal[1] = 0 - 0;
1394         frustum[0].normal[2] = -1 - 0;
1395         frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
1396         frustum[1].normal[1] = 0 + 0;
1397         frustum[1].normal[2] = -1 + 0;
1398         frustum[2].normal[0] = 0 - 0;
1399         frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
1400         frustum[2].normal[2] = -1 - 0;
1401         frustum[3].normal[0] = 0 + 0;
1402         frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
1403         frustum[3].normal[2] = -1 + 0;
1404 #endif
1405
1406 #if 0
1407         zNear = r_nearclip.value;
1408         nudge = 1.0 - 1.0 / (1<<23);
1409         frustum[4].normal[0] = 0 - 0;
1410         frustum[4].normal[1] = 0 - 0;
1411         frustum[4].normal[2] = -1 - -nudge;
1412         frustum[4].dist = 0 - -2 * zNear * nudge;
1413         frustum[5].normal[0] = 0 + 0;
1414         frustum[5].normal[1] = 0 + 0;
1415         frustum[5].normal[2] = -1 + -nudge;
1416         frustum[5].dist = 0 + -2 * zNear * nudge;
1417 #endif
1418
1419
1420
1421 #if 0
1422         frustum[0].normal[0] = m[3] - m[0];
1423         frustum[0].normal[1] = m[7] - m[4];
1424         frustum[0].normal[2] = m[11] - m[8];
1425         frustum[0].dist = m[15] - m[12];
1426
1427         frustum[1].normal[0] = m[3] + m[0];
1428         frustum[1].normal[1] = m[7] + m[4];
1429         frustum[1].normal[2] = m[11] + m[8];
1430         frustum[1].dist = m[15] + m[12];
1431
1432         frustum[2].normal[0] = m[3] - m[1];
1433         frustum[2].normal[1] = m[7] - m[5];
1434         frustum[2].normal[2] = m[11] - m[9];
1435         frustum[2].dist = m[15] - m[13];
1436
1437         frustum[3].normal[0] = m[3] + m[1];
1438         frustum[3].normal[1] = m[7] + m[5];
1439         frustum[3].normal[2] = m[11] + m[9];
1440         frustum[3].dist = m[15] + m[13];
1441
1442         frustum[4].normal[0] = m[3] - m[2];
1443         frustum[4].normal[1] = m[7] - m[6];
1444         frustum[4].normal[2] = m[11] - m[10];
1445         frustum[4].dist = m[15] - m[14];
1446
1447         frustum[5].normal[0] = m[3] + m[2];
1448         frustum[5].normal[1] = m[7] + m[6];
1449         frustum[5].normal[2] = m[11] + m[10];
1450         frustum[5].dist = m[15] + m[14];
1451 #endif
1452
1453
1454
1455         VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
1456         VectorMAM(1, r_viewforward, 1.0 /  r_refdef.frustum_x, r_viewleft, frustum[1].normal);
1457         VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
1458         VectorMAM(1, r_viewforward, 1.0 /  r_refdef.frustum_y, r_viewup, frustum[3].normal);
1459         VectorCopy(r_viewforward, frustum[4].normal);
1460         VectorNormalize(frustum[0].normal);
1461         VectorNormalize(frustum[1].normal);
1462         VectorNormalize(frustum[2].normal);
1463         VectorNormalize(frustum[3].normal);
1464         frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1465         frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1466         frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1467         frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1468         frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1469         PlaneClassify(&frustum[0]);
1470         PlaneClassify(&frustum[1]);
1471         PlaneClassify(&frustum[2]);
1472         PlaneClassify(&frustum[3]);
1473         PlaneClassify(&frustum[4]);
1474
1475         // LordHavoc: note to all quake engine coders, Quake had a special case
1476         // for 90 degrees which assumed a square view (wrong), so I removed it,
1477         // Quake2 has it disabled as well.
1478
1479         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1480         //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
1481         //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1482         //PlaneClassify(&frustum[0]);
1483
1484         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1485         //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
1486         //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1487         //PlaneClassify(&frustum[1]);
1488
1489         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1490         //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
1491         //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1492         //PlaneClassify(&frustum[2]);
1493
1494         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1495         //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
1496         //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1497         //PlaneClassify(&frustum[3]);
1498
1499         // nearclip plane
1500         //VectorCopy(r_viewforward, frustum[4].normal);
1501         //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1502         //PlaneClassify(&frustum[4]);
1503 }
1504
1505 static void R_BlendView(void)
1506 {
1507         int screenwidth, screenheight;
1508         qboolean dobloom;
1509         qboolean doblend;
1510         rmeshstate_t m;
1511
1512         // set the (poorly named) screenwidth and screenheight variables to
1513         // a power of 2 at least as large as the screen, these will define the
1514         // size of the texture to allocate
1515         for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1516         for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1517
1518         doblend = r_refdef.viewblend[3] >= 0.01f;
1519         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;
1520
1521         if (!dobloom && !doblend)
1522                 return;
1523
1524         GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1525         GL_DepthMask(true);
1526         GL_DepthTest(false);
1527         R_Mesh_Matrix(&identitymatrix);
1528         // vertex coordinates for a quad that covers the screen exactly
1529         varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
1530         varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
1531         varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
1532         varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
1533         if (dobloom)
1534         {
1535                 int bloomwidth, bloomheight, x, dobloomblend, range;
1536                 float xoffset, yoffset, r;
1537                 renderstats.bloom++;
1538                 // allocate textures as needed
1539                 if (!r_bloom_texture_screen)
1540                         r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1541                 if (!r_bloom_texture_bloom)
1542                         r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1543                 // set bloomwidth and bloomheight to the bloom resolution that will be
1544                 // used (often less than the screen resolution for faster rendering)
1545                 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
1546                 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
1547                 // set up a texcoord array for the full resolution screen image
1548                 // (we have to keep this around to copy back during final render)
1549                 varray_texcoord2f[0][0] = 0;
1550                 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
1551                 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
1552                 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
1553                 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
1554                 varray_texcoord2f[0][5] = 0;
1555                 varray_texcoord2f[0][6] = 0;
1556                 varray_texcoord2f[0][7] = 0;
1557                 // set up a texcoord array for the reduced resolution bloom image
1558                 // (which will be additive blended over the screen image)
1559                 varray_texcoord2f[1][0] = 0;
1560                 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1561                 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1562                 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1563                 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1564                 varray_texcoord2f[1][5] = 0;
1565                 varray_texcoord2f[1][6] = 0;
1566                 varray_texcoord2f[1][7] = 0;
1567                 memset(&m, 0, sizeof(m));
1568                 m.pointer_vertex = varray_vertex3f;
1569                 m.pointer_texcoord[0] = varray_texcoord2f[0];
1570                 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1571                 R_Mesh_State(&m);
1572                 // copy view into the full resolution screen image texture
1573                 GL_ActiveTexture(0);
1574                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1575                 renderstats.bloom_copypixels += r_view_width * r_view_height;
1576                 // now scale it down to the bloom size and raise to a power of itself
1577                 // to darken it (this leaves the really bright stuff bright, and
1578                 // everything else becomes very dark)
1579                 // TODO: optimize with multitexture or GLSL
1580                 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1581                 GL_BlendFunc(GL_ONE, GL_ZERO);
1582                 GL_Color(1, 1, 1, 1);
1583                 R_Mesh_Draw(0, 4, 2, polygonelements);
1584                 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1585                 // render multiple times with a multiply blendfunc to raise to a power
1586                 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1587                 for (x = 1;x < r_bloom_power.integer;x++)
1588                 {
1589                         R_Mesh_Draw(0, 4, 2, polygonelements);
1590                         renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1591                 }
1592                 // we now have a darkened bloom image in the framebuffer, copy it into
1593                 // the bloom image texture for more processing
1594                 memset(&m, 0, sizeof(m));
1595                 m.pointer_vertex = varray_vertex3f;
1596                 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1597                 m.pointer_texcoord[0] = varray_texcoord2f[2];
1598                 R_Mesh_State(&m);
1599                 GL_ActiveTexture(0);
1600                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1601                 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1602                 // blend on at multiple vertical offsets to achieve a vertical blur
1603                 // TODO: do offset blends using GLSL
1604                 range = r_bloom_blur.integer * bloomwidth / 320;
1605                 GL_BlendFunc(GL_ONE, GL_ZERO);
1606                 for (x = -range;x <= range;x++)
1607                 {
1608                         xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1609                         yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1610                         // compute a texcoord array with the specified x and y offset
1611                         varray_texcoord2f[2][0] = xoffset+0;
1612                         varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1613                         varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1614                         varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1615                         varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1616                         varray_texcoord2f[2][5] = yoffset+0;
1617                         varray_texcoord2f[2][6] = xoffset+0;
1618                         varray_texcoord2f[2][7] = yoffset+0;
1619                         // this r value looks like a 'dot' particle, fading sharply to
1620                         // black at the edges
1621                         // (probably not realistic but looks good enough)
1622                         r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1623                         if (r < 0.01f)
1624                                 continue;
1625                         GL_Color(r, r, r, 1);
1626                         R_Mesh_Draw(0, 4, 2, polygonelements);
1627                         renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1628                         GL_BlendFunc(GL_ONE, GL_ONE);
1629                 }
1630                 // copy the vertically blurred bloom view to a texture
1631                 GL_ActiveTexture(0);
1632                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1633                 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1634                 // blend the vertically blurred image at multiple offsets horizontally
1635                 // to finish the blur effect
1636                 // TODO: do offset blends using GLSL
1637                 range = r_bloom_blur.integer * bloomwidth / 320;
1638                 GL_BlendFunc(GL_ONE, GL_ZERO);
1639                 for (x = -range;x <= range;x++)
1640                 {
1641                         xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1642                         yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1643                         // compute a texcoord array with the specified x and y offset
1644                         varray_texcoord2f[2][0] = xoffset+0;
1645                         varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1646                         varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1647                         varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1648                         varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1649                         varray_texcoord2f[2][5] = yoffset+0;
1650                         varray_texcoord2f[2][6] = xoffset+0;
1651                         varray_texcoord2f[2][7] = yoffset+0;
1652                         // this r value looks like a 'dot' particle, fading sharply to
1653                         // black at the edges
1654                         // (probably not realistic but looks good enough)
1655                         r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1656                         if (r < 0.01f)
1657                                 continue;
1658                         GL_Color(r, r, r, 1);
1659                         R_Mesh_Draw(0, 4, 2, polygonelements);
1660                         renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1661                         GL_BlendFunc(GL_ONE, GL_ONE);
1662                 }
1663                 // copy the blurred bloom view to a texture
1664                 GL_ActiveTexture(0);
1665                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1666                 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1667                 // go back to full view area
1668                 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1669                 // put the original screen image back in place and blend the bloom
1670                 // texture on it
1671                 memset(&m, 0, sizeof(m));
1672                 m.pointer_vertex = varray_vertex3f;
1673                 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1674                 m.pointer_texcoord[0] = varray_texcoord2f[0];
1675 #if 0
1676                 dobloomblend = false;
1677 #else
1678                 // do both in one pass if possible
1679                 if (r_textureunits.integer >= 2 && gl_combine.integer)
1680                 {
1681                         dobloomblend = false;
1682                         m.texcombinergb[1] = GL_ADD;
1683                         m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
1684                         m.pointer_texcoord[1] = varray_texcoord2f[1];
1685                 }
1686                 else
1687                         dobloomblend = true;
1688 #endif
1689                 R_Mesh_State(&m);
1690                 GL_BlendFunc(GL_ONE, GL_ZERO);
1691                 GL_Color(1,1,1,1);
1692                 R_Mesh_Draw(0, 4, 2, polygonelements);
1693                 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1694                 // now blend on the bloom texture if multipass
1695                 if (dobloomblend)
1696                 {
1697                         memset(&m, 0, sizeof(m));
1698                         m.pointer_vertex = varray_vertex3f;
1699                         m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1700                         m.pointer_texcoord[0] = varray_texcoord2f[1];
1701                         R_Mesh_State(&m);
1702                         GL_BlendFunc(GL_ONE, GL_ONE);
1703                         GL_Color(1,1,1,1);
1704                         R_Mesh_Draw(0, 4, 2, polygonelements);
1705                         renderstats.bloom_drawpixels += r_view_width * r_view_height;
1706                 }
1707         }
1708         if (doblend)
1709         {
1710                 // apply a color tint to the whole view
1711                 memset(&m, 0, sizeof(m));
1712                 m.pointer_vertex = varray_vertex3f;
1713                 R_Mesh_State(&m);
1714                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1715                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1716                 R_Mesh_Draw(0, 4, 2, polygonelements);
1717         }
1718 }
1719
1720 void R_RenderScene(void);
1721
1722 matrix4x4_t r_waterscrollmatrix;
1723
1724 /*
1725 ================
1726 R_RenderView
1727 ================
1728 */
1729 void R_RenderView(void)
1730 {
1731         if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1732                 return; //Host_Error ("R_RenderView: NULL worldmodel");
1733
1734         r_view_width = bound(0, r_refdef.width, vid.width);
1735         r_view_height = bound(0, r_refdef.height, vid.height);
1736         r_view_depth = 1;
1737         r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1738         r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1739         r_view_z = 0;
1740         r_view_matrix = r_refdef.viewentitymatrix;
1741         GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1742         r_rtworld = r_shadow_realtime_world.integer;
1743         r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1744         r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1745         r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1746         r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1747
1748         // GL is weird because it's bottom to top, r_view_y is top to bottom
1749         qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1750         GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1751         GL_ScissorTest(true);
1752         GL_DepthMask(true);
1753         R_ClearScreen();
1754         R_Textures_Frame();
1755         R_UpdateFog();
1756         if (r_timereport_active)
1757                 R_TimeReport("setup");
1758
1759         qglDepthFunc(GL_LEQUAL);
1760         qglPolygonOffset(0, 0);
1761         qglEnable(GL_POLYGON_OFFSET_FILL);
1762
1763         R_RenderScene();
1764
1765         qglPolygonOffset(0, 0);
1766         qglDisable(GL_POLYGON_OFFSET_FILL);
1767
1768         R_BlendView();
1769         if (r_timereport_active)
1770                 R_TimeReport("blendview");
1771
1772         GL_Scissor(0, 0, vid.width, vid.height);
1773         GL_ScissorTest(false);
1774 }
1775
1776 //[515]: csqc
1777 void CSQC_R_ClearScreen (void)
1778 {
1779         if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1780                 return; //Host_Error ("R_RenderView: NULL worldmodel");
1781
1782         r_view_width = bound(0, r_refdef.width, vid.width);
1783         r_view_height = bound(0, r_refdef.height, vid.height);
1784         r_view_depth = 1;
1785         r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1786         r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1787         r_view_z = 0;
1788         r_view_matrix = r_refdef.viewentitymatrix;
1789         GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1790         r_rtworld = r_shadow_realtime_world.integer;
1791         r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1792         r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1793         r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1794         r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1795
1796         // GL is weird because it's bottom to top, r_view_y is top to bottom
1797         qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1798         GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1799         GL_ScissorTest(true);
1800         GL_DepthMask(true);
1801         R_ClearScreen();
1802         R_Textures_Frame();
1803         R_UpdateFog();
1804         if (r_timereport_active)
1805                 R_TimeReport("setup");
1806 }
1807
1808 //[515]: csqc
1809 void CSQC_R_RenderScene (void)
1810 {
1811         qglDepthFunc(GL_LEQUAL);
1812         qglPolygonOffset(0, 0);
1813         qglEnable(GL_POLYGON_OFFSET_FILL);
1814
1815         R_RenderScene();
1816
1817         qglPolygonOffset(0, 0);
1818         qglDisable(GL_POLYGON_OFFSET_FILL);
1819
1820         R_BlendView();
1821         if (r_timereport_active)
1822                 R_TimeReport("blendview");
1823
1824         GL_Scissor(0, 0, vid.width, vid.height);
1825         GL_ScissorTest(false);
1826 }
1827
1828 extern void R_DrawLightningBeams (void);
1829 extern void VM_AddPolygonsToMeshQueue (void);
1830 void R_RenderScene(void)
1831 {
1832         float nearclip;
1833
1834         // don't let sound skip if going slow
1835         if (r_refdef.extraupdate)
1836                 S_ExtraUpdate ();
1837
1838         r_framecount++;
1839
1840         if (gl_support_fragment_shader)
1841                 qglUseProgramObjectARB(0);
1842
1843         R_MeshQueue_BeginScene();
1844
1845         R_SetFrustum();
1846
1847         r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1848         nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
1849
1850         if (r_rtworldshadows || r_rtdlightshadows)
1851                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
1852         else
1853                 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
1854
1855         GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1856
1857         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);
1858
1859         R_SkyStartFrame();
1860
1861         R_WorldVisibility();
1862         if (r_timereport_active)
1863                 R_TimeReport("worldvis");
1864
1865         R_MarkEntities();
1866         if (r_timereport_active)
1867                 R_TimeReport("markentity");
1868
1869         R_Shadow_UpdateWorldLightSelection();
1870
1871         for (r_showtrispass = 0;r_showtrispass <= (r_showtris.value > 0);r_showtrispass++)
1872         {
1873                 if (r_showtrispass)
1874                 {
1875                         rmeshstate_t m;
1876                         r_showtrispass = 0;
1877                         GL_BlendFunc(GL_ONE, GL_ONE);
1878                         GL_DepthTest(!r_showdisabledepthtest.integer);
1879                         GL_DepthMask(GL_FALSE);
1880                         memset(&m, 0, sizeof(m));
1881                         R_Mesh_State(&m);
1882                         //qglEnable(GL_LINE_SMOOTH);
1883                         qglEnable(GL_POLYGON_OFFSET_LINE);
1884                         qglPolygonOffset(0, r_showtris_polygonoffset.value);
1885                         r_showtrispass = 1;
1886                 }
1887
1888                 if (cl.csqc_vidvars.drawworld)
1889                 {
1890                         // don't let sound skip if going slow
1891                         if (r_refdef.extraupdate)
1892                                 S_ExtraUpdate ();
1893
1894                         if (r_showtrispass)
1895                                 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1896                         if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1897                         {
1898                                 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1899                                 if (r_timereport_active)
1900                                         R_TimeReport("worldsky");
1901                         }
1902
1903                         if (R_DrawBrushModelsSky() && r_timereport_active)
1904                                 R_TimeReport("bmodelsky");
1905
1906                         if (r_showtrispass)
1907                                 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1908                         if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1909                         {
1910                                 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1911                                 if (r_timereport_active)
1912                                         R_TimeReport("world");
1913                         }
1914                 }
1915
1916                 // don't let sound skip if going slow
1917                 if (r_refdef.extraupdate)
1918                         S_ExtraUpdate ();
1919
1920                 if (r_showtrispass)
1921                         GL_ShowTrisColor(0, 0.015, 0, 1);
1922
1923                 R_DrawModels();
1924                 if (r_timereport_active)
1925                         R_TimeReport("models");
1926
1927                 // don't let sound skip if going slow
1928                 if (r_refdef.extraupdate)
1929                         S_ExtraUpdate ();
1930
1931                 if (r_showtrispass)
1932                         GL_ShowTrisColor(0, 0, 0.033, 1);
1933                 R_ShadowVolumeLighting(false);
1934                 if (r_timereport_active)
1935                         R_TimeReport("rtlights");
1936
1937                 // don't let sound skip if going slow
1938                 if (r_refdef.extraupdate)
1939                         S_ExtraUpdate ();
1940
1941                 if (r_showtrispass)
1942                         GL_ShowTrisColor(0.1, 0, 0, 1);
1943
1944                 if (cl.csqc_vidvars.drawworld)
1945                 {
1946                         R_DrawLightningBeams();
1947                         if (r_timereport_active)
1948                                 R_TimeReport("lightning");
1949
1950                         R_DrawParticles();
1951                         if (r_timereport_active)
1952                                 R_TimeReport("particles");
1953
1954                         R_DrawExplosions();
1955                         if (r_timereport_active)
1956                                 R_TimeReport("explosions");
1957                 }
1958
1959                 R_MeshQueue_RenderTransparent();
1960                 if (r_timereport_active)
1961                         R_TimeReport("drawtrans");
1962
1963                 if (cl.csqc_vidvars.drawworld)
1964                 {
1965                         R_DrawCoronas();
1966                         if (r_timereport_active)
1967                                 R_TimeReport("coronas");
1968                 }
1969                 if(cl.csqc_vidvars.drawcrosshair)
1970                 {
1971                         R_DrawWorldCrosshair();
1972                         if (r_timereport_active)
1973                                 R_TimeReport("crosshair");
1974                 }
1975
1976                 VM_AddPolygonsToMeshQueue();
1977
1978                 R_MeshQueue_Render();
1979
1980                 if (r_showtrispass)
1981                 {
1982                         //qglDisable(GL_LINE_SMOOTH);
1983                         qglDisable(GL_POLYGON_OFFSET_LINE);
1984                 }
1985         }
1986
1987         r_showtrispass = 0;
1988
1989         R_MeshQueue_EndScene();
1990
1991         // don't let sound skip if going slow
1992         if (r_refdef.extraupdate)
1993                 S_ExtraUpdate ();
1994
1995         if (gl_support_fragment_shader)
1996                 qglUseProgramObjectARB(0);
1997 }
1998
1999 /*
2000 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2001 {
2002         int i;
2003         float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2004         rmeshstate_t m;
2005         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2006         GL_DepthMask(false);
2007         GL_DepthTest(true);
2008         R_Mesh_Matrix(&identitymatrix);
2009
2010         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2011         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2012         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2013         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2014         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2015         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2016         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2017         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2018         R_FillColors(color, 8, cr, cg, cb, ca);
2019         if (fogenabled)
2020         {
2021                 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2022                 {
2023                         f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
2024                         f1 = 1 - f2;
2025                         c[0] = c[0] * f1 + fogcolor[0] * f2;
2026                         c[1] = c[1] * f1 + fogcolor[1] * f2;
2027                         c[2] = c[2] * f1 + fogcolor[2] * f2;
2028                 }
2029         }
2030         memset(&m, 0, sizeof(m));
2031         m.pointer_vertex = vertex3f;
2032         m.pointer_color = color;
2033         R_Mesh_State(&m);
2034         R_Mesh_Draw(8, 12);
2035 }
2036 */
2037
2038 int nomodelelements[24] =
2039 {
2040         5, 2, 0,
2041         5, 1, 2,
2042         5, 0, 3,
2043         5, 3, 1,
2044         0, 2, 4,
2045         2, 1, 4,
2046         3, 0, 4,
2047         1, 3, 4
2048 };
2049
2050 float nomodelvertex3f[6*3] =
2051 {
2052         -16,   0,   0,
2053          16,   0,   0,
2054           0, -16,   0,
2055           0,  16,   0,
2056           0,   0, -16,
2057           0,   0,  16
2058 };
2059
2060 float nomodelcolor4f[6*4] =
2061 {
2062         0.0f, 0.0f, 0.5f, 1.0f,
2063         0.0f, 0.0f, 0.5f, 1.0f,
2064         0.0f, 0.5f, 0.0f, 1.0f,
2065         0.0f, 0.5f, 0.0f, 1.0f,
2066         0.5f, 0.0f, 0.0f, 1.0f,
2067         0.5f, 0.0f, 0.0f, 1.0f
2068 };
2069
2070 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2071 {
2072         int i;
2073         float f1, f2, *c;
2074         float color4f[6*4];
2075         rmeshstate_t m;
2076         R_Mesh_Matrix(&ent->matrix);
2077
2078         memset(&m, 0, sizeof(m));
2079         m.pointer_vertex = nomodelvertex3f;
2080
2081         if (ent->flags & EF_ADDITIVE)
2082         {
2083                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2084                 GL_DepthMask(false);
2085         }
2086         else if (ent->alpha < 1)
2087         {
2088                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2089                 GL_DepthMask(false);
2090         }
2091         else
2092         {
2093                 GL_BlendFunc(GL_ONE, GL_ZERO);
2094                 GL_DepthMask(true);
2095         }
2096         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2097         if (fogenabled)
2098         {
2099                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2100                 m.pointer_color = color4f;
2101                 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
2102                 f1 = 1 - f2;
2103                 for (i = 0, c = color4f;i < 6;i++, c += 4)
2104                 {
2105                         c[0] = (c[0] * f1 + fogcolor[0] * f2);
2106                         c[1] = (c[1] * f1 + fogcolor[1] * f2);
2107                         c[2] = (c[2] * f1 + fogcolor[2] * f2);
2108                         c[3] *= ent->alpha;
2109                 }
2110         }
2111         else if (ent->alpha != 1)
2112         {
2113                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2114                 m.pointer_color = color4f;
2115                 for (i = 0, c = color4f;i < 6;i++, c += 4)
2116                         c[3] *= ent->alpha;
2117         }
2118         else
2119                 m.pointer_color = nomodelcolor4f;
2120         R_Mesh_State(&m);
2121         R_Mesh_Draw(0, 6, 8, nomodelelements);
2122 }
2123
2124 void R_DrawNoModel(entity_render_t *ent)
2125 {
2126         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2127                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2128         //else
2129         //      R_DrawNoModelCallback(ent, 0);
2130 }
2131
2132 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2133 {
2134         vec3_t right1, right2, diff, normal;
2135
2136         VectorSubtract (org2, org1, normal);
2137
2138         // calculate 'right' vector for start
2139         VectorSubtract (r_vieworigin, org1, diff);
2140         CrossProduct (normal, diff, right1);
2141         VectorNormalize (right1);
2142
2143         // calculate 'right' vector for end
2144         VectorSubtract (r_vieworigin, org2, diff);
2145         CrossProduct (normal, diff, right2);
2146         VectorNormalize (right2);
2147
2148         vert[ 0] = org1[0] + width * right1[0];
2149         vert[ 1] = org1[1] + width * right1[1];
2150         vert[ 2] = org1[2] + width * right1[2];
2151         vert[ 3] = org1[0] - width * right1[0];
2152         vert[ 4] = org1[1] - width * right1[1];
2153         vert[ 5] = org1[2] - width * right1[2];
2154         vert[ 6] = org2[0] - width * right2[0];
2155         vert[ 7] = org2[1] - width * right2[1];
2156         vert[ 8] = org2[2] - width * right2[2];
2157         vert[ 9] = org2[0] + width * right2[0];
2158         vert[10] = org2[1] + width * right2[1];
2159         vert[11] = org2[2] + width * right2[2];
2160 }
2161
2162 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2163
2164 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)
2165 {
2166         float fog = 0.0f, ifog;
2167         rmeshstate_t m;
2168
2169         if (fogenabled)
2170                 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
2171         ifog = 1 - fog;
2172
2173         R_Mesh_Matrix(&identitymatrix);
2174         GL_BlendFunc(blendfunc1, blendfunc2);
2175         GL_DepthMask(false);
2176         GL_DepthTest(!depthdisable);
2177
2178         varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2179         varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2180         varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2181         varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2182         varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2183         varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2184         varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2185         varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2186         varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2187         varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2188         varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2189         varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2190
2191         memset(&m, 0, sizeof(m));
2192         m.tex[0] = R_GetTexture(texture);
2193         m.pointer_texcoord[0] = spritetexcoord2f;
2194         m.pointer_vertex = varray_vertex3f;
2195         R_Mesh_State(&m);
2196         GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2197         R_Mesh_Draw(0, 4, 2, polygonelements);
2198
2199         if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2200         {
2201                 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2202                 GL_BlendFunc(blendfunc1, GL_ONE);
2203                 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
2204                 R_Mesh_Draw(0, 4, 2, polygonelements);
2205         }
2206 }
2207
2208 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2209 {
2210         int i;
2211         float *vertex3f;
2212         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2213                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2214                         break;
2215         if (i == mesh->numvertices)
2216         {
2217                 if (mesh->numvertices < mesh->maxvertices)
2218                 {
2219                         VectorCopy(v, vertex3f);
2220                         mesh->numvertices++;
2221                 }
2222                 return mesh->numvertices;
2223         }
2224         else
2225                 return i;
2226 }
2227
2228 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2229 {
2230         int i;
2231         int *e, element[3];
2232         element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2233         element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2234         e = mesh->element3i + mesh->numtriangles * 3;
2235         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2236         {
2237                 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2238                 if (mesh->numtriangles < mesh->maxtriangles)
2239                 {
2240                         *e++ = element[0];
2241                         *e++ = element[1];
2242                         *e++ = element[2];
2243                         mesh->numtriangles++;
2244                 }
2245                 element[1] = element[2];
2246         }
2247 }
2248
2249 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2250 {
2251         int planenum, planenum2;
2252         int w;
2253         int tempnumpoints;
2254         mplane_t *plane, *plane2;
2255         float temppoints[2][256*3];
2256         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2257         {
2258                 w = 0;
2259                 tempnumpoints = 4;
2260                 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2261                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2262                 {
2263                         if (planenum2 == planenum)
2264                                 continue;
2265                         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);
2266                         w = !w;
2267                 }
2268                 if (tempnumpoints < 3)
2269                         continue;
2270                 // generate elements forming a triangle fan for this polygon
2271                 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2272         }
2273 }
2274
2275 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)
2276 {
2277         texturelayer_t *layer;
2278         layer = t->currentlayers + t->currentnumlayers++;
2279         layer->type = type;
2280         layer->depthmask = depthmask;
2281         layer->blendfunc1 = blendfunc1;
2282         layer->blendfunc2 = blendfunc2;
2283         layer->texture = texture;
2284         layer->texmatrix = *matrix;
2285         layer->color[0] = r;
2286         layer->color[1] = g;
2287         layer->color[2] = b;
2288         layer->color[3] = a;
2289 }
2290
2291 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2292 {
2293         // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2294         //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2295
2296         {
2297                 texture_t *texture = t;
2298                 model_t *model = ent->model;
2299                 int s = ent->skinnum;
2300                 if ((unsigned int)s >= (unsigned int)model->numskins)
2301                         s = 0;
2302                 if (model->skinscenes)
2303                 {
2304                         if (model->skinscenes[s].framecount > 1)
2305                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2306                         else
2307                                 s = model->skinscenes[s].firstframe;
2308                 }
2309                 if (s > 0)
2310                         t = t + s * model->num_surfaces;
2311                 if (t->animated)
2312                         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];
2313                 texture->currentframe = t;
2314         }
2315
2316         t->currentmaterialflags = t->basematerialflags;
2317         t->currentalpha = ent->alpha;
2318         if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2319                 t->currentalpha *= r_wateralpha.value;
2320         if (!(ent->flags & RENDER_LIGHT))
2321                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2322         if (ent->effects & EF_ADDITIVE)
2323                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
2324         else if (t->currentalpha < 1)
2325                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
2326         if (ent->effects & EF_NODEPTHTEST)
2327                 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2328         if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2329                 t->currenttexmatrix = r_waterscrollmatrix;
2330         else
2331                 t->currenttexmatrix = identitymatrix;
2332
2333         t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2334         t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2335         t->glosstexture = r_texture_white;
2336         t->specularpower = 8;
2337         t->specularscale = 0;
2338         if (r_shadow_gloss.integer > 0)
2339         {
2340                 if (t->skin.gloss)
2341                 {
2342                         if (r_shadow_glossintensity.value > 0)
2343                         {
2344                                 t->glosstexture = t->skin.gloss;
2345                                 t->specularscale = r_shadow_glossintensity.value;
2346                         }
2347                 }
2348                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2349                         t->specularscale = r_shadow_gloss2intensity.value;
2350         }
2351
2352         t->currentnumlayers = 0;
2353         if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2354         {
2355                 if (gl_lightmaps.integer)
2356                         R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2357                 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2358                 {
2359                         int blendfunc1, blendfunc2, depthmask;
2360                         if (t->currentmaterialflags & MATERIALFLAG_ADD)
2361                         {
2362                                 blendfunc1 = GL_SRC_ALPHA;
2363                                 blendfunc2 = GL_ONE;
2364                                 depthmask = false;
2365                         }
2366                         else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2367                         {
2368                                 blendfunc1 = GL_SRC_ALPHA;
2369                                 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2370                                 depthmask = false;
2371                         }
2372                         else
2373                         {
2374                                 blendfunc1 = GL_ONE;
2375                                 blendfunc2 = GL_ZERO;
2376                                 depthmask = true;
2377                         }
2378                         if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2379                         {
2380                                 rtexture_t *currentbasetexture;
2381                                 int layerflags = 0;
2382                                 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2383                                         layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2384                                 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2385                                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2386                                 {
2387                                         // fullbright is not affected by r_lightmapintensity
2388                                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2389                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2390                                                 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);
2391                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2392                                                 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);
2393                                 }
2394                                 else
2395                                 {
2396                                         float colorscale;
2397                                         colorscale = 2;
2398                                         // q3bsp has no lightmap updates, so the lightstylevalue that
2399                                         // would normally be baked into the lightmaptexture must be
2400                                         // applied to the color
2401                                         if (ent->model->type == mod_brushq3)
2402                                                 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2403                                         colorscale *= r_lightmapintensity;
2404                                         if (r_textureunits.integer >= 2 && gl_combine.integer)
2405                                                 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);
2406                                         else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
2407                                                 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);
2408                                         else
2409                                                 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);
2410                                         if (r_ambient.value >= (1.0f/64.0f))
2411                                                 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);
2412                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2413                                         {
2414                                                 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);
2415                                                 if (r_ambient.value >= (1.0f/64.0f))
2416                                                         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);
2417                                         }
2418                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2419                                         {
2420                                                 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);
2421                                                 if (r_ambient.value >= (1.0f/64.0f))
2422                                                         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);
2423                                         }
2424                                 }
2425                                 if (t->skin.glow != NULL)
2426                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2427                                 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2428                                 {
2429                                         // if this is opaque use alpha blend which will darken the earlier
2430                                         // passes cheaply.
2431                                         //
2432                                         // if this is an alpha blended material, all the earlier passes
2433                                         // were darkened by fog already, so we only need to add the fog
2434                                         // color ontop through the fog mask texture
2435                                         //
2436                                         // if this is an additive blended material, all the earlier passes
2437                                         // were darkened by fog already, and we should not add fog color
2438                                         // (because the background was not darkened, there is no fog color
2439                                         // that was lost behind it).
2440                                         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);
2441                                 }
2442                         }
2443                 }
2444         }
2445 }
2446
2447 void R_UpdateAllTextureInfo(entity_render_t *ent)
2448 {
2449         int i;
2450         if (ent->model)
2451                 for (i = 0;i < ent->model->num_textures;i++)
2452                         R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2453 }
2454
2455 float *rsurface_vertex3f;
2456 float *rsurface_svector3f;
2457 float *rsurface_tvector3f;
2458 float *rsurface_normal3f;
2459 float *rsurface_lightmapcolor4f;
2460
2461 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, qboolean generatenormals, qboolean generatetangents)
2462 {
2463         if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
2464         {
2465                 rsurface_vertex3f = varray_vertex3f;
2466                 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
2467                 if (generatetangents || (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)))
2468                 {
2469                         rsurface_svector3f = varray_svector3f;
2470                         rsurface_tvector3f = varray_tvector3f;
2471                         rsurface_normal3f = varray_normal3f;
2472                         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);
2473                 }
2474                 else
2475                 {
2476                         rsurface_svector3f = NULL;
2477                         rsurface_tvector3f = NULL;
2478                         if (generatenormals)
2479                         {
2480                                 rsurface_normal3f = varray_normal3f;
2481                                 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);
2482                         }
2483                         else
2484                                 rsurface_normal3f = NULL;
2485                 }
2486         }
2487         else
2488         {
2489                 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
2490                 rsurface_svector3f = surface->groupmesh->data_svector3f;
2491                 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
2492                 rsurface_normal3f = surface->groupmesh->data_normal3f;
2493         }
2494         if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2495         {
2496                 int i, j;
2497                 float center[3], forward[3], right[3], up[3], v[4][3];
2498                 matrix4x4_t matrix1, imatrix1;
2499                 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
2500                 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
2501                 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
2502                 // a single autosprite surface can contain multiple sprites...
2503                 for (j = 0;j < surface->num_vertices - 3;j += 4)
2504                 {
2505                         VectorClear(center);
2506                         for (i = 0;i < 4;i++)
2507                                 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2508                         VectorScale(center, 0.25f, center);
2509                         // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2510                         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);
2511                         Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2512                         for (i = 0;i < 4;i++)
2513                                 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2514                         if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2515                         {
2516                                 forward[0] = modelorg[0] - center[0];
2517                                 forward[1] = modelorg[1] - center[1];
2518                                 forward[2] = 0;
2519                                 VectorNormalize(forward);
2520                                 right[0] = forward[1];
2521                                 right[1] = -forward[0];
2522                                 right[2] = 0;
2523                                 VectorSet(up, 0, 0, 1);
2524                         }
2525                         for (i = 0;i < 4;i++)
2526                                 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
2527                 }
2528                 rsurface_vertex3f = varray_vertex3f;
2529                 rsurface_svector3f = varray_svector3f;
2530                 rsurface_tvector3f = varray_tvector3f;
2531                 rsurface_normal3f = varray_normal3f;
2532                 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);
2533         }
2534         R_Mesh_VertexPointer(rsurface_vertex3f);
2535 }
2536
2537 static void RSurf_Draw(const msurface_t *surface)
2538 {
2539         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2540         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2541         GL_LockArrays(0, 0);
2542 }
2543
2544 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)
2545 {
2546         int i;
2547         float f;
2548         float *v, *c, *c2;
2549         RSurf_SetVertexPointer(ent, texture, surface, modelorg, lightmode >= 2, false);
2550         if (lightmode >= 2)
2551         {
2552                 // model lighting
2553                 vec3_t ambientcolor;
2554                 vec3_t diffusecolor;
2555                 vec3_t lightdir;
2556                 VectorCopy(ent->modellight_lightdir, lightdir);
2557                 ambientcolor[0] = ent->modellight_ambient[0] * r * 0.5f;
2558                 ambientcolor[1] = ent->modellight_ambient[1] * g * 0.5f;
2559                 ambientcolor[2] = ent->modellight_ambient[2] * b * 0.5f;
2560                 diffusecolor[0] = ent->modellight_diffuse[0] * r * 0.5f;
2561                 diffusecolor[1] = ent->modellight_diffuse[1] * g * 0.5f;
2562                 diffusecolor[2] = ent->modellight_diffuse[2] * b * 0.5f;
2563                 if (VectorLength2(diffusecolor) > 0)
2564                 {
2565                         int numverts = surface->num_vertices;
2566                         v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2567                         c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2568                         c = varray_color4f + 4 * surface->num_firstvertex;
2569                         // q3-style directional shading
2570                         for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2571                         {
2572                                 if ((f = DotProduct(c2, lightdir)) > 0)
2573                                         VectorMA(ambientcolor, f, diffusecolor, c);
2574                                 else
2575                                         VectorCopy(ambientcolor, c);
2576                                 c[3] = a;
2577                         }
2578                         r = 1;
2579                         g = 1;
2580                         b = 1;
2581                         a = 1;
2582                         applycolor = false;
2583                         rsurface_lightmapcolor4f = varray_color4f;
2584                 }
2585                 else
2586                 {
2587                         r = ambientcolor[0];
2588                         g = ambientcolor[1];
2589                         b = ambientcolor[2];
2590                         rsurface_lightmapcolor4f = NULL;
2591                 }
2592         }
2593         else if (lightmode >= 1)
2594         {
2595                 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
2596                 {
2597                         for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2598                         {
2599                                 if (surface->lightmapinfo->samples)
2600                                 {
2601                                         const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
2602                                         float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2603                                         VectorScale(lm, scale, c);
2604                                         if (surface->lightmapinfo->styles[1] != 255)
2605                                         {
2606                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2607                                                 lm += size3;
2608                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2609                                                 VectorMA(c, scale, lm, c);
2610                                                 if (surface->lightmapinfo->styles[2] != 255)
2611                                                 {
2612                                                         lm += size3;
2613                                                         scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2614                                                         VectorMA(c, scale, lm, c);
2615                                                         if (surface->lightmapinfo->styles[3] != 255)
2616                                                         {
2617                                                                 lm += size3;
2618                                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2619                                                                 VectorMA(c, scale, lm, c);
2620                                                         }
2621                                                 }
2622                                         }
2623                                 }
2624                                 else
2625                                         VectorClear(c);
2626                         }
2627                         rsurface_lightmapcolor4f = varray_color4f;
2628                 }
2629                 else
2630                         rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
2631         }
2632         else
2633                 rsurface_lightmapcolor4f = NULL;
2634         if (applyfog)
2635         {
2636                 if (rsurface_lightmapcolor4f)
2637                 {
2638                         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)
2639                         {
2640                                 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2641                                 c2[0] = c[0] * f;
2642                                 c2[1] = c[1] * f;
2643                                 c2[2] = c[2] * f;
2644                                 c2[3] = c[3];
2645                         }
2646                 }
2647                 else
2648                 {
2649                         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)
2650                         {
2651                                 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2652                                 c2[0] = f;
2653                                 c2[1] = f;
2654                                 c2[2] = f;
2655                                 c2[3] = 1;
2656                         }
2657                 }
2658                 rsurface_lightmapcolor4f = varray_color4f;
2659         }
2660         if (applycolor && rsurface_lightmapcolor4f)
2661         {
2662                 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)
2663                 {
2664                         c2[0] = c[0] * r;
2665                         c2[1] = c[1] * g;
2666                         c2[2] = c[2] * b;
2667                         c2[3] = c[3] * a;
2668                 }
2669                 rsurface_lightmapcolor4f = varray_color4f;
2670         }
2671         R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2672         GL_Color(r, g, b, a);
2673         RSurf_Draw(surface);
2674 }
2675
2676 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2677 {
2678         int texturesurfaceindex;
2679         int lightmode;
2680         const msurface_t *surface;
2681         qboolean applycolor;
2682         qboolean applyfog;
2683         rmeshstate_t m;
2684         if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
2685                 return;
2686         r_shadow_rtlight = NULL;
2687         renderstats.entities_surfaces += texturenumsurfaces;
2688         // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2689         lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2690         GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
2691         if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2692                 qglDisable(GL_CULL_FACE);
2693         if (texture->currentmaterialflags & MATERIALFLAG_SKY)
2694         {
2695                 // transparent sky would be ridiculous
2696                 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2697                 {
2698                         GL_DepthMask(true);
2699                         if (skyrendernow)
2700                         {
2701                                 skyrendernow = false;
2702                                 if (skyrendermasked)
2703                                 {
2704                                         R_Sky();
2705                                         // restore entity matrix and GL_Color
2706                                         R_Mesh_Matrix(&ent->matrix);
2707                                         GL_Color(1,1,1,1);
2708                                 }
2709                         }
2710                         // LordHavoc: HalfLife maps have freaky skypolys...
2711                         //if (!ent->model->brush.ishlbsp)
2712                         {
2713                                 if (skyrendermasked)
2714                                 {
2715                                         // depth-only (masking)
2716                                         GL_ColorMask(0,0,0,0);
2717                                         // just to make sure that braindead drivers don't draw anything
2718                                         // despite that colormask...
2719                                         GL_BlendFunc(GL_ZERO, GL_ONE);
2720                                 }
2721                                 else
2722                                 {
2723                                         // fog sky
2724                                         GL_BlendFunc(GL_ONE, GL_ZERO);
2725                                 }
2726                                 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2727                                 memset(&m, 0, sizeof(m));
2728                                 R_Mesh_State(&m);
2729                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2730                                 {
2731                                         surface = texturesurfacelist[texturesurfaceindex];
2732                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2733                                         RSurf_Draw(surface);
2734                                 }
2735                                 if (skyrendermasked)
2736                                         GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2737                         }
2738                 }
2739         }
2740         else if (r_glsl.integer && gl_support_fragment_shader)
2741         {
2742                 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
2743                 {
2744                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2745                         GL_DepthMask(false);
2746                 }
2747                 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
2748                 {
2749                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2750                         GL_DepthMask(false);
2751                 }
2752                 else
2753                 {
2754                         GL_BlendFunc(GL_ONE, GL_ZERO);
2755                         GL_DepthMask(true);
2756                 }
2757
2758                 memset(&m, 0, sizeof(m));
2759                 R_Mesh_State(&m);
2760                 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], texture->currentalpha);
2761                 R_SetupSurfaceShader(ent, texture, modelorg, vec3_origin, lightmode == 2);
2762                 if (!r_glsl_permutation)
2763                         return;
2764                 if (lightmode == 2)
2765                 {
2766                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2767                         {
2768                                 surface = texturesurfacelist[texturesurfaceindex];
2769                                 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2770                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2771                                 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2772                                 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2773                                 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2774                                 RSurf_Draw(surface);
2775                         }
2776                 }
2777                 else
2778                 {
2779                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2780                         {
2781                                 surface = texturesurfacelist[texturesurfaceindex];
2782                                 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2783                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2784                                 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2785                                 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2786                                 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2787                                 R_Mesh_TexCoordPointer(4, 2, surface->groupmesh->data_texcoordlightmap2f);
2788                                 if (surface->lightmaptexture)
2789                                 {
2790                                         R_Mesh_TexBind(7, R_GetTexture(surface->lightmaptexture));
2791                                         if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2792                                                 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2793                                                 //R_Mesh_TexBind(8, R_GetTexture(surface->deluxemaptexture));
2794                                         R_Mesh_ColorPointer(NULL);
2795                                 }
2796                                 else
2797                                 {
2798                                         R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2799                                         if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2800                                                 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2801                                         R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
2802                                 }
2803                                 RSurf_Draw(surface);
2804                         }
2805                 }
2806                 qglUseProgramObjectARB(0);
2807         }
2808         else if (texture->currentnumlayers)
2809         {
2810                 int layerindex;
2811                 texturelayer_t *layer;
2812                 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
2813                 {
2814                         vec4_t layercolor;
2815                         int layertexrgbscale;
2816                         GL_DepthMask(layer->depthmask);
2817                         GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2818                         if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2819                         {
2820                                 layertexrgbscale = 4;
2821                                 VectorScale(layer->color, 0.25f, layercolor);
2822                         }
2823                         else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2824                         {
2825                                 layertexrgbscale = 2;
2826                                 VectorScale(layer->color, 0.5f, layercolor);
2827                         }
2828                         else
2829                         {
2830                                 layertexrgbscale = 1;
2831                                 VectorScale(layer->color, 1.0f, layercolor);
2832                         }
2833                         layercolor[3] = layer->color[3];
2834                         GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2835                         applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2836                         applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2837                         switch (layer->type)
2838                         {
2839                         case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2840                                 memset(&m, 0, sizeof(m));
2841                                 m.tex[1] = R_GetTexture(layer->texture);
2842                                 m.texmatrix[1] = layer->texmatrix;
2843                                 m.texrgbscale[1] = layertexrgbscale;
2844                                 m.pointer_color = varray_color4f;
2845                                 R_Mesh_State(&m);
2846                                 if (lightmode == 2)
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                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2854                                                 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2855                                         }
2856                                 }
2857                                 else
2858                                 {
2859                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2860                                         {
2861                                                 surface = texturesurfacelist[texturesurfaceindex];
2862                                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2863                                                 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2864                                                 if (surface->lightmaptexture)
2865                                                 {
2866                                                         R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2867                                                         RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2868                                                 }
2869                                                 else
2870                                                 {
2871                                                         R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2872                                                         RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2873                                                 }
2874                                         }
2875                                 }
2876                                 break;
2877                         case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2878                                 memset(&m, 0, sizeof(m));
2879                                 m.tex[0] = R_GetTexture(layer->texture);
2880                                 m.texmatrix[0] = layer->texmatrix;
2881                                 m.pointer_color = varray_color4f;
2882                                 m.texrgbscale[0] = layertexrgbscale;
2883                                 R_Mesh_State(&m);
2884                                 if (lightmode == 2)
2885                                 {
2886                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2887                                         {
2888                                                 surface = texturesurfacelist[texturesurfaceindex];
2889                                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2890                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2891                                                 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 2, false, false);
2892                                         }
2893                                 }
2894                                 else
2895                                 {
2896                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2897                                         {
2898                                                 surface = texturesurfacelist[texturesurfaceindex];
2899                                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2900                                                 if (surface->lightmaptexture)
2901                                                 {
2902                                                         R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2903                                                         RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 0, false, false);
2904                                                 }
2905                                                 else
2906                                                 {
2907                                                         R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2908                                                         RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 1, false, false);
2909                                                 }
2910                                         }
2911                                 }
2912                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2913                                 memset(&m, 0, sizeof(m));
2914                                 m.tex[0] = R_GetTexture(layer->texture);
2915                                 m.texmatrix[0] = layer->texmatrix;
2916                                 m.pointer_color = varray_color4f;
2917                                 m.texrgbscale[0] = layertexrgbscale;
2918                                 R_Mesh_State(&m);
2919                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2920                                 {
2921                                         surface = texturesurfacelist[texturesurfaceindex];
2922                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2923                                         RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2924                                 }
2925                                 break;
2926                         case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
2927                                 memset(&m, 0, sizeof(m));
2928                                 m.tex[0] = R_GetTexture(layer->texture);
2929                                 m.texmatrix[0] = layer->texmatrix;
2930                                 m.texrgbscale[0] = layertexrgbscale;
2931                                 m.pointer_color = varray_color4f;
2932                                 R_Mesh_State(&m);
2933                                 if (lightmode == 2)
2934                                 {
2935                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2936                                         {
2937                                                 surface = texturesurfacelist[texturesurfaceindex];
2938                                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2939                                                 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2940                                         }
2941                                 }
2942                                 else
2943                                 {
2944                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2945                                         {
2946                                                 surface = texturesurfacelist[texturesurfaceindex];
2947                                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2948                                                 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2949                                         }
2950                                 }
2951                                 break;
2952                         case TEXTURELAYERTYPE_TEXTURE:
2953                                 memset(&m, 0, sizeof(m));
2954                                 m.tex[0] = R_GetTexture(layer->texture);
2955                                 m.texmatrix[0] = layer->texmatrix;
2956                                 m.pointer_color = varray_color4f;
2957                                 m.texrgbscale[0] = layertexrgbscale;
2958                                 R_Mesh_State(&m);
2959                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2960                                 {
2961                                         surface = texturesurfacelist[texturesurfaceindex];
2962                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2963                                         RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2964                                 }
2965                                 break;
2966                         case TEXTURELAYERTYPE_FOG:
2967                                 memset(&m, 0, sizeof(m));
2968                                 if (layer->texture)
2969                                 {
2970                                         m.tex[0] = R_GetTexture(layer->texture);
2971                                         m.texmatrix[0] = layer->texmatrix;
2972                                 }
2973                                 R_Mesh_State(&m);
2974                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2975                                 {
2976                                         int i;
2977                                         float f, *v, *c;
2978                                         surface = texturesurfacelist[texturesurfaceindex];
2979                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2980                                         if (layer->texture)
2981                                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2982                                         R_Mesh_ColorPointer(varray_color4f);
2983                                         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)
2984                                         {
2985                                                 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
2986                                                 c[0] = layercolor[0];
2987                                                 c[1] = layercolor[1];
2988                                                 c[2] = layercolor[2];
2989                                                 c[3] = f * layercolor[3];
2990                                         }
2991                                         RSurf_Draw(surface);
2992                                 }
2993                                 break;
2994                         default:
2995                                 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2996                         }
2997                         // if trying to do overbright on first pass of an opaque surface
2998                         // when combine is not supported, brighten as a post process
2999                         if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
3000                         {
3001                                 int scale;
3002                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3003                                 GL_Color(1, 1, 1, 1);
3004                                 memset(&m, 0, sizeof(m));
3005                                 R_Mesh_State(&m);
3006                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3007                                 {
3008                                         surface = texturesurfacelist[texturesurfaceindex];
3009                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
3010                                         for (scale = 1;scale < layertexrgbscale;scale <<= 1)
3011                                                 RSurf_Draw(surface);
3012                                 }
3013                         }
3014                 }
3015                 if (r_shownormals.integer && !r_showtrispass)
3016                 {
3017                         int j, k;
3018                         float v[3];
3019                         GL_DepthTest(!r_showdisabledepthtest.integer);
3020                         GL_DepthMask(texture->currentlayers->depthmask);
3021                         GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
3022                         memset(&m, 0, sizeof(m));
3023                         R_Mesh_State(&m);
3024                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3025                         {
3026                                 surface = texturesurfacelist[texturesurfaceindex];
3027                                 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
3028                                 GL_Color(1, 0, 0, 1);
3029                                 qglBegin(GL_LINES);
3030                                 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
3031                                 {
3032                                         VectorCopy(rsurface_vertex3f + k * 3, v);
3033                                         qglVertex3f(v[0], v[1], v[2]);
3034                                         VectorMA(v, 8, rsurface_svector3f + k * 3, v);
3035                                         qglVertex3f(v[0], v[1], v[2]);
3036                                 }
3037                                 GL_Color(0, 0, 1, 1);
3038                                 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
3039                                 {
3040                                         VectorCopy(rsurface_vertex3f + k * 3, v);
3041                                         qglVertex3f(v[0], v[1], v[2]);
3042                                         VectorMA(v, 8, rsurface_tvector3f + k * 3, v);
3043                                         qglVertex3f(v[0], v[1], v[2]);
3044                                 }
3045                                 GL_Color(0, 1, 0, 1);
3046                                 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
3047                                 {
3048                                         VectorCopy(rsurface_vertex3f + k * 3, v);
3049                                         qglVertex3f(v[0], v[1], v[2]);
3050                                         VectorMA(v, 8, rsurface_normal3f + k * 3, v);
3051                                         qglVertex3f(v[0], v[1], v[2]);
3052                                 }
3053                                 qglEnd();
3054                         }
3055                 }
3056         }
3057         if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
3058                 qglEnable(GL_CULL_FACE);
3059 }
3060
3061 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
3062 {
3063         const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
3064         vec3_t modelorg;
3065         texture_t *texture;
3066
3067         texture = surface->texture;
3068         if (texture->basematerialflags & MATERIALFLAG_SKY)
3069                 return; // transparent sky is too difficult
3070         R_UpdateTextureInfo(ent, texture);
3071
3072         R_Mesh_Matrix(&ent->matrix);
3073         Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3074         R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
3075 }
3076
3077 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
3078 {
3079         int texturesurfaceindex;
3080         const msurface_t *surface;
3081         vec3_t tempcenter, center;
3082         if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
3083         {
3084                 // drawing sky transparently would be too difficult
3085                 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
3086                 {
3087                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3088                         {
3089                                 surface = texturesurfacelist[texturesurfaceindex];
3090                                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3091                                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3092                                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3093                                 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
3094                                 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
3095                         }
3096                 }
3097         }
3098         else
3099                 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
3100 }
3101
3102 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3103 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3104 {
3105         int i, j, f, flagsmask;
3106         int counttriangles = 0;
3107         msurface_t *surface, **surfacechain;
3108         texture_t *t, *texture;
3109         model_t *model = ent->model;
3110         vec3_t modelorg;
3111         const int maxsurfacelist = 1024;
3112         int numsurfacelist = 0;
3113         const msurface_t *surfacelist[1024];
3114         if (model == NULL)
3115                 return;
3116         R_Mesh_Matrix(&ent->matrix);
3117         Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3118
3119         // update light styles
3120         if (!skysurfaces && model->brushq1.light_styleupdatechains)
3121         {
3122                 for (i = 0;i < model->brushq1.light_styles;i++)
3123                 {
3124                         if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3125                         {
3126                                 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3127                                 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3128                                         for (;(surface = *surfacechain);surfacechain++)
3129                                                 surface->cached_dlight = true;
3130                         }
3131                 }
3132         }
3133
3134         R_UpdateAllTextureInfo(ent);
3135         flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3136         f = 0;
3137         t = NULL;
3138         texture = NULL;
3139         numsurfacelist = 0;
3140         if (ent == r_refdef.worldentity)
3141         {
3142                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3143                 {
3144                         if (!r_worldsurfacevisible[j])
3145                                 continue;
3146                         if (t != surface->texture)
3147                         {
3148                                 if (numsurfacelist)
3149                                 {
3150                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3151                                         numsurfacelist = 0;
3152                                 }
3153                                 t = surface->texture;
3154                                 texture = t->currentframe;
3155                                 f = texture->currentmaterialflags & flagsmask;
3156                         }
3157                         if (f && surface->num_triangles)
3158                         {
3159                                 // if lightmap parameters changed, rebuild lightmap texture
3160                                 if (surface->cached_dlight)
3161                                         R_BuildLightMap(ent, surface);
3162                                 // add face to draw list
3163                                 surfacelist[numsurfacelist++] = surface;
3164                                 counttriangles += surface->num_triangles;
3165                                 if (numsurfacelist >= maxsurfacelist)
3166                                 {
3167                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3168                                         numsurfacelist = 0;
3169                                 }
3170                         }
3171                 }
3172         }
3173         else
3174         {
3175                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3176                 {
3177                         if (t != surface->texture)
3178                         {
3179                                 if (numsurfacelist)
3180                                 {
3181                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3182                                         numsurfacelist = 0;
3183                                 }
3184                                 t = surface->texture;
3185                                 texture = t->currentframe;
3186                                 f = texture->currentmaterialflags & flagsmask;
3187                         }
3188                         if (f && surface->num_triangles)
3189                         {
3190                                 // if lightmap parameters changed, rebuild lightmap texture
3191                                 if (surface->cached_dlight)
3192                                         R_BuildLightMap(ent, surface);
3193                                 // add face to draw list
3194                                 surfacelist[numsurfacelist++] = surface;
3195                                 counttriangles += surface->num_triangles;
3196                                 if (numsurfacelist >= maxsurfacelist)
3197                                 {
3198                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3199                                         numsurfacelist = 0;
3200                                 }
3201                         }
3202                 }
3203         }
3204         if (numsurfacelist)
3205                 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3206         if (!r_showtrispass)
3207                 renderstats.entities_triangles += counttriangles;
3208         if (gl_support_fragment_shader)
3209                 qglUseProgramObjectARB(0);
3210 }
3211