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