replaced Mod_LoadSkinFrame functions with R_SkinFrame system, this
[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         // mark the skinframe as used for the purging code
1059         skinframe->loadsequence = r_skinframe.loadsequence;
1060 }
1061
1062 void R_SkinFrame_Purge(void)
1063 {
1064         int i;
1065         skinframe_t *s;
1066         for (i = 0;i < SKINFRAME_HASH;i++)
1067         {
1068                 for (s = r_skinframe.hash[i];s;s = s->next)
1069                 {
1070                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1071                         {
1072                                 if (s->base == r_texture_notexture)     s->base   = NULL;
1073                                 if (s->nmap == r_texture_blanknormalmap)s->nmap   = NULL;
1074                                 if (s->merged == s->base)               s->merged = NULL;
1075                                 if (s->stain ) R_FreeTexture(s->stain );s->stain  = NULL;
1076                                 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1077                                 if (s->base  ) R_FreeTexture(s->base  );s->base   = NULL;
1078                                 if (s->pants ) R_FreeTexture(s->pants );s->pants  = NULL;
1079                                 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt  = NULL;
1080                                 if (s->nmap  ) R_FreeTexture(s->nmap  );s->nmap   = NULL;
1081                                 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss  = NULL;
1082                                 if (s->glow  ) R_FreeTexture(s->glow  );s->glow   = NULL;
1083                                 if (s->fog   ) R_FreeTexture(s->fog   );s->fog    = NULL;
1084                                 s->loadsequence = 0;
1085                         }
1086                 }
1087         }
1088 }
1089
1090 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1091 {
1092         skinframe_t *item;
1093         int hashindex;
1094         char basename[MAX_QPATH];
1095
1096         Image_StripImageExtension(name, basename, sizeof(basename));
1097
1098         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1099         for (item = r_skinframe.hash[hashindex];item;item = item->next)
1100                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1101                         break;
1102         if (!item)
1103         {
1104                 if (!add)
1105                         return NULL;
1106                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1107                 memset(item, 0, sizeof(*item));
1108                 strlcpy(item->basename, basename, sizeof(item->basename));
1109                 item->textureflags = textureflags;
1110                 item->comparewidth = comparewidth;
1111                 item->compareheight = compareheight;
1112                 item->comparecrc = comparecrc;
1113                 item->next = r_skinframe.hash[hashindex];
1114                 r_skinframe.hash[hashindex] = item;
1115         }
1116         R_SkinFrame_MarkUsed(item);
1117         return item;
1118 }
1119
1120 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags)
1121 {
1122         // FIXME: it should be possible to disable loading various layers using
1123         // cvars, to prevent wasted loading time and memory usage if the user does
1124         // not want them
1125         qboolean loadnormalmap = true;
1126         qboolean loadgloss = true;
1127         qboolean loadpantsandshirt = true;
1128         qboolean loadglow = true;
1129         int j;
1130         unsigned char *pixels;
1131         unsigned char *bumppixels;
1132         unsigned char *basepixels = NULL;
1133         int basepixels_width;
1134         int basepixels_height;
1135         skinframe_t *skinframe;
1136
1137         if (cls.state == ca_dedicated)
1138                 return NULL;
1139
1140         // return an existing skinframe if already loaded
1141         // if loading of the first image fails, don't make a new skinframe as it
1142         // would cause all future lookups of this to be missing
1143         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1144         if (skinframe && skinframe->base)
1145                 return skinframe;
1146
1147         basepixels = loadimagepixels(name, false, 0, 0);
1148         if (basepixels == NULL)
1149                 return NULL;
1150
1151         // we've got some pixels to store, so really allocate this new texture now
1152         if (!skinframe)
1153                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1154         skinframe->stain = NULL;
1155         skinframe->merged = NULL;
1156         skinframe->base = r_texture_notexture;
1157         skinframe->pants = NULL;
1158         skinframe->shirt = NULL;
1159         skinframe->nmap = r_texture_blanknormalmap;
1160         skinframe->gloss = NULL;
1161         skinframe->glow = NULL;
1162         skinframe->fog = NULL;
1163
1164         basepixels_width = image_width;
1165         basepixels_height = image_height;
1166         skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1167
1168         if (textureflags & TEXF_ALPHA)
1169         {
1170                 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1171                         if (basepixels[j] < 255)
1172                                 break;
1173                 if (j < basepixels_width * basepixels_height * 4)
1174                 {
1175                         // has transparent pixels
1176                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1177                         for (j = 0;j < image_width * image_height * 4;j += 4)
1178                         {
1179                                 pixels[j+0] = 255;
1180                                 pixels[j+1] = 255;
1181                                 pixels[j+2] = 255;
1182                                 pixels[j+3] = basepixels[j+3];
1183                         }
1184                         skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1185                         Mem_Free(pixels);
1186                 }
1187         }
1188
1189         // _norm is the name used by tenebrae and has been adopted as standard
1190         if (loadnormalmap)
1191         {
1192                 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0)) != NULL)
1193                 {
1194                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1195                         Mem_Free(pixels);
1196                         pixels = NULL;
1197                 }
1198                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0)) != NULL)
1199                 {
1200                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1201                         Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1202                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1203                         Mem_Free(pixels);
1204                         Mem_Free(bumppixels);
1205                 }
1206                 else if (r_shadow_bumpscale_basetexture.value > 0)
1207                 {
1208                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1209                         Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1210                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1211                         Mem_Free(pixels);
1212                 }
1213         }
1214         // _luma is supported for tenebrae compatibility
1215         // (I think it's a very stupid name, but oh well)
1216         // _glow is the preferred name
1217         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;}
1218         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;}
1219         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;}
1220         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;}
1221
1222         if (basepixels)
1223                 Mem_Free(basepixels);
1224
1225         return skinframe;
1226 }
1227
1228 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)
1229 {
1230         int i;
1231         if (!force)
1232         {
1233                 for (i = 0;i < width*height;i++)
1234                         if (((unsigned char *)&palette[in[i]])[3] > 0)
1235                                 break;
1236                 if (i == width*height)
1237                         return NULL;
1238         }
1239         return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1240 }
1241
1242 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)
1243 {
1244         int i;
1245         unsigned char *temp1, *temp2;
1246         skinframe_t *skinframe;
1247
1248         if (cls.state == ca_dedicated)
1249                 return NULL;
1250
1251         // if already loaded just return it, otherwise make a new skinframe
1252         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1253         if (skinframe && skinframe->base)
1254                 return skinframe;
1255
1256         skinframe->stain = NULL;
1257         skinframe->merged = NULL;
1258         skinframe->base = r_texture_notexture;
1259         skinframe->pants = NULL;
1260         skinframe->shirt = NULL;
1261         skinframe->nmap = r_texture_blanknormalmap;
1262         skinframe->gloss = NULL;
1263         skinframe->glow = NULL;
1264         skinframe->fog = NULL;
1265
1266         // if no data was provided, then clearly the caller wanted to get a blank skinframe
1267         if (!skindata)
1268                 return NULL;
1269
1270         if (bitsperpixel == 32)
1271         {
1272                 if (r_shadow_bumpscale_basetexture.value > 0)
1273                 {
1274                         temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1275                         temp2 = temp1 + width * height * 4;
1276                         Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1277                         skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL);
1278                         Mem_Free(temp1);
1279                 }
1280                 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, textureflags, NULL);
1281                 if (textureflags & TEXF_ALPHA)
1282                 {
1283                         for (i = 3;i < width * height * 4;i += 4)
1284                                 if (skindata[i] < 255)
1285                                         break;
1286                         if (i < width * height * 4)
1287                         {
1288                                 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1289                                 memcpy(fogpixels, skindata, width * height * 4);
1290                                 for (i = 0;i < width * height * 4;i += 4)
1291                                         fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1292                                 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, textureflags, NULL);
1293                                 Mem_Free(fogpixels);
1294                         }
1295                 }
1296         }
1297         else if (bitsperpixel == 8)
1298         {
1299                 if (r_shadow_bumpscale_basetexture.value > 0)
1300                 {
1301                         temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1302                         temp2 = temp1 + width * height * 4;
1303                         if (bitsperpixel == 32)
1304                                 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1305                         else
1306                         {
1307                                 // use either a custom palette or the quake palette
1308                                 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1309                                 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1310                         }
1311                         skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL);
1312                         Mem_Free(temp1);
1313                 }
1314                 // use either a custom palette, or the quake palette
1315                 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
1316                 if (!palette && loadglowtexture)
1317                         skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, textureflags, false); // glow
1318                 if (!palette && loadpantsandshirt)
1319                 {
1320                         skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, textureflags, false); // pants
1321                         skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, textureflags, false); // shirt
1322                 }
1323                 if (skinframe->pants || skinframe->shirt)
1324                         skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, textureflags, false); // no special colors
1325                 if (textureflags & TEXF_ALPHA)
1326                 {
1327                         // if not using a custom alphapalette, use the quake one
1328                         if (!alphapalette)
1329                                 alphapalette = palette_alpha;
1330                         for (i = 0;i < width * height;i++)
1331                                 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1332                                         break;
1333                         if (i < width * height)
1334                                 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, textureflags, true); // fog mask
1335                 }
1336         }
1337
1338         return skinframe;
1339 }
1340
1341 skinframe_t *R_SkinFrame_LoadMissing(void)
1342 {
1343         skinframe_t *skinframe;
1344
1345         if (cls.state == ca_dedicated)
1346                 return NULL;
1347
1348         skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1349         skinframe->stain = NULL;
1350         skinframe->merged = NULL;
1351         skinframe->base = r_texture_notexture;
1352         skinframe->pants = NULL;
1353         skinframe->shirt = NULL;
1354         skinframe->nmap = r_texture_blanknormalmap;
1355         skinframe->gloss = NULL;
1356         skinframe->glow = NULL;
1357         skinframe->fog = NULL;
1358
1359         return skinframe;
1360 }
1361
1362 void gl_main_start(void)
1363 {
1364         int x;
1365         double r, alpha;
1366
1367         r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1368         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1369         {
1370                 alpha = 1 - exp(r / ((double)x*(double)x));
1371                 if (x == FOGMASKTABLEWIDTH - 1)
1372                         alpha = 0;
1373                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1374         }
1375
1376         // set up r_skinframe loading system for textures
1377         memset(&r_skinframe, 0, sizeof(r_skinframe));
1378         r_skinframe.loadsequence = 1;
1379         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1380
1381         r_main_texturepool = R_AllocTexturePool();
1382         R_BuildBlankTextures();
1383         R_BuildNoTexture();
1384         if (gl_texturecubemap)
1385         {
1386                 R_BuildWhiteCube();
1387                 R_BuildNormalizationCube();
1388         }
1389         R_BuildFogTexture();
1390         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1391         memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1392         memset(&r_svbsp, 0, sizeof (r_svbsp));
1393 }
1394
1395 void gl_main_shutdown(void)
1396 {
1397         // clear out the r_skinframe state
1398         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1399         memset(&r_skinframe, 0, sizeof(r_skinframe));
1400
1401         if (r_svbsp.nodes)
1402                 Mem_Free(r_svbsp.nodes);
1403         memset(&r_svbsp, 0, sizeof (r_svbsp));
1404         R_FreeTexturePool(&r_main_texturepool);
1405         r_texture_blanknormalmap = NULL;
1406         r_texture_white = NULL;
1407         r_texture_black = NULL;
1408         r_texture_whitecube = NULL;
1409         r_texture_normalizationcube = NULL;
1410         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1411         R_GLSL_Restart_f();
1412 }
1413
1414 extern void CL_ParseEntityLump(char *entitystring);
1415 void gl_main_newmap(void)
1416 {
1417         // FIXME: move this code to client
1418         int l;
1419         char *entities, entname[MAX_QPATH];
1420         if (cl.worldmodel)
1421         {
1422                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1423                 l = (int)strlen(entname) - 4;
1424                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1425                 {
1426                         memcpy(entname + l, ".ent", 5);
1427                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1428                         {
1429                                 CL_ParseEntityLump(entities);
1430                                 Mem_Free(entities);
1431                                 return;
1432                         }
1433                 }
1434                 if (cl.worldmodel->brush.entities)
1435                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
1436         }
1437 }
1438
1439 void GL_Main_Init(void)
1440 {
1441         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1442
1443         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1444         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1445         if (gamemode == GAME_NEHAHRA)
1446         {
1447                 Cvar_RegisterVariable (&gl_fogenable);
1448                 Cvar_RegisterVariable (&gl_fogdensity);
1449                 Cvar_RegisterVariable (&gl_fogred);
1450                 Cvar_RegisterVariable (&gl_foggreen);
1451                 Cvar_RegisterVariable (&gl_fogblue);
1452                 Cvar_RegisterVariable (&gl_fogstart);
1453                 Cvar_RegisterVariable (&gl_fogend);
1454         }
1455         Cvar_RegisterVariable(&r_nearclip);
1456         Cvar_RegisterVariable(&r_showbboxes);
1457         Cvar_RegisterVariable(&r_showsurfaces);
1458         Cvar_RegisterVariable(&r_showtris);
1459         Cvar_RegisterVariable(&r_shownormals);
1460         Cvar_RegisterVariable(&r_showlighting);
1461         Cvar_RegisterVariable(&r_showshadowvolumes);
1462         Cvar_RegisterVariable(&r_showcollisionbrushes);
1463         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1464         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1465         Cvar_RegisterVariable(&r_showdisabledepthtest);
1466         Cvar_RegisterVariable(&r_drawportals);
1467         Cvar_RegisterVariable(&r_drawentities);
1468         Cvar_RegisterVariable(&r_cullentities_trace);
1469         Cvar_RegisterVariable(&r_cullentities_trace_samples);
1470         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1471         Cvar_RegisterVariable(&r_cullentities_trace_delay);
1472         Cvar_RegisterVariable(&r_drawviewmodel);
1473         Cvar_RegisterVariable(&r_speeds);
1474         Cvar_RegisterVariable(&r_fullbrights);
1475         Cvar_RegisterVariable(&r_wateralpha);
1476         Cvar_RegisterVariable(&r_dynamic);
1477         Cvar_RegisterVariable(&r_fullbright);
1478         Cvar_RegisterVariable(&r_shadows);
1479         Cvar_RegisterVariable(&r_shadows_throwdistance);
1480         Cvar_RegisterVariable(&r_q1bsp_skymasking);
1481         Cvar_RegisterVariable(&r_textureunits);
1482         Cvar_RegisterVariable(&r_glsl);
1483         Cvar_RegisterVariable(&r_glsl_offsetmapping);
1484         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1485         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1486         Cvar_RegisterVariable(&r_glsl_deluxemapping);
1487         Cvar_RegisterVariable(&r_lerpsprites);
1488         Cvar_RegisterVariable(&r_lerpmodels);
1489         Cvar_RegisterVariable(&r_waterscroll);
1490         Cvar_RegisterVariable(&r_bloom);
1491         Cvar_RegisterVariable(&r_bloom_colorscale);
1492         Cvar_RegisterVariable(&r_bloom_brighten);
1493         Cvar_RegisterVariable(&r_bloom_blur);
1494         Cvar_RegisterVariable(&r_bloom_resolution);
1495         Cvar_RegisterVariable(&r_bloom_colorexponent);
1496         Cvar_RegisterVariable(&r_bloom_colorsubtract);
1497         Cvar_RegisterVariable(&r_hdr);
1498         Cvar_RegisterVariable(&r_hdr_scenebrightness);
1499         Cvar_RegisterVariable(&r_hdr_glowintensity);
1500         Cvar_RegisterVariable(&r_hdr_range);
1501         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1502         Cvar_RegisterVariable(&developer_texturelogging);
1503         Cvar_RegisterVariable(&gl_lightmaps);
1504         Cvar_RegisterVariable(&r_test);
1505         Cvar_RegisterVariable(&r_batchmode);
1506         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1507                 Cvar_SetValue("r_fullbrights", 0);
1508         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1509 }
1510
1511 extern void R_Textures_Init(void);
1512 extern void GL_Draw_Init(void);
1513 extern void GL_Main_Init(void);
1514 extern void R_Shadow_Init(void);
1515 extern void R_Sky_Init(void);
1516 extern void GL_Surf_Init(void);
1517 extern void R_Light_Init(void);
1518 extern void R_Particles_Init(void);
1519 extern void R_Explosion_Init(void);
1520 extern void gl_backend_init(void);
1521 extern void Sbar_Init(void);
1522 extern void R_LightningBeams_Init(void);
1523 extern void Mod_RenderInit(void);
1524
1525 void Render_Init(void)
1526 {
1527         gl_backend_init();
1528         R_Textures_Init();
1529         GL_Main_Init();
1530         GL_Draw_Init();
1531         R_Shadow_Init();
1532         R_Sky_Init();
1533         GL_Surf_Init();
1534         Sbar_Init();
1535         R_Light_Init();
1536         R_Particles_Init();
1537         R_Explosion_Init();
1538         R_LightningBeams_Init();
1539         Mod_RenderInit();
1540 }
1541
1542 /*
1543 ===============
1544 GL_Init
1545 ===============
1546 */
1547 extern char *ENGINE_EXTENSIONS;
1548 void GL_Init (void)
1549 {
1550         VID_CheckExtensions();
1551
1552         // LordHavoc: report supported extensions
1553         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1554
1555         // clear to black (loading plaque will be seen over this)
1556         CHECKGLERROR
1557         qglClearColor(0,0,0,1);CHECKGLERROR
1558         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1559 }
1560
1561 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1562 {
1563         int i;
1564         mplane_t *p;
1565         for (i = 0;i < 4;i++)
1566         {
1567                 p = r_view.frustum + i;
1568                 switch(p->signbits)
1569                 {
1570                 default:
1571                 case 0:
1572                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1573                                 return true;
1574                         break;
1575                 case 1:
1576                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1577                                 return true;
1578                         break;
1579                 case 2:
1580                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1581                                 return true;
1582                         break;
1583                 case 3:
1584                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1585                                 return true;
1586                         break;
1587                 case 4:
1588                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1589                                 return true;
1590                         break;
1591                 case 5:
1592                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1593                                 return true;
1594                         break;
1595                 case 6:
1596                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1597                                 return true;
1598                         break;
1599                 case 7:
1600                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1601                                 return true;
1602                         break;
1603                 }
1604         }
1605         return false;
1606 }
1607
1608 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1609 {
1610         int i;
1611         const mplane_t *p;
1612         for (i = 0;i < numplanes;i++)
1613         {
1614                 p = planes + i;
1615                 switch(p->signbits)
1616                 {
1617                 default:
1618                 case 0:
1619                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1620                                 return true;
1621                         break;
1622                 case 1:
1623                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1624                                 return true;
1625                         break;
1626                 case 2:
1627                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1628                                 return true;
1629                         break;
1630                 case 3:
1631                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1632                                 return true;
1633                         break;
1634                 case 4:
1635                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1636                                 return true;
1637                         break;
1638                 case 5:
1639                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1640                                 return true;
1641                         break;
1642                 case 6:
1643                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1644                                 return true;
1645                         break;
1646                 case 7:
1647                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1648                                 return true;
1649                         break;
1650                 }
1651         }
1652         return false;
1653 }
1654
1655 //==================================================================================
1656
1657 static void R_UpdateEntityLighting(entity_render_t *ent)
1658 {
1659         vec3_t tempdiffusenormal;
1660
1661         // fetch the lighting from the worldmodel data
1662         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));
1663         VectorClear(ent->modellight_diffuse);
1664         VectorClear(tempdiffusenormal);
1665         if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1666         {
1667                 vec3_t org;
1668                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1669                 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1670         }
1671         else // highly rare
1672                 VectorSet(ent->modellight_ambient, 1, 1, 1);
1673
1674         // move the light direction into modelspace coordinates for lighting code
1675         Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1676         VectorNormalize(ent->modellight_lightdir);
1677
1678         // scale ambient and directional light contributions according to rendering variables
1679         ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1680         ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1681         ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1682         ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1683         ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1684         ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1685 }
1686
1687 static void R_View_UpdateEntityVisible (void)
1688 {
1689         int i, renderimask;
1690         entity_render_t *ent;
1691
1692         if (!r_drawentities.integer)
1693                 return;
1694
1695         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1696         if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1697         {
1698                 // worldmodel can check visibility
1699                 for (i = 0;i < r_refdef.numentities;i++)
1700                 {
1701                         ent = r_refdef.entities[i];
1702                         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));
1703                 }
1704                 if(r_cullentities_trace.integer)
1705                 {
1706                         for (i = 0;i < r_refdef.numentities;i++)
1707                         {
1708                                 ent = r_refdef.entities[i];
1709                                 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
1710                                 {
1711                                         if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
1712                                                 ent->last_trace_visibility = realtime;
1713                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
1714                                                 r_viewcache.entityvisible[i] = 0;
1715                                 }
1716                         }
1717                 }
1718         }
1719         else
1720         {
1721                 // no worldmodel or it can't check visibility
1722                 for (i = 0;i < r_refdef.numentities;i++)
1723                 {
1724                         ent = r_refdef.entities[i];
1725                         r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1726                 }
1727         }
1728
1729         // update entity lighting (even on hidden entities for r_shadows)
1730         for (i = 0;i < r_refdef.numentities;i++)
1731                 R_UpdateEntityLighting(r_refdef.entities[i]);
1732 }
1733
1734 // only used if skyrendermasked, and normally returns false
1735 int R_DrawBrushModelsSky (void)
1736 {
1737         int i, sky;
1738         entity_render_t *ent;
1739
1740         if (!r_drawentities.integer)
1741                 return false;
1742
1743         sky = false;
1744         for (i = 0;i < r_refdef.numentities;i++)
1745         {
1746                 if (!r_viewcache.entityvisible[i])
1747                         continue;
1748                 ent = r_refdef.entities[i];
1749                 if (!ent->model || !ent->model->DrawSky)
1750                         continue;
1751                 ent->model->DrawSky(ent);
1752                 sky = true;
1753         }
1754         return sky;
1755 }
1756
1757 void R_DrawNoModel(entity_render_t *ent);
1758 void R_DrawModels(void)
1759 {
1760         int i;
1761         entity_render_t *ent;
1762
1763         if (!r_drawentities.integer)
1764                 return;
1765
1766         for (i = 0;i < r_refdef.numentities;i++)
1767         {
1768                 if (!r_viewcache.entityvisible[i])
1769                         continue;
1770                 ent = r_refdef.entities[i];
1771                 r_refdef.stats.entities++;
1772                 if (ent->model && ent->model->Draw != NULL)
1773                         ent->model->Draw(ent);
1774                 else
1775                         R_DrawNoModel(ent);
1776         }
1777 }
1778
1779 static void R_View_SetFrustum(void)
1780 {
1781         double slopex, slopey;
1782
1783         // break apart the view matrix into vectors for various purposes
1784         Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1785         VectorNegate(r_view.left, r_view.right);
1786
1787 #if 0
1788         r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1789         r_view.frustum[0].normal[1] = 0 - 0;
1790         r_view.frustum[0].normal[2] = -1 - 0;
1791         r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1792         r_view.frustum[1].normal[1] = 0 + 0;
1793         r_view.frustum[1].normal[2] = -1 + 0;
1794         r_view.frustum[2].normal[0] = 0 - 0;
1795         r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1796         r_view.frustum[2].normal[2] = -1 - 0;
1797         r_view.frustum[3].normal[0] = 0 + 0;
1798         r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1799         r_view.frustum[3].normal[2] = -1 + 0;
1800 #endif
1801
1802 #if 0
1803         zNear = r_refdef.nearclip;
1804         nudge = 1.0 - 1.0 / (1<<23);
1805         r_view.frustum[4].normal[0] = 0 - 0;
1806         r_view.frustum[4].normal[1] = 0 - 0;
1807         r_view.frustum[4].normal[2] = -1 - -nudge;
1808         r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1809         r_view.frustum[5].normal[0] = 0 + 0;
1810         r_view.frustum[5].normal[1] = 0 + 0;
1811         r_view.frustum[5].normal[2] = -1 + -nudge;
1812         r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1813 #endif
1814
1815
1816
1817 #if 0
1818         r_view.frustum[0].normal[0] = m[3] - m[0];
1819         r_view.frustum[0].normal[1] = m[7] - m[4];
1820         r_view.frustum[0].normal[2] = m[11] - m[8];
1821         r_view.frustum[0].dist = m[15] - m[12];
1822
1823         r_view.frustum[1].normal[0] = m[3] + m[0];
1824         r_view.frustum[1].normal[1] = m[7] + m[4];
1825         r_view.frustum[1].normal[2] = m[11] + m[8];
1826         r_view.frustum[1].dist = m[15] + m[12];
1827
1828         r_view.frustum[2].normal[0] = m[3] - m[1];
1829         r_view.frustum[2].normal[1] = m[7] - m[5];
1830         r_view.frustum[2].normal[2] = m[11] - m[9];
1831         r_view.frustum[2].dist = m[15] - m[13];
1832
1833         r_view.frustum[3].normal[0] = m[3] + m[1];
1834         r_view.frustum[3].normal[1] = m[7] + m[5];
1835         r_view.frustum[3].normal[2] = m[11] + m[9];
1836         r_view.frustum[3].dist = m[15] + m[13];
1837
1838         r_view.frustum[4].normal[0] = m[3] - m[2];
1839         r_view.frustum[4].normal[1] = m[7] - m[6];
1840         r_view.frustum[4].normal[2] = m[11] - m[10];
1841         r_view.frustum[4].dist = m[15] - m[14];
1842
1843         r_view.frustum[5].normal[0] = m[3] + m[2];
1844         r_view.frustum[5].normal[1] = m[7] + m[6];
1845         r_view.frustum[5].normal[2] = m[11] + m[10];
1846         r_view.frustum[5].dist = m[15] + m[14];
1847 #endif
1848
1849
1850
1851         slopex = 1.0 / r_view.frustum_x;
1852         slopey = 1.0 / r_view.frustum_y;
1853         VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
1854         VectorMA(r_view.forward,  slopex, r_view.left, r_view.frustum[1].normal);
1855         VectorMA(r_view.forward, -slopey, r_view.up  , r_view.frustum[2].normal);
1856         VectorMA(r_view.forward,  slopey, r_view.up  , r_view.frustum[3].normal);
1857         VectorCopy(r_view.forward, r_view.frustum[4].normal);
1858         VectorNormalize(r_view.frustum[0].normal);
1859         VectorNormalize(r_view.frustum[1].normal);
1860         VectorNormalize(r_view.frustum[2].normal);
1861         VectorNormalize(r_view.frustum[3].normal);
1862         r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1863         r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1864         r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1865         r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1866         r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1867         PlaneClassify(&r_view.frustum[0]);
1868         PlaneClassify(&r_view.frustum[1]);
1869         PlaneClassify(&r_view.frustum[2]);
1870         PlaneClassify(&r_view.frustum[3]);
1871         PlaneClassify(&r_view.frustum[4]);
1872
1873         // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
1874         VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
1875         VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward,  1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
1876         VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left,  1024 * slopey, r_view.up, r_view.frustumcorner[2]);
1877         VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward,  1024 * slopex, r_view.left,  1024 * slopey, r_view.up, r_view.frustumcorner[3]);
1878
1879         // LordHavoc: note to all quake engine coders, Quake had a special case
1880         // for 90 degrees which assumed a square view (wrong), so I removed it,
1881         // Quake2 has it disabled as well.
1882
1883         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1884         //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1885         //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1886         //PlaneClassify(&frustum[0]);
1887
1888         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1889         //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1890         //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1891         //PlaneClassify(&frustum[1]);
1892
1893         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1894         //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1895         //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1896         //PlaneClassify(&frustum[2]);
1897
1898         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1899         //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1900         //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1901         //PlaneClassify(&frustum[3]);
1902
1903         // nearclip plane
1904         //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1905         //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1906         //PlaneClassify(&frustum[4]);
1907 }
1908
1909 void R_View_Update(void)
1910 {
1911         R_View_SetFrustum();
1912         R_View_WorldVisibility();
1913         R_View_UpdateEntityVisible();
1914 }
1915
1916 void R_SetupView(const matrix4x4_t *matrix)
1917 {
1918         if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1919                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1920         else
1921                 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1922
1923         GL_SetupView_Orientation_FromEntity(matrix);
1924 }
1925
1926 void R_ResetViewRendering2D(void)
1927 {
1928         if (gl_support_fragment_shader)
1929         {
1930                 qglUseProgramObjectARB(0);CHECKGLERROR
1931         }
1932
1933         DrawQ_Finish();
1934
1935         // GL is weird because it's bottom to top, r_view.y is top to bottom
1936         qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1937         GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1938         GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1939         GL_Color(1, 1, 1, 1);
1940         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1941         GL_BlendFunc(GL_ONE, GL_ZERO);
1942         GL_AlphaTest(false);
1943         GL_ScissorTest(false);
1944         GL_DepthMask(false);
1945         GL_DepthRange(0, 1);
1946         GL_DepthTest(false);
1947         R_Mesh_Matrix(&identitymatrix);
1948         R_Mesh_ResetTextureState();
1949         qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1950         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1951         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1952         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1953         qglStencilMask(~0);CHECKGLERROR
1954         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1955         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1956         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1957 }
1958
1959 void R_ResetViewRendering3D(void)
1960 {
1961         if (gl_support_fragment_shader)
1962         {
1963                 qglUseProgramObjectARB(0);CHECKGLERROR
1964         }
1965
1966         DrawQ_Finish();
1967
1968         // GL is weird because it's bottom to top, r_view.y is top to bottom
1969         qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1970         R_SetupView(&r_view.matrix);
1971         GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1972         GL_Color(1, 1, 1, 1);
1973         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1974         GL_BlendFunc(GL_ONE, GL_ZERO);
1975         GL_AlphaTest(false);
1976         GL_ScissorTest(true);
1977         GL_DepthMask(true);
1978         GL_DepthRange(0, 1);
1979         GL_DepthTest(true);
1980         R_Mesh_Matrix(&identitymatrix);
1981         R_Mesh_ResetTextureState();
1982         qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1983         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1984         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1985         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1986         qglStencilMask(~0);CHECKGLERROR
1987         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1988         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1989         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1990 }
1991
1992 /*
1993         R_Bloom_SetupShader(
1994 "// bloom shader\n"
1995 "// written by Forest 'LordHavoc' Hale\n"
1996 "\n"
1997 "// common definitions between vertex shader and fragment shader:\n"
1998 "\n"
1999 "#ifdef __GLSL_CG_DATA_TYPES\n"
2000 "#define myhalf half\n"
2001 "#define myhvec2 hvec2\n"
2002 "#define myhvec3 hvec3\n"
2003 "#define myhvec4 hvec4\n"
2004 "#else\n"
2005 "#define myhalf float\n"
2006 "#define myhvec2 vec2\n"
2007 "#define myhvec3 vec3\n"
2008 "#define myhvec4 vec4\n"
2009 "#endif\n"
2010 "\n"
2011 "varying vec2 ScreenTexCoord;\n"
2012 "varying vec2 BloomTexCoord;\n"
2013 "\n"
2014 "\n"
2015 "\n"
2016 "\n"
2017 "// vertex shader specific:\n"
2018 "#ifdef VERTEX_SHADER\n"
2019 "\n"
2020 "void main(void)\n"
2021 "{\n"
2022 "       ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2023 "       BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2024 "       // transform vertex to camera space, using ftransform to match non-VS\n"
2025 "       // rendering\n"
2026 "       gl_Position = ftransform();\n"
2027 "}\n"
2028 "\n"
2029 "#endif // VERTEX_SHADER\n"
2030 "\n"
2031 "\n"
2032 "\n"
2033 "\n"
2034 "// fragment shader specific:\n"
2035 "#ifdef FRAGMENT_SHADER\n"
2036 "\n"
2037 "void main(void)\n"
2038 "{\n"
2039 "       int x, y;
2040 "       myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2041 "       for (x = -BLUR_X;x <= BLUR_X;x++)
2042 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2043 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2044 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2045 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2046
2047 "       gl_FragColor = vec4(color);\n"
2048 "}\n"
2049 "\n"
2050 "#endif // FRAGMENT_SHADER\n"
2051 */
2052
2053 void R_RenderScene(void);
2054
2055 void R_Bloom_StartFrame(void)
2056 {
2057         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2058
2059         // set bloomwidth and bloomheight to the bloom resolution that will be
2060         // used (often less than the screen resolution for faster rendering)
2061         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2062         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2063         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2064
2065         // calculate desired texture sizes
2066         if (gl_support_arb_texture_non_power_of_two)
2067         {
2068                 screentexturewidth = r_view.width;
2069                 screentextureheight = r_view.height;
2070                 bloomtexturewidth = r_bloomstate.bloomwidth;
2071                 bloomtextureheight = r_bloomstate.bloomheight;
2072         }
2073         else
2074         {
2075                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
2076                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
2077                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
2078                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
2079         }
2080
2081         if (r_hdr.integer)
2082         {
2083                 screentexturewidth = screentextureheight = 0;
2084         }
2085         else if (r_bloom.integer)
2086         {
2087         }
2088         else
2089         {
2090                 screentexturewidth = screentextureheight = 0;
2091                 bloomtexturewidth = bloomtextureheight = 0;
2092         }
2093
2094         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)
2095         {
2096                 // can't use bloom if the parameters are too weird
2097                 // can't use bloom if the card does not support the texture size
2098                 if (r_bloomstate.texture_screen)
2099                         R_FreeTexture(r_bloomstate.texture_screen);
2100                 if (r_bloomstate.texture_bloom)
2101                         R_FreeTexture(r_bloomstate.texture_bloom);
2102                 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2103                 return;
2104         }
2105
2106         r_bloomstate.enabled = true;
2107         r_bloomstate.hdr = r_hdr.integer != 0;
2108
2109         // allocate textures as needed
2110         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2111         {
2112                 if (r_bloomstate.texture_screen)
2113                         R_FreeTexture(r_bloomstate.texture_screen);
2114                 r_bloomstate.texture_screen = NULL;
2115                 r_bloomstate.screentexturewidth = screentexturewidth;
2116                 r_bloomstate.screentextureheight = screentextureheight;
2117                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2118                         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);
2119         }
2120         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2121         {
2122                 if (r_bloomstate.texture_bloom)
2123                         R_FreeTexture(r_bloomstate.texture_bloom);
2124                 r_bloomstate.texture_bloom = NULL;
2125                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2126                 r_bloomstate.bloomtextureheight = bloomtextureheight;
2127                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2128                         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);
2129         }
2130
2131         // set up a texcoord array for the full resolution screen image
2132         // (we have to keep this around to copy back during final render)
2133         r_bloomstate.screentexcoord2f[0] = 0;
2134         r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2135         r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2136         r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2137         r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2138         r_bloomstate.screentexcoord2f[5] = 0;
2139         r_bloomstate.screentexcoord2f[6] = 0;
2140         r_bloomstate.screentexcoord2f[7] = 0;
2141
2142         // set up a texcoord array for the reduced resolution bloom image
2143         // (which will be additive blended over the screen image)
2144         r_bloomstate.bloomtexcoord2f[0] = 0;
2145         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2146         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2147         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2148         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2149         r_bloomstate.bloomtexcoord2f[5] = 0;
2150         r_bloomstate.bloomtexcoord2f[6] = 0;
2151         r_bloomstate.bloomtexcoord2f[7] = 0;
2152 }
2153
2154 void R_Bloom_CopyScreenTexture(float colorscale)
2155 {
2156         r_refdef.stats.bloom++;
2157
2158         R_ResetViewRendering2D();
2159         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2160         R_Mesh_ColorPointer(NULL, 0, 0);
2161         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2162         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2163
2164         // copy view into the screen texture
2165         GL_ActiveTexture(0);
2166         CHECKGLERROR
2167         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
2168         r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2169
2170         // now scale it down to the bloom texture size
2171         CHECKGLERROR
2172         qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2173         GL_BlendFunc(GL_ONE, GL_ZERO);
2174         GL_Color(colorscale, colorscale, colorscale, 1);
2175         // TODO: optimize with multitexture or GLSL
2176         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2177         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2178
2179         // we now have a bloom image in the framebuffer
2180         // copy it into the bloom image texture for later processing
2181         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2182         GL_ActiveTexture(0);
2183         CHECKGLERROR
2184         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
2185         r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2186 }
2187
2188 void R_Bloom_CopyHDRTexture(void)
2189 {
2190         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2191         GL_ActiveTexture(0);
2192         CHECKGLERROR
2193         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
2194         r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2195 }
2196
2197 void R_Bloom_MakeTexture(void)
2198 {
2199         int x, range, dir;
2200         float xoffset, yoffset, r, brighten;
2201
2202         r_refdef.stats.bloom++;
2203
2204         R_ResetViewRendering2D();
2205         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2206         R_Mesh_ColorPointer(NULL, 0, 0);
2207
2208         // we have a bloom image in the framebuffer
2209         CHECKGLERROR
2210         qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2211
2212         for (x = 1;x < r_bloom_colorexponent.value;)
2213         {
2214                 x *= 2;
2215                 r = bound(0, r_bloom_colorexponent.value / x, 1);
2216                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2217                 GL_Color(r, r, r, 1);
2218                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2219                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2220                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2221                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2222
2223                 // copy the vertically blurred bloom view to a texture
2224                 GL_ActiveTexture(0);
2225                 CHECKGLERROR
2226                 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
2227                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2228         }
2229
2230         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2231         brighten = r_bloom_brighten.value;
2232         if (r_hdr.integer)
2233                 brighten *= r_hdr_range.value;
2234         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2235         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2236
2237         for (dir = 0;dir < 2;dir++)
2238         {
2239                 // blend on at multiple vertical offsets to achieve a vertical blur
2240                 // TODO: do offset blends using GLSL
2241                 GL_BlendFunc(GL_ONE, GL_ZERO);
2242                 for (x = -range;x <= range;x++)
2243                 {
2244                         if (!dir){xoffset = 0;yoffset = x;}
2245                         else {xoffset = x;yoffset = 0;}
2246                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
2247                         yoffset /= (float)r_bloomstate.bloomtextureheight;
2248                         // compute a texcoord array with the specified x and y offset
2249                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2250                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2251                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2252                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2253                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2254                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2255                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2256                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2257                         // this r value looks like a 'dot' particle, fading sharply to
2258                         // black at the edges
2259                         // (probably not realistic but looks good enough)
2260                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2261                         //r = (dir ? 1.0f : brighten)/(range*2+1);
2262                         r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2263                         GL_Color(r, r, r, 1);
2264                         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2265                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2266                         GL_BlendFunc(GL_ONE, GL_ONE);
2267                 }
2268
2269                 // copy the vertically blurred bloom view to a texture
2270                 GL_ActiveTexture(0);
2271                 CHECKGLERROR
2272                 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
2273                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2274         }
2275
2276         // apply subtract last
2277         // (just like it would be in a GLSL shader)
2278         if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
2279         {
2280                 GL_BlendFunc(GL_ONE, GL_ZERO);
2281                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2282                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2283                 GL_Color(1, 1, 1, 1);
2284                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2285                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2286
2287                 GL_BlendFunc(GL_ONE, GL_ONE);
2288                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2289                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2290                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2291                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
2292                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2293                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2294                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2295
2296                 // copy the darkened bloom view to a texture
2297                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2298                 GL_ActiveTexture(0);
2299                 CHECKGLERROR
2300                 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
2301                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2302         }
2303 }
2304
2305 void R_HDR_RenderBloomTexture(void)
2306 {
2307         int oldwidth, oldheight;
2308
2309         oldwidth = r_view.width;
2310         oldheight = r_view.height;
2311         r_view.width = r_bloomstate.bloomwidth;
2312         r_view.height = r_bloomstate.bloomheight;
2313
2314         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
2315         // TODO: add exposure compensation features
2316         // TODO: add fp16 framebuffer support
2317
2318         r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
2319         if (r_hdr.integer)
2320                 r_view.colorscale /= r_hdr_range.value;
2321         R_RenderScene();
2322
2323         R_ResetViewRendering2D();
2324
2325         R_Bloom_CopyHDRTexture();
2326         R_Bloom_MakeTexture();
2327
2328         R_ResetViewRendering3D();
2329
2330         R_ClearScreen();
2331         if (r_timereport_active)
2332                 R_TimeReport("clear");
2333
2334
2335         // restore the view settings
2336         r_view.width = oldwidth;
2337         r_view.height = oldheight;
2338 }
2339
2340 static void R_BlendView(void)
2341 {
2342         if (r_bloomstate.enabled && r_bloomstate.hdr)
2343         {
2344                 // render high dynamic range bloom effect
2345                 // the bloom texture was made earlier this render, so we just need to
2346                 // blend it onto the screen...
2347                 R_ResetViewRendering2D();
2348                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2349                 R_Mesh_ColorPointer(NULL, 0, 0);
2350                 GL_Color(1, 1, 1, 1);
2351                 GL_BlendFunc(GL_ONE, GL_ONE);
2352                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2353                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2354                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2355                 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2356         }
2357         else if (r_bloomstate.enabled)
2358         {
2359                 // render simple bloom effect
2360                 // copy the screen and shrink it and darken it for the bloom process
2361                 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2362                 // make the bloom texture
2363                 R_Bloom_MakeTexture();
2364                 // put the original screen image back in place and blend the bloom
2365                 // texture on it
2366                 R_ResetViewRendering2D();
2367                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2368                 R_Mesh_ColorPointer(NULL, 0, 0);
2369                 GL_Color(1, 1, 1, 1);
2370                 GL_BlendFunc(GL_ONE, GL_ZERO);
2371                 // do both in one pass if possible
2372                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2373                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2374                 if (r_textureunits.integer >= 2 && gl_combine.integer)
2375                 {
2376                         R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2377                         R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2378                         R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
2379                 }
2380                 else
2381                 {
2382                         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2383                         r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2384                         // now blend on the bloom texture
2385                         GL_BlendFunc(GL_ONE, GL_ONE);
2386                         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2387                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2388                 }
2389                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2390                 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2391         }
2392         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
2393         {
2394                 // apply a color tint to the whole view
2395                 R_ResetViewRendering2D();
2396                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2397                 R_Mesh_ColorPointer(NULL, 0, 0);
2398                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2399                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
2400                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2401         }
2402 }
2403
2404 void R_RenderScene(void);
2405
2406 matrix4x4_t r_waterscrollmatrix;
2407
2408 void R_UpdateVariables(void)
2409 {
2410         R_Textures_Frame();
2411
2412         r_refdef.farclip = 4096;
2413         if (r_refdef.worldmodel)
2414                 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
2415         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
2416
2417         r_refdef.polygonfactor = 0;
2418         r_refdef.polygonoffset = 0;
2419         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
2420         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
2421
2422         r_refdef.rtworld = r_shadow_realtime_world.integer;
2423         r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
2424         r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
2425         r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
2426         r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
2427         if (r_showsurfaces.integer)
2428         {
2429                 r_refdef.rtworld = false;
2430                 r_refdef.rtworldshadows = false;
2431                 r_refdef.rtdlight = false;
2432                 r_refdef.rtdlightshadows = false;
2433                 r_refdef.lightmapintensity = 0;
2434         }
2435
2436         if (gamemode == GAME_NEHAHRA)
2437         {
2438                 if (gl_fogenable.integer)
2439                 {
2440                         r_refdef.oldgl_fogenable = true;
2441                         r_refdef.fog_density = gl_fogdensity.value;
2442                         r_refdef.fog_red = gl_fogred.value;
2443                         r_refdef.fog_green = gl_foggreen.value;
2444                         r_refdef.fog_blue = gl_fogblue.value;
2445                 }
2446                 else if (r_refdef.oldgl_fogenable)
2447                 {
2448                         r_refdef.oldgl_fogenable = false;
2449                         r_refdef.fog_density = 0;
2450                         r_refdef.fog_red = 0;
2451                         r_refdef.fog_green = 0;
2452                         r_refdef.fog_blue = 0;
2453                 }
2454         }
2455         if (r_refdef.fog_density)
2456         {
2457                 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red  , 1.0f);
2458                 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
2459                 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
2460         }
2461         if (r_refdef.fog_density)
2462         {
2463                 r_refdef.fogenabled = true;
2464                 // this is the point where the fog reaches 0.9986 alpha, which we
2465                 // consider a good enough cutoff point for the texture
2466                 // (0.9986 * 256 == 255.6)
2467                 r_refdef.fogrange = 400 / r_refdef.fog_density;
2468                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
2469                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
2470                 // fog color was already set
2471         }
2472         else
2473                 r_refdef.fogenabled = false;
2474 }
2475
2476 /*
2477 ================
2478 R_RenderView
2479 ================
2480 */
2481 void R_RenderView(void)
2482 {
2483         if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
2484                 return; //Host_Error ("R_RenderView: NULL worldmodel");
2485
2486         R_Shadow_UpdateWorldLightSelection();
2487
2488         CHECKGLERROR
2489         if (r_timereport_active)
2490                 R_TimeReport("setup");
2491
2492         R_View_Update();
2493         if (r_timereport_active)
2494                 R_TimeReport("visibility");
2495
2496         R_ResetViewRendering3D();
2497
2498         R_ClearScreen();
2499         if (r_timereport_active)
2500                 R_TimeReport("clear");
2501
2502         R_Bloom_StartFrame();
2503
2504         // this produces a bloom texture to be used in R_BlendView() later
2505         if (r_hdr.integer)
2506                 R_HDR_RenderBloomTexture();
2507
2508         r_view.colorscale = r_hdr_scenebrightness.value;
2509         R_RenderScene();
2510
2511         R_BlendView();
2512         if (r_timereport_active)
2513                 R_TimeReport("blendview");
2514
2515         GL_Scissor(0, 0, vid.width, vid.height);
2516         GL_ScissorTest(false);
2517         CHECKGLERROR
2518 }
2519
2520 extern void R_DrawLightningBeams (void);
2521 extern void VM_CL_AddPolygonsToMeshQueue (void);
2522 extern void R_DrawPortals (void);
2523 extern cvar_t cl_locs_show;
2524 static void R_DrawLocs(void);
2525 static void R_DrawEntityBBoxes(void);
2526 void R_RenderScene(void)
2527 {
2528         // don't let sound skip if going slow
2529         if (r_refdef.extraupdate)
2530                 S_ExtraUpdate ();
2531
2532         R_ResetViewRendering3D();
2533
2534         R_MeshQueue_BeginScene();
2535
2536         R_SkyStartFrame();
2537
2538         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);
2539
2540         if (cl.csqc_vidvars.drawworld)
2541         {
2542                 // don't let sound skip if going slow
2543                 if (r_refdef.extraupdate)
2544                         S_ExtraUpdate ();
2545
2546                 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2547                 {
2548                         r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2549                         if (r_timereport_active)
2550                                 R_TimeReport("worldsky");
2551                 }
2552
2553                 if (R_DrawBrushModelsSky() && r_timereport_active)
2554                         R_TimeReport("bmodelsky");
2555
2556                 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2557                 {
2558                         r_refdef.worldmodel->Draw(r_refdef.worldentity);
2559                         if (r_timereport_active)
2560                                 R_TimeReport("world");
2561                 }
2562         }
2563
2564         // don't let sound skip if going slow
2565         if (r_refdef.extraupdate)
2566                 S_ExtraUpdate ();
2567
2568         R_DrawModels();
2569         if (r_timereport_active)
2570                 R_TimeReport("models");
2571
2572         // don't let sound skip if going slow
2573         if (r_refdef.extraupdate)
2574                 S_ExtraUpdate ();
2575
2576         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2577         {
2578                 R_DrawModelShadows();
2579
2580                 R_ResetViewRendering3D();
2581
2582                 // don't let sound skip if going slow
2583                 if (r_refdef.extraupdate)
2584                         S_ExtraUpdate ();
2585         }
2586
2587         R_ShadowVolumeLighting(false);
2588         if (r_timereport_active)
2589                 R_TimeReport("rtlights");
2590
2591         // don't let sound skip if going slow
2592         if (r_refdef.extraupdate)
2593                 S_ExtraUpdate ();
2594
2595         if (cl.csqc_vidvars.drawworld)
2596         {
2597                 R_DrawLightningBeams();
2598                 if (r_timereport_active)
2599                         R_TimeReport("lightning");
2600
2601                 R_DrawParticles();
2602                 if (r_timereport_active)
2603                         R_TimeReport("particles");
2604
2605                 R_DrawExplosions();
2606                 if (r_timereport_active)
2607                         R_TimeReport("explosions");
2608         }
2609
2610         if (gl_support_fragment_shader)
2611         {
2612                 qglUseProgramObjectARB(0);CHECKGLERROR
2613         }
2614         VM_CL_AddPolygonsToMeshQueue();
2615
2616         if (cl_locs_show.integer)
2617         {
2618                 R_DrawLocs();
2619                 if (r_timereport_active)
2620                         R_TimeReport("showlocs");
2621         }
2622
2623         if (r_drawportals.integer)
2624         {
2625                 R_DrawPortals();
2626                 if (r_timereport_active)
2627                         R_TimeReport("portals");
2628         }
2629
2630         if (r_showbboxes.value > 0)
2631         {
2632                 R_DrawEntityBBoxes();
2633                 if (r_timereport_active)
2634                         R_TimeReport("bboxes");
2635         }
2636
2637         if (gl_support_fragment_shader)
2638         {
2639                 qglUseProgramObjectARB(0);CHECKGLERROR
2640         }
2641         R_MeshQueue_RenderTransparent();
2642         if (r_timereport_active)
2643                 R_TimeReport("drawtrans");
2644
2645         if (gl_support_fragment_shader)
2646         {
2647                 qglUseProgramObjectARB(0);CHECKGLERROR
2648         }
2649
2650         if (cl.csqc_vidvars.drawworld)
2651         {
2652                 R_DrawCoronas();
2653                 if (r_timereport_active)
2654                         R_TimeReport("coronas");
2655         }
2656
2657         // don't let sound skip if going slow
2658         if (r_refdef.extraupdate)
2659                 S_ExtraUpdate ();
2660
2661         R_ResetViewRendering2D();
2662 }
2663
2664 static const int bboxelements[36] =
2665 {
2666         5, 1, 3, 5, 3, 7,
2667         6, 2, 0, 6, 0, 4,
2668         7, 3, 2, 7, 2, 6,
2669         4, 0, 1, 4, 1, 5,
2670         4, 5, 7, 4, 7, 6,
2671         1, 0, 2, 1, 2, 3,
2672 };
2673
2674 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2675 {
2676         int i;
2677         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
2678         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2679         GL_DepthMask(false);
2680         GL_DepthRange(0, 1);
2681         R_Mesh_Matrix(&identitymatrix);
2682         R_Mesh_ResetTextureState();
2683
2684         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
2685         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2686         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2687         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2688         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2689         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2690         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2691         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2692         R_FillColors(color4f, 8, cr, cg, cb, ca);
2693         if (r_refdef.fogenabled)
2694         {
2695                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
2696                 {
2697                         f1 = FogPoint_World(v);
2698                         f2 = 1 - f1;
2699                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2700                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2701                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2702                 }
2703         }
2704         R_Mesh_VertexPointer(vertex3f, 0, 0);
2705         R_Mesh_ColorPointer(color4f, 0, 0);
2706         R_Mesh_ResetTextureState();
2707         R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
2708 }
2709
2710 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2711 {
2712         int i;
2713         float color[4];
2714         prvm_edict_t *edict;
2715         // this function draws bounding boxes of server entities
2716         if (!sv.active)
2717                 return;
2718         SV_VM_Begin();
2719         for (i = 0;i < numsurfaces;i++)
2720         {
2721                 edict = PRVM_EDICT_NUM(surfacelist[i]);
2722                 switch ((int)edict->fields.server->solid)
2723                 {
2724                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
2725                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
2726                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
2727                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
2728                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
2729                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
2730                 }
2731                 color[3] *= r_showbboxes.value;
2732                 color[3] = bound(0, color[3], 1);
2733                 GL_DepthTest(!r_showdisabledepthtest.integer);
2734                 GL_CullFace(GL_BACK);
2735                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
2736         }
2737         SV_VM_End();
2738 }
2739
2740 static void R_DrawEntityBBoxes(void)
2741 {
2742         int i;
2743         prvm_edict_t *edict;
2744         vec3_t center;
2745         // this function draws bounding boxes of server entities
2746         if (!sv.active)
2747                 return;
2748         SV_VM_Begin();
2749         for (i = 0;i < prog->num_edicts;i++)
2750         {
2751                 edict = PRVM_EDICT_NUM(i);
2752                 if (edict->priv.server->free)
2753                         continue;
2754                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
2755                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
2756         }
2757         SV_VM_End();
2758 }
2759
2760 int nomodelelements[24] =
2761 {
2762         5, 2, 0,
2763         5, 1, 2,
2764         5, 0, 3,
2765         5, 3, 1,
2766         0, 2, 4,
2767         2, 1, 4,
2768         3, 0, 4,
2769         1, 3, 4
2770 };
2771
2772 float nomodelvertex3f[6*3] =
2773 {
2774         -16,   0,   0,
2775          16,   0,   0,
2776           0, -16,   0,
2777           0,  16,   0,
2778           0,   0, -16,
2779           0,   0,  16
2780 };
2781
2782 float nomodelcolor4f[6*4] =
2783 {
2784         0.0f, 0.0f, 0.5f, 1.0f,
2785         0.0f, 0.0f, 0.5f, 1.0f,
2786         0.0f, 0.5f, 0.0f, 1.0f,
2787         0.0f, 0.5f, 0.0f, 1.0f,
2788         0.5f, 0.0f, 0.0f, 1.0f,
2789         0.5f, 0.0f, 0.0f, 1.0f
2790 };
2791
2792 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2793 {
2794         int i;
2795         float f1, f2, *c;
2796         float color4f[6*4];
2797         // this is only called once per entity so numsurfaces is always 1, and
2798         // surfacelist is always {0}, so this code does not handle batches
2799         R_Mesh_Matrix(&ent->matrix);
2800
2801         if (ent->flags & EF_ADDITIVE)
2802         {
2803                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2804                 GL_DepthMask(false);
2805         }
2806         else if (ent->alpha < 1)
2807         {
2808                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2809                 GL_DepthMask(false);
2810         }
2811         else
2812         {
2813                 GL_BlendFunc(GL_ONE, GL_ZERO);
2814                 GL_DepthMask(true);
2815         }
2816         GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
2817         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2818         GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
2819         R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
2820         if (r_refdef.fogenabled)
2821         {
2822                 vec3_t org;
2823                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2824                 R_Mesh_ColorPointer(color4f, 0, 0);
2825                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2826                 f1 = FogPoint_World(org);
2827                 f2 = 1 - f1;
2828                 for (i = 0, c = color4f;i < 6;i++, c += 4)
2829                 {
2830                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2831                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2832                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2833                         c[3] *= ent->alpha;
2834                 }
2835         }
2836         else if (ent->alpha != 1)
2837         {
2838                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2839                 R_Mesh_ColorPointer(color4f, 0, 0);
2840                 for (i = 0, c = color4f;i < 6;i++, c += 4)
2841                         c[3] *= ent->alpha;
2842         }
2843         else
2844                 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
2845         R_Mesh_ResetTextureState();
2846         R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
2847 }
2848
2849 void R_DrawNoModel(entity_render_t *ent)
2850 {
2851         vec3_t org;
2852         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2853         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2854                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2855         //else
2856         //      R_DrawNoModelCallback(ent, 0);
2857 }
2858
2859 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2860 {
2861         vec3_t right1, right2, diff, normal;
2862
2863         VectorSubtract (org2, org1, normal);
2864
2865         // calculate 'right' vector for start
2866         VectorSubtract (r_view.origin, org1, diff);
2867         CrossProduct (normal, diff, right1);
2868         VectorNormalize (right1);
2869
2870         // calculate 'right' vector for end
2871         VectorSubtract (r_view.origin, org2, diff);
2872         CrossProduct (normal, diff, right2);
2873         VectorNormalize (right2);
2874
2875         vert[ 0] = org1[0] + width * right1[0];
2876         vert[ 1] = org1[1] + width * right1[1];
2877         vert[ 2] = org1[2] + width * right1[2];
2878         vert[ 3] = org1[0] - width * right1[0];
2879         vert[ 4] = org1[1] - width * right1[1];
2880         vert[ 5] = org1[2] - width * right1[2];
2881         vert[ 6] = org2[0] - width * right2[0];
2882         vert[ 7] = org2[1] - width * right2[1];
2883         vert[ 8] = org2[2] - width * right2[2];
2884         vert[ 9] = org2[0] + width * right2[0];
2885         vert[10] = org2[1] + width * right2[1];
2886         vert[11] = org2[2] + width * right2[2];
2887 }
2888
2889 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2890
2891 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)
2892 {
2893         float fog = 1.0f;
2894         float vertex3f[12];
2895
2896         if (r_refdef.fogenabled)
2897                 fog = FogPoint_World(origin);
2898
2899         R_Mesh_Matrix(&identitymatrix);
2900         GL_BlendFunc(blendfunc1, blendfunc2);
2901         GL_DepthMask(false);
2902         GL_DepthRange(0, depthshort ? 0.0625 : 1);
2903         GL_DepthTest(!depthdisable);
2904
2905         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2906         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2907         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2908         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2909         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2910         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2911         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2912         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2913         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2914         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2915         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2916         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2917
2918         R_Mesh_VertexPointer(vertex3f, 0, 0);
2919         R_Mesh_ColorPointer(NULL, 0, 0);
2920         R_Mesh_ResetTextureState();
2921         R_Mesh_TexBind(0, R_GetTexture(texture));
2922         R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
2923         // FIXME: fixed function path can't properly handle r_view.colorscale > 1
2924         GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
2925         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2926
2927         if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2928         {
2929                 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2930                 GL_BlendFunc(blendfunc1, GL_ONE);
2931                 fog = 1 - fog;
2932                 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);
2933                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2934         }
2935 }
2936
2937 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
2938 {
2939         int i;
2940         float *vertex3f;
2941         float v[3];
2942         VectorSet(v, x, y, z);
2943         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2944                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2945                         break;
2946         if (i == mesh->numvertices)
2947         {
2948                 if (mesh->numvertices < mesh->maxvertices)
2949                 {
2950                         VectorCopy(v, vertex3f);
2951                         mesh->numvertices++;
2952                 }
2953                 return mesh->numvertices;
2954         }
2955         else
2956                 return i;
2957 }
2958
2959 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2960 {
2961         int i;
2962         int *e, element[3];
2963         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2964         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2965         e = mesh->element3i + mesh->numtriangles * 3;
2966         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2967         {
2968                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
2969                 if (mesh->numtriangles < mesh->maxtriangles)
2970                 {
2971                         *e++ = element[0];
2972                         *e++ = element[1];
2973                         *e++ = element[2];
2974                         mesh->numtriangles++;
2975                 }
2976                 element[1] = element[2];
2977         }
2978 }
2979
2980 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
2981 {
2982         int i;
2983         int *e, element[3];
2984         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2985         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2986         e = mesh->element3i + mesh->numtriangles * 3;
2987         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
2988         {
2989                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
2990                 if (mesh->numtriangles < mesh->maxtriangles)
2991                 {
2992                         *e++ = element[0];
2993                         *e++ = element[1];
2994                         *e++ = element[2];
2995                         mesh->numtriangles++;
2996                 }
2997                 element[1] = element[2];
2998         }
2999 }
3000
3001 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3002 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3003 {
3004         int planenum, planenum2;
3005         int w;
3006         int tempnumpoints;
3007         mplane_t *plane, *plane2;
3008         double maxdist;
3009         double temppoints[2][256*3];
3010         // figure out how large a bounding box we need to properly compute this brush
3011         maxdist = 0;
3012         for (w = 0;w < numplanes;w++)
3013                 maxdist = max(maxdist, planes[w].dist);
3014         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3015         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3016         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3017         {
3018                 w = 0;
3019                 tempnumpoints = 4;
3020                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3021                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3022                 {
3023                         if (planenum2 == planenum)
3024                                 continue;
3025                         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);
3026                         w = !w;
3027                 }
3028                 if (tempnumpoints < 3)
3029                         continue;
3030                 // generate elements forming a triangle fan for this polygon
3031                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3032         }
3033 }
3034
3035 static void R_DrawCollisionBrush(const colbrushf_t *brush)
3036 {
3037         int i;
3038         R_Mesh_VertexPointer(brush->points->v, 0, 0);
3039         i = (int)(((size_t)brush) / sizeof(colbrushf_t));
3040         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);
3041         GL_LockArrays(0, brush->numpoints);
3042         R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements, 0, 0);
3043         GL_LockArrays(0, 0);
3044 }
3045
3046 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
3047 {
3048         int i;
3049         if (!surface->num_collisiontriangles)
3050                 return;
3051         R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
3052         i = (int)(((size_t)surface) / sizeof(msurface_t));
3053         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);
3054         GL_LockArrays(0, surface->num_collisionvertices);
3055         R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
3056         GL_LockArrays(0, 0);
3057 }
3058
3059 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)
3060 {
3061         texturelayer_t *layer;
3062         layer = t->currentlayers + t->currentnumlayers++;
3063         layer->type = type;
3064         layer->depthmask = depthmask;
3065         layer->blendfunc1 = blendfunc1;
3066         layer->blendfunc2 = blendfunc2;
3067         layer->texture = texture;
3068         layer->texmatrix = *matrix;
3069         layer->color[0] = r * r_view.colorscale;
3070         layer->color[1] = g * r_view.colorscale;
3071         layer->color[2] = b * r_view.colorscale;
3072         layer->color[3] = a;
3073 }
3074
3075 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3076 {
3077         model_t *model = ent->model;
3078
3079         // switch to an alternate material if this is a q1bsp animated material
3080         {
3081                 texture_t *texture = t;
3082                 int s = ent->skinnum;
3083                 if ((unsigned int)s >= (unsigned int)model->numskins)
3084                         s = 0;
3085                 if (model->skinscenes)
3086                 {
3087                         if (model->skinscenes[s].framecount > 1)
3088                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3089                         else
3090                                 s = model->skinscenes[s].firstframe;
3091                 }
3092                 if (s > 0)
3093                         t = t + s * model->num_surfaces;
3094                 if (t->animated)
3095                 {
3096                         // use an alternate animation if the entity's frame is not 0,
3097                         // and only if the texture has an alternate animation
3098                         if (ent->frame != 0 && t->anim_total[1])
3099                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3100                         else
3101                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3102                 }
3103                 texture->currentframe = t;
3104         }
3105
3106         // pick a new currentskinframe if the material is animated
3107         if (t->numskinframes >= 2)
3108                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3109         if (t->backgroundnumskinframes >= 2)
3110                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3111
3112         t->currentmaterialflags = t->basematerialflags;
3113         t->currentalpha = ent->alpha;
3114         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3115                 t->currentalpha *= r_wateralpha.value;
3116         if (!(ent->flags & RENDER_LIGHT))
3117                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3118         if (ent->effects & EF_ADDITIVE)
3119                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3120         else if (t->currentalpha < 1)
3121                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3122         if (ent->effects & EF_DOUBLESIDED)
3123                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3124         if (ent->effects & EF_NODEPTHTEST)
3125                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3126         if (ent->flags & RENDER_VIEWMODEL)
3127                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3128         if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3129                 t->currenttexmatrix = r_waterscrollmatrix;
3130         else
3131                 t->currenttexmatrix = identitymatrix;
3132         if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3133                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3134
3135         t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
3136         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3137         t->glosstexture = r_texture_white;
3138         t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
3139         t->backgroundglosstexture = r_texture_white;
3140         t->specularpower = r_shadow_glossexponent.value;
3141         // TODO: store reference values for these in the texture?
3142         t->specularscale = 0;
3143         if (r_shadow_gloss.integer > 0)
3144         {
3145                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
3146                 {
3147                         if (r_shadow_glossintensity.value > 0)
3148                         {
3149                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_black;
3150                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_black;
3151                                 t->specularscale = r_shadow_glossintensity.value;
3152                         }
3153                 }
3154                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
3155                         t->specularscale = r_shadow_gloss2intensity.value;
3156         }
3157
3158         t->currentnumlayers = 0;
3159         if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
3160         {
3161                 if (gl_lightmaps.integer)
3162                         R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
3163                 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
3164                 {
3165                         int blendfunc1, blendfunc2, depthmask;
3166                         if (t->currentmaterialflags & MATERIALFLAG_ADD)
3167                         {
3168                                 blendfunc1 = GL_SRC_ALPHA;
3169                                 blendfunc2 = GL_ONE;
3170                         }
3171                         else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
3172                         {
3173                                 blendfunc1 = GL_SRC_ALPHA;
3174                                 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
3175                         }
3176                         else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
3177                         {
3178                                 blendfunc1 = t->customblendfunc[0];
3179                                 blendfunc2 = t->customblendfunc[1];
3180                         }
3181                         else
3182                         {
3183                                 blendfunc1 = GL_ONE;
3184                                 blendfunc2 = GL_ZERO;
3185                         }
3186                         depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
3187                         if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
3188                         {
3189                                 rtexture_t *currentbasetexture;
3190                                 int layerflags = 0;
3191                                 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
3192                                         layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
3193                                 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3194                                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3195                                 {
3196                                         // fullbright is not affected by r_refdef.lightmapintensity
3197                                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
3198                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3199                                                 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);
3200                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3201                                                 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);
3202                                 }
3203                                 else
3204                                 {
3205                                         float colorscale;
3206                                         colorscale = 2;
3207                                         // q3bsp has no lightmap updates, so the lightstylevalue that
3208                                         // would normally be baked into the lightmap must be
3209                                         // applied to the color
3210                                         if (ent->model->type == mod_brushq3)
3211                                                 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
3212                                         colorscale *= r_refdef.lightmapintensity;
3213                                         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);
3214                                         if (r_ambient.value >= (1.0f/64.0f))
3215                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
3216