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