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