]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
improved setinfo handling so that quakeworld works much better now (name/topcolor...
[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, 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                                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha);
2391                                         if (r_ambient.value >= (1.0f/64.0f))
2392                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, 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);
2393                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2394                                         {
2395                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, 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);
2396                                                 if (r_ambient.value >= (1.0f/64.0f))
2397                                                         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);
2398                                         }
2399                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2400                                         {
2401                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, 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);
2402                                                 if (r_ambient.value >= (1.0f/64.0f))
2403                                                         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);
2404                                         }
2405                                 }
2406                                 if (t->skin.glow != NULL)
2407                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2408                                 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2409                                 {
2410                                         // if this is opaque use alpha blend which will darken the earlier
2411                                         // passes cheaply.
2412                                         //
2413                                         // if this is an alpha blended material, all the earlier passes
2414                                         // were darkened by fog already, so we only need to add the fog
2415                                         // color ontop through the fog mask texture
2416                                         //
2417                                         // if this is an additive blended material, all the earlier passes
2418                                         // were darkened by fog already, and we should not add fog color
2419                                         // (because the background was not darkened, there is no fog color
2420                                         // that was lost behind it).
2421                                         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);
2422                                 }
2423                         }
2424                 }
2425         }
2426 }
2427
2428 void R_UpdateAllTextureInfo(entity_render_t *ent)
2429 {
2430         int i;
2431         if (ent->model)
2432                 for (i = 0;i < ent->model->num_textures;i++)
2433                         R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2434 }
2435
2436 int rsurface_array_size = 0;
2437 float *rsurface_array_modelvertex3f = NULL;
2438 float *rsurface_array_modelsvector3f = NULL;
2439 float *rsurface_array_modeltvector3f = NULL;
2440 float *rsurface_array_modelnormal3f = NULL;
2441 float *rsurface_array_deformedvertex3f = NULL;
2442 float *rsurface_array_deformedsvector3f = NULL;
2443 float *rsurface_array_deformedtvector3f = NULL;
2444 float *rsurface_array_deformednormal3f = NULL;
2445 float *rsurface_array_color4f = NULL;
2446 float *rsurface_array_texcoord3f = NULL;
2447
2448 void R_Mesh_ResizeArrays(int newvertices)
2449 {
2450         float *base;
2451         if (rsurface_array_size >= newvertices)
2452                 return;
2453         if (rsurface_array_modelvertex3f)
2454                 Mem_Free(rsurface_array_modelvertex3f);
2455         rsurface_array_size = (newvertices + 1023) & ~1023;
2456         base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2457         rsurface_array_modelvertex3f     = base + rsurface_array_size * 0;
2458         rsurface_array_modelsvector3f    = base + rsurface_array_size * 3;
2459         rsurface_array_modeltvector3f    = base + rsurface_array_size * 6;
2460         rsurface_array_modelnormal3f     = base + rsurface_array_size * 9;
2461         rsurface_array_deformedvertex3f  = base + rsurface_array_size * 12;
2462         rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2463         rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2464         rsurface_array_deformednormal3f  = base + rsurface_array_size * 21;
2465         rsurface_array_texcoord3f        = base + rsurface_array_size * 24;
2466         rsurface_array_color4f           = base + rsurface_array_size * 27;
2467 }
2468
2469 float *rsurface_modelvertex3f;
2470 float *rsurface_modelsvector3f;
2471 float *rsurface_modeltvector3f;
2472 float *rsurface_modelnormal3f;
2473 float *rsurface_vertex3f;
2474 float *rsurface_svector3f;
2475 float *rsurface_tvector3f;
2476 float *rsurface_normal3f;
2477 float *rsurface_lightmapcolor4f;
2478 vec3_t rsurface_modelorg;
2479 qboolean rsurface_generatedvertex;
2480 const entity_render_t *rsurface_entity;
2481 const model_t *rsurface_model;
2482 texture_t *rsurface_texture;
2483 rtexture_t *rsurface_lightmaptexture;
2484 rsurfmode_t rsurface_mode;
2485 texture_t *rsurface_glsl_texture;
2486 qboolean rsurface_glsl_uselightmap;
2487
2488 void RSurf_ActiveEntity(const entity_render_t *ent)
2489 {
2490         Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, rsurface_modelorg);
2491         rsurface_entity = ent;
2492         rsurface_model = ent->model;
2493         if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2494                 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2495         R_Mesh_Matrix(&ent->matrix);
2496         Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, rsurface_modelorg);
2497         if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && (rsurface_model->surfmesh.data_morphvertex3f || rsurface_model->surfmesh.data_vertexboneweights))
2498         {
2499                 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2500                 rsurface_modelsvector3f = NULL;
2501                 rsurface_modeltvector3f = NULL;
2502                 rsurface_modelnormal3f = NULL;
2503                 Mod_Alias_GetMesh_Vertex3f(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f);
2504                 rsurface_generatedvertex = true;
2505         }
2506         else
2507         {
2508                 rsurface_modelvertex3f  = rsurface_model->surfmesh.data_vertex3f;
2509                 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2510                 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2511                 rsurface_modelnormal3f  = rsurface_model->surfmesh.data_normal3f;
2512                 rsurface_generatedvertex = false;
2513         }
2514         rsurface_vertex3f  = rsurface_modelvertex3f;
2515         rsurface_svector3f = rsurface_modelsvector3f;
2516         rsurface_tvector3f = rsurface_modeltvector3f;
2517         rsurface_normal3f  = rsurface_modelnormal3f;
2518         rsurface_mode = RSURFMODE_NONE;
2519         rsurface_lightmaptexture = NULL;
2520         rsurface_texture = NULL;
2521         rsurface_glsl_texture = NULL;
2522         rsurface_glsl_uselightmap = false;
2523 }
2524
2525 void RSurf_CleanUp(void)
2526 {
2527         CHECKGLERROR
2528         if (rsurface_mode == RSURFMODE_GLSL)
2529         {
2530                 qglUseProgramObjectARB(0);CHECKGLERROR
2531         }
2532         GL_AlphaTest(false);
2533         rsurface_mode = RSURFMODE_NONE;
2534         rsurface_lightmaptexture = NULL;
2535         rsurface_texture = NULL;
2536         rsurface_glsl_texture = NULL;
2537         rsurface_glsl_uselightmap = false;
2538 }
2539
2540 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2541 {
2542         if (rsurface_generatedvertex)
2543         {
2544                 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2545                         generatetangents = true;
2546                 if (generatetangents)
2547                         generatenormals = true;
2548                 if (generatenormals && !rsurface_modelnormal3f)
2549                 {
2550                         rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2551                         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);
2552                 }
2553                 if (generatetangents && !rsurface_modelsvector3f)
2554                 {
2555                         rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2556                         rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2557                         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);
2558                 }
2559         }
2560         if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2561         {
2562                 int texturesurfaceindex;
2563                 float center[3], forward[3], right[3], up[3], v[4][3];
2564                 matrix4x4_t matrix1, imatrix1;
2565                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewforward, forward);
2566                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewright, right);
2567                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewup, up);
2568                 // make deformed versions of only the vertices used by the specified surfaces
2569                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2570                 {
2571                         int i, j;
2572                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2573                         // a single autosprite surface can contain multiple sprites...
2574                         for (j = 0;j < surface->num_vertices - 3;j += 4)
2575                         {
2576                                 VectorClear(center);
2577                                 for (i = 0;i < 4;i++)
2578                                         VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2579                                 VectorScale(center, 0.25f, center);
2580                                 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2581                                 {
2582                                         forward[0] = rsurface_modelorg[0] - center[0];
2583                                         forward[1] = rsurface_modelorg[1] - center[1];
2584                                         forward[2] = 0;
2585                                         VectorNormalize(forward);
2586                                         right[0] = forward[1];
2587                                         right[1] = -forward[0];
2588                                         right[2] = 0;
2589                                         VectorSet(up, 0, 0, 1);
2590                                 }
2591                                 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2592                                 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);
2593                                 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2594                                 for (i = 0;i < 4;i++)
2595                                         Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2596                                 for (i = 0;i < 4;i++)
2597                                         VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_modelvertex3f + (surface->num_firstvertex+i+j) * 3);
2598                         }
2599                         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);
2600                         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);
2601                 }
2602                 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2603                 rsurface_svector3f = rsurface_array_deformedsvector3f;
2604                 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2605                 rsurface_normal3f = rsurface_array_deformednormal3f;
2606         }
2607         R_Mesh_VertexPointer(rsurface_vertex3f);
2608 }
2609
2610 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
2611 {
2612         int texturesurfaceindex;
2613         const msurface_t *surface = texturesurfacelist[0];
2614         int firstvertex = surface->num_firstvertex;
2615         int endvertex = surface->num_firstvertex + surface->num_vertices;
2616         if (texturenumsurfaces == 1)
2617         {
2618                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2619                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2620         }
2621         else if (r_batchmode.integer == 2)
2622         {
2623                 #define MAXBATCHTRIANGLES 4096
2624                 int batchtriangles = 0;
2625                 int batchelements[MAXBATCHTRIANGLES*3];
2626                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2627                 {
2628                         surface = texturesurfacelist[texturesurfaceindex];
2629                         if (surface->num_triangles >= 256 || (batchtriangles == 0 && texturesurfaceindex + 1 >= texturenumsurfaces))
2630                         {
2631                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2632                                 continue;
2633                         }
2634                         if (batchtriangles + surface->num_triangles > MAXBATCHTRIANGLES)
2635                         {
2636                                 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2637                                 batchtriangles = 0;
2638                                 firstvertex = surface->num_firstvertex;
2639                                 endvertex = surface->num_firstvertex + surface->num_vertices;
2640                         }
2641                         else
2642                         {
2643                                 firstvertex = min(firstvertex, surface->num_firstvertex);
2644                                 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2645                         }
2646                         memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
2647                         batchtriangles += surface->num_triangles;
2648                 }
2649                 if (batchtriangles)
2650                         R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2651         }
2652         else if (r_batchmode.integer == 1)
2653         {
2654                 int firsttriangle = 0;
2655                 int endtriangle = -1;
2656                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2657                 {
2658                         surface = texturesurfacelist[texturesurfaceindex];
2659                         if (surface->num_firsttriangle != endtriangle)
2660                         {
2661                                 if (endtriangle > firsttriangle)
2662                                 {
2663                                         GL_LockArrays(firstvertex, endvertex - firstvertex);
2664                                         R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2665                                 }
2666                                 firstvertex = surface->num_firstvertex;
2667                                 endvertex = surface->num_firstvertex + surface->num_vertices;
2668                                 firsttriangle = surface->num_firsttriangle;
2669                         }
2670                         else
2671                         {
2672                                 firstvertex = min(firstvertex, surface->num_firstvertex);
2673                                 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2674                         }
2675                         endtriangle = surface->num_firsttriangle + surface->num_triangles;
2676                 }
2677                 if (endtriangle > firsttriangle)
2678                 {
2679                         GL_LockArrays(firstvertex, endvertex - firstvertex);
2680                         R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2681                 }
2682         }
2683         else
2684         {
2685                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2686                 {
2687                         surface = texturesurfacelist[texturesurfaceindex];
2688                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2689                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2690                 }
2691         }
2692 }
2693
2694 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2695 {
2696         int texturesurfaceindex;
2697         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2698         {
2699                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2700                 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2701                 GL_Color((k & 15) * (1.0f / 16.0f), ((k >> 4) & 15) * (1.0f / 16.0f), ((k >> 8) & 15) * (1.0f / 16.0f), 0.2f);
2702                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2703                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2704         }
2705 }
2706
2707 static void RSurf_DrawBatch_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2708 {
2709         int texturesurfaceindex;
2710         int i;
2711         float f;
2712         float *v, *c, *c2;
2713         // TODO: optimize
2714         if (lightmode >= 2)
2715         {
2716                 // model lighting
2717                 vec3_t ambientcolor;
2718                 vec3_t diffusecolor;
2719                 vec3_t lightdir;
2720                 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2721                 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2722                 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2723                 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2724                 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2725                 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2726                 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2727                 if (VectorLength2(diffusecolor) > 0)
2728                 {
2729                         // generate color arrays for the surfaces in this list
2730                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2731                         {
2732                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2733                                 int numverts = surface->num_vertices;
2734                                 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2735                                 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2736                                 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2737                                 // q3-style directional shading
2738                                 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2739                                 {
2740                                         if ((f = DotProduct(c2, lightdir)) > 0)
2741                                                 VectorMA(ambientcolor, f, diffusecolor, c);
2742                                         else
2743                                                 VectorCopy(ambientcolor, c);
2744                                         c[3] = a;
2745                                 }
2746                         }
2747                         r = 1;
2748                         g = 1;
2749                         b = 1;
2750                         a = 1;
2751                         applycolor = false;
2752                         rsurface_lightmapcolor4f = rsurface_array_color4f;
2753                 }
2754                 else
2755                 {
2756                         r = ambientcolor[0];
2757                         g = ambientcolor[1];
2758                         b = ambientcolor[2];
2759                         rsurface_lightmapcolor4f = NULL;
2760                 }
2761         }
2762         else if (lightmode >= 1 || !rsurface_lightmaptexture)
2763         {
2764                 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
2765                 {
2766                         // generate color arrays for the surfaces in this list
2767                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2768                         {
2769                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2770                                 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2771                                 {
2772                                         if (surface->lightmapinfo->samples)
2773                                         {
2774                                                 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2775                                                 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2776                                                 VectorScale(lm, scale, c);
2777                                                 if (surface->lightmapinfo->styles[1] != 255)
2778                                                 {
2779                                                         int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2780                                                         lm += size3;
2781                                                         scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2782                                                         VectorMA(c, scale, lm, c);
2783                                                         if (surface->lightmapinfo->styles[2] != 255)
2784                                                         {
2785                                                                 lm += size3;
2786                                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2787                                                                 VectorMA(c, scale, lm, c);
2788                                                                 if (surface->lightmapinfo->styles[3] != 255)
2789                                                                 {
2790                                                                         lm += size3;
2791                                                                         scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2792                                                                         VectorMA(c, scale, lm, c);
2793                                                                 }
2794                                                         }
2795                                                 }
2796                                         }
2797                                         else
2798                                                 VectorClear(c);
2799                                         c[3] = 1;
2800                                 }
2801                         }
2802                         rsurface_lightmapcolor4f = rsurface_array_color4f;
2803                 }
2804                 else
2805                         rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2806         }
2807         else
2808         {
2809                 // just lightmap it
2810                 rsurface_lightmapcolor4f = NULL;
2811         }
2812         if (applyfog)
2813         {
2814                 if (rsurface_lightmapcolor4f)
2815                 {
2816                         // generate color arrays for the surfaces in this list
2817                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2818                         {
2819                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2820                                 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)
2821                                 {
2822                                         f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2823                                         c2[0] = c[0] * f;
2824                                         c2[1] = c[1] * f;
2825                                         c2[2] = c[2] * f;
2826                                         c2[3] = c[3];
2827                                 }
2828                         }
2829                 }
2830                 else
2831                 {
2832                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2833                         {
2834                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2835                                 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)
2836                                 {
2837                                         f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2838                                         c2[0] = f;
2839                                         c2[1] = f;
2840                                         c2[2] = f;
2841                                         c2[3] = 1;
2842                                 }
2843                         }
2844                 }
2845                 rsurface_lightmapcolor4f = rsurface_array_color4f;
2846         }
2847         if (applycolor && rsurface_lightmapcolor4f)
2848         {
2849                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2850                 {
2851                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2852                         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)
2853                         {
2854                                 c2[0] = c[0] * r;
2855                                 c2[1] = c[1] * g;
2856                                 c2[2] = c[2] * b;
2857                                 c2[3] = c[3] * a;
2858                         }
2859                 }
2860                 rsurface_lightmapcolor4f = rsurface_array_color4f;
2861         }
2862         R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2863         GL_Color(r, g, b, a);
2864         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2865 }
2866
2867 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2868 {
2869         if (rsurface_mode != RSURFMODE_SHOWSURFACES)
2870         {
2871                 rsurface_mode = RSURFMODE_SHOWSURFACES;
2872                 GL_DepthMask(true);
2873                 GL_BlendFunc(GL_ONE, GL_ZERO);
2874                 R_Mesh_ColorPointer(NULL);
2875                 R_Mesh_ResetTextureState();
2876         }
2877         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2878         RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
2879 }
2880
2881 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
2882 {
2883         // transparent sky would be ridiculous
2884         if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2885                 return;
2886         if (rsurface_mode != RSURFMODE_SKY)
2887         {
2888                 if (rsurface_mode == RSURFMODE_GLSL)
2889                 {
2890                         qglUseProgramObjectARB(0);CHECKGLERROR
2891                 }
2892                 rsurface_mode = RSURFMODE_SKY;
2893         }
2894         if (skyrendernow)
2895         {
2896                 skyrendernow = false;
2897                 R_Sky();
2898                 // restore entity matrix
2899                 R_Mesh_Matrix(&rsurface_entity->matrix);
2900         }
2901         GL_DepthMask(true);
2902         // LordHavoc: HalfLife maps have freaky skypolys so don't use
2903         // skymasking on them, and Quake3 never did sky masking (unlike
2904         // software Quake and software Quake2), so disable the sky masking
2905         // in Quake3 maps as it causes problems with q3map2 sky tricks,
2906         // and skymasking also looks very bad when noclipping outside the
2907         // level, so don't use it then either.
2908         if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_worldnovis)
2909         {
2910                 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2911                 R_Mesh_ColorPointer(NULL);
2912                 R_Mesh_ResetTextureState();
2913                 if (skyrendermasked)
2914                 {
2915                         // depth-only (masking)
2916                         GL_ColorMask(0,0,0,0);
2917                         // just to make sure that braindead drivers don't draw
2918                         // anything despite that colormask...
2919                         GL_BlendFunc(GL_ZERO, GL_ONE);
2920                 }
2921                 else
2922                 {
2923                         // fog sky
2924                         GL_BlendFunc(GL_ONE, GL_ZERO);
2925                 }
2926         }
2927         // LordHavoc: HalfLife maps have freaky skypolys so don't use
2928         // skymasking on them, and Quake3 never did sky masking (unlike
2929         // software Quake and software Quake2), so disable the sky masking
2930         // in Quake3 maps as it causes problems with q3map2 sky tricks,
2931         // and skymasking also looks very bad when noclipping outside the
2932         // level, so don't use it then either.
2933         if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_worldnovis)
2934         {
2935                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2936                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2937                 if (skyrendermasked)
2938                         GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2939         }
2940 }
2941
2942 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
2943 {
2944         int lightmode;
2945         // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
2946         lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
2947         if (rsurface_mode != RSURFMODE_GLSL)
2948         {
2949                 rsurface_mode = RSURFMODE_GLSL;
2950                 rsurface_glsl_texture = NULL;
2951                 rsurface_glsl_uselightmap = false;
2952                 R_Mesh_ResetTextureState();
2953         }
2954         if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != (rsurface_lightmaptexture != NULL))
2955         {
2956                 rsurface_glsl_texture = rsurface_texture;
2957                 rsurface_glsl_uselightmap = rsurface_lightmaptexture != NULL;
2958                 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
2959                 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
2960                 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
2961                 R_SetupSurfaceShader(vec3_origin, lightmode == 2);
2962                 //permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, false);
2963                 //if (r_glsl_deluxemapping.integer)
2964                 //      permutation_deluxemapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, true);
2965                 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
2966                 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
2967                 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2968         }
2969         if (!r_glsl_permutation)
2970                 return;
2971         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
2972         R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2973         R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2974         R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2975         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2976         {
2977                 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2978                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2979                         R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2980                 R_Mesh_ColorPointer(NULL);
2981         }
2982         else if (rsurface_lightmaptexture)
2983         {
2984                 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
2985                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2986                         R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
2987                 R_Mesh_ColorPointer(NULL);
2988         }
2989         else
2990         {
2991                 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2992                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2993                         R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2994                 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
2995         }
2996         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2997 }
2998
2999 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
3000 {
3001         // OpenGL 1.3 path - anything not completely ancient
3002         int texturesurfaceindex;
3003         int lightmode;
3004         qboolean applycolor;
3005         qboolean applyfog;
3006         rmeshstate_t m;
3007         int layerindex;
3008         const texturelayer_t *layer;
3009         CHECKGLERROR
3010         // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3011         lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3012         if (rsurface_mode != RSURFMODE_MULTIPASS)
3013                 rsurface_mode = RSURFMODE_MULTIPASS;
3014         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3015         for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3016         {
3017                 vec4_t layercolor;
3018                 int layertexrgbscale;
3019                 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3020                 {
3021                         if (layerindex == 0)
3022                                 GL_AlphaTest(true);
3023                         else
3024                         {
3025                                 GL_AlphaTest(false);
3026                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3027                         }
3028                 }
3029                 GL_DepthMask(layer->depthmask);
3030                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3031                 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
3032                 {
3033                         layertexrgbscale = 4;
3034                         VectorScale(layer->color, 0.25f, layercolor);
3035                 }
3036                 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
3037                 {
3038                         layertexrgbscale = 2;
3039                         VectorScale(layer->color, 0.5f, layercolor);
3040                 }
3041                 else
3042                 {
3043                         layertexrgbscale = 1;
3044                         VectorScale(layer->color, 1.0f, layercolor);
3045                 }
3046                 layercolor[3] = layer->color[3];
3047                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
3048                 R_Mesh_ColorPointer(NULL);
3049                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3050                 switch (layer->type)
3051                 {
3052                 case TEXTURELAYERTYPE_LITTEXTURE:
3053                         memset(&m, 0, sizeof(m));
3054                         if (lightmode >= 1 || !rsurface_lightmaptexture)
3055                                 m.tex[0] = R_GetTexture(r_texture_white);
3056                         else
3057                                 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3058                         m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3059                         m.tex[1] = R_GetTexture(layer->texture);
3060                         m.texmatrix[1] = layer->texmatrix;
3061                         m.texrgbscale[1] = layertexrgbscale;
3062                         m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
3063                         R_Mesh_TextureState(&m);
3064                         RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode, applycolor, applyfog);
3065                         break;
3066                 case TEXTURELAYERTYPE_TEXTURE:
3067                         memset(&m, 0, sizeof(m));
3068                         m.tex[0] = R_GetTexture(layer->texture);
3069                         m.texmatrix[0] = layer->texmatrix;
3070                         m.texrgbscale[0] = layertexrgbscale;
3071                         m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3072                         R_Mesh_TextureState(&m);
3073                         RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3074                         break;
3075                 case TEXTURELAYERTYPE_FOG:
3076                         memset(&m, 0, sizeof(m));
3077                         m.texrgbscale[0] = layertexrgbscale;
3078                         if (layer->texture)
3079                         {
3080                                 m.tex[0] = R_GetTexture(layer->texture);
3081                                 m.texmatrix[0] = layer->texmatrix;
3082                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3083                         }
3084                         R_Mesh_TextureState(&m);
3085                         // generate a color array for the fog pass
3086                         R_Mesh_ColorPointer(rsurface_array_color4f);
3087                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3088                         {
3089                                 int i;
3090                                 float f, *v, *c;
3091                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3092                                 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)
3093                                 {
3094                                         f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3095                                         c[0] = layercolor[0];
3096                                         c[1] = layercolor[1];
3097                                         c[2] = layercolor[2];
3098                                         c[3] = f * layercolor[3];
3099                                 }
3100                         }
3101                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3102                         break;
3103                 default:
3104                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3105                 }
3106                 GL_LockArrays(0, 0);
3107         }
3108         CHECKGLERROR
3109         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3110         {
3111                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3112                 GL_AlphaTest(false);
3113         }
3114 }
3115
3116 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3117 {
3118         // OpenGL 1.1 - crusty old voodoo path
3119         int texturesurfaceindex;
3120         int lightmode;
3121         qboolean applyfog;
3122         rmeshstate_t m;
3123         int layerindex;
3124         const texturelayer_t *layer;
3125         CHECKGLERROR
3126         // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3127         lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3128         if (rsurface_mode != RSURFMODE_MULTIPASS)
3129                 rsurface_mode = RSURFMODE_MULTIPASS;
3130         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3131         for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3132         {
3133                 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3134                 {
3135                         if (layerindex == 0)
3136                                 GL_AlphaTest(true);
3137                         else
3138                         {
3139                                 GL_AlphaTest(false);
3140                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3141                         }
3142                 }
3143                 GL_DepthMask(layer->depthmask);
3144                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3145                 R_Mesh_ColorPointer(NULL);
3146                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3147                 switch (layer->type)
3148                 {
3149                 case TEXTURELAYERTYPE_LITTEXTURE:
3150                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3151                         {
3152                                 // two-pass lit texture with 2x rgbscale
3153                                 // first the lightmap pass
3154                                 memset(&m, 0, sizeof(m));
3155                                 if (lightmode >= 1 || !rsurface_lightmaptexture)
3156                                         m.tex[0] = R_GetTexture(r_texture_white);
3157                                 else
3158                                         m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3159                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3160                                 R_Mesh_TextureState(&m);
3161                                 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, lightmode, false, false);
3162                                 GL_LockArrays(0, 0);
3163                                 // then apply the texture to it
3164                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3165                                 memset(&m, 0, sizeof(m));
3166                                 m.tex[0] = R_GetTexture(layer->texture);
3167                                 m.texmatrix[0] = layer->texmatrix;
3168                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3169                                 R_Mesh_TextureState(&m);
3170                                 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], 0, layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
3171                         }
3172                         else
3173                         {
3174                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3175                                 memset(&m, 0, sizeof(m));
3176                                 m.tex[0] = R_GetTexture(layer->texture);
3177                                 m.texmatrix[0] = layer->texmatrix;
3178                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3179                                 R_Mesh_TextureState(&m);
3180                                 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], lightmode == 2 ? 2 : 1, layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
3181                         }
3182                         break;
3183                 case TEXTURELAYERTYPE_TEXTURE:
3184                         // singletexture unlit texture with transparency support
3185                         memset(&m, 0, sizeof(m));
3186                         m.tex[0] = R_GetTexture(layer->texture);
3187                         m.texmatrix[0] = layer->texmatrix;
3188                         m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3189                         R_Mesh_TextureState(&m);
3190                         RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], 0, layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
3191                         break;
3192                 case TEXTURELAYERTYPE_FOG:
3193                         // singletexture fogging
3194                         R_Mesh_ColorPointer(rsurface_array_color4f);
3195                         if (layer->texture)
3196                         {
3197                                 memset(&m, 0, sizeof(m));
3198                                 m.tex[0] = R_GetTexture(layer->texture);
3199                                 m.texmatrix[0] = layer->texmatrix;
3200                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3201                                 R_Mesh_TextureState(&m);
3202                         }
3203                         else
3204                                 R_Mesh_ResetTextureState();
3205                         // generate a color array for the fog pass
3206                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3207                         {
3208                                 int i;
3209                                 float f, *v, *c;
3210                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3211                                 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)
3212                                 {
3213                                         f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3214                                         c[0] = layer->color[0];
3215                                         c[1] = layer->color[1];
3216                                         c[2] = layer->color[2];
3217                                         c[3] = f * layer->color[3];
3218                                 }
3219                         }
3220                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3221                         break;
3222                 default:
3223                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3224                 }
3225                 GL_LockArrays(0, 0);
3226         }
3227         CHECKGLERROR
3228         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3229         {
3230                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3231                 GL_AlphaTest(false);
3232         }
3233 }
3234
3235 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3236 {
3237         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3238                 return;
3239         r_shadow_rtlight = NULL;
3240         renderstats.entities_surfaces += texturenumsurfaces;
3241         CHECKGLERROR
3242         GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3243         if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3244         {
3245                 qglDisable(GL_CULL_FACE);CHECKGLERROR
3246         }
3247         if (r_showsurfaces.integer)
3248                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3249         else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3250                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3251         else if (rsurface_texture->currentnumlayers)
3252         {
3253                 if (r_glsl.integer && gl_support_fragment_shader)
3254                         R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3255                 else if (gl_combine.integer && r_textureunits.integer >= 2)
3256                         R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3257                 else
3258                         R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3259         }
3260         CHECKGLERROR
3261         GL_LockArrays(0, 0);
3262         if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3263         {
3264                 qglEnable(GL_CULL_FACE);CHECKGLERROR
3265         }
3266 }
3267
3268 #define BATCHSIZE 256
3269 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3270 {
3271         int surfacelistindex;
3272         int batchcount;
3273         texture_t *t;
3274         msurface_t *texturesurfacelist[BATCHSIZE];
3275         RSurf_ActiveEntity(ent);
3276         batchcount = 0;
3277         t = NULL;
3278         for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3279         {
3280                 msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
3281
3282                 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3283                 {
3284                         if (batchcount > 0)
3285                                 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3286                         batchcount = 0;
3287                         t = surface->texture;
3288                         rsurface_lightmaptexture = surface->lightmaptexture;
3289                         R_UpdateTextureInfo(ent, t);
3290                         rsurface_texture = t->currentframe;
3291                 }
3292                 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3293                         continue; // transparent sky is too difficult
3294
3295                 texturesurfacelist[batchcount++] = surface;
3296         }
3297         if (batchcount > 0)
3298                 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3299         RSurf_CleanUp();
3300 }
3301
3302 void R_QueueTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3303 {
3304         int texturesurfaceindex;
3305         vec3_t tempcenter, center;
3306         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3307         {
3308                 // drawing sky transparently would be too difficult
3309                 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY))
3310                 {
3311                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3312                         {
3313                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3314                                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3315                                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3316                                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3317                                 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3318                                 R_MeshQueue_AddTransparent(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, rsurface_entity, surface - rsurface_model->data_surfaces, r_shadow_rtlight);
3319                         }
3320                 }
3321         }
3322         else
3323                 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3324 }
3325
3326 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3327 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3328 {
3329         int i, j, f, flagsmask;
3330         int counttriangles = 0;
3331         texture_t *t;
3332         model_t *model = ent->model;
3333         const int maxsurfacelist = 1024;
3334         int numsurfacelist = 0;
3335         msurface_t *surfacelist[1024];
3336         if (model == NULL)
3337                 return;
3338
3339         RSurf_ActiveEntity(ent);
3340
3341         // update light styles
3342         if (!skysurfaces && model->brushq1.light_styleupdatechains)
3343         {
3344                 msurface_t *surface, **surfacechain;
3345                 for (i = 0;i < model->brushq1.light_styles;i++)
3346                 {
3347                         if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3348                         {
3349                                 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3350                                 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3351                                         for (;(surface = *surfacechain);surfacechain++)
3352                                                 surface->cached_dlight = true;
3353                         }
3354                 }
3355         }
3356
3357         R_UpdateAllTextureInfo(ent);
3358         flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3359         f = 0;
3360         t = NULL;
3361         rsurface_lightmaptexture = NULL;
3362         rsurface_texture = NULL;
3363         numsurfacelist = 0;
3364         if (ent == r_refdef.worldentity)
3365         {
3366                 msurface_t *surface;
3367                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3368                 {
3369                         if (!r_worldsurfacevisible[j])
3370                                 continue;
3371                         if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3372                         {
3373                                 if (numsurfacelist)
3374                                 {
3375                                         R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3376                                         numsurfacelist = 0;
3377                                 }
3378                                 t = surface->texture;
3379                                 rsurface_lightmaptexture = surface->lightmaptexture;
3380                                 rsurface_texture = t->currentframe;
3381                                 f = rsurface_texture->currentmaterialflags & flagsmask;
3382                         }
3383                         if (f && surface->num_triangles)
3384                         {
3385                                 // if lightmap parameters changed, rebuild lightmap texture
3386                                 if (surface->cached_dlight)
3387                                         R_BuildLightMap(ent, surface);
3388                                 // add face to draw list
3389                                 surfacelist[numsurfacelist++] = surface;
3390                                 counttriangles += surface->num_triangles;
3391                                 if (numsurfacelist >= maxsurfacelist)
3392                                 {
3393                                         R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3394                                         numsurfacelist = 0;
3395                                 }
3396                         }
3397                 }
3398         }
3399         else
3400         {
3401                 msurface_t *surface;
3402                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3403                 {
3404                         if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3405                         {
3406                                 if (numsurfacelist)
3407                                 {
3408                                         R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3409                                         numsurfacelist = 0;
3410                                 }
3411                                 t = surface->texture;
3412                                 rsurface_lightmaptexture = surface->lightmaptexture;
3413                                 rsurface_texture = t->currentframe;
3414                                 f = rsurface_texture->currentmaterialflags & flagsmask;
3415                         }
3416                         if (f && surface->num_triangles)
3417                         {
3418                                 // if lightmap parameters changed, rebuild lightmap texture
3419                                 if (surface->cached_dlight)
3420                                         R_BuildLightMap(ent, surface);
3421                                 // add face to draw list
3422                                 surfacelist[numsurfacelist++] = surface;
3423                                 counttriangles += surface->num_triangles;
3424                                 if (numsurfacelist >= maxsurfacelist)
3425                                 {
3426                                         R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3427                                         numsurfacelist = 0;
3428                                 }
3429                         }
3430                 }
3431         }
3432         if (numsurfacelist)
3433                 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3434         renderstats.entities_triangles += counttriangles;
3435         RSurf_CleanUp();
3436
3437         if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3438         {
3439                 int i;
3440                 const msurface_t *surface;
3441                 q3mbrush_t *brush;
3442                 CHECKGLERROR
3443                 R_Mesh_Matrix(&ent->matrix);
3444                 R_Mesh_ColorPointer(NULL);
3445                 R_Mesh_ResetTextureState();
3446                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3447                 GL_DepthMask(false);
3448                 GL_DepthTest(!r_showdisabledepthtest.integer);
3449                 qglPolygonOffset(r_polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3450                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3451                         if (brush->colbrushf && brush->colbrushf->numtriangles)
3452                                 R_DrawCollisionBrush(brush->colbrushf);
3453                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3454                         if (surface->num_collisiontriangles)
3455                                 R_DrawCollisionSurface(ent, surface);
3456                 qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
3457         }
3458
3459         if (r_showtris.integer || r_shownormals.integer)
3460         {
3461                 int k, l;
3462                 msurface_t *surface;
3463                 const int *elements;
3464                 vec3_t v;
3465                 CHECKGLERROR
3466                 GL_DepthTest(true);
3467                 GL_DepthMask(true);
3468                 if (r_showdisabledepthtest.integer)
3469                 {
3470                         qglDepthFunc(GL_ALWAYS);CHECKGLERROR
3471                 }
3472                 GL_BlendFunc(GL_ONE, GL_ZERO);
3473                 R_Mesh_ColorPointer(NULL);
3474                 R_Mesh_ResetTextureState();
3475                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3476                 {
3477                         if (ent == r_refdef.worldentity && !r_worldsurfacevisible[j])
3478                                 continue;
3479                         rsurface_texture = surface->texture->currentframe;
3480                         if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3481                         {
3482                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3483                                 if (r_showtris.integer)
3484                                 {
3485                                         if (!rsurface_texture->currentlayers->depthmask)
3486                                                 GL_Color(r_showtris.value, 0, 0, 1);
3487                                         else if (ent == r_refdef.worldentity)
3488                                                 GL_Color(r_showtris.value, r_showtris.value, r_showtris.value, 1);
3489                                         else
3490                                                 GL_Color(0, r_showtris.value, 0, 1);
3491                                         elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3492                                         CHECKGLERROR
3493                                         qglBegin(GL_LINES);
3494                                         for (k = 0;k < surface->num_triangles;k++, elements += 3)
3495                                         {
3496                                                 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3497                                                 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3498                                                 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3499                                         }
3500                                         qglEnd();
3501                                         CHECKGLERROR
3502                                 }
3503                                 if (r_shownormals.integer)
3504                                 {
3505                                         GL_Color(r_shownormals.value, 0, 0, 1);
3506                                         qglBegin(GL_LINES);
3507                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3508                                         {
3509                                                 VectorCopy(rsurface_vertex3f + l * 3, v);
3510                                                 qglVertex3f(v[0], v[1], v[2]);
3511                                                 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3512                                                 qglVertex3f(v[0], v[1], v[2]);
3513                                         }
3514                                         qglEnd();
3515                                         CHECKGLERROR
3516                                         GL_Color(0, 0, r_shownormals.value, 1);
3517                                         qglBegin(GL_LINES);
3518                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3519                                         {
3520                                                 VectorCopy(rsurface_vertex3f + l * 3, v);
3521                                                 qglVertex3f(v[0], v[1], v[2]);
3522                                                 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3523                                                 qglVertex3f(v[0], v[1], v[2]);
3524                                         }
3525                                         qglEnd();
3526                                         CHECKGLERROR
3527                                         GL_Color(0, r_shownormals.value, 0, 1);
3528                                         qglBegin(GL_LINES);
3529                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3530                                         {
3531                                                 VectorCopy(rsurface_vertex3f + l * 3, v);
3532                                                 qglVertex3f(v[0], v[1], v[2]);
3533                                                 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3534                                                 qglVertex3f(v[0], v[1], v[2]);
3535                                         }
3536                                         qglEnd();
3537                                         CHECKGLERROR
3538                                 }
3539                         }
3540                 }
3541                 rsurface_texture = NULL;
3542                 if (r_showdisabledepthtest.integer)
3543                 {
3544                         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3545                 }
3546         }
3547 }
3548