eliminated model->meshlist, replaced with an embedded model->surfmesh to cut down...
[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
2582 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, qboolean generatenormals, qboolean generatetangents)
2583 {
2584         model_t *model = ent->model;
2585         if (rsurface_array_size < model->surfmesh.num_vertices)
2586                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
2587         if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (model->surfmesh.data_morphvertex3f || model->surfmesh.data_vertexboneweights))
2588         {
2589                 rsurface_vertex3f = rsurface_array_vertex3f;
2590                 Mod_Alias_GetMesh_Vertex3f(model, ent->frameblend, rsurface_vertex3f);
2591                 if (generatetangents || (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)))
2592                 {
2593                         rsurface_svector3f = rsurface_array_svector3f;
2594                         rsurface_tvector3f = rsurface_array_tvector3f;
2595                         rsurface_normal3f = rsurface_array_normal3f;
2596                         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_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
2597                 }
2598                 else
2599                 {
2600                         rsurface_svector3f = NULL;
2601                         rsurface_tvector3f = NULL;
2602                         if (generatenormals)
2603                         {
2604                                 rsurface_normal3f = rsurface_array_normal3f;
2605                                 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
2606                         }
2607                         else
2608                                 rsurface_normal3f = NULL;
2609                 }
2610         }
2611         else
2612         {
2613                 rsurface_vertex3f = model->surfmesh.data_vertex3f;
2614                 rsurface_svector3f = model->surfmesh.data_svector3f;
2615                 rsurface_tvector3f = model->surfmesh.data_tvector3f;
2616                 rsurface_normal3f = model->surfmesh.data_normal3f;
2617         }
2618         if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2619         {
2620                 int i, j;
2621                 float center[3], forward[3], right[3], up[3], v[4][3];
2622                 matrix4x4_t matrix1, imatrix1;
2623                 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
2624                 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
2625                 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
2626                 // a single autosprite surface can contain multiple sprites...
2627                 for (j = 0;j < surface->num_vertices - 3;j += 4)
2628                 {
2629                         VectorClear(center);
2630                         for (i = 0;i < 4;i++)
2631                                 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2632                         VectorScale(center, 0.25f, center);
2633                         // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2634                         Matrix4x4_FromVectors(&matrix1, (rsurface_normal3f + 3 * surface->num_firstvertex) + j*3, (rsurface_svector3f + 3 * surface->num_firstvertex) + j*3, (rsurface_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
2635                         Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2636                         for (i = 0;i < 4;i++)
2637                                 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2638                         if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2639                         {
2640                                 forward[0] = modelorg[0] - center[0];
2641                                 forward[1] = modelorg[1] - center[1];
2642                                 forward[2] = 0;
2643                                 VectorNormalize(forward);
2644                                 right[0] = forward[1];
2645                                 right[1] = -forward[0];
2646                                 right[2] = 0;
2647                                 VectorSet(up, 0, 0, 1);
2648                         }
2649                         for (i = 0;i < 4;i++)
2650                                 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_vertex3f + (surface->num_firstvertex+i+j) * 3);
2651                 }
2652                 rsurface_vertex3f = rsurface_array_vertex3f;
2653                 rsurface_svector3f = rsurface_array_svector3f;
2654                 rsurface_tvector3f = rsurface_array_tvector3f;
2655                 rsurface_normal3f = rsurface_array_normal3f;
2656                 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_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
2657         }
2658         R_Mesh_VertexPointer(rsurface_vertex3f);
2659 }
2660
2661 static void RSurf_Draw(model_t *model, const msurface_t *surface)
2662 {
2663         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2664         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2665         GL_LockArrays(0, 0);
2666 }
2667
2668 static void RSurf_DrawLightmap(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2669 {
2670         int i;
2671         float f;
2672         float *v, *c, *c2;
2673         model_t *model = ent->model;
2674         RSurf_SetVertexPointer(ent, texture, surface, modelorg, lightmode >= 2, false);
2675         if (lightmode >= 2)
2676         {
2677                 // model lighting
2678                 vec3_t ambientcolor;
2679                 vec3_t diffusecolor;
2680                 vec3_t lightdir;
2681                 VectorCopy(ent->modellight_lightdir, lightdir);
2682                 ambientcolor[0] = ent->modellight_ambient[0] * r * 0.5f;
2683                 ambientcolor[1] = ent->modellight_ambient[1] * g * 0.5f;
2684                 ambientcolor[2] = ent->modellight_ambient[2] * b * 0.5f;
2685                 diffusecolor[0] = ent->modellight_diffuse[0] * r * 0.5f;
2686                 diffusecolor[1] = ent->modellight_diffuse[1] * g * 0.5f;
2687                 diffusecolor[2] = ent->modellight_diffuse[2] * b * 0.5f;
2688                 if (VectorLength2(diffusecolor) > 0)
2689                 {
2690                         int numverts = surface->num_vertices;
2691                         v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2692                         c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2693                         c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2694                         // q3-style directional shading
2695                         for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2696                         {
2697                                 if ((f = DotProduct(c2, lightdir)) > 0)
2698                                         VectorMA(ambientcolor, f, diffusecolor, c);
2699                                 else
2700                                         VectorCopy(ambientcolor, c);
2701                                 c[3] = a;
2702                         }
2703                         r = 1;
2704                         g = 1;
2705                         b = 1;
2706                         a = 1;
2707                         applycolor = false;
2708                         rsurface_lightmapcolor4f = rsurface_array_color4f;
2709                 }
2710                 else
2711                 {
2712                         r = ambientcolor[0];
2713                         g = ambientcolor[1];
2714                         b = ambientcolor[2];
2715                         rsurface_lightmapcolor4f = NULL;
2716                 }
2717         }
2718         else if (lightmode >= 1)
2719         {
2720                 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
2721                 {
2722                         for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2723                         {
2724                                 if (surface->lightmapinfo->samples)
2725                                 {
2726                                         const unsigned char *lm = surface->lightmapinfo->samples + (model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2727                                         float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2728                                         VectorScale(lm, scale, c);
2729                                         if (surface->lightmapinfo->styles[1] != 255)
2730                                         {
2731                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2732                                                 lm += size3;
2733                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2734                                                 VectorMA(c, scale, lm, c);
2735                                                 if (surface->lightmapinfo->styles[2] != 255)
2736                                                 {
2737                                                         lm += size3;
2738                                                         scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2739                                                         VectorMA(c, scale, lm, c);
2740                                                         if (surface->lightmapinfo->styles[3] != 255)
2741                                                         {
2742                                                                 lm += size3;
2743                                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2744                                                                 VectorMA(c, scale, lm, c);
2745                                                         }
2746                                                 }
2747                                         }
2748                                 }
2749                                 else
2750                                         VectorClear(c);
2751                         }
2752                         rsurface_lightmapcolor4f = rsurface_array_color4f;
2753                 }
2754                 else
2755                         rsurface_lightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
2756         }
2757         else
2758                 rsurface_lightmapcolor4f = NULL;
2759         if (applyfog)
2760         {
2761                 if (rsurface_lightmapcolor4f)
2762                 {
2763                         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)
2764                         {
2765                                 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2766                                 c2[0] = c[0] * f;
2767                                 c2[1] = c[1] * f;
2768                                 c2[2] = c[2] * f;
2769                                 c2[3] = c[3];
2770                         }
2771                 }
2772                 else
2773                 {
2774                         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)
2775                         {
2776                                 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2777                                 c2[0] = f;
2778                                 c2[1] = f;
2779                                 c2[2] = f;
2780                                 c2[3] = 1;
2781                         }
2782                 }
2783                 rsurface_lightmapcolor4f = rsurface_array_color4f;
2784         }
2785         if (applycolor && rsurface_lightmapcolor4f)
2786         {
2787                 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)
2788                 {
2789                         c2[0] = c[0] * r;
2790                         c2[1] = c[1] * g;
2791                         c2[2] = c[2] * b;
2792                         c2[3] = c[3] * a;
2793                 }
2794                 rsurface_lightmapcolor4f = rsurface_array_color4f;
2795         }
2796         R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2797         GL_Color(r, g, b, a);
2798         RSurf_Draw(model, surface);
2799 }
2800
2801 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2802 {
2803         int texturesurfaceindex;
2804         int lightmode;
2805         const msurface_t *surface;
2806         model_t *model = ent->model;
2807         qboolean applycolor;
2808         qboolean applyfog;
2809         rmeshstate_t m;
2810         if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
2811                 return;
2812         r_shadow_rtlight = NULL;
2813         renderstats.entities_surfaces += texturenumsurfaces;
2814         // FIXME: identify models using a better check than model->brush.shadowmesh
2815         lightmode = ((ent->effects & EF_FULLBRIGHT) || model->brush.shadowmesh) ? 0 : 2;
2816         GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
2817         if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2818                 qglDisable(GL_CULL_FACE);
2819         if (texture->currentmaterialflags & MATERIALFLAG_SKY)
2820         {
2821                 // transparent sky would be ridiculous
2822                 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2823                 {
2824                         if (skyrendernow)
2825                         {
2826                                 skyrendernow = false;
2827                                 R_Sky();
2828                                 // restore entity matrix
2829                                 R_Mesh_Matrix(&ent->matrix);
2830                         }
2831                         GL_DepthMask(true);
2832                         // LordHavoc: HalfLife maps have freaky skypolys...
2833                         // LordHavoc: Quake3 never did sky masking (unlike software Quake
2834                         // and Quake2), so disable the sky masking in Quake3 maps as it
2835                         // causes problems with q3map2 sky tricks
2836                         if (!model->brush.ishlbsp && model->type != mod_brushq3)
2837                         {
2838                                 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2839                                 memset(&m, 0, sizeof(m));
2840                                 R_Mesh_State(&m);
2841                                 if (skyrendermasked)
2842                                 {
2843                                         // depth-only (masking)
2844                                         GL_ColorMask(0,0,0,0);
2845                                         // just to make sure that braindead drivers don't draw
2846                                         // anything despite that colormask...
2847                                         GL_BlendFunc(GL_ZERO, GL_ONE);
2848                                 }
2849                                 else
2850                                 {
2851                                         // fog sky
2852                                         GL_BlendFunc(GL_ONE, GL_ZERO);
2853                                 }
2854                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2855                                 {
2856                                         surface = texturesurfacelist[texturesurfaceindex];
2857                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2858                                         RSurf_Draw(model, surface);
2859                                 }
2860                                 if (skyrendermasked)
2861                                         GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2862                         }
2863                 }
2864         }
2865         else if (r_glsl.integer && gl_support_fragment_shader)
2866         {
2867                 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
2868                 {
2869                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2870                         GL_DepthMask(false);
2871                 }
2872                 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
2873                 {
2874                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2875                         GL_DepthMask(false);
2876                 }
2877                 else
2878                 {
2879                         GL_BlendFunc(GL_ONE, GL_ZERO);
2880                         GL_DepthMask(true);
2881                 }
2882
2883                 memset(&m, 0, sizeof(m));
2884                 R_Mesh_State(&m);
2885                 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], texture->currentalpha);
2886                 R_SetupSurfaceShader(ent, texture, modelorg, vec3_origin, lightmode == 2);
2887                 if (!r_glsl_permutation)
2888                         return;
2889                 if (lightmode == 2)
2890                 {
2891                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2892                         {
2893                                 surface = texturesurfacelist[texturesurfaceindex];
2894                                 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2895                                 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
2896                                 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2897                                 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2898                                 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2899                                 RSurf_Draw(model, surface);
2900                         }
2901                 }
2902                 else
2903                 {
2904                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2905                         {
2906                                 surface = texturesurfacelist[texturesurfaceindex];
2907                                 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2908                                 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
2909                                 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2910                                 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2911                                 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2912                                 R_Mesh_TexCoordPointer(4, 2, model->surfmesh.data_texcoordlightmap2f);
2913                                 if (surface->lightmaptexture)
2914                                 {
2915                                         R_Mesh_TexBind(7, R_GetTexture(surface->lightmaptexture));
2916                                         if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2917                                                 R_Mesh_TexBind(8, R_GetTexture(surface->deluxemaptexture));
2918                                         R_Mesh_ColorPointer(NULL);
2919                                 }
2920                                 else
2921                                 {
2922                                         R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2923                                         if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2924                                                 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2925                                         R_Mesh_ColorPointer(model->surfmesh.data_lightmapcolor4f);
2926                                 }
2927                                 RSurf_Draw(model, surface);
2928                         }
2929                 }
2930                 qglUseProgramObjectARB(0);
2931         }
2932         else if (texture->currentnumlayers)
2933         {
2934                 int layerindex;
2935                 texturelayer_t *layer;
2936                 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
2937                 {
2938                         vec4_t layercolor;
2939                         int layertexrgbscale;
2940                         GL_DepthMask(layer->depthmask);
2941                         GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2942                         if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2943                         {
2944                                 layertexrgbscale = 4;
2945                                 VectorScale(layer->color, 0.25f, layercolor);
2946                         }
2947                         else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2948                         {
2949                                 layertexrgbscale = 2;
2950                                 VectorScale(layer->color, 0.5f, layercolor);
2951                         }
2952                         else
2953                         {
2954                                 layertexrgbscale = 1;
2955                                 VectorScale(layer->color, 1.0f, layercolor);
2956                         }
2957                         layercolor[3] = layer->color[3];
2958                         GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2959                         applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2960                         applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2961                         switch (layer->type)
2962                         {
2963                         case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2964                                 memset(&m, 0, sizeof(m));
2965                                 m.tex[1] = R_GetTexture(layer->texture);
2966                                 m.texmatrix[1] = layer->texmatrix;
2967                                 m.texrgbscale[1] = layertexrgbscale;
2968                                 m.pointer_color = rsurface_array_color4f;
2969                                 R_Mesh_State(&m);
2970                                 if (lightmode == 2)
2971                                 {
2972                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2973                                         {
2974                                                 surface = texturesurfacelist[texturesurfaceindex];
2975                                                 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordlightmap2f);
2976                                                 R_Mesh_TexCoordPointer(1, 2, model->surfmesh.data_texcoordtexture2f);
2977                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2978                                                 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2979                                         }
2980                                 }
2981                                 else
2982                                 {
2983                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2984                                         {
2985                                                 surface = texturesurfacelist[texturesurfaceindex];
2986                                                 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordlightmap2f);
2987                                                 R_Mesh_TexCoordPointer(1, 2, model->surfmesh.data_texcoordtexture2f);
2988                                                 if (surface->lightmaptexture)
2989                                                 {
2990                                                         R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2991                                                         RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2992                                                 }
2993                                                 else
2994                                                 {
2995                                                         R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2996                                                         RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2997                                                 }
2998                                         }
2999                                 }
3000                                 break;
3001                         case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
3002                                 memset(&m, 0, sizeof(m));
3003                                 m.tex[0] = R_GetTexture(layer->texture);
3004                                 m.texmatrix[0] = layer->texmatrix;
3005                                 m.pointer_color = rsurface_array_color4f;
3006                                 m.texrgbscale[0] = layertexrgbscale;
3007                                 R_Mesh_State(&m);
3008                                 if (lightmode == 2)
3009                                 {
3010                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3011                                         {
3012                                                 surface = texturesurfacelist[texturesurfaceindex];
3013                                                 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordlightmap2f);
3014                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3015                                                 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 2, false, false);
3016                                         }
3017                                 }
3018                                 else
3019                                 {
3020                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3021                                         {
3022                                                 surface = texturesurfacelist[texturesurfaceindex];
3023                                                 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordlightmap2f);
3024                                                 if (surface->lightmaptexture)
3025                                                 {
3026                                                         R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
3027                                                         RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 0, false, false);
3028                                                 }
3029                                                 else
3030                                                 {
3031                                                         R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3032                                                         RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 1, false, false);
3033                                                 }
3034                                         }
3035                                 }
3036                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3037                                 memset(&m, 0, sizeof(m));
3038                                 m.tex[0] = R_GetTexture(layer->texture);
3039                                 m.texmatrix[0] = layer->texmatrix;
3040                                 m.pointer_color = rsurface_array_color4f;
3041                                 m.texrgbscale[0] = layertexrgbscale;
3042                                 R_Mesh_State(&m);
3043                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3044                                 {
3045                                         surface = texturesurfacelist[texturesurfaceindex];
3046                                         R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
3047                                         RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3048                                 }
3049                                 break;
3050                         case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
3051                                 memset(&m, 0, sizeof(m));
3052                                 m.tex[0] = R_GetTexture(layer->texture);
3053                                 m.texmatrix[0] = layer->texmatrix;
3054                                 m.texrgbscale[0] = layertexrgbscale;
3055                                 m.pointer_color = rsurface_array_color4f;
3056                                 R_Mesh_State(&m);
3057                                 if (lightmode == 2)
3058                                 {
3059                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3060                                         {
3061                                                 surface = texturesurfacelist[texturesurfaceindex];
3062                                                 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
3063                                                 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
3064                                         }
3065                                 }
3066                                 else
3067                                 {
3068                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3069                                         {
3070                                                 surface = texturesurfacelist[texturesurfaceindex];
3071                                                 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
3072                                                 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
3073                                         }
3074                                 }
3075                                 break;
3076                         case TEXTURELAYERTYPE_TEXTURE:
3077                                 memset(&m, 0, sizeof(m));
3078                                 m.tex[0] = R_GetTexture(layer->texture);
3079                                 m.texmatrix[0] = layer->texmatrix;
3080                                 m.pointer_color = rsurface_array_color4f;
3081                                 m.texrgbscale[0] = layertexrgbscale;
3082                                 R_Mesh_State(&m);
3083                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3084                                 {
3085                                         surface = texturesurfacelist[texturesurfaceindex];
3086                                         R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
3087