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