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