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