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