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