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