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