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