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