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