]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
7af8009a7a92ed0ca88da60dcf767b79d5873ef8
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "r_shadow.h"
24 #include "polygon.h"
25
26 mempool_t *r_main_mempool;
27 rtexturepool_t *r_main_texturepool;
28
29 // used for dlight push checking and other things
30 int r_framecount;
31
32 mplane_t frustum[5];
33
34 renderstats_t renderstats;
35
36 // true during envmap command capture
37 qboolean envmap;
38
39 // maximum visible distance (recalculated from world box each frame)
40 float r_farclip;
41 // brightness of world lightmaps and related lighting
42 // (often reduced when world rtlights are enabled)
43 float r_lightmapintensity;
44 // whether to draw world lights realtime, dlights realtime, and their shadows
45 qboolean r_rtworld;
46 qboolean r_rtworldshadows;
47 qboolean r_rtdlight;
48 qboolean r_rtdlightshadows;
49
50
51 // view origin
52 vec3_t r_vieworigin;
53 vec3_t r_viewforward;
54 vec3_t r_viewleft;
55 vec3_t r_viewright;
56 vec3_t r_viewup;
57 int r_view_x;
58 int r_view_y;
59 int r_view_z;
60 int r_view_width;
61 int r_view_height;
62 int r_view_depth;
63 matrix4x4_t r_view_matrix;
64 float r_polygonfactor;
65 float r_polygonoffset;
66 float r_shadowpolygonfactor;
67 float r_shadowpolygonoffset;
68 //
69 // screen size info
70 //
71 refdef_t r_refdef;
72
73 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "shows surfaces as different colors"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing\n"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
85 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
86 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
87 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
88 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
89 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
90
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_TexBindCubeMap(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, r_lightmapintensity * 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_showsurfaces);
1172         Cvar_RegisterVariable(&r_showtris);
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         r_polygonfactor = 0;
1829         r_polygonoffset = 0;
1830         r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
1831         r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
1832         if (r_showsurfaces.integer)
1833         {
1834                 r_rtworld = false;
1835                 r_rtworldshadows = false;
1836                 r_rtdlight = false;
1837                 r_rtdlightshadows = false;
1838                 r_lightmapintensity = 0;
1839         }
1840
1841         // GL is weird because it's bottom to top, r_view_y is top to bottom
1842         qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1843         GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1844         GL_ScissorTest(true);
1845         GL_DepthMask(true);
1846         R_ClearScreen();
1847         R_Textures_Frame();
1848         R_UpdateFog();
1849         if (r_timereport_active)
1850                 R_TimeReport("setup");
1851
1852         qglDepthFunc(GL_LEQUAL);
1853         qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1854         qglEnable(GL_POLYGON_OFFSET_FILL);
1855
1856         R_RenderScene();
1857
1858         qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1859         qglDisable(GL_POLYGON_OFFSET_FILL);
1860
1861         R_BlendView();
1862         if (r_timereport_active)
1863                 R_TimeReport("blendview");
1864
1865         GL_Scissor(0, 0, vid.width, vid.height);
1866         GL_ScissorTest(false);
1867 }
1868
1869 //[515]: csqc
1870 void CSQC_R_ClearScreen (void)
1871 {
1872         if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1873                 return; //Host_Error ("R_RenderView: NULL worldmodel");
1874
1875         r_view_width = bound(0, r_refdef.width, vid.width);
1876         r_view_height = bound(0, r_refdef.height, vid.height);
1877         r_view_depth = 1;
1878         r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1879         r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1880         r_view_z = 0;
1881         r_view_matrix = r_refdef.viewentitymatrix;
1882         GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1883         r_rtworld = r_shadow_realtime_world.integer;
1884         r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1885         r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1886         r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1887         r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1888         r_polygonfactor = 0;
1889         r_polygonoffset = 0;
1890         r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
1891         r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
1892         if (r_showsurfaces.integer)
1893         {
1894                 r_rtworld = false;
1895                 r_rtworldshadows = false;
1896                 r_rtdlight = false;
1897                 r_rtdlightshadows = false;
1898                 r_lightmapintensity = 0;
1899         }
1900
1901         // GL is weird because it's bottom to top, r_view_y is top to bottom
1902         qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1903         GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1904         GL_ScissorTest(true);
1905         GL_DepthMask(true);
1906         R_ClearScreen();
1907         R_Textures_Frame();
1908         R_UpdateFog();
1909         if (r_timereport_active)
1910                 R_TimeReport("setup");
1911 }
1912
1913 //[515]: csqc
1914 void CSQC_R_RenderScene (void)
1915 {
1916         qglDepthFunc(GL_LEQUAL);
1917         qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1918         qglEnable(GL_POLYGON_OFFSET_FILL);
1919
1920         R_RenderScene();
1921
1922         qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1923         qglDisable(GL_POLYGON_OFFSET_FILL);
1924
1925         R_BlendView();
1926         if (r_timereport_active)
1927                 R_TimeReport("blendview");
1928
1929         GL_Scissor(0, 0, vid.width, vid.height);
1930         GL_ScissorTest(false);
1931 }
1932
1933 extern void R_DrawLightningBeams (void);
1934 extern void VM_AddPolygonsToMeshQueue (void);
1935 void R_RenderScene(void)
1936 {
1937         float nearclip;
1938
1939         // don't let sound skip if going slow
1940         if (r_refdef.extraupdate)
1941                 S_ExtraUpdate ();
1942
1943         r_framecount++;
1944
1945         if (gl_support_fragment_shader)
1946                 qglUseProgramObjectARB(0);
1947
1948         R_MeshQueue_BeginScene();
1949
1950         R_SetFrustum();
1951
1952         r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1953         nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
1954
1955         if (r_rtworldshadows || r_rtdlightshadows)
1956                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
1957         else
1958                 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
1959
1960         GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1961
1962         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);
1963
1964         R_SkyStartFrame();
1965
1966         R_WorldVisibility();
1967         if (r_timereport_active)
1968                 R_TimeReport("worldvis");
1969
1970         R_MarkEntities();
1971         if (r_timereport_active)
1972                 R_TimeReport("markentity");
1973
1974         R_Shadow_UpdateWorldLightSelection();
1975
1976         if (cl.csqc_vidvars.drawworld)
1977         {
1978                 // don't let sound skip if going slow
1979                 if (r_refdef.extraupdate)
1980                         S_ExtraUpdate ();
1981
1982                 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1983                 {
1984                         r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1985                         if (r_timereport_active)
1986                                 R_TimeReport("worldsky");
1987                 }
1988
1989                 if (R_DrawBrushModelsSky() && r_timereport_active)
1990                         R_TimeReport("bmodelsky");
1991
1992                 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1993                 {
1994                         r_refdef.worldmodel->Draw(r_refdef.worldentity);
1995                         if (r_timereport_active)
1996                                 R_TimeReport("world");
1997                 }
1998         }
1999
2000         // don't let sound skip if going slow
2001         if (r_refdef.extraupdate)
2002                 S_ExtraUpdate ();
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         R_ShadowVolumeLighting(false);
2013         if (r_timereport_active)
2014                 R_TimeReport("rtlights");
2015
2016         // don't let sound skip if going slow
2017         if (r_refdef.extraupdate)
2018                 S_ExtraUpdate ();
2019
2020         if (cl.csqc_vidvars.drawworld)
2021         {
2022                 R_DrawLightningBeams();
2023                 if (r_timereport_active)
2024                         R_TimeReport("lightning");
2025
2026                 R_DrawParticles();
2027                 if (r_timereport_active)
2028                         R_TimeReport("particles");
2029
2030                 R_DrawExplosions();
2031                 if (r_timereport_active)
2032                         R_TimeReport("explosions");
2033         }
2034
2035         R_MeshQueue_RenderTransparent();
2036         if (r_timereport_active)
2037                 R_TimeReport("drawtrans");
2038
2039         if (cl.csqc_vidvars.drawworld)
2040         {
2041                 R_DrawCoronas();
2042                 if (r_timereport_active)
2043                         R_TimeReport("coronas");
2044         }
2045         if(cl.csqc_vidvars.drawcrosshair)
2046         {
2047                 R_DrawWorldCrosshair();
2048                 if (r_timereport_active)
2049                         R_TimeReport("crosshair");
2050         }
2051
2052         VM_AddPolygonsToMeshQueue();
2053
2054         R_MeshQueue_Render();
2055
2056         R_MeshQueue_EndScene();
2057
2058         // don't let sound skip if going slow
2059         if (r_refdef.extraupdate)
2060                 S_ExtraUpdate ();
2061
2062         if (gl_support_fragment_shader)
2063                 qglUseProgramObjectARB(0);
2064 }
2065
2066 /*
2067 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2068 {
2069         int i;
2070         float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2071         rmeshstate_t m;
2072         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2073         GL_DepthMask(false);
2074         GL_DepthTest(true);
2075         R_Mesh_Matrix(&identitymatrix);
2076
2077         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2078         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2079         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2080         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2081         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2082         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2083         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2084         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2085         R_FillColors(color, 8, cr, cg, cb, ca);
2086         if (fogenabled)
2087         {
2088                 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2089                 {
2090                         f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
2091                         f1 = 1 - f2;
2092                         c[0] = c[0] * f1 + fogcolor[0] * f2;
2093                         c[1] = c[1] * f1 + fogcolor[1] * f2;
2094                         c[2] = c[2] * f1 + fogcolor[2] * f2;
2095                 }
2096         }
2097         memset(&m, 0, sizeof(m));
2098         m.pointer_vertex = vertex3f;
2099         m.pointer_color = color;
2100         R_Mesh_State(&m);
2101         R_Mesh_Draw(8, 12);
2102 }
2103 */
2104
2105 int nomodelelements[24] =
2106 {
2107         5, 2, 0,
2108         5, 1, 2,
2109         5, 0, 3,
2110         5, 3, 1,
2111         0, 2, 4,
2112         2, 1, 4,
2113         3, 0, 4,
2114         1, 3, 4
2115 };
2116
2117 float nomodelvertex3f[6*3] =
2118 {
2119         -16,   0,   0,
2120          16,   0,   0,
2121           0, -16,   0,
2122           0,  16,   0,
2123           0,   0, -16,
2124           0,   0,  16
2125 };
2126
2127 float nomodelcolor4f[6*4] =
2128 {
2129         0.0f, 0.0f, 0.5f, 1.0f,
2130         0.0f, 0.0f, 0.5f, 1.0f,
2131         0.0f, 0.5f, 0.0f, 1.0f,
2132         0.0f, 0.5f, 0.0f, 1.0f,
2133         0.5f, 0.0f, 0.0f, 1.0f,
2134         0.5f, 0.0f, 0.0f, 1.0f
2135 };
2136
2137 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2138 {
2139         int i;
2140         float f1, f2, *c;
2141         float color4f[6*4];
2142         rmeshstate_t m;
2143         R_Mesh_Matrix(&ent->matrix);
2144
2145         memset(&m, 0, sizeof(m));
2146         m.pointer_vertex = nomodelvertex3f;
2147
2148         if (ent->flags & EF_ADDITIVE)
2149         {
2150                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2151                 GL_DepthMask(false);
2152         }
2153         else if (ent->alpha < 1)
2154         {
2155                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2156                 GL_DepthMask(false);
2157         }
2158         else
2159         {
2160                 GL_BlendFunc(GL_ONE, GL_ZERO);
2161                 GL_DepthMask(true);
2162         }
2163         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2164         if (fogenabled)
2165         {
2166                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2167                 m.pointer_color = color4f;
2168                 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
2169                 f1 = 1 - f2;
2170                 for (i = 0, c = color4f;i < 6;i++, c += 4)
2171                 {
2172                         c[0] = (c[0] * f1 + fogcolor[0] * f2);
2173                         c[1] = (c[1] * f1 + fogcolor[1] * f2);
2174                         c[2] = (c[2] * f1 + fogcolor[2] * f2);
2175                         c[3] *= ent->alpha;
2176                 }
2177         }
2178         else if (ent->alpha != 1)
2179         {
2180                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2181                 m.pointer_color = color4f;
2182                 for (i = 0, c = color4f;i < 6;i++, c += 4)
2183                         c[3] *= ent->alpha;
2184         }
2185         else
2186                 m.pointer_color = nomodelcolor4f;
2187         R_Mesh_State(&m);
2188         R_Mesh_Draw(0, 6, 8, nomodelelements);
2189 }
2190
2191 void R_DrawNoModel(entity_render_t *ent)
2192 {
2193         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2194                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2195         //else
2196         //      R_DrawNoModelCallback(ent, 0);
2197 }
2198
2199 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2200 {
2201         vec3_t right1, right2, diff, normal;
2202
2203         VectorSubtract (org2, org1, normal);
2204
2205         // calculate 'right' vector for start
2206         VectorSubtract (r_vieworigin, org1, diff);
2207         CrossProduct (normal, diff, right1);
2208         VectorNormalize (right1);
2209
2210         // calculate 'right' vector for end
2211         VectorSubtract (r_vieworigin, org2, diff);
2212         CrossProduct (normal, diff, right2);
2213         VectorNormalize (right2);
2214
2215         vert[ 0] = org1[0] + width * right1[0];
2216         vert[ 1] = org1[1] + width * right1[1];
2217         vert[ 2] = org1[2] + width * right1[2];
2218         vert[ 3] = org1[0] - width * right1[0];
2219         vert[ 4] = org1[1] - width * right1[1];
2220         vert[ 5] = org1[2] - width * right1[2];
2221         vert[ 6] = org2[0] - width * right2[0];
2222         vert[ 7] = org2[1] - width * right2[1];
2223         vert[ 8] = org2[2] - width * right2[2];
2224         vert[ 9] = org2[0] + width * right2[0];
2225         vert[10] = org2[1] + width * right2[1];
2226         vert[11] = org2[2] + width * right2[2];
2227 }
2228
2229 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2230
2231 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)
2232 {
2233         float fog = 0.0f, ifog;
2234         rmeshstate_t m;
2235         float vertex3f[12];
2236
2237         if (fogenabled)
2238                 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
2239         ifog = 1 - fog;
2240
2241         R_Mesh_Matrix(&identitymatrix);
2242         GL_BlendFunc(blendfunc1, blendfunc2);
2243         GL_DepthMask(false);
2244         GL_DepthTest(!depthdisable);
2245
2246         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2247         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2248         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2249         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2250         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2251         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2252         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2253         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2254         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2255         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2256         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2257         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2258
2259         memset(&m, 0, sizeof(m));
2260         m.tex[0] = R_GetTexture(texture);
2261         m.pointer_texcoord[0] = spritetexcoord2f;
2262         m.pointer_vertex = vertex3f;
2263         R_Mesh_State(&m);
2264         GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2265         R_Mesh_Draw(0, 4, 2, polygonelements);
2266
2267         if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2268         {
2269                 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2270                 GL_BlendFunc(blendfunc1, GL_ONE);
2271                 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
2272                 R_Mesh_Draw(0, 4, 2, polygonelements);
2273         }
2274 }
2275
2276 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2277 {
2278         int i;
2279         float *vertex3f;
2280         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2281                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2282                         break;
2283         if (i == mesh->numvertices)
2284         {
2285                 if (mesh->numvertices < mesh->maxvertices)
2286                 {
2287                         VectorCopy(v, vertex3f);
2288                         mesh->numvertices++;
2289                 }
2290                 return mesh->numvertices;
2291         }
2292         else
2293                 return i;
2294 }
2295
2296 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2297 {
2298         int i;
2299         int *e, element[3];
2300         element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2301         element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2302         e = mesh->element3i + mesh->numtriangles * 3;
2303         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2304         {
2305                 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2306                 if (mesh->numtriangles < mesh->maxtriangles)
2307                 {
2308                         *e++ = element[0];
2309                         *e++ = element[1];
2310                         *e++ = element[2];
2311                         mesh->numtriangles++;
2312                 }
2313                 element[1] = element[2];
2314         }
2315 }
2316
2317 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2318 {
2319         int planenum, planenum2;
2320         int w;
2321         int tempnumpoints;
2322         mplane_t *plane, *plane2;
2323         float temppoints[2][256*3];
2324         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2325         {
2326                 w = 0;
2327                 tempnumpoints = 4;
2328                 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2329                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2330                 {
2331                         if (planenum2 == planenum)
2332                                 continue;
2333                         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);
2334                         w = !w;
2335                 }
2336                 if (tempnumpoints < 3)
2337                         continue;
2338                 // generate elements forming a triangle fan for this polygon
2339                 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2340         }
2341 }
2342
2343 static void R_DrawCollisionBrush(colbrushf_t *brush)
2344 {
2345         int i;
2346         rmeshstate_t m;
2347         memset(&m, 0, sizeof(m));
2348         m.pointer_vertex = brush->points->v;
2349         R_Mesh_State(&m);
2350         i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2351         GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2352         GL_LockArrays(0, brush->numpoints);
2353         R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2354         GL_LockArrays(0, 0);
2355 }
2356
2357 static void R_DrawCollisionSurface(entity_render_t *ent, msurface_t *surface)
2358 {
2359         int i;
2360         rmeshstate_t m;
2361         if (!surface->num_collisiontriangles)
2362                 return;
2363         memset(&m, 0, sizeof(m));
2364         m.pointer_vertex = surface->data_collisionvertex3f;
2365         R_Mesh_State(&m);
2366         i = (int)(((size_t)surface) / sizeof(msurface_t));
2367         GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2368         GL_LockArrays(0, surface->num_collisionvertices);
2369         R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2370         GL_LockArrays(0, 0);
2371 }
2372
2373 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)
2374 {
2375         texturelayer_t *layer;
2376         layer = t->currentlayers + t->currentnumlayers++;
2377         layer->type = type;
2378         layer->depthmask = depthmask;
2379         layer->blendfunc1 = blendfunc1;
2380         layer->blendfunc2 = blendfunc2;
2381         layer->texture = texture;
2382         layer->texmatrix = *matrix;
2383         layer->color[0] = r;
2384         layer->color[1] = g;
2385         layer->color[2] = b;
2386         layer->color[3] = a;
2387 }
2388
2389 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2390 {
2391         // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2392         //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2393
2394         {
2395                 texture_t *texture = t;
2396                 model_t *model = ent->model;
2397                 int s = ent->skinnum;
2398                 if ((unsigned int)s >= (unsigned int)model->numskins)
2399                         s = 0;
2400                 if (model->skinscenes)
2401                 {
2402                         if (model->skinscenes[s].framecount > 1)
2403                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2404                         else
2405                                 s = model->skinscenes[s].firstframe;
2406                 }
2407                 if (s > 0)
2408                         t = t + s * model->num_surfaces;
2409                 if (t->animated)
2410                         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];
2411                 texture->currentframe = t;
2412         }
2413
2414         t->currentmaterialflags = t->basematerialflags;
2415         t->currentalpha = ent->alpha;
2416         if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2417                 t->currentalpha *= r_wateralpha.value;
2418         if (!(ent->flags & RENDER_LIGHT))
2419                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2420         if (ent->effects & EF_ADDITIVE)
2421                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
2422         else if (t->currentalpha < 1)
2423                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
2424         if (ent->effects & EF_NODEPTHTEST)
2425                 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2426         if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2427                 t->currenttexmatrix = r_waterscrollmatrix;
2428         else
2429                 t->currenttexmatrix = identitymatrix;
2430
2431         t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2432         t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2433         t->glosstexture = r_texture_white;
2434         t->specularpower = 8;
2435         t->specularscale = 0;
2436         if (r_shadow_gloss.integer > 0)
2437         {
2438                 if (t->skin.gloss)
2439                 {
2440                         if (r_shadow_glossintensity.value > 0)
2441                         {
2442                                 t->glosstexture = t->skin.gloss;
2443                                 t->specularscale = r_shadow_glossintensity.value;
2444                         }
2445                 }
2446                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2447                         t->specularscale = r_shadow_gloss2intensity.value;
2448         }
2449
2450         t->currentnumlayers = 0;
2451         if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2452         {
2453                 if (gl_lightmaps.integer)
2454                         R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2455                 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2456                 {
2457                         int blendfunc1, blendfunc2, depthmask;
2458                         if (t->currentmaterialflags & MATERIALFLAG_ADD)
2459                         {
2460                                 blendfunc1 = GL_SRC_ALPHA;
2461                                 blendfunc2 = GL_ONE;
2462                                 depthmask = false;
2463                         }
2464                         else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2465                         {
2466                                 blendfunc1 = GL_SRC_ALPHA;
2467                                 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2468                                 depthmask = false;
2469                         }
2470                         else
2471                         {
2472                                 blendfunc1 = GL_ONE;
2473                                 blendfunc2 = GL_ZERO;
2474                                 depthmask = true;
2475                         }
2476                         if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2477                         {
2478                                 rtexture_t *currentbasetexture;
2479                                 int layerflags = 0;
2480                                 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2481                                         layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2482                                 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2483                                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2484                                 {
2485                                         // fullbright is not affected by r_lightmapintensity
2486                                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2487                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2488                                                 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);
2489                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2490                                                 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);
2491                                 }
2492                                 else
2493                                 {
2494                                         float colorscale;
2495                                         colorscale = 2;
2496                                         // q3bsp has no lightmap updates, so the lightstylevalue that
2497                                         // would normally be baked into the lightmaptexture must be
2498                                         // applied to the color
2499                                         if (ent->model->type == mod_brushq3)
2500                                                 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2501                                         colorscale *= r_lightmapintensity;
2502                                         if (r_textureunits.integer >= 2 && gl_combine.integer)
2503                                                 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);
2504                                         else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
2505                                                 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);
2506                                         else
2507                                                 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);
2508                                         if (r_ambient.value >= (1.0f/64.0f))
2509                                                 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);
2510                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2511                                         {
2512                                                 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);
2513                                                 if (r_ambient.value >= (1.0f/64.0f))
2514                                                         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);
2515                                         }
2516                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2517                                         {
2518                                                 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);
2519                                                 if (r_ambient.value >= (1.0f/64.0f))
2520                                                         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);
2521                                         }
2522                                 }
2523                                 if (t->skin.glow != NULL)
2524                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2525                                 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2526                                 {
2527                                         // if this is opaque use alpha blend which will darken the earlier
2528                                         // passes cheaply.
2529                                         //
2530                                         // if this is an alpha blended material, all the earlier passes
2531                                         // were darkened by fog already, so we only need to add the fog
2532                                         // color ontop through the fog mask texture
2533                                         //
2534                                         // if this is an additive blended material, all the earlier passes
2535                                         // were darkened by fog already, and we should not add fog color
2536                                         // (because the background was not darkened, there is no fog color
2537                                         // that was lost behind it).
2538                                         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);
2539                                 }
2540                         }
2541                 }
2542         }
2543 }
2544
2545 void R_UpdateAllTextureInfo(entity_render_t *ent)
2546 {
2547         int i;
2548         if (ent->model)
2549                 for (i = 0;i < ent->model->num_textures;i++)
2550                         R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2551 }
2552
2553 int rsurface_array_size = 0;
2554 float *rsurface_array_vertex3f = NULL;
2555 float *rsurface_array_svector3f = NULL;
2556 float *rsurface_array_tvector3f = NULL;
2557 float *rsurface_array_normal3f = NULL;
2558 float *rsurface_array_color4f = NULL;
2559 float *rsurface_array_texcoord3f = NULL;
2560
2561 void R_Mesh_ResizeArrays(int newvertices)
2562 {
2563         if (rsurface_array_size >= newvertices)
2564                 return;
2565         if (rsurface_array_vertex3f)
2566                 Mem_Free(rsurface_array_vertex3f);
2567         rsurface_array_size = (newvertices + 1023) & ~1023;
2568         rsurface_array_vertex3f = Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[19]));
2569         rsurface_array_svector3f = rsurface_array_vertex3f + rsurface_array_size * 3;
2570         rsurface_array_tvector3f = rsurface_array_vertex3f + rsurface_array_size * 6;
2571         rsurface_array_normal3f = rsurface_array_vertex3f + rsurface_array_size * 9;
2572         rsurface_array_color4f = rsurface_array_vertex3f + rsurface_array_size * 12;
2573         rsurface_array_texcoord3f = rsurface_array_vertex3f + rsurface_array_size * 16;
2574 }
2575
2576 float *rsurface_vertex3f;
2577 float *rsurface_svector3f;
2578 float *rsurface_tvector3f;
2579 float *rsurface_normal3f;
2580 float *rsurface_lightmapcolor4f;
2581 qboolean rsurface_generatevertex;
2582 qboolean rsurface_generatetangents;
2583 qboolean rsurface_generatenormals;
2584 qboolean rsurface_deformvertex;
2585 qboolean rsurface_dynamicvertex;
2586 vec3_t rsurface_modelorg;
2587 const entity_render_t *rsurface_entity;
2588 const model_t *rsurface_model;
2589 const texture_t *rsurface_texture;
2590
2591 void RSurf_PrepareForBatch(const entity_render_t *ent, const texture_t *texture, const vec3_t modelorg)
2592 {
2593         VectorCopy(modelorg, rsurface_modelorg);
2594         rsurface_entity = ent;
2595         rsurface_model = ent->model;
2596         rsurface_texture = texture;
2597 }
2598
2599 void RSurf_SetPointersForPass(qboolean generatenormals, qboolean generatetangents)
2600 {
2601         if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2602                 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2603         if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && (rsurface_model->surfmesh.data_morphvertex3f || rsurface_model->surfmesh.data_vertexboneweights))
2604         {
2605                 rsurface_generatevertex = true;
2606                 rsurface_generatetangents = false;
2607                 rsurface_generatenormals = false;
2608                 rsurface_vertex3f = rsurface_array_vertex3f;
2609                 if (generatetangents || (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)))
2610                 {
2611                         rsurface_generatetangents = true;
2612                         rsurface_svector3f = rsurface_array_svector3f;
2613                         rsurface_tvector3f = rsurface_array_tvector3f;
2614                         rsurface_normal3f = rsurface_array_normal3f;
2615                 }
2616                 else
2617                 {
2618                         rsurface_svector3f = NULL;
2619                         rsurface_tvector3f = NULL;
2620                         if (generatenormals)
2621                         {
2622                                 rsurface_generatenormals = true;
2623                                 rsurface_normal3f = rsurface_array_normal3f;
2624                         }
2625                         else
2626                                 rsurface_normal3f = NULL;
2627                 }
2628         }
2629         else
2630         {
2631                 rsurface_generatevertex = false;
2632                 rsurface_generatetangents = false;
2633                 rsurface_generatenormals = false;
2634                 rsurface_vertex3f = rsurface_model->surfmesh.data_vertex3f;
2635                 rsurface_svector3f = rsurface_model->surfmesh.data_svector3f;
2636                 rsurface_tvector3f = rsurface_model->surfmesh.data_tvector3f;
2637                 rsurface_normal3f = rsurface_model->surfmesh.data_normal3f;
2638         }
2639         if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2640         {
2641                 rsurface_deformvertex = true;
2642                 rsurface_vertex3f = rsurface_array_vertex3f;
2643                 rsurface_svector3f = rsurface_array_svector3f;
2644                 rsurface_tvector3f = rsurface_array_tvector3f;
2645                 rsurface_normal3f = rsurface_array_normal3f;
2646         }
2647         else
2648                 rsurface_deformvertex = false;
2649         R_Mesh_VertexPointer(rsurface_vertex3f);
2650         rsurface_dynamicvertex = rsurface_generatevertex || rsurface_deformvertex;
2651 }
2652
2653 void RSurf_PrepareDynamicSurfaceVertices(const msurface_t *surface)
2654 {
2655         float *vertex3f, *svector3f, *tvector3f, *normal3f;
2656         model_t *model = rsurface_entity->model;
2657         if (!rsurface_dynamicvertex)
2658                 return;
2659         if (rsurface_generatevertex)
2660         {
2661                 Mod_Alias_GetMesh_Vertex3f(model, rsurface_entity->frameblend, rsurface_array_vertex3f);
2662                 if (rsurface_generatetangents)
2663                         Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, model->surfmesh.data_texcoordtexture2f, model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_svector3f, rsurface_array_tvector3f, rsurface_array_normal3f, r_smoothnormals_areaweighting.integer);
2664                 else if (rsurface_generatenormals)
2665                         Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_array_vertex3f, model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, rsurface_array_normal3f, r_smoothnormals_areaweighting.integer);
2666         }
2667         if (rsurface_deformvertex)
2668         {
2669                 int i, j;
2670                 float center[3], forward[3], right[3], up[3], v[4][3];
2671                 matrix4x4_t matrix1, imatrix1;
2672                 if (rsurface_generatevertex)
2673                 {
2674                         vertex3f = rsurface_array_vertex3f;
2675                         svector3f = rsurface_array_svector3f;
2676                         tvector3f = rsurface_array_tvector3f;
2677                         normal3f = rsurface_array_normal3f;
2678                 }
2679                 else
2680                 {
2681                         vertex3f = rsurface_vertex3f;
2682                         svector3f = rsurface_svector3f;
2683                         tvector3f = rsurface_tvector3f;
2684                         normal3f = rsurface_normal3f;
2685                 }
2686                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewforward, forward);
2687                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewright, right);
2688                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewup, up);
2689                 // a single autosprite surface can contain multiple sprites...
2690                 for (j = 0;j < surface->num_vertices - 3;j += 4)
2691                 {
2692                         VectorClear(center);
2693                         for (i = 0;i < 4;i++)
2694                                 VectorAdd(center, (vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2695                         VectorScale(center, 0.25f, center);
2696                         // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2697                         Matrix4x4_FromVectors(&matrix1, (normal3f + 3 * surface->num_firstvertex) + j*3, (svector3f + 3 * surface->num_firstvertex) + j*3, (tvector3f + 3 * surface->num_firstvertex) + j*3, center);
2698                         Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2699                         for (i = 0;i < 4;i++)
2700                                 Matrix4x4_Transform(&imatrix1, (vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2701                         if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2702                         {
2703                                 forward[0] = rsurface_modelorg[0] - center[0];
2704                                 forward[1] = rsurface_modelorg[1] - center[1];
2705                                 forward[2] = 0;
2706                                 VectorNormalize(forward);
2707                                 right[0] = forward[1];
2708                                 right[1] = -forward[0];
2709                                 right[2] = 0;
2710                                 VectorSet(up, 0, 0, 1);
2711                         }
2712                         for (i = 0;i < 4;i++)
2713                                 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_vertex3f + (surface->num_firstvertex+i+j) * 3);
2714                 }
2715                 Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_array_vertex3f, model->surfmesh.data_texcoordtexture2f, model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_svector3f, rsurface_array_tvector3f, rsurface_array_normal3f, r_smoothnormals_areaweighting.integer);
2716         }
2717 }
2718
2719 static void RSurf_Draw(const msurface_t *surface)
2720 {
2721         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2722         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2723         GL_LockArrays(0, 0);
2724 }
2725
2726 static void RSurf_DrawLightmap(const msurface_t *surface, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2727 {
2728         int i;
2729         float f;
2730         float *v, *c, *c2;
2731         if (lightmode >= 2)
2732         {
2733                 // model lighting
2734                 vec3_t ambientcolor;
2735                 vec3_t diffusecolor;
2736                 vec3_t lightdir;
2737                 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2738                 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2739                 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2740                 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2741                 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2742                 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2743                 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2744                 if (VectorLength2(diffusecolor) > 0)
2745                 {
2746                         int numverts = surface->num_vertices;
2747                         v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2748                         c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2749                         c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2750                         // q3-style directional shading
2751                         for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2752                         {
2753                                 if ((f = DotProduct(c2, lightdir)) > 0)
2754                                         VectorMA(ambientcolor, f, diffusecolor, c);
2755                                 else
2756                                         VectorCopy(ambientcolor, c);
2757                                 c[3] = a;
2758                         }
2759                         r = 1;
2760                         g = 1;
2761                         b = 1;
2762                         a = 1;
2763                         applycolor = false;
2764                         rsurface_lightmapcolor4f = rsurface_array_color4f;
2765                 }
2766                 else
2767                 {
2768                         r = ambientcolor[0];
2769                         g = ambientcolor[1];
2770                         b = ambientcolor[2];
2771                         rsurface_lightmapcolor4f = NULL;
2772                 }
2773         }
2774         else if (lightmode >= 1)
2775         {
2776                 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
2777                 {
2778                         for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2779                         {
2780                                 if (surface->lightmapinfo->samples)
2781                                 {
2782                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2783                                         float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2784                                         VectorScale(lm, scale, c);
2785                                         if (surface->lightmapinfo->styles[1] != 255)
2786                                         {
2787                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2788                                                 lm += size3;
2789                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2790                                                 VectorMA(c, scale, lm, c);
2791                                                 if (surface->lightmapinfo->styles[2] != 255)
2792                                                 {
2793                                                         lm += size3;
2794                                                         scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2795                                                         VectorMA(c, scale, lm, c);
2796                                                         if (surface->lightmapinfo->styles[3] != 255)
2797                                                         {
2798                                                                 lm += size3;
2799                                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2800                                                                 VectorMA(c, scale, lm, c);
2801                                                         }
2802                                                 }
2803                                         }
2804                                 }
2805                                 else
2806                                         VectorClear(c);
2807                         }
2808                         rsurface_lightmapcolor4f = rsurface_array_color4f;
2809                 }
2810                 else
2811                         rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2812         }
2813         else
2814                 rsurface_lightmapcolor4f = NULL;
2815         if (applyfog)
2816         {
2817                 if (rsurface_lightmapcolor4f)
2818                 {
2819                         for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
2820                         {
2821                                 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2822                                 c2[0] = c[0] * f;
2823                                 c2[1] = c[1] * f;
2824                                 c2[2] = c[2] * f;
2825                                 c2[3] = c[3];
2826                         }
2827                 }
2828                 else
2829                 {
2830                         for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
2831                         {
2832                                 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2833                                 c2[0] = f;
2834                                 c2[1] = f;
2835                                 c2[2] = f;
2836                                 c2[3] = 1;
2837                         }
2838                 }
2839                 rsurface_lightmapcolor4f = rsurface_array_color4f;
2840         }
2841         if (applycolor && rsurface_lightmapcolor4f)
2842         {
2843                 for (i = 0, c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
2844                 {
2845                         c2[0] = c[0] * r;
2846                         c2[1] = c[1] * g;
2847                         c2[2] = c[2] * b;
2848                         c2[3] = c[3] * a;
2849                 }
2850                 rsurface_lightmapcolor4f = rsurface_array_color4f;
2851         }
2852         R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2853         GL_Color(r, g, b, a);
2854         RSurf_Draw(surface);
2855 }
2856
2857 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2858 {
2859         int texturesurfaceindex;
2860         int lightmode;
2861         const msurface_t *surface;
2862         model_t *model = ent->model;
2863         qboolean applycolor;
2864         qboolean applyfog;
2865         rmeshstate_t m;
2866         if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
2867                 return;
2868         r_shadow_rtlight = NULL;
2869         renderstats.entities_surfaces += texturenumsurfaces;
2870         // FIXME: identify models using a better check than model->brush.shadowmesh
2871         lightmode = ((ent->effects & EF_FULLBRIGHT) || model->brush.shadowmesh) ? 0 : 2;
2872         GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
2873         if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2874                 qglDisable(GL_CULL_FACE);
2875         RSurf_PrepareForBatch(ent, texture, modelorg);
2876         if (texture->currentmaterialflags & MATERIALFLAG_SKY)
2877         {
2878                 // transparent sky would be ridiculous
2879                 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2880                 {
2881                         if (skyrendernow)
2882                         {
2883                                 skyrendernow = false;
2884                                 R_Sky();
2885                                 // restore entity matrix
2886                                 R_Mesh_Matrix(&ent->matrix);
2887                         }
2888                         GL_DepthMask(true);
2889                         // LordHavoc: HalfLife maps have freaky skypolys...
2890                         // LordHavoc: Quake3 never did sky masking (unlike software Quake
2891                         // and Quake2), so disable the sky masking in Quake3 maps as it
2892                         // causes problems with q3map2 sky tricks
2893                         if (!model->brush.ishlbsp && model->type != mod_brushq3)
2894                         {
2895                                 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2896                                 memset(&m, 0, sizeof(m));
2897                                 R_Mesh_State(&m);
2898                                 if (skyrendermasked)
2899                                 {
2900                                         // depth-only (masking)
2901                                         GL_ColorMask(0,0,0,0);
2902                                         // just to make sure that braindead drivers don't draw
2903                                         // anything despite that colormask...
2904                                         GL_BlendFunc(GL_ZERO, GL_ONE);
2905                                 }
2906                                 else
2907                                 {
2908                                         // fog sky
2909                                         GL_BlendFunc(GL_ONE, GL_ZERO);
2910                                 }
2911                                 RSurf_SetPointersForPass(false, false);
2912                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2913                                 {
2914                                         surface = texturesurfacelist[texturesurfaceindex];
2915                                         if (rsurface_dynamicvertex)
2916                                                 RSurf_PrepareDynamicSurfaceVertices(surface);
2917                                         RSurf_Draw(surface);
2918                                 }
2919                                 if (skyrendermasked)
2920                                         GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2921                         }
2922                 }
2923         }
2924         else if (r_glsl.integer && gl_support_fragment_shader)
2925         {
2926                 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
2927                 {
2928                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2929                         GL_DepthMask(false);
2930                 }
2931                 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
2932                 {
2933                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2934                         GL_DepthMask(false);
2935                 }
2936                 else
2937                 {
2938                         GL_BlendFunc(GL_ONE, GL_ZERO);
2939                         GL_DepthMask(true);
2940                 }
2941
2942                 memset(&m, 0, sizeof(m));
2943                 R_Mesh_State(&m);
2944                 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], texture->currentalpha);
2945                 R_SetupSurfaceShader(ent, texture, modelorg, vec3_origin, lightmode == 2);
2946                 if (!r_glsl_permutation)
2947                         return;
2948                 RSurf_SetPointersForPass(false, true);
2949                 if (lightmode == 2)
2950                 {
2951                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2952                         {
2953                                 surface = texturesurfacelist[texturesurfaceindex];
2954                                 if (rsurface_dynamicvertex)
2955                                         RSurf_PrepareDynamicSurfaceVertices(surface);
2956                                 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
2957                                 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2958                                 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2959                                 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2960                                 RSurf_Draw(surface);
2961                         }
2962                 }
2963                 else
2964                 {
2965                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2966                         {
2967                                 surface = texturesurfacelist[texturesurfaceindex];
2968                                 if (rsurface_dynamicvertex)
2969                                         RSurf_PrepareDynamicSurfaceVertices(surface);
2970                                 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
2971                                 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2972                                 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2973                                 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2974                                 R_Mesh_TexCoordPointer(4, 2, model->surfmesh.data_texcoordlightmap2f);
2975                                 if (surface->lightmaptexture)
2976                                 {
2977                                         R_Mesh_TexBind(7, R_GetTexture(surface->lightmaptexture));
2978                                         if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2979                                                 R_Mesh_TexBind(8, R_GetTexture(surface->deluxemaptexture));
2980                                         R_Mesh_ColorPointer(NULL);
2981                                 }
2982                                 else
2983                                 {
2984                                         R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2985                                         if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2986                                                 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2987                                         R_Mesh_ColorPointer(model->surfmesh.data_lightmapcolor4f);
2988                                 }
2989                                 RSurf_Draw(surface);
2990                         }
2991                 }
2992                 qglUseProgramObjectARB(0);
2993         }
2994         else if (texture->currentnumlayers)
2995         {
2996                 int layerindex;
2997                 texturelayer_t *layer;
2998                 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
2999                 {
3000                         vec4_t layercolor;
3001                         int layertexrgbscale;
3002                         GL_DepthMask(layer->depthmask);
3003                         GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3004                         if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
3005                         {
3006                                 layertexrgbscale = 4;
3007                                 VectorScale(layer->color, 0.25f, layercolor);
3008                         }
3009                         else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
3010                         {
3011                                 layertexrgbscale = 2;
3012                                 VectorScale(layer->color, 0.5f, layercolor);
3013                         }
3014                         else
3015                         {
3016                                 layertexrgbscale = 1;
3017                                 VectorScale(layer->color, 1.0f, layercolor);
3018                         }
3019                         layercolor[3] = layer->color[3];
3020                         GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
3021                         applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
3022                         applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3023                         switch (layer->type)
3024                         {
3025                         case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
3026                                 memset(&m, 0, sizeof(m));
3027                                 m.tex[1] = R_GetTexture(layer->texture);
3028                                 m.texmatrix[1] = layer->texmatrix;
3029                                 m.texrgbscale[1] = layertexrgbscale;
3030                                 m.pointer_color = rsurface_array_color4f;
3031                                 R_Mesh_State(&m);
3032                                 RSurf_SetPointersForPass(lightmode == 2, false);
3033                                 if (lightmode == 2)
3034                                 {
3035                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3036                                         {
3037                                                 surface = texturesurfacelist[texturesurfaceindex];
3038                                                 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordlightmap2f);
3039                                                 R_Mesh_TexCoordPointer(1, 2, model->surfmesh.data_texcoordtexture2f);
3040                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3041                                                 if (rsurface_dynamicvertex)
3042                                                         RSurf_PrepareDynamicSurfaceVertices(surface);
3043                                                 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
3044                                         }
3045                                 }
3046                                 else
3047                                 {
3048                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3049                                         {
3050                                                 surface = texturesurfacelist[texturesurfaceindex];
3051                                                 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordlightmap2f);
3052                                                 R_Mesh_TexCoordPointer(1, 2, model->surfmesh.data_texcoordtexture2f);
3053                                                 if (rsurface_dynamicvertex)
3054                                                         RSurf_PrepareDynamicSurfaceVertices(surface);
3055                                                 if (surface->lightmaptexture)
3056                                                 {
3057                                                         R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
3058                                                         RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3059                                                 }
3060                                                 else
3061                                                 {
3062                                                         R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3063                                                         RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
3064                                                 }
3065                                         }
3066                                 }
3067                                 break;
3068                         case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
3069                                 memset(&m, 0, sizeof(m));
3070                                 m.tex[0] = R_GetTexture(layer->texture);
3071                                 m.texmatrix[0] = layer->texmatrix;
3072                                 m.pointer_color = rsurface_array_color4f;
3073                                 m.texrgbscale[0] = layertexrgbscale;
3074                                 R_Mesh_State(&m);
3075                                 RSurf_SetPointersForPass(lightmode == 2, false);
3076                                 if (lightmode == 2)
3077                                 {
3078                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3079                                         {
3080                                                 surface = texturesurfacelist[texturesurfaceindex];
3081                                                 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordlightmap2f);
3082                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3083                                                 if (rsurface_dynamicvertex)
3084                                                         RSurf_PrepareDynamicSurfaceVertices(surface);
3085                                                 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 2, false, false);
3086                                         }
3087                                 }
3088                                 else
3089                                 {
3090                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3091                                         {
3092                                                 surface = texturesurfacelist[texturesurfaceindex];
3093                                                 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordlightmap2f);
3094                                                 if (rsurface_dynamicvertex)
3095                                                         RSurf_PrepareDynamicSurfaceVertices(surface);
3096                                                 if (surface->lightmaptexture)
3097                                                 {
3098                                                         R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
3099                                                         RSurf_DrawLightmap(surface, 1, 1, 1, 1, 0, false, false);
3100                                                 }
3101                                                 else
3102                                                 {
3103                                                         R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3104                                                         RSurf_DrawLightmap(surface, 1, 1, 1, 1, 1, false, false);
3105                                                 }
3106                                         }
3107                                 }
3108                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3109                                 memset(&m, 0, sizeof(m));
3110                                 m.tex[0] = R_GetTexture(layer->texture);
3111                                 m.texmatrix[0] = layer->texmatrix;
3112                                 m.pointer_color = rsurface_array_color4f;
3113                                 m.texrgbscale[0] = layertexrgbscale;
3114                                 R_Mesh_State(&m);
3115                                 RSurf_SetPointersForPass(false, false);
3116                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3117                                 {
3118                                         surface = texturesurfacelist[texturesurfaceindex];
3119                                         R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
3120                                         if (rsurface_dynamicvertex)
3121                                                 RSurf_PrepareDynamicSurfaceVertices(surface);
3122                                         RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, false);
3123                                 }
3124                                 break;
3125                         case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
3126                                 memset(&m, 0, sizeof(m));
3127                                 m.tex[0] = R_GetTexture(layer->texture);
3128                                 m.texmatrix[0] = layer->texmatrix;
3129                                 m.texrgbscale[0] = layertexrgbscale;
3130                                 m.pointer_color = rsurface_array_color4f;
3131                                 R_Mesh_State(&m);
3132                                 RSurf_SetPointersForPass(lightmode == 2, false);
3133                                 if (lightmode == 2)
3134                                 {
3135                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3136                                         {
3137                                                 surface = texturesurfacelist[texturesurfaceindex];
3138                                                 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
3139                                                 if (rsurface_dynamicvertex)
3140                                                         RSurf_PrepareDynamicSurfaceVertices(surface);
3141                                                 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
3142                                         }
3143                                 }
3144                                 else
3145                                 {
3146                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3147                                         {
3148                                                 surface = texturesurfacelist[texturesurfaceindex];
3149                                                 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
3150                                                 if (rsurface_dynamicvertex)
3151                                                         RSurf_PrepareDynamicSurfaceVertices(surface);
3152                                                 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
3153                                         }
3154                                 }
3155                                 break;
3156                         case TEXTURELAYERTYPE_TEXTURE:
3157                                 memset(&m, 0, sizeof(m));
3158                                 m.tex[0] = R_GetTexture(layer->texture);
3159                                 m.texmatrix[0] = layer->texmatrix;
3160                                 m.pointer_color = rsurface_array_color4f;
3161                                 m.texrgbscale[0] = layertexrgbscale;
3162                                 R_Mesh_State(&m);
3163                                 RSurf_SetPointersForPass(false, false);
3164                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3165                                 {
3166                                         surface = texturesurfacelist[texturesurfaceindex];
3167                                         R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
3168                                         if (rsurface_dynamicvertex)
3169                                                 RSurf_PrepareDynamicSurfaceVertices(surface);
3170                                         RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3171                                 }
3172                                 break;
3173                         case TEXTURELAYERTYPE_FOG:
3174                                 memset(&m, 0, sizeof(m));
3175                                 if (layer->texture)
3176                                 {
3177                                         m.tex[0] = R_GetTexture(layer->texture);
3178                                         m.texmatrix[0] = layer->texmatrix;
3179                                 }
3180                                 R_Mesh_State(&m);
3181                                 RSurf_SetPointersForPass(false, false);
3182                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3183                                 {
3184                                         int i;
3185                                         float f, *v, *c;
3186                                         surface = texturesurfacelist[texturesurfaceindex];
3187                                         if (layer->texture)
3188                                                 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
3189                                         R_Mesh_ColorPointer(rsurface_array_color4f);
3190                                         if (rsurface_dynamicvertex)
3191                                                 RSurf_PrepareDynamicSurfaceVertices(surface);
3192                                         for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
3193                                         {
3194                                                 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
3195                                                 c[0] = layercolor[0];
3196                                                 c[1] = layercolor[1];
3197                                                 c[2] = layercolor[2];
3198                                                 c[3] = f * layercolor[3];
3199                                         }
3200                                         RSurf_Draw(surface);
3201                                 }
3202                                 break;
3203                         default:
3204                                 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3205                         }
3206                         // if trying to do overbright on first pass of an opaque surface
3207                         // when combine is not supported, brighten as a post process
3208                         if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
3209                         {
3210                                 int scale;
3211                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3212                                 GL_Color(1, 1, 1, 1);
3213                                 memset(&m, 0, sizeof(m));
3214                                 R_Mesh_State(&m);
3215                                 RSurf_SetPointersForPass(false, false);
3216                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3217                                 {
3218                                         surface = texturesurfacelist[texturesurfaceindex];
3219                                         if (rsurface_dynamicvertex)
3220                                                 RSurf_PrepareDynamicSurfaceVertices(surface);
3221                                         for (scale = 1;scale < layertexrgbscale;scale <<= 1)
3222                                                 RSurf_Draw(surface);
3223                                 }
3224                         }
3225                 }
3226         }
3227         if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
3228                 qglEnable(GL_CULL_FACE);
3229 }
3230
3231 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
3232 {
3233         const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
3234         vec3_t modelorg;
3235         texture_t *texture;
3236
3237         texture = surface->texture;
3238         if (texture->basematerialflags & MATERIALFLAG_SKY)
3239                 return; // transparent sky is too difficult
3240         R_UpdateTextureInfo(ent, texture);
3241
3242         R_Mesh_Matrix(&ent->matrix);
3243         Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3244         R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
3245 }
3246
3247 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
3248 {
3249         int texturesurfaceindex;
3250         const msurface_t *surface;
3251         vec3_t tempcenter, center;
3252         if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
3253         {
3254                 // drawing sky transparently would be too difficult
3255                 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
3256                 {
3257                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3258                         {
3259                                 surface = texturesurfacelist[texturesurfaceindex];
3260                                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3261                                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3262                                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3263                                 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
3264                                 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
3265                         }
3266                 }
3267         }
3268         else
3269                 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
3270 }
3271
3272 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3273 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3274 {
3275         int i, j, f, flagsmask;
3276         int counttriangles = 0;
3277         msurface_t *surface, **surfacechain;
3278         texture_t *t, *texture;
3279         model_t *model = ent->model;
3280         vec3_t modelorg;
3281         const int maxsurfacelist = 1024;
3282         int numsurfacelist = 0;
3283         const msurface_t *surfacelist[1024];
3284         if (model == NULL)
3285                 return;
3286         R_Mesh_Matrix(&ent->matrix);
3287         Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3288
3289         // update light styles
3290         if (!skysurfaces && model->brushq1.light_styleupdatechains)
3291         {
3292                 for (i = 0;i < model->brushq1.light_styles;i++)
3293                 {
3294                         if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3295                         {
3296                                 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3297                                 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3298                                         for (;(surface = *surfacechain);surfacechain++)
3299                                                 surface->cached_dlight = true;
3300                         }
3301                 }
3302         }
3303
3304         R_UpdateAllTextureInfo(ent);
3305         flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3306         f = 0;
3307         t = NULL;
3308         texture = NULL;
3309         numsurfacelist = 0;
3310         if (r_showsurfaces.integer)
3311         {
3312                 rmeshstate_t m;
3313                 GL_DepthTest(true);
3314                 GL_DepthMask(true);
3315                 GL_BlendFunc(GL_ONE, GL_ZERO);
3316                 memset(&m, 0, sizeof(m));
3317                 R_Mesh_State(&m);
3318                 t = NULL;
3319                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3320                 {
3321                         if (ent == r_refdef.worldentity && !r_worldsurfacevisible[j])
3322                                 continue;
3323                         if (t != surface->texture)
3324                         {
3325                                 t = surface->texture;
3326                                 texture = t->currentframe;
3327                                 RSurf_PrepareForBatch(ent, texture, modelorg);
3328                                 RSurf_SetPointersForPass(false, false);
3329                         }
3330                         if ((texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3331                         {
3332                                 int k = (int)(((size_t)surface) / sizeof(msurface_t));
3333                                 GL_Color((k & 15) * (1.0f / 16.0f), ((k >> 4) & 15) * (1.0f / 16.0f), ((k >> 8) & 15) * (1.0f / 16.0f), 0.2f);
3334                                 if (rsurface_dynamicvertex)
3335                                         RSurf_PrepareDynamicSurfaceVertices(surface);
3336                                 RSurf_Draw(surface);
3337                                 renderstats.entities_triangles += surface->num_triangles;
3338                         }
3339                         renderstats.entities_surfaces++;
3340                 }
3341         }
3342         else if (ent == r_refdef.worldentity)
3343         {
3344                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3345                 {
3346                         if (!r_worldsurfacevisible[j])
3347                                 continue;
3348                         if (t != surface->texture)
3349                         {
3350                                 if (numsurfacelist)
3351                                 {
3352                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3353                                         numsurfacelist = 0;
3354                                 }
3355                                 t = surface->texture;
3356                                 texture = t->currentframe;
3357                                 f = texture->currentmaterialflags & flagsmask;
3358                         }
3359                         if (f && surface->num_triangles)
3360                         {
3361                                 // if lightmap parameters changed, rebuild lightmap texture
3362                                 if (surface->cached_dlight)
3363                                         R_BuildLightMap(ent, surface);
3364                                 // add face to draw list
3365                                 surfacelist[numsurfacelist++] = surface;
3366                                 counttriangles += surface->num_triangles;
3367                                 if (numsurfacelist >= maxsurfacelist)
3368                                 {
3369                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3370                                         numsurfacelist = 0;
3371                                 }
3372                         }
3373                 }
3374         }
3375         else
3376         {
3377                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3378                 {
3379                         if (t != surface->texture)
3380                         {
3381                                 if (numsurfacelist)
3382                                 {
3383                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3384                                         numsurfacelist = 0;
3385                                 }
3386                                 t = surface->texture;
3387                                 texture = t->currentframe;
3388                                 f = texture->currentmaterialflags & flagsmask;
3389                         }
3390                         if (f && surface->num_triangles)
3391                         {
3392                                 // if lightmap parameters changed, rebuild lightmap texture
3393                                 if (surface->cached_dlight)
3394                                         R_BuildLightMap(ent, surface);
3395                                 // add face to draw list
3396                                 surfacelist[numsurfacelist++] = surface;
3397                                 counttriangles += surface->num_triangles;
3398                                 if (numsurfacelist >= maxsurfacelist)
3399                                 {
3400                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3401                                         numsurfacelist = 0;
3402                                 }
3403                         }
3404                 }
3405         }
3406         if (numsurfacelist)
3407                 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3408         renderstats.entities_triangles += counttriangles;
3409         if (gl_support_fragment_shader)
3410                 qglUseProgramObjectARB(0);
3411
3412         if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3413         {
3414                 int i;
3415                 msurface_t *surface;
3416                 q3mbrush_t *brush;
3417                 R_Mesh_Matrix(&ent->matrix);
3418                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3419                 GL_DepthMask(false);
3420                 GL_DepthTest(!r_showdisabledepthtest.integer);
3421                 qglPolygonOffset(r_polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_polygonoffset + r_showcollisionbrushes_polygonoffset.value);
3422                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3423                         if (brush->colbrushf && brush->colbrushf->numtriangles)
3424                                 R_DrawCollisionBrush(brush->colbrushf);
3425                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3426                         if (surface->num_collisiontriangles)
3427                                 R_DrawCollisionSurface(ent, surface);
3428                 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
3429         }
3430
3431         if (r_showtris.integer || r_shownormals.integer)
3432         {
3433                 int k, l;
3434                 const int *elements;
3435                 rmeshstate_t m;
3436                 vec3_t v;
3437                 GL_DepthTest(true);
3438                 GL_DepthMask(true);
3439                 if (r_showdisabledepthtest.integer)
3440                         qglDepthFunc(GL_ALWAYS);
3441                 GL_BlendFunc(GL_ONE, GL_ZERO);
3442                 memset(&m, 0, sizeof(m));
3443                 R_Mesh_State(&m);
3444                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3445                 {
3446                         if (ent == r_refdef.worldentity && !r_worldsurfacevisible[j])
3447                                 continue;
3448                         texture = surface->texture->currentframe;
3449                         if ((texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3450                         {
3451                                 RSurf_PrepareForBatch(ent, texture, modelorg);
3452                                 RSurf_SetPointersForPass(false, r_shownormals.integer != 0);
3453                                 if (rsurface_dynamicvertex)
3454                                         RSurf_PrepareDynamicSurfaceVertices(surface);
3455                                 if (r_showtris.integer)
3456                                 {
3457                                         if (!texture->currentlayers->depthmask)
3458                                                 GL_Color(r_showtris.value, 0, 0, 1);
3459                                         else if (ent == r_refdef.worldentity)
3460                                                 GL_Color(r_showtris.value, r_showtris.value, r_showtris.value, 1);
3461                                         else
3462                                                 GL_Color(0, r_showtris.value, 0, 1);
3463                                         elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3464                                         qglBegin(GL_LINES);
3465                                         for (k = 0;k < surface->num_triangles;k++, elements += 3)
3466                                         {
3467                                                 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3468                                                 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3469                                                 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3470                                         }
3471                                         qglEnd();
3472                                 }
3473                                 if (r_shownormals.integer)
3474                                 {
3475                                         GL_Color(r_shownormals.value, 0, 0, 1);
3476                                         qglBegin(GL_LINES);
3477                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3478                                         {
3479                                                 VectorCopy(rsurface_vertex3f + l * 3, v);
3480                                                 qglVertex3f(v[0], v[1], v[2]);
3481                                                 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3482                                                 qglVertex3f(v[0], v[1], v[2]);
3483                                         }
3484                                         qglEnd();
3485                                         GL_Color(0, 0, r_shownormals.value, 1);
3486                                         qglBegin(GL_LINES);
3487                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3488                                         {
3489                                                 VectorCopy(rsurface_vertex3f + l * 3, v);
3490                                                 qglVertex3f(v[0], v[1], v[2]);
3491                                                 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3492                                                 qglVertex3f(v[0], v[1], v[2]);
3493                                         }
3494                                         qglEnd();
3495                                         GL_Color(0, r_shownormals.value, 0, 1);
3496                                         qglBegin(GL_LINES);
3497                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3498                                         {
3499                                                 VectorCopy(rsurface_vertex3f + l * 3, v);
3500                                                 qglVertex3f(v[0], v[1], v[2]);
3501                                                 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3502                                                 qglVertex3f(v[0], v[1], v[2]);
3503                                         }
3504                                         qglEnd();
3505                                 }
3506                         }
3507                 }
3508                 if (r_showdisabledepthtest.integer)
3509                         qglDepthFunc(GL_LEQUAL);
3510         }
3511 }
3512