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