oops, missing \n
[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("data/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         r_glsl_permutation = NULL;
858         // TODO: implement geometry-shader based shadow volumes someday
859         if (rsurface.rtlight)
860         {
861                 // light source
862                 shaderfilename = "glsl/default.glsl";
863                 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
864                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
865                         permutation |= SHADERPERMUTATION_CUBEFILTER;
866                 if (diffusescale > 0)
867                         permutation |= SHADERPERMUTATION_DIFFUSE;
868                 if (specularscale > 0)
869                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
870                 if (r_refdef.fogenabled)
871                         permutation |= SHADERPERMUTATION_FOG;
872                 if (rsurface.texture->colormapping)
873                         permutation |= SHADERPERMUTATION_COLORMAPPING;
874                 if (r_glsl_offsetmapping.integer)
875                 {
876                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
877                         if (r_glsl_offsetmapping_reliefmapping.integer)
878                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
879                 }
880                 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
881                         permutation |= SHADERPERMUTATION_CONTRASTBOOST;
882         }
883         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
884         {
885                 // bright unshaded geometry
886                 shaderfilename = "glsl/default.glsl";
887                 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
888                 if (rsurface.texture->currentskinframe->glow)
889                         permutation |= SHADERPERMUTATION_GLOW;
890                 if (r_refdef.fogenabled)
891                         permutation |= SHADERPERMUTATION_FOG;
892                 if (rsurface.texture->colormapping)
893                         permutation |= SHADERPERMUTATION_COLORMAPPING;
894                 if (r_glsl_offsetmapping.integer)
895                 {
896                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
897                         if (r_glsl_offsetmapping_reliefmapping.integer)
898                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
899                 }
900                 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
901                         permutation |= SHADERPERMUTATION_CONTRASTBOOST;
902         }
903         else if (modellighting)
904         {
905                 // directional model lighting
906                 shaderfilename = "glsl/default.glsl";
907                 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
908                 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
909                 if (rsurface.texture->currentskinframe->glow)
910                         permutation |= SHADERPERMUTATION_GLOW;
911                 if (specularscale > 0)
912                         permutation |= SHADERPERMUTATION_SPECULAR;
913                 if (r_refdef.fogenabled)
914                         permutation |= SHADERPERMUTATION_FOG;
915                 if (rsurface.texture->colormapping)
916                         permutation |= SHADERPERMUTATION_COLORMAPPING;
917                 if (r_glsl_offsetmapping.integer)
918                 {
919                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
920                         if (r_glsl_offsetmapping_reliefmapping.integer)
921                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
922                 }
923                 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
924                         permutation |= SHADERPERMUTATION_CONTRASTBOOST;
925         }
926         else
927         {
928                 // lightmapped wall
929                 shaderfilename = "glsl/default.glsl";
930                 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
931                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
932                 {
933                         // deluxemapping (light direction texture)
934                         if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
935                                 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
936                         else
937                                 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
938                         if (specularscale > 0)
939                                 permutation |= SHADERPERMUTATION_SPECULAR;
940                 }
941                 else if (r_glsl_deluxemapping.integer >= 2)
942                 {
943                         // fake deluxemapping (uniform light direction in tangentspace)
944                         permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
945                         if (specularscale > 0)
946                                 permutation |= SHADERPERMUTATION_SPECULAR;
947                 }
948                 else
949                 {
950                         // ordinary lightmapping
951                         permutation |= 0;
952                 }
953                 if (rsurface.texture->currentskinframe->glow)
954                         permutation |= SHADERPERMUTATION_GLOW;
955                 if (r_refdef.fogenabled)
956                         permutation |= SHADERPERMUTATION_FOG;
957                 if (rsurface.texture->colormapping)
958                         permutation |= SHADERPERMUTATION_COLORMAPPING;
959                 if (r_glsl_offsetmapping.integer)
960                 {
961                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
962                         if (r_glsl_offsetmapping_reliefmapping.integer)
963                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
964                 }
965                 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
966                         permutation |= SHADERPERMUTATION_CONTRASTBOOST;
967         }
968         if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
969         {
970                 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
971                         R_GLSL_CompilePermutation(shaderfilename, permutation);
972                 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
973                 {
974                         // remove features until we find a valid permutation
975                         unsigned int i;
976                         for (i = (SHADERPERMUTATION_MAX >> 1);;i>>=1)
977                         {
978                                 if (!i)
979                                         return 0; // no bit left to clear
980                                 // reduce i more quickly whenever it would not remove any bits
981                                 if (!(permutation & i))
982                                         continue;
983                                 permutation &= ~i;
984                                 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
985                                         R_GLSL_CompilePermutation(shaderfilename, permutation);
986                                 if (r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
987                                         break;
988                         }
989                 }
990         }
991         r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
992         CHECKGLERROR
993         qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
994         R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
995         if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
996         {
997                 if (r_glsl_permutation->loc_Texture_Cube >= 0 && rsurface.rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
998                 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
999                 if (permutation & SHADERPERMUTATION_DIFFUSE)
1000                 {
1001                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1002                         if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1003                         if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1004                         if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1005                 }
1006                 else
1007                 {
1008                         // ambient only is simpler
1009                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1010                         if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1011                         if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1012                         if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1013                 }
1014         }
1015         else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
1016         {
1017                 if (r_glsl_permutation->loc_AmbientColor >= 0)
1018                         qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface.modellight_ambient[0] * ambientscale, rsurface.modellight_ambient[1] * ambientscale, rsurface.modellight_ambient[2] * ambientscale);
1019                 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1020                         qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface.modellight_diffuse[0] * diffusescale, rsurface.modellight_diffuse[1] * diffusescale, rsurface.modellight_diffuse[2] * diffusescale);
1021                 if (r_glsl_permutation->loc_SpecularColor >= 0)
1022                         qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale, rsurface.modellight_diffuse[1] * specularscale, rsurface.modellight_diffuse[2] * specularscale);
1023                 if (r_glsl_permutation->loc_LightDir >= 0)
1024                         qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1025         }
1026         else
1027         {
1028                 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1029                 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1030                 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1031         }
1032         if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
1033         if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
1034         if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
1035         //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
1036         if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(10, R_GetTexture(r_shadow_attenuationgradienttexture));
1037         if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1038         if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
1039         if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
1040         //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
1041         //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
1042         if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
1043         if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1044         if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1045         {
1046                 // The formula used is actually:
1047                 //   color.rgb *= SceneBrightness;
1048                 //   color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1049                 // I simplify that to
1050                 //   color.rgb *= [[SceneBrightness * ContrastBoost]];
1051                 //   color.rgb /= [[(ContrastBoost - 1) / ContrastBoost]] * color.rgb + 1;
1052                 // and Black:
1053                 //   color.rgb = [[SceneBrightness * ContrastBoost]] / ([[(ContrastBoost - 1) * SceneBrightness]] + 1 / color.rgb);
1054                 // and do [[calculations]] here in the engine
1055                 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, (r_glsl_contrastboost.value - 1) * r_view.colorscale);
1056                 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
1057         }
1058         else
1059                 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1060         if (r_glsl_permutation->loc_FogColor >= 0)
1061         {
1062                 // additive passes are only darkened by fog, not tinted
1063                 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1064                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1065                 else
1066                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1067         }
1068         if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1069         if (r_glsl_permutation->loc_Color_Pants >= 0)
1070         {
1071                 if (rsurface.texture->currentskinframe->pants)
1072                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1073                 else
1074                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1075         }
1076         if (r_glsl_permutation->loc_Color_Shirt >= 0)
1077         {
1078                 if (rsurface.texture->currentskinframe->shirt)
1079                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1080                 else
1081                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1082         }
1083         if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1084         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1085         if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1086         CHECKGLERROR
1087         return permutation;
1088 }
1089
1090 void R_SwitchSurfaceShader(int permutation)
1091 {
1092         if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK))
1093         {
1094                 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1095                 CHECKGLERROR
1096                 qglUseProgramObjectARB(r_glsl_permutation->program);
1097                 CHECKGLERROR
1098         }
1099 }
1100
1101 #define SKINFRAME_HASH 1024
1102
1103 struct
1104 {
1105         int loadsequence; // incremented each level change
1106         memexpandablearray_t array;
1107         skinframe_t *hash[SKINFRAME_HASH];
1108 }
1109 r_skinframe;
1110
1111 void R_SkinFrame_PrepareForPurge(void)
1112 {
1113         r_skinframe.loadsequence++;
1114         // wrap it without hitting zero
1115         if (r_skinframe.loadsequence >= 200)
1116                 r_skinframe.loadsequence = 1;
1117 }
1118
1119 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1120 {
1121         if (!skinframe)
1122                 return;
1123         // mark the skinframe as used for the purging code
1124         skinframe->loadsequence = r_skinframe.loadsequence;
1125 }
1126
1127 void R_SkinFrame_Purge(void)
1128 {
1129         int i;
1130         skinframe_t *s;
1131         for (i = 0;i < SKINFRAME_HASH;i++)
1132         {
1133                 for (s = r_skinframe.hash[i];s;s = s->next)
1134                 {
1135                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1136                         {
1137                                 if (s->base == r_texture_notexture)     s->base   = NULL;
1138                                 if (s->nmap == r_texture_blanknormalmap)s->nmap   = NULL;
1139                                 if (s->merged == s->base)               s->merged = NULL;
1140                                 if (s->stain ) R_FreeTexture(s->stain );s->stain  = NULL;
1141                                 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1142                                 if (s->base  ) R_FreeTexture(s->base  );s->base   = NULL;
1143                                 if (s->pants ) R_FreeTexture(s->pants );s->pants  = NULL;
1144                                 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt  = NULL;
1145                                 if (s->nmap  ) R_FreeTexture(s->nmap  );s->nmap   = NULL;
1146                                 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss  = NULL;
1147                                 if (s->glow  ) R_FreeTexture(s->glow  );s->glow   = NULL;
1148                                 if (s->fog   ) R_FreeTexture(s->fog   );s->fog    = NULL;
1149                                 s->loadsequence = 0;
1150                         }
1151                 }
1152         }
1153 }
1154
1155 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1156 {
1157         skinframe_t *item;
1158         int hashindex;
1159         char basename[MAX_QPATH];
1160
1161         Image_StripImageExtension(name, basename, sizeof(basename));
1162
1163         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1164         for (item = r_skinframe.hash[hashindex];item;item = item->next)
1165                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1166                         break;
1167         if (!item)
1168         {
1169                 if (!add)
1170                         return NULL;
1171                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1172                 memset(item, 0, sizeof(*item));
1173                 strlcpy(item->basename, basename, sizeof(item->basename));
1174                 item->textureflags = textureflags;
1175                 item->comparewidth = comparewidth;
1176                 item->compareheight = compareheight;
1177                 item->comparecrc = comparecrc;
1178                 item->next = r_skinframe.hash[hashindex];
1179                 r_skinframe.hash[hashindex] = item;
1180         }
1181         R_SkinFrame_MarkUsed(item);
1182         return item;
1183 }
1184
1185 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1186 {
1187         // FIXME: it should be possible to disable loading various layers using
1188         // cvars, to prevent wasted loading time and memory usage if the user does
1189         // not want them
1190         qboolean loadnormalmap = true;
1191         qboolean loadgloss = true;
1192         qboolean loadpantsandshirt = true;
1193         qboolean loadglow = true;
1194         int j;
1195         unsigned char *pixels;
1196         unsigned char *bumppixels;
1197         unsigned char *basepixels = NULL;
1198         int basepixels_width;
1199         int basepixels_height;
1200         skinframe_t *skinframe;
1201
1202         if (cls.state == ca_dedicated)
1203                 return NULL;
1204
1205         // return an existing skinframe if already loaded
1206         // if loading of the first image fails, don't make a new skinframe as it
1207         // would cause all future lookups of this to be missing
1208         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1209         if (skinframe && skinframe->base)
1210                 return skinframe;
1211
1212         basepixels = loadimagepixels(name, complain, 0, 0);
1213         if (basepixels == NULL)
1214                 return NULL;
1215
1216         // we've got some pixels to store, so really allocate this new texture now
1217         if (!skinframe)
1218                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1219         skinframe->stain = NULL;
1220         skinframe->merged = NULL;
1221         skinframe->base = r_texture_notexture;
1222         skinframe->pants = NULL;
1223         skinframe->shirt = NULL;
1224         skinframe->nmap = r_texture_blanknormalmap;
1225         skinframe->gloss = NULL;
1226         skinframe->glow = NULL;
1227         skinframe->fog = NULL;
1228
1229         basepixels_width = image_width;
1230         basepixels_height = image_height;
1231         skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1232
1233         if (textureflags & TEXF_ALPHA)
1234         {
1235                 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1236                         if (basepixels[j] < 255)
1237                                 break;
1238                 if (j < basepixels_width * basepixels_height * 4)
1239                 {
1240                         // has transparent pixels
1241                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1242                         for (j = 0;j < image_width * image_height * 4;j += 4)
1243                         {
1244                                 pixels[j+0] = 255;
1245                                 pixels[j+1] = 255;
1246                                 pixels[j+2] = 255;
1247                                 pixels[j+3] = basepixels[j+3];
1248                         }
1249                         skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1250                         Mem_Free(pixels);
1251                 }
1252         }
1253
1254         // _norm is the name used by tenebrae and has been adopted as standard
1255         if (loadnormalmap)
1256         {
1257                 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0)) != NULL)
1258                 {
1259                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1260                         Mem_Free(pixels);
1261                         pixels = NULL;
1262                 }
1263                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0)) != NULL)
1264                 {
1265                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1266                         Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1267                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1268                         Mem_Free(pixels);
1269                         Mem_Free(bumppixels);
1270                 }
1271                 else if (r_shadow_bumpscale_basetexture.value > 0)
1272                 {
1273                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1274                         Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1275                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1276                         Mem_Free(pixels);
1277                 }
1278         }
1279         // _luma is supported for tenebrae compatibility
1280         // (I think it's a very stupid name, but oh well)
1281         // _glow is the preferred name
1282         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;}
1283         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;}
1284         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;}
1285         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;}
1286
1287         if (basepixels)
1288                 Mem_Free(basepixels);
1289
1290         return skinframe;
1291 }
1292
1293 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)
1294 {
1295         int i;
1296         if (!force)
1297         {
1298                 for (i = 0;i < width*height;i++)
1299                         if (((unsigned char *)&palette[in[i]])[3] > 0)
1300                                 break;
1301                 if (i == width*height)
1302                         return NULL;
1303         }
1304         return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1305 }
1306
1307 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)
1308 {
1309         int i;
1310         unsigned char *temp1, *temp2;
1311         skinframe_t *skinframe;
1312
1313         if (cls.state == ca_dedicated)
1314                 return NULL;
1315
1316         // if already loaded just return it, otherwise make a new skinframe
1317         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1318         if (skinframe && skinframe->base)
1319                 return skinframe;
1320
1321         skinframe->stain = NULL;
1322         skinframe->merged = NULL;
1323         skinframe->base = r_texture_notexture;
1324         skinframe->pants = NULL;
1325         skinframe->shirt = NULL;
1326         skinframe->nmap = r_texture_blanknormalmap;
1327         skinframe->gloss = NULL;
1328         skinframe->glow = NULL;
1329         skinframe->fog = NULL;
1330
1331         // if no data was provided, then clearly the caller wanted to get a blank skinframe
1332         if (!skindata)
1333                 return NULL;
1334
1335         if (bitsperpixel == 32)
1336         {
1337                 if (r_shadow_bumpscale_basetexture.value > 0)
1338                 {
1339                         temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1340                         temp2 = temp1 + width * height * 4;
1341                         Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1342                         skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL);
1343                         Mem_Free(temp1);
1344                 }
1345                 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, textureflags, NULL);
1346                 if (textureflags & TEXF_ALPHA)
1347                 {
1348                         for (i = 3;i < width * height * 4;i += 4)
1349                                 if (skindata[i] < 255)
1350                                         break;
1351                         if (i < width * height * 4)
1352                         {
1353                                 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1354                                 memcpy(fogpixels, skindata, width * height * 4);
1355                                 for (i = 0;i < width * height * 4;i += 4)
1356                                         fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1357                                 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, textureflags, NULL);
1358                                 Mem_Free(fogpixels);
1359                         }
1360                 }
1361         }
1362         else if (bitsperpixel == 8)
1363         {
1364                 if (r_shadow_bumpscale_basetexture.value > 0)
1365                 {
1366                         temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1367                         temp2 = temp1 + width * height * 4;
1368                         if (bitsperpixel == 32)
1369                                 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1370                         else
1371                         {
1372                                 // use either a custom palette or the quake palette
1373                                 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1374                                 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1375                         }
1376                         skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL);
1377                         Mem_Free(temp1);
1378                 }
1379                 // use either a custom palette, or the quake palette
1380                 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
1381                 if (!palette && loadglowtexture)
1382                         skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, textureflags, false); // glow
1383                 if (!palette && loadpantsandshirt)
1384                 {
1385                         skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, textureflags, false); // pants
1386                         skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, textureflags, false); // shirt
1387                 }
1388                 if (skinframe->pants || skinframe->shirt)
1389                         skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, textureflags, false); // no special colors
1390                 if (textureflags & TEXF_ALPHA)
1391                 {
1392                         // if not using a custom alphapalette, use the quake one
1393                         if (!alphapalette)
1394                                 alphapalette = palette_alpha;
1395                         for (i = 0;i < width * height;i++)
1396                                 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1397                                         break;
1398                         if (i < width * height)
1399                                 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, textureflags, true); // fog mask
1400                 }
1401         }
1402
1403         return skinframe;
1404 }
1405
1406 skinframe_t *R_SkinFrame_LoadMissing(void)
1407 {
1408         skinframe_t *skinframe;
1409
1410         if (cls.state == ca_dedicated)
1411                 return NULL;
1412
1413         skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1414         skinframe->stain = NULL;
1415         skinframe->merged = NULL;
1416         skinframe->base = r_texture_notexture;
1417         skinframe->pants = NULL;
1418         skinframe->shirt = NULL;
1419         skinframe->nmap = r_texture_blanknormalmap;
1420         skinframe->gloss = NULL;
1421         skinframe->glow = NULL;
1422         skinframe->fog = NULL;
1423
1424         return skinframe;
1425 }
1426
1427 void gl_main_start(void)
1428 {
1429         int x;
1430         double r, alpha;
1431
1432         r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1433         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1434         {
1435                 alpha = 1 - exp(r / ((double)x*(double)x));
1436                 if (x == FOGMASKTABLEWIDTH - 1)
1437                         alpha = 0;
1438                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1439         }
1440
1441         memset(r_qwskincache, 0, sizeof(r_qwskincache));
1442         memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1443
1444         // set up r_skinframe loading system for textures
1445         memset(&r_skinframe, 0, sizeof(r_skinframe));
1446         r_skinframe.loadsequence = 1;
1447         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1448
1449         r_main_texturepool = R_AllocTexturePool();
1450         R_BuildBlankTextures();
1451         R_BuildNoTexture();
1452         if (gl_texturecubemap)
1453         {
1454                 R_BuildWhiteCube();
1455                 R_BuildNormalizationCube();
1456         }
1457         R_BuildFogTexture();
1458         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1459         memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1460         memset(&r_svbsp, 0, sizeof (r_svbsp));
1461 }
1462
1463 void gl_main_shutdown(void)
1464 {
1465         memset(r_qwskincache, 0, sizeof(r_qwskincache));
1466         memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1467
1468         // clear out the r_skinframe state
1469         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1470         memset(&r_skinframe, 0, sizeof(r_skinframe));
1471
1472         if (r_svbsp.nodes)
1473                 Mem_Free(r_svbsp.nodes);
1474         memset(&r_svbsp, 0, sizeof (r_svbsp));
1475         R_FreeTexturePool(&r_main_texturepool);
1476         r_texture_blanknormalmap = NULL;
1477         r_texture_white = NULL;
1478         r_texture_black = NULL;
1479         r_texture_whitecube = NULL;
1480         r_texture_normalizationcube = NULL;
1481         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1482         R_GLSL_Restart_f();
1483 }
1484
1485 extern void CL_ParseEntityLump(char *entitystring);
1486 void gl_main_newmap(void)
1487 {
1488         // FIXME: move this code to client
1489         int l;
1490         char *entities, entname[MAX_QPATH];
1491         if (cl.worldmodel)
1492         {
1493                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1494                 l = (int)strlen(entname) - 4;
1495                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1496                 {
1497                         memcpy(entname + l, ".ent", 5);
1498                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1499                         {
1500                                 CL_ParseEntityLump(entities);
1501                                 Mem_Free(entities);
1502                                 return;
1503                         }
1504                 }
1505                 if (cl.worldmodel->brush.entities)
1506                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
1507         }
1508 }
1509
1510 void GL_Main_Init(void)
1511 {
1512         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1513
1514         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1515         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1516         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1517         if (gamemode == GAME_NEHAHRA)
1518         {
1519                 Cvar_RegisterVariable (&gl_fogenable);
1520                 Cvar_RegisterVariable (&gl_fogdensity);
1521                 Cvar_RegisterVariable (&gl_fogred);
1522                 Cvar_RegisterVariable (&gl_foggreen);
1523                 Cvar_RegisterVariable (&gl_fogblue);
1524                 Cvar_RegisterVariable (&gl_fogstart);
1525                 Cvar_RegisterVariable (&gl_fogend);
1526         }
1527         Cvar_RegisterVariable(&r_depthfirst);
1528         Cvar_RegisterVariable(&r_nearclip);
1529         Cvar_RegisterVariable(&r_showbboxes);
1530         Cvar_RegisterVariable(&r_showsurfaces);
1531         Cvar_RegisterVariable(&r_showtris);
1532         Cvar_RegisterVariable(&r_shownormals);
1533         Cvar_RegisterVariable(&r_showlighting);
1534         Cvar_RegisterVariable(&r_showshadowvolumes);
1535         Cvar_RegisterVariable(&r_showcollisionbrushes);
1536         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1537         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1538         Cvar_RegisterVariable(&r_showdisabledepthtest);
1539         Cvar_RegisterVariable(&r_drawportals);
1540         Cvar_RegisterVariable(&r_drawentities);
1541         Cvar_RegisterVariable(&r_cullentities_trace);
1542         Cvar_RegisterVariable(&r_cullentities_trace_samples);
1543         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1544         Cvar_RegisterVariable(&r_cullentities_trace_delay);
1545         Cvar_RegisterVariable(&r_drawviewmodel);
1546         Cvar_RegisterVariable(&r_speeds);
1547         Cvar_RegisterVariable(&r_fullbrights);
1548         Cvar_RegisterVariable(&r_wateralpha);
1549         Cvar_RegisterVariable(&r_dynamic);
1550         Cvar_RegisterVariable(&r_fullbright);
1551         Cvar_RegisterVariable(&r_shadows);
1552         Cvar_RegisterVariable(&r_shadows_throwdistance);
1553         Cvar_RegisterVariable(&r_q1bsp_skymasking);
1554         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
1555         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
1556         Cvar_RegisterVariable(&r_textureunits);
1557         Cvar_RegisterVariable(&r_glsl);
1558         Cvar_RegisterVariable(&r_glsl_offsetmapping);
1559         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1560         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1561         Cvar_RegisterVariable(&r_glsl_deluxemapping);
1562         Cvar_RegisterVariable(&r_lerpsprites);
1563         Cvar_RegisterVariable(&r_lerpmodels);
1564         Cvar_RegisterVariable(&r_waterscroll);
1565         Cvar_RegisterVariable(&r_bloom);
1566         Cvar_RegisterVariable(&r_bloom_colorscale);
1567         Cvar_RegisterVariable(&r_bloom_brighten);
1568         Cvar_RegisterVariable(&r_bloom_blur);
1569         Cvar_RegisterVariable(&r_bloom_resolution);
1570         Cvar_RegisterVariable(&r_bloom_colorexponent);
1571         Cvar_RegisterVariable(&r_bloom_colorsubtract);
1572         Cvar_RegisterVariable(&r_hdr);
1573         Cvar_RegisterVariable(&r_hdr_scenebrightness);
1574         Cvar_RegisterVariable(&r_glsl_contrastboost);
1575         Cvar_RegisterVariable(&r_hdr_glowintensity);
1576         Cvar_RegisterVariable(&r_hdr_range);
1577         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1578         Cvar_RegisterVariable(&developer_texturelogging);
1579         Cvar_RegisterVariable(&gl_lightmaps);
1580         Cvar_RegisterVariable(&r_test);
1581         Cvar_RegisterVariable(&r_batchmode);
1582         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1583                 Cvar_SetValue("r_fullbrights", 0);
1584         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1585 }
1586
1587 extern void R_Textures_Init(void);
1588 extern void GL_Draw_Init(void);
1589 extern void GL_Main_Init(void);
1590 extern void R_Shadow_Init(void);
1591 extern void R_Sky_Init(void);
1592 extern void GL_Surf_Init(void);
1593 extern void R_Light_Init(void);
1594 extern void R_Particles_Init(void);
1595 extern void R_Explosion_Init(void);
1596 extern void gl_backend_init(void);
1597 extern void Sbar_Init(void);
1598 extern void R_LightningBeams_Init(void);
1599 extern void Mod_RenderInit(void);
1600
1601 void Render_Init(void)
1602 {
1603         gl_backend_init();
1604         R_Textures_Init();
1605         GL_Main_Init();
1606         GL_Draw_Init();
1607         R_Shadow_Init();
1608         R_Sky_Init();
1609         GL_Surf_Init();
1610         Sbar_Init();
1611         R_Light_Init();
1612         R_Particles_Init();
1613         R_Explosion_Init();
1614         R_LightningBeams_Init();
1615         Mod_RenderInit();
1616 }
1617
1618 /*
1619 ===============
1620 GL_Init
1621 ===============
1622 */
1623 extern char *ENGINE_EXTENSIONS;
1624 void GL_Init (void)
1625 {
1626         VID_CheckExtensions();
1627
1628         // LordHavoc: report supported extensions
1629         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1630
1631         // clear to black (loading plaque will be seen over this)
1632         CHECKGLERROR
1633         qglClearColor(0,0,0,1);CHECKGLERROR
1634         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1635 }
1636
1637 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1638 {
1639         int i;
1640         mplane_t *p;
1641         for (i = 0;i < 4;i++)
1642         {
1643                 p = r_view.frustum + i;
1644                 switch(p->signbits)
1645                 {
1646                 default:
1647                 case 0:
1648                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1649                                 return true;
1650                         break;
1651                 case 1:
1652                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1653                                 return true;
1654                         break;
1655                 case 2:
1656                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1657                                 return true;
1658                         break;
1659                 case 3:
1660                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1661                                 return true;
1662                         break;
1663                 case 4:
1664                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1665                                 return true;
1666                         break;
1667                 case 5:
1668                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1669                                 return true;
1670                         break;
1671                 case 6:
1672                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1673                                 return true;
1674                         break;
1675                 case 7:
1676                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1677                                 return true;
1678                         break;
1679                 }
1680         }
1681         return false;
1682 }
1683
1684 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1685 {
1686         int i;
1687         const mplane_t *p;
1688         for (i = 0;i < numplanes;i++)
1689         {
1690                 p = planes + i;
1691                 switch(p->signbits)
1692                 {
1693                 default:
1694                 case 0:
1695                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1696                                 return true;
1697                         break;
1698                 case 1:
1699                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1700                                 return true;
1701                         break;
1702                 case 2:
1703                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1704                                 return true;
1705                         break;
1706                 case 3:
1707                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1708                                 return true;
1709                         break;
1710                 case 4:
1711                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1712                                 return true;
1713                         break;
1714                 case 5:
1715                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1716                                 return true;
1717                         break;
1718                 case 6:
1719                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1720                                 return true;
1721                         break;
1722                 case 7:
1723                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1724                                 return true;
1725                         break;
1726                 }
1727         }
1728         return false;
1729 }
1730
1731 //==================================================================================
1732
1733 static void R_UpdateEntityLighting(entity_render_t *ent)
1734 {
1735         vec3_t tempdiffusenormal;
1736
1737         // fetch the lighting from the worldmodel data
1738         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));
1739         VectorClear(ent->modellight_diffuse);
1740         VectorClear(tempdiffusenormal);
1741         if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1742         {
1743                 vec3_t org;
1744                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1745                 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1746         }
1747         else // highly rare
1748                 VectorSet(ent->modellight_ambient, 1, 1, 1);
1749
1750         // move the light direction into modelspace coordinates for lighting code
1751         Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1752         if(VectorLength2(ent->modellight_lightdir) > 0)
1753         {
1754                 VectorNormalize(ent->modellight_lightdir);
1755         }
1756         else
1757         {
1758                 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
1759         }
1760
1761         // scale ambient and directional light contributions according to rendering variables
1762         ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1763         ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1764         ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1765         ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1766         ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1767         ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1768 }
1769
1770 static void R_View_UpdateEntityVisible (void)
1771 {
1772         int i, renderimask;
1773         entity_render_t *ent;
1774
1775         if (!r_drawentities.integer)
1776                 return;
1777
1778         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1779         if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1780         {
1781                 // worldmodel can check visibility
1782                 for (i = 0;i < r_refdef.numentities;i++)
1783                 {
1784                         ent = r_refdef.entities[i];
1785                         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));
1786                 }
1787                 if(r_cullentities_trace.integer)
1788                 {
1789                         for (i = 0;i < r_refdef.numentities;i++)
1790                         {
1791                                 ent = r_refdef.entities[i];
1792                                 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
1793                                 {
1794                                         if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
1795                                                 ent->last_trace_visibility = realtime;
1796                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
1797                                                 r_viewcache.entityvisible[i] = 0;
1798                                 }
1799                         }
1800                 }
1801         }
1802         else
1803         {
1804                 // no worldmodel or it can't check visibility
1805                 for (i = 0;i < r_refdef.numentities;i++)
1806                 {
1807                         ent = r_refdef.entities[i];
1808                         r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1809                 }
1810         }
1811
1812         // update entity lighting (even on hidden entities for r_shadows)
1813         for (i = 0;i < r_refdef.numentities;i++)
1814                 R_UpdateEntityLighting(r_refdef.entities[i]);
1815 }
1816
1817 // only used if skyrendermasked, and normally returns false
1818 int R_DrawBrushModelsSky (void)
1819 {
1820         int i, sky;
1821         entity_render_t *ent;
1822
1823         if (!r_drawentities.integer)
1824                 return false;
1825
1826         sky = false;
1827         for (i = 0;i < r_refdef.numentities;i++)
1828         {
1829                 if (!r_viewcache.entityvisible[i])
1830                         continue;
1831                 ent = r_refdef.entities[i];
1832                 if (!ent->model || !ent->model->DrawSky)
1833                         continue;
1834                 ent->model->DrawSky(ent);
1835                 sky = true;
1836         }
1837         return sky;
1838 }
1839
1840 void R_DrawNoModel(entity_render_t *ent);
1841 void R_DrawModels(void)
1842 {
1843         int i;
1844         entity_render_t *ent;
1845
1846         if (!r_drawentities.integer)
1847                 return;
1848
1849         for (i = 0;i < r_refdef.numentities;i++)
1850         {
1851                 if (!r_viewcache.entityvisible[i])
1852                         continue;
1853                 ent = r_refdef.entities[i];
1854                 r_refdef.stats.entities++;
1855                 if (ent->model && ent->model->Draw != NULL)
1856                         ent->model->Draw(ent);
1857                 else
1858                         R_DrawNoModel(ent);
1859         }
1860 }
1861
1862 void R_DrawModelsDepth(void)
1863 {
1864         int i;
1865         entity_render_t *ent;
1866
1867         if (!r_drawentities.integer)
1868                 return;
1869
1870         for (i = 0;i < r_refdef.numentities;i++)
1871         {
1872                 if (!r_viewcache.entityvisible[i])
1873                         continue;
1874                 ent = r_refdef.entities[i];
1875                 r_refdef.stats.entities++;
1876                 if (ent->model && ent->model->DrawDepth != NULL)
1877                         ent->model->DrawDepth(ent);
1878         }
1879 }
1880
1881 static void R_View_SetFrustum(void)
1882 {
1883         double slopex, slopey;
1884
1885         // break apart the view matrix into vectors for various purposes
1886         Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1887         VectorNegate(r_view.left, r_view.right);
1888
1889 #if 0
1890         r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1891         r_view.frustum[0].normal[1] = 0 - 0;
1892         r_view.frustum[0].normal[2] = -1 - 0;
1893         r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1894         r_view.frustum[1].normal[1] = 0 + 0;
1895         r_view.frustum[1].normal[2] = -1 + 0;
1896         r_view.frustum[2].normal[0] = 0 - 0;
1897         r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1898         r_view.frustum[2].normal[2] = -1 - 0;
1899         r_view.frustum[3].normal[0] = 0 + 0;
1900         r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1901         r_view.frustum[3].normal[2] = -1 + 0;
1902 #endif
1903
1904 #if 0
1905         zNear = r_refdef.nearclip;
1906         nudge = 1.0 - 1.0 / (1<<23);
1907         r_view.frustum[4].normal[0] = 0 - 0;
1908         r_view.frustum[4].normal[1] = 0 - 0;
1909         r_view.frustum[4].normal[2] = -1 - -nudge;
1910         r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1911         r_view.frustum[5].normal[0] = 0 + 0;
1912         r_view.frustum[5].normal[1] = 0 + 0;
1913         r_view.frustum[5].normal[2] = -1 + -nudge;
1914         r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1915 #endif
1916
1917
1918
1919 #if 0
1920         r_view.frustum[0].normal[0] = m[3] - m[0];
1921         r_view.frustum[0].normal[1] = m[7] - m[4];
1922         r_view.frustum[0].normal[2] = m[11] - m[8];
1923         r_view.frustum[0].dist = m[15] - m[12];
1924
1925         r_view.frustum[1].normal[0] = m[3] + m[0];
1926         r_view.frustum[1].normal[1] = m[7] + m[4];
1927         r_view.frustum[1].normal[2] = m[11] + m[8];
1928         r_view.frustum[1].dist = m[15] + m[12];
1929
1930         r_view.frustum[2].normal[0] = m[3] - m[1];
1931         r_view.frustum[2].normal[1] = m[7] - m[5];
1932         r_view.frustum[2].normal[2] = m[11] - m[9];
1933         r_view.frustum[2].dist = m[15] - m[13];
1934
1935         r_view.frustum[3].normal[0] = m[3] + m[1];
1936         r_view.frustum[3].normal[1] = m[7] + m[5];
1937         r_view.frustum[3].normal[2] = m[11] + m[9];
1938         r_view.frustum[3].dist = m[15] + m[13];
1939
1940         r_view.frustum[4].normal[0] = m[3] - m[2];
1941         r_view.frustum[4].normal[1] = m[7] - m[6];
1942         r_view.frustum[4].normal[2] = m[11] - m[10];
1943         r_view.frustum[4].dist = m[15] - m[14];
1944
1945         r_view.frustum[5].normal[0] = m[3] + m[2];
1946         r_view.frustum[5].normal[1] = m[7] + m[6];
1947         r_view.frustum[5].normal[2] = m[11] + m[10];
1948         r_view.frustum[5].dist = m[15] + m[14];
1949 #endif
1950
1951
1952
1953         if (r_view.useperspective)
1954         {
1955                 slopex = 1.0 / r_view.frustum_x;
1956                 slopey = 1.0 / r_view.frustum_y;
1957                 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
1958                 VectorMA(r_view.forward,  slopex, r_view.left, r_view.frustum[1].normal);
1959                 VectorMA(r_view.forward, -slopey, r_view.up  , r_view.frustum[2].normal);
1960                 VectorMA(r_view.forward,  slopey, r_view.up  , r_view.frustum[3].normal);
1961                 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1962
1963                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
1964                 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
1965                 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward,  1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
1966                 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left,  1024 * slopey, r_view.up, r_view.frustumcorner[2]);
1967                 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward,  1024 * slopex, r_view.left,  1024 * slopey, r_view.up, r_view.frustumcorner[3]);
1968
1969                 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1970                 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1971                 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1972                 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1973                 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1974         }
1975         else
1976         {
1977                 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
1978                 VectorScale(r_view.left,  r_view.ortho_x, r_view.frustum[1].normal);
1979                 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
1980                 VectorScale(r_view.up,  r_view.ortho_y, r_view.frustum[3].normal);
1981                 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1982                 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
1983                 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
1984                 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
1985                 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
1986                 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1987         }
1988
1989         PlaneClassify(&r_view.frustum[0]);
1990         PlaneClassify(&r_view.frustum[1]);
1991         PlaneClassify(&r_view.frustum[2]);
1992         PlaneClassify(&r_view.frustum[3]);
1993         PlaneClassify(&r_view.frustum[4]);
1994
1995         // LordHavoc: note to all quake engine coders, Quake had a special case
1996         // for 90 degrees which assumed a square view (wrong), so I removed it,
1997         // Quake2 has it disabled as well.
1998
1999         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2000         //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2001         //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2002         //PlaneClassify(&frustum[0]);
2003
2004         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2005         //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2006         //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2007         //PlaneClassify(&frustum[1]);
2008
2009         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2010         //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2011         //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2012         //PlaneClassify(&frustum[2]);
2013
2014         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2015         //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2016         //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2017         //PlaneClassify(&frustum[3]);
2018
2019         // nearclip plane
2020         //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2021         //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2022         //PlaneClassify(&frustum[4]);
2023 }
2024
2025 void R_View_Update(void)
2026 {
2027         R_View_SetFrustum();
2028         R_View_WorldVisibility();
2029         R_View_UpdateEntityVisible();
2030 }
2031
2032 void R_SetupView(const matrix4x4_t *matrix)
2033 {
2034         if (!r_view.useperspective)
2035                 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);
2036         else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2037                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2038         else
2039                 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2040
2041         GL_SetupView_Orientation_FromEntity(matrix);
2042 }
2043
2044 void R_ResetViewRendering2D(void)
2045 {
2046         if (gl_support_fragment_shader)
2047         {
2048                 qglUseProgramObjectARB(0);CHECKGLERROR
2049         }
2050
2051         DrawQ_Finish();
2052
2053         // GL is weird because it's bottom to top, r_view.y is top to bottom
2054         qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2055         GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2056         GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2057         GL_Color(1, 1, 1, 1);
2058         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2059         GL_BlendFunc(GL_ONE, GL_ZERO);
2060         GL_AlphaTest(false);
2061         GL_ScissorTest(false);
2062         GL_DepthMask(false);
2063         GL_DepthRange(0, 1);
2064         GL_DepthTest(false);
2065         R_Mesh_Matrix(&identitymatrix);
2066         R_Mesh_ResetTextureState();
2067         GL_PolygonOffset(0, 0);
2068         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2069         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2070         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2071         qglStencilMask(~0);CHECKGLERROR
2072         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2073         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2074         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2075 }
2076
2077 void R_ResetViewRendering3D(void)
2078 {
2079         if (gl_support_fragment_shader)
2080         {
2081                 qglUseProgramObjectARB(0);CHECKGLERROR
2082         }
2083
2084         DrawQ_Finish();
2085
2086         // GL is weird because it's bottom to top, r_view.y is top to bottom
2087         qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2088         R_SetupView(&r_view.matrix);
2089         GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2090         GL_Color(1, 1, 1, 1);
2091         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2092         GL_BlendFunc(GL_ONE, GL_ZERO);
2093         GL_AlphaTest(false);
2094         GL_ScissorTest(true);
2095         GL_DepthMask(true);
2096         GL_DepthRange(0, 1);
2097         GL_DepthTest(true);
2098         R_Mesh_Matrix(&identitymatrix);
2099         R_Mesh_ResetTextureState();
2100         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2101         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2102         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2103         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2104         qglStencilMask(~0);CHECKGLERROR
2105         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2106         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2107         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2108 }
2109
2110 /*
2111         R_Bloom_SetupShader(
2112 "// bloom shader\n"
2113 "// written by Forest 'LordHavoc' Hale\n"
2114 "\n"
2115 "// common definitions between vertex shader and fragment shader:\n"
2116 "\n"
2117 "#ifdef __GLSL_CG_DATA_TYPES\n"
2118 "#define myhalf half\n"
2119 "#define myhvec2 hvec2\n"
2120 "#define myhvec3 hvec3\n"
2121 "#define myhvec4 hvec4\n"
2122 "#else\n"
2123 "#define myhalf float\n"
2124 "#define myhvec2 vec2\n"
2125 "#define myhvec3 vec3\n"
2126 "#define myhvec4 vec4\n"
2127 "#endif\n"
2128 "\n"
2129 "varying vec2 ScreenTexCoord;\n"
2130 "varying vec2 BloomTexCoord;\n"
2131 "\n"
2132 "\n"
2133 "\n"
2134 "\n"
2135 "// vertex shader specific:\n"
2136 "#ifdef VERTEX_SHADER\n"
2137 "\n"
2138 "void main(void)\n"
2139 "{\n"
2140 "       ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2141 "       BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2142 "       // transform vertex to camera space, using ftransform to match non-VS\n"
2143 "       // rendering\n"
2144 "       gl_Position = ftransform();\n"
2145 "}\n"
2146 "\n"
2147 "#endif // VERTEX_SHADER\n"
2148 "\n"
2149 "\n"
2150 "\n"
2151 "\n"
2152 "// fragment shader specific:\n"
2153 "#ifdef FRAGMENT_SHADER\n"
2154 "\n"
2155 "void main(void)\n"
2156 "{\n"
2157 "       int x, y;
2158 "       myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2159 "       for (x = -BLUR_X;x <= BLUR_X;x++)
2160 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2161 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2162 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2163 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2164
2165 "       gl_FragColor = vec4(color);\n"
2166 "}\n"
2167 "\n"
2168 "#endif // FRAGMENT_SHADER\n"
2169 */
2170
2171 void R_RenderScene(void);
2172
2173 void R_Bloom_StartFrame(void)
2174 {
2175         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2176
2177         // set bloomwidth and bloomheight to the bloom resolution that will be
2178         // used (often less than the screen resolution for faster rendering)
2179         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2180         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2181         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2182
2183         // calculate desired texture sizes
2184         if (gl_support_arb_texture_non_power_of_two)
2185         {
2186                 screentexturewidth = r_view.width;
2187                 screentextureheight = r_view.height;
2188                 bloomtexturewidth = r_bloomstate.bloomwidth;
2189                 bloomtextureheight = r_bloomstate.bloomheight;
2190         }
2191         else
2192         {
2193                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
2194                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
2195                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
2196                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
2197         }
2198
2199         if (r_hdr.integer)
2200         {
2201                 screentexturewidth = screentextureheight = 0;
2202         }
2203         else if (r_bloom.integer)
2204         {
2205         }
2206         else
2207         {
2208                 screentexturewidth = screentextureheight = 0;
2209                 bloomtexturewidth = bloomtextureheight = 0;
2210         }
2211
2212         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)
2213         {
2214                 // can't use bloom if the parameters are too weird
2215                 // can't use bloom if the card does not support the texture size
2216                 if (r_bloomstate.texture_screen)
2217                         R_FreeTexture(r_bloomstate.texture_screen);
2218                 if (r_bloomstate.texture_bloom)
2219                         R_FreeTexture(r_bloomstate.texture_bloom);
2220                 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2221                 return;
2222         }
2223
2224         r_bloomstate.enabled = true;
2225         r_bloomstate.hdr = r_hdr.integer != 0;
2226
2227         // allocate textures as needed
2228         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2229         {
2230                 if (r_bloomstate.texture_screen)
2231                         R_FreeTexture(r_bloomstate.texture_screen);
2232                 r_bloomstate.texture_screen = NULL;
2233                 r_bloomstate.screentexturewidth = screentexturewidth;
2234                 r_bloomstate.screentextureheight = screentextureheight;
2235                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2236                         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);
2237         }
2238         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2239         {
2240                 if (r_bloomstate.texture_bloom)
2241                         R_FreeTexture(r_bloomstate.texture_bloom);
2242                 r_bloomstate.texture_bloom = NULL;
2243                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2244                 r_bloomstate.bloomtextureheight = bloomtextureheight;
2245                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2246                         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);
2247         }
2248
2249         // set up a texcoord array for the full resolution screen image
2250         // (we have to keep this around to copy back during final render)
2251         r_bloomstate.screentexcoord2f[0] = 0;
2252         r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2253         r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2254         r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2255         r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2256         r_bloomstate.screentexcoord2f[5] = 0;
2257         r_bloomstate.screentexcoord2f[6] = 0;
2258         r_bloomstate.screentexcoord2f[7] = 0;
2259
2260         // set up a texcoord array for the reduced resolution bloom image
2261         // (which will be additive blended over the screen image)
2262         r_bloomstate.bloomtexcoord2f[0] = 0;
2263         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2264         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2265         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2266         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2267         r_bloomstate.bloomtexcoord2f[5] = 0;
2268         r_bloomstate.bloomtexcoord2f[6] = 0;
2269         r_bloomstate.bloomtexcoord2f[7] = 0;
2270 }
2271
2272 void R_Bloom_CopyScreenTexture(float colorscale)
2273 {
2274         r_refdef.stats.bloom++;
2275
2276         R_ResetViewRendering2D();
2277         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2278         R_Mesh_ColorPointer(NULL, 0, 0);
2279         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2280         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2281
2282         // copy view into the screen texture
2283         GL_ActiveTexture(0);
2284         CHECKGLERROR
2285         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
2286         r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2287
2288         // now scale it down to the bloom texture size
2289         CHECKGLERROR
2290         qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2291         GL_BlendFunc(GL_ONE, GL_ZERO);
2292         GL_Color(colorscale, colorscale, colorscale, 1);
2293         // TODO: optimize with multitexture or GLSL
2294         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2295         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2296
2297         // we now have a bloom image in the framebuffer
2298         // copy it into the bloom image texture for later processing
2299         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2300         GL_ActiveTexture(0);
2301         CHECKGLERROR
2302         qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2303         r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2304 }
2305
2306 void R_Bloom_CopyHDRTexture(void)
2307 {
2308         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2309         GL_ActiveTexture(0);
2310         CHECKGLERROR
2311         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
2312         r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2313 }
2314
2315 void R_Bloom_MakeTexture(void)
2316 {
2317         int x, range, dir;
2318         float xoffset, yoffset, r, brighten;
2319
2320         r_refdef.stats.bloom++;
2321
2322         R_ResetViewRendering2D();
2323         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2324         R_Mesh_ColorPointer(NULL, 0, 0);
2325
2326         // we have a bloom image in the framebuffer
2327         CHECKGLERROR
2328         qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2329
2330         for (x = 1;x < r_bloom_colorexponent.value;)
2331         {
2332                 x *= 2;
2333                 r = bound(0, r_bloom_colorexponent.value / x, 1);
2334                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2335                 GL_Color(r, r, r, 1);
2336                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2337                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2338                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2339                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2340
2341                 // copy the vertically blurred bloom view to a texture
2342                 GL_ActiveTexture(0);
2343                 CHECKGLERROR
2344                 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
2345                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2346         }
2347
2348         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2349         brighten = r_bloom_brighten.value;
2350         if (r_hdr.integer)
2351                 brighten *= r_hdr_range.value;
2352         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2353         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2354
2355         for (dir = 0;dir < 2;dir++)
2356         {
2357                 // blend on at multiple vertical offsets to achieve a vertical blur
2358                 // TODO: do offset blends using GLSL
2359                 GL_BlendFunc(GL_ONE, GL_ZERO);
2360                 for (x = -range;x <= range;x++)
2361                 {
2362                         if (!dir){xoffset = 0;yoffset = x;}
2363                         else {xoffset = x;yoffset = 0;}
2364                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
2365                         yoffset /= (float)r_bloomstate.bloomtextureheight;
2366                         // compute a texcoord array with the specified x and y offset
2367                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2368                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2369                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2370                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2371                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2372                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2373                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2374                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2375                         // this r value looks like a 'dot' particle, fading sharply to
2376                         // black at the edges
2377                         // (probably not realistic but looks good enough)
2378                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2379                         //r = (dir ? 1.0f : brighten)/(range*2+1);
2380                         r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2381                         GL_Color(r, r, r, 1);
2382                         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2383                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2384                         GL_BlendFunc(GL_ONE, GL_ONE);
2385                 }
2386
2387                 // copy the vertically blurred bloom view to a texture
2388                 GL_ActiveTexture(0);
2389                 CHECKGLERROR
2390                 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
2391                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2392         }
2393
2394         // apply subtract last
2395         // (just like it would be in a GLSL shader)
2396         if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
2397         {
2398                 GL_BlendFunc(GL_ONE, GL_ZERO);
2399                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2400                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2401                 GL_Color(1, 1, 1, 1);
2402                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2403                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2404
2405                 GL_BlendFunc(GL_ONE, GL_ONE);
2406                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2407                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2408                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2409                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
2410                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2411                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2412                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2413
2414                 // copy the darkened bloom view to a texture
2415                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2416                 GL_ActiveTexture(0);
2417                 CHECKGLERROR
2418                 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
2419                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2420         }
2421 }
2422
2423 void R_HDR_RenderBloomTexture(void)
2424 {
2425         int oldwidth, oldheight;
2426
2427         oldwidth = r_view.width;
2428         oldheight = r_view.height;
2429         r_view.width = r_bloomstate.bloomwidth;
2430         r_view.height = r_bloomstate.bloomheight;
2431
2432         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
2433         // TODO: add exposure compensation features
2434         // TODO: add fp16 framebuffer support
2435
2436         r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
2437         if (r_hdr.integer)
2438                 r_view.colorscale /= r_hdr_range.value;
2439         R_RenderScene();
2440
2441         R_ResetViewRendering2D();
2442
2443         R_Bloom_CopyHDRTexture();
2444         R_Bloom_MakeTexture();
2445
2446         R_ResetViewRendering3D();
2447
2448         R_ClearScreen();
2449         if (r_timereport_active)
2450                 R_TimeReport("clear");
2451
2452
2453         // restore the view settings
2454         r_view.width = oldwidth;
2455         r_view.height = oldheight;
2456 }
2457
2458 static void R_BlendView(void)
2459 {
2460         if (r_bloomstate.enabled && r_bloomstate.hdr)
2461         {
2462                 // render high dynamic range bloom effect
2463                 // the bloom texture was made earlier this render, so we just need to
2464                 // blend it onto the screen...
2465                 R_ResetViewRendering2D();
2466                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2467                 R_Mesh_ColorPointer(NULL, 0, 0);
2468                 GL_Color(1, 1, 1, 1);
2469                 GL_BlendFunc(GL_ONE, GL_ONE);
2470                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2471                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2472                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2473                 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2474         }
2475         else if (r_bloomstate.enabled)
2476         {
2477                 // render simple bloom effect
2478                 // copy the screen and shrink it and darken it for the bloom process
2479                 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2480                 // make the bloom texture
2481                 R_Bloom_MakeTexture();
2482                 // put the original screen image back in place and blend the bloom
2483                 // texture on it
2484                 R_ResetViewRendering2D();
2485                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2486                 R_Mesh_ColorPointer(NULL, 0, 0);
2487                 GL_Color(1, 1, 1, 1);
2488                 GL_BlendFunc(GL_ONE, GL_ZERO);
2489                 // do both in one pass if possible
2490                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2491                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2492                 if (r_textureunits.integer >= 2 && gl_combine.integer)
2493                 {
2494                         R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2495                         R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2496                         R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
2497                 }
2498                 else
2499                 {
2500                         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2501                         r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2502                         // now blend on the bloom texture
2503                         GL_BlendFunc(GL_ONE, GL_ONE);
2504                         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2505                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2506                 }
2507                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2508                 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2509         }
2510         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
2511         {
2512                 // apply a color tint to the whole view
2513                 R_ResetViewRendering2D();
2514                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2515                 R_Mesh_ColorPointer(NULL, 0, 0);
2516                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2517                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
2518                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2519         }
2520 }
2521
2522 void R_RenderScene(void);
2523
2524 matrix4x4_t r_waterscrollmatrix;
2525
2526 void R_UpdateVariables(void)
2527 {
2528         R_Textures_Frame();
2529
2530         r_refdef.farclip = 4096;
2531         if (r_refdef.worldmodel)
2532                 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
2533         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
2534
2535         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
2536                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
2537         r_refdef.polygonfactor = 0;
2538         r_refdef.polygonoffset = 0;
2539         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
2540         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
2541
2542         r_refdef.rtworld = r_shadow_realtime_world.integer;
2543         r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
2544         r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
2545         r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
2546         r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
2547         if (r_showsurfaces.integer)
2548         {
2549                 r_refdef.rtworld = false;
2550                 r_refdef.rtworldshadows = false;
2551                 r_refdef.rtdlight = false;
2552                 r_refdef.rtdlightshadows = false;
2553                 r_refdef.lightmapintensity = 0;
2554         }
2555
2556         if (gamemode == GAME_NEHAHRA)
2557         {
2558                 if (gl_fogenable.integer)
2559                 {
2560                         r_refdef.oldgl_fogenable = true;
2561                         r_refdef.fog_density = gl_fogdensity.value;
2562                         r_refdef.fog_red = gl_fogred.value;
2563                         r_refdef.fog_green = gl_foggreen.value;
2564                         r_refdef.fog_blue = gl_fogblue.value;
2565                 }
2566                 else if (r_refdef.oldgl_fogenable)
2567                 {
2568                         r_refdef.oldgl_fogenable = false;
2569                         r_refdef.fog_density = 0;
2570                         r_refdef.fog_red = 0;
2571                         r_refdef.fog_green = 0;
2572                         r_refdef.fog_blue = 0;
2573                 }
2574         }
2575         if (r_refdef.fog_density)
2576         {
2577                 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red  , 1.0f);
2578                 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
2579                 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
2580         }
2581         if (r_refdef.fog_density)
2582         {
2583                 r_refdef.fogenabled = true;
2584                 // this is the point where the fog reaches 0.9986 alpha, which we
2585                 // consider a good enough cutoff point for the texture
2586                 // (0.9986 * 256 == 255.6)
2587                 r_refdef.fogrange = 400 / r_refdef.fog_density;
2588                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
2589                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
2590                 // fog color was already set
2591         }
2592         else
2593                 r_refdef.fogenabled = false;
2594 }
2595
2596 /*
2597 ================
2598 R_RenderView
2599 ================
2600 */
2601 void R_RenderView(void)
2602 {
2603         if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
2604                 return; //Host_Error ("R_RenderView: NULL worldmodel");
2605
2606         R_Shadow_UpdateWorldLightSelection();
2607
2608         CHECKGLERROR
2609         if (r_timereport_active)
2610                 R_TimeReport("setup");
2611
2612         R_View_Update();
2613         if (r_timereport_active)
2614                 R_TimeReport("visibility");
2615
2616         R_ResetViewRendering3D();
2617
2618         R_ClearScreen();
2619         if (r_timereport_active)
2620                 R_TimeReport("clear");
2621
2622         R_Bloom_StartFrame();
2623
2624         // this produces a bloom texture to be used in R_BlendView() later
2625         if (r_hdr.integer)
2626                 R_HDR_RenderBloomTexture();
2627
2628         r_view.colorscale = r_hdr_scenebrightness.value;
2629         R_RenderScene();
2630
2631         R_BlendView();
2632         if (r_timereport_active)
2633                 R_TimeReport("blendview");
2634
2635         GL_Scissor(0, 0, vid.width, vid.height);
2636         GL_ScissorTest(false);
2637         CHECKGLERROR
2638 }
2639
2640 extern void R_DrawLightningBeams (void);
2641 extern void VM_CL_AddPolygonsToMeshQueue (void);
2642 extern void R_DrawPortals (void);
2643 extern cvar_t cl_locs_show;
2644 static void R_DrawLocs(void);
2645 static void R_DrawEntityBBoxes(void);
2646 void R_RenderScene(void)
2647 {
2648         // don't let sound skip if going slow
2649         if (r_refdef.extraupdate)
2650                 S_ExtraUpdate ();
2651
2652         R_ResetViewRendering3D();
2653
2654         R_MeshQueue_BeginScene();
2655
2656         R_SkyStartFrame();
2657
2658         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);
2659
2660         if (cl.csqc_vidvars.drawworld)
2661         {
2662                 // don't let sound skip if going slow
2663                 if (r_refdef.extraupdate)
2664                         S_ExtraUpdate ();
2665
2666                 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2667                 {
2668                         r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2669                         if (r_timereport_active)
2670                                 R_TimeReport("worldsky");
2671                 }
2672
2673                 if (R_DrawBrushModelsSky() && r_timereport_active)
2674                         R_TimeReport("bmodelsky");
2675         }
2676
2677         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
2678         {
2679                 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
2680                 if (r_timereport_active)
2681                         R_TimeReport("worlddepth");
2682         }
2683         if (r_depthfirst.integer >= 2)
2684         {
2685                 R_DrawModelsDepth();
2686                 if (r_timereport_active)
2687                         R_TimeReport("modeldepth");
2688         }
2689
2690         if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2691         {
2692                 r_refdef.worldmodel->Draw(r_refdef.worldentity);
2693                 if (r_timereport_active)
2694                         R_TimeReport("world");
2695         }
2696
2697         // don't let sound skip if going slow
2698         if (r_refdef.extraupdate)
2699                 S_ExtraUpdate ();
2700
2701         R_DrawModels();
2702         if (r_timereport_active)
2703                 R_TimeReport("models");
2704
2705         // don't let sound skip if going slow
2706         if (r_refdef.extraupdate)
2707                 S_ExtraUpdate ();
2708
2709         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2710         {
2711                 R_DrawModelShadows();
2712
2713                 R_ResetViewRendering3D();
2714
2715                 // don't let sound skip if going slow
2716                 if (r_refdef.extraupdate)
2717                         S_ExtraUpdate ();
2718         }
2719
2720         R_ShadowVolumeLighting(false);
2721         if (r_timereport_active)
2722                 R_TimeReport("rtlights");
2723
2724         // don't let sound skip if going slow
2725         if (r_refdef.extraupdate)
2726                 S_ExtraUpdate ();
2727
2728         if (cl.csqc_vidvars.drawworld)
2729         {
2730                 R_DrawLightningBeams();
2731                 if (r_timereport_active)
2732                         R_TimeReport("lightning");
2733
2734                 R_DrawParticles();
2735                 if (r_timereport_active)
2736                         R_TimeReport("particles");
2737
2738                 R_DrawExplosions();
2739                 if (r_timereport_active)
2740                         R_TimeReport("explosions");
2741         }
2742
2743         if (gl_support_fragment_shader)
2744         {
2745                 qglUseProgramObjectARB(0);CHECKGLERROR
2746         }
2747         VM_CL_AddPolygonsToMeshQueue();
2748
2749         if (cl_locs_show.integer)
2750         {
2751                 R_DrawLocs();
2752                 if (r_timereport_active)
2753                         R_TimeReport("showlocs");
2754         }
2755
2756         if (r_drawportals.integer)
2757         {
2758                 R_DrawPortals();
2759                 if (r_timereport_active)
2760                         R_TimeReport("portals");
2761         }
2762
2763         if (r_showbboxes.value > 0)
2764         {
2765                 R_DrawEntityBBoxes();
2766                 if (r_timereport_active)
2767                         R_TimeReport("bboxes");
2768         }
2769
2770         if (gl_support_fragment_shader)
2771         {
2772                 qglUseProgramObjectARB(0);CHECKGLERROR
2773         }
2774         R_MeshQueue_RenderTransparent();
2775         if (r_timereport_active)
2776                 R_TimeReport("drawtrans");
2777
2778         if (gl_support_fragment_shader)
2779         {
2780                 qglUseProgramObjectARB(0);CHECKGLERROR
2781         }
2782
2783         if (cl.csqc_vidvars.drawworld)
2784         {
2785                 R_DrawCoronas();
2786                 if (r_timereport_active)
2787                         R_TimeReport("coronas");
2788         }
2789
2790         // don't let sound skip if going slow
2791         if (r_refdef.extraupdate)
2792                 S_ExtraUpdate ();
2793
2794         R_ResetViewRendering2D();
2795 }
2796
2797 static const int bboxelements[36] =
2798 {
2799         5, 1, 3, 5, 3, 7,
2800         6, 2, 0, 6, 0, 4,
2801         7, 3, 2, 7, 2, 6,
2802         4, 0, 1, 4, 1, 5,
2803         4, 5, 7, 4, 7, 6,
2804         1, 0, 2, 1, 2, 3,
2805 };
2806
2807 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2808 {
2809         int i;
2810         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
2811         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2812         GL_DepthMask(false);
2813         GL_DepthRange(0, 1);
2814         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2815         R_Mesh_Matrix(&identitymatrix);
2816         R_Mesh_ResetTextureState();
2817
2818         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
2819         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2820         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2821         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2822         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2823         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2824         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2825         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2826         R_FillColors(color4f, 8, cr, cg, cb, ca);
2827         if (r_refdef.fogenabled)
2828         {
2829                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
2830                 {
2831                         f1 = FogPoint_World(v);
2832                         f2 = 1 - f1;
2833                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2834                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2835                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2836                 }
2837         }
2838         R_Mesh_VertexPointer(vertex3f, 0, 0);
2839         R_Mesh_ColorPointer(color4f, 0, 0);
2840         R_Mesh_ResetTextureState();
2841         R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
2842 }
2843
2844 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2845 {
2846         int i;
2847         float color[4];
2848         prvm_edict_t *edict;
2849         // this function draws bounding boxes of server entities
2850         if (!sv.active)
2851                 return;
2852         SV_VM_Begin();
2853         for (i = 0;i < numsurfaces;i++)
2854         {
2855                 edict = PRVM_EDICT_NUM(surfacelist[i]);
2856                 switch ((int)edict->fields.server->solid)
2857                 {
2858                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
2859                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
2860                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
2861                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
2862                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
2863                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
2864                 }
2865                 color[3] *= r_showbboxes.value;
2866                 color[3] = bound(0, color[3], 1);
2867                 GL_DepthTest(!r_showdisabledepthtest.integer);
2868                 GL_CullFace(GL_BACK);
2869                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
2870         }
2871         SV_VM_End();
2872 }
2873
2874 static void R_DrawEntityBBoxes(void)
2875 {
2876         int i;
2877         prvm_edict_t *edict;
2878         vec3_t center;
2879         // this function draws bounding boxes of server entities
2880         if (!sv.active)
2881                 return;
2882         SV_VM_Begin();
2883         for (i = 0;i < prog->num_edicts;i++)
2884         {
2885                 edict = PRVM_EDICT_NUM(i);
2886                 if (edict->priv.server->free)
2887                         continue;
2888                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
2889                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
2890         }
2891         SV_VM_End();
2892 }
2893
2894 int nomodelelements[24] =
2895 {
2896         5, 2, 0,
2897         5, 1, 2,
2898         5, 0, 3,
2899         5, 3, 1,
2900         0, 2, 4,
2901         2, 1, 4,
2902         3, 0, 4,
2903         1, 3, 4
2904 };
2905
2906 float nomodelvertex3f[6*3] =
2907 {
2908         -16,   0,   0,
2909          16,   0,   0,
2910           0, -16,   0,
2911           0,  16,   0,
2912           0,   0, -16,
2913           0,   0,  16
2914 };
2915
2916 float nomodelcolor4f[6*4] =
2917 {
2918         0.0f, 0.0f, 0.5f, 1.0f,
2919         0.0f, 0.0f, 0.5f, 1.0f,
2920         0.0f, 0.5f, 0.0f, 1.0f,
2921         0.0f, 0.5f, 0.0f, 1.0f,
2922         0.5f, 0.0f, 0.0f, 1.0f,
2923         0.5f, 0.0f, 0.0f, 1.0f
2924 };
2925
2926 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2927 {
2928         int i;
2929         float f1, f2, *c;
2930         float color4f[6*4];
2931         // this is only called once per entity so numsurfaces is always 1, and
2932         // surfacelist is always {0}, so this code does not handle batches
2933         R_Mesh_Matrix(&ent->matrix);
2934
2935         if (ent->flags & EF_ADDITIVE)
2936         {
2937                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2938                 GL_DepthMask(false);
2939         }
2940         else if (ent->alpha < 1)
2941         {
2942                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2943                 GL_DepthMask(false);
2944         }
2945         else
2946         {
2947                 GL_BlendFunc(GL_ONE, GL_ZERO);
2948                 GL_DepthMask(true);
2949         }
2950         GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
2951         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2952         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2953         GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
2954         R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
2955         if (r_refdef.fogenabled)
2956         {
2957                 vec3_t org;
2958                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2959                 R_Mesh_ColorPointer(color4f, 0, 0);
2960                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2961                 f1 = FogPoint_World(org);
2962                 f2 = 1 - f1;
2963                 for (i = 0, c = color4f;i < 6;i++, c += 4)
2964                 {
2965                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2966                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2967                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2968                         c[3] *= ent->alpha;
2969                 }
2970         }
2971         else if (ent->alpha != 1)
2972         {
2973                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2974                 R_Mesh_ColorPointer(color4f, 0, 0);
2975                 for (i = 0, c = color4f;i < 6;i++, c += 4)
2976                         c[3] *= ent->alpha;
2977         }
2978         else
2979                 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
2980         R_Mesh_ResetTextureState();
2981         R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
2982 }
2983
2984 void R_DrawNoModel(entity_render_t *ent)
2985 {
2986         vec3_t org;
2987         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2988         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2989                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
2990         //else
2991         //      R_DrawNoModelCallback(ent, 0);
2992 }
2993
2994 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2995 {
2996         vec3_t right1, right2, diff, normal;
2997
2998         VectorSubtract (org2, org1, normal);
2999
3000         // calculate 'right' vector for start
3001         VectorSubtract (r_view.origin, org1, diff);
3002         CrossProduct (normal, diff, right1);
3003         VectorNormalize (right1);
3004
3005         // calculate 'right' vector for end
3006         VectorSubtract (r_view.origin, org2, diff);
3007         CrossProduct (normal, diff, right2);
3008         VectorNormalize (right2);
3009
3010         vert[ 0] = org1[0] + width * right1[0];
3011         vert[ 1] = org1[1] + width * right1[1];
3012         vert[ 2] = org1[2] + width * right1[2];
3013         vert[ 3] = org1[0] - width * right1[0];
3014         vert[ 4] = org1[1] - width * right1[1];
3015         vert[ 5] = org1[2] - width * right1[2];
3016         vert[ 6] = org2[0] - width * right2[0];
3017         vert[ 7] = org2[1] - width * right2[1];
3018         vert[ 8] = org2[2] - width * right2[2];
3019         vert[ 9] = org2[0] + width * right2[0];
3020         vert[10] = org2[1] + width * right2[1];
3021         vert[11] = org2[2] + width * right2[2];
3022 }
3023
3024 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3025
3026 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)
3027 {
3028         float fog = 1.0f;
3029         float vertex3f[12];
3030
3031         if (r_refdef.fogenabled)
3032                 fog = FogPoint_World(origin);
3033
3034         R_Mesh_Matrix(&identitymatrix);
3035         GL_BlendFunc(blendfunc1, blendfunc2);
3036
3037         if(v_flipped_state)
3038         {
3039                 scalex1 = -scalex1;
3040                 scalex2 = -scalex2;
3041                 GL_CullFace(GL_BACK);
3042         }
3043         else
3044                 GL_CullFace(GL_FRONT);
3045
3046         GL_DepthMask(false);
3047         GL_DepthRange(0, depthshort ? 0.0625 : 1);
3048         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3049         GL_DepthTest(!depthdisable);
3050
3051         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3052         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3053         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3054         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3055         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3056         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3057         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3058         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3059         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3060         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3061         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3062         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3063
3064         R_Mesh_VertexPointer(vertex3f, 0, 0);
3065         R_Mesh_ColorPointer(NULL, 0, 0);
3066         R_Mesh_ResetTextureState();
3067         R_Mesh_TexBind(0, R_GetTexture(texture));
3068         R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3069         // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3070         GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3071         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3072
3073         if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3074         {
3075                 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3076                 GL_BlendFunc(blendfunc1, GL_ONE);
3077                 fog = 1 - fog;
3078                 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);
3079                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3080         }
3081 }
3082
3083 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3084 {
3085         int i;
3086         float *vertex3f;
3087         float v[3];
3088         VectorSet(v, x, y, z);
3089         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3090                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3091                         break;
3092         if (i == mesh->numvertices)
3093         {
3094                 if (mesh->numvertices < mesh->maxvertices)
3095                 {
3096                         VectorCopy(v, vertex3f);
3097                         mesh->numvertices++;
3098                 }
3099                 return mesh->numvertices;
3100         }
3101         else
3102                 return i;
3103 }
3104
3105 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3106 {
3107         int i;
3108         int *e, element[3];
3109         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3110         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3111         e = mesh->element3i + mesh->numtriangles * 3;
3112         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3113         {
3114                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3115                 if (mesh->numtriangles < mesh->maxtriangles)
3116                 {
3117                         *e++ = element[0];
3118                         *e++ = element[1];
3119                         *e++ = element[2];
3120                         mesh->numtriangles++;
3121                 }
3122                 element[1] = element[2];
3123         }
3124 }
3125
3126 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3127 {
3128         int i;
3129         int *e, element[3];
3130         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3131         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3132         e = mesh->element3i + mesh->numtriangles * 3;
3133         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3134         {
3135                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3136                 if (mesh->numtriangles < mesh->maxtriangles)
3137                 {
3138                         *e++ = element[0];
3139                         *e++ = element[1];
3140                         *e++ = element[2];
3141                         mesh->numtriangles++;
3142                 }
3143                 element[1] = element[2];
3144         }
3145 }
3146
3147 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3148 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3149 {
3150         int planenum, planenum2;
3151         int w;
3152         int tempnumpoints;
3153         mplane_t *plane, *plane2;
3154         double maxdist;
3155         double temppoints[2][256*3];
3156         // figure out how large a bounding box we need to properly compute this brush
3157         maxdist = 0;
3158         for (w = 0;w < numplanes;w++)
3159                 maxdist = max(maxdist, planes[w].dist);
3160         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3161         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3162         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3163         {
3164                 w = 0;
3165                 tempnumpoints = 4;
3166                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3167                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3168                 {
3169                         if (planenum2 == planenum)
3170                                 continue;
3171                         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);
3172                         w = !w;
3173                 }
3174                 if (tempnumpoints < 3)
3175                         continue;
3176                 // generate elements forming a triangle fan for this polygon
3177                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3178         }
3179 }
3180
3181 static void R_DrawCollisionBrush(const colbrushf_t *brush)
3182 {
3183         int i;
3184         R_Mesh_VertexPointer(brush->points->v, 0, 0);
3185         i = (int)(((size_t)brush) / sizeof(colbrushf_t));
3186         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);
3187         GL_LockArrays(0, brush->numpoints);
3188         R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements, 0, 0);
3189         GL_LockArrays(0, 0);
3190 }
3191
3192 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
3193 {
3194         int i;
3195         if (!surface->num_collisiontriangles)
3196                 return;
3197         R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
3198         i = (int)(((size_t)surface) / sizeof(msurface_t));
3199         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);
3200         GL_LockArrays(0, surface->num_collisionvertices);
3201         R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
3202         GL_LockArrays(0, 0);
3203 }
3204
3205 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)
3206 {
3207         texturelayer_t *layer;
3208         layer = t->currentlayers + t->currentnumlayers++;
3209         layer->type = type;
3210         layer->depthmask = depthmask;
3211         layer->blendfunc1 = blendfunc1;
3212         layer->blendfunc2 = blendfunc2;
3213         layer->texture = texture;
3214         layer->texmatrix = *matrix;
3215         layer->color[0] = r * r_view.colorscale;
3216         layer->color[1] = g * r_view.colorscale;
3217         layer->color[2] = b * r_view.colorscale;
3218         layer->color[3] = a;
3219 }
3220
3221 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3222 {
3223         double index, f;
3224         index = parms[2] + r_refdef.time * parms[3];
3225         index -= floor(index);
3226         switch (func)
3227         {
3228         default:
3229         case Q3WAVEFUNC_NONE:
3230         case Q3WAVEFUNC_NOISE:
3231         case Q3WAVEFUNC_COUNT:
3232                 f = 0;
3233                 break;
3234         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3235         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3236         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3237         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3238         case Q3WAVEFUNC_TRIANGLE:
3239                 index *= 4;
3240                 f = index - floor(index);
3241                 if (index < 1)
3242                         f = f;
3243                 else if (index < 2)
3244                         f = 1 - f;
3245                 else if (index < 3)
3246                         f = -f;
3247                 else
3248                         f = -(1 - f);
3249                 break;
3250         }
3251         return (float)(parms[0] + parms[1] * f);
3252 }
3253
3254 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3255 {
3256         int i;
3257         model_t *model = ent->model;
3258         float f;
3259         float tcmat[12];
3260         q3shaderinfo_layer_tcmod_t *tcmod;
3261
3262         // switch to an alternate material if this is a q1bsp animated material
3263         {
3264                 texture_t *texture = t;
3265                 int s = ent->skinnum;
3266                 if ((unsigned int)s >= (unsigned int)model->numskins)
3267                         s = 0;
3268                 if (model->skinscenes)
3269                 {
3270                         if (model->skinscenes[s].framecount > 1)
3271                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3272                         else
3273                                 s = model->skinscenes[s].firstframe;
3274                 }
3275                 if (s > 0)
3276                         t = t + s * model->num_surfaces;
3277                 if (t->animated)
3278                 {
3279                         // use an alternate animation if the entity's frame is not 0,
3280                         // and only if the texture has an alternate animation
3281                         if (ent->frame2 != 0 && t->anim_total[1])
3282                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3283                         else
3284                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3285                 }
3286                 texture->currentframe = t;
3287         }
3288
3289         // update currentskinframe to be a qw skin or animation frame
3290         if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
3291         {
3292                 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
3293                 {
3294                         strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
3295                         Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
3296                         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);
3297                 }
3298                 t->currentskinframe = r_qwskincache_skinframe[i];
3299                 if (t->currentskinframe == NULL)
3300                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3301         }
3302         else if (t->numskinframes >= 2)
3303                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3304         if (t->backgroundnumskinframes >= 2)
3305                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3306
3307         t->currentmaterialflags = t->basematerialflags;
3308         t->currentalpha = ent->alpha;
3309         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3310                 t->currentalpha *= r_wateralpha.value;
3311         if (!(ent->flags & RENDER_LIGHT))
3312                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3313         if (ent->effects & EF_ADDITIVE)
3314                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3315         else if (t->currentalpha < 1)
3316                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3317         if (ent->effects & EF_DOUBLESIDED)
3318                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3319         if (ent->effects & EF_NODEPTHTEST)
3320                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3321         if (ent->flags & RENDER_VIEWMODEL)
3322                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3323         if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3324                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3325
3326         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
3327         {
3328                 matrix4x4_t matrix;
3329                 switch(tcmod->tcmod)
3330                 {
3331                 case Q3TCMOD_COUNT:
3332                 case Q3TCMOD_NONE:
3333                         if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3334                                 matrix = r_waterscrollmatrix;
3335                         else
3336                                 matrix = identitymatrix;
3337                         break;
3338                 case Q3TCMOD_ENTITYTRANSLATE:
3339                         // this is used in Q3 to allow the gamecode to control texcoord
3340                         // scrolling on the entity, which is not supported in darkplaces yet.
3341                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
3342                         break;
3343                 case Q3TCMOD_ROTATE:
3344                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
3345                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
3346                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
3347                         break;
3348                 case Q3TCMOD_SCALE:
3349                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
3350                         break;
3351                 case Q3TCMOD_SCROLL:
3352                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
3353                         break;
3354                 case Q3TCMOD_STRETCH:
3355                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
3356                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
3357                         break;
3358                 case Q3TCMOD_TRANSFORM:
3359                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
3360                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
3361                         VectorSet(tcmat +  6, 0                   , 0                , 1);
3362                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
3363                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
3364                         break;
3365                 case Q3TCMOD_TURBULENT:
3366                         // this is handled in the RSurf_PrepareVertices function
3367                         matrix = identitymatrix;
3368                         break;
3369                 }
3370                 // either replace or concatenate the transformation
3371                 if (i < 1)
3372                         t->currenttexmatrix = matrix;
3373                 else
3374                 {
3375                         matrix4x4_t temp = t->currenttexmatrix;
3376                         Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
3377                 }
3378         }
3379
3380         t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
3381         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3382         t->glosstexture = r_texture_white;
3383         t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
3384         t->backgroundglosstexture = r_texture_white;
3385         t->specularpower = r_shadow_glossexponent.value;
3386         // TODO: store reference values for these in the texture?
3387         t->specularscale = 0;
3388         if (r_shadow_gloss.integer > 0)
3389         {
3390                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
3391                 {
3392                         if (r_shadow_glossintensity.value > 0)
3393                         {
3394                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_black;
3395                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_black;
3396                                 t->specularscale = r_shadow_glossintensity.value;
3397                         }
3398                 }
3399                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
3400                         t->specularscale = r_shadow_gloss2intensity.value;
3401         }
3402
3403         t->currentpolygonfactor = r_refdef.polygonfactor;
3404         t->currentpolygonoffset = r_refdef.polygonoffset;
3405         // submodels are biased to avoid z-fighting with world surfaces that they
3406         // may be exactly overlapping (avoids z-fighting artifacts on certain
3407         // doors and things in Quake maps)
3408         if (ent->model->brush.submodel)
3409         {
3410                 t->currentpolygonfactor = r_refdef.polygonfactor + r_polygonoffset_submodel_factor.value;
3411                 t->currentpolygonoffset = r_refdef.polygonoffset + r_polygonoffset_submodel_offset.value;
3412         }
3413
3414         VectorClear(t->dlightcolor);
3415         t->currentnumlayers = 0;
3416         if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
3417         {
3418                 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
3419                 {
3420                         int blendfunc1, blendfunc2, depthmask;
3421                         if (t->currentmaterialflags & MATERIALFLAG_ADD)
3422                         {
3423                                 blendfunc1 = GL_SRC_ALPHA;
3424                                 blendfunc2 = GL_ONE;
3425                         }
3426                         else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
3427                         {
3428                                 blendfunc1 = GL_SRC_ALPHA;
3429                                 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
3430                         }
3431                         else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
3432                         {
3433                                 blendfunc1 = t->customblendfunc[0];
3434                                 blendfunc2 = t->customblendfunc[1];
3435                         }
3436                         else
3437                         {
3438                                 blendfunc1 = GL_ONE;
3439                                 blendfunc2 = GL_ZERO;
3440                         }
3441                         depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
3442                         if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
3443                         {
3444                                 rtexture_t *currentbasetexture;
3445                                 int layerflags = 0;
3446                                 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
3447                                         layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
3448                                 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3449                                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3450                                 {
3451                                         // fullbright is not affected by r_refdef.lightmapintensity
3452                                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
3453                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3454                                                 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);
3455                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3456                                                 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);
3457                                 }
3458                                 else
3459                                 {
3460                                         float colorscale;
3461                                         // set the color tint used for lights affecting this surface
3462                                         VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
3463                                         colorscale = 2;
3464                                         // q3bsp has no lightmap updates, so the lightstylevalue that
3465                                         // would normally be baked into the lightmap must be
3466                                         // applied to the color
3467                                         if (ent->model->type == mod_brushq3)
3468                                                 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
3469                                         colorscale *= r_refdef.lightmapintensity;
3470                                         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);
3471                                         if (r_ambient.value >= (1.0f/64.0f))
3472                                                 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);
3473                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3474                                         {
3475                                                 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);
3476                                                 if (r_ambient.value >= (1.0f/64.0f))
3477                                                         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);
3478                                         }
3479                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3480                                         {
3481                                                 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);
3482                                                 if (r_ambient.value >= (1.0f/64.0f))
3483                                                         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);
3484                                         }
3485                                 }
3486                                 if (t->currentskinframe->glow != NULL)
3487                                         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);
3488                                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
3489                                 {
3490                                         // if this is opaque use alpha blend which will darken the earlier
3491                                         // passes cheaply.
3492                                         //
3493                                         // if this is an alpha blended material, all the earlier passes
3494                                         // were darkened by fog already, so we only need to add the fog
3495                                         // color ontop through the fog mask texture
3496                                         //
3497                                         // if this is an additive blended material, all the earlier passes
3498                                         // were darkened by fog already, and we should not add fog color
3499                                         // (because the background was not darkened, there is no fog color
3500                                         // that was lost behind it).
3501                                         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);
3502                                 }
3503                         }
3504                 }
3505         }
3506 }
3507
3508 void R_UpdateAllTextureInfo(entity_render_t *ent)
3509 {
3510         int i;
3511         if (ent->model)
3512                 for (i = 0;i < ent->model->num_texturesperskin;i++)
3513                         R_UpdateTextureInfo(ent, ent->model->data_textures + i);
3514 }
3515
3516 rsurfacestate_t rsurface;
3517
3518 void R_Mesh_ResizeArrays(int newvertices)
3519 {
3520         float *base;
3521         if (rsurface.array_size >= newvertices)
3522                 return;
3523         if (rsurface.array_modelvertex3f)
3524                 Mem_Free(rsurface.array_modelvertex3f);
3525         rsurface.array_size = (newvertices + 1023) & ~1023;
3526         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
3527         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
3528         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
3529         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
3530         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
3531         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
3532         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
3533         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
3534         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
3535         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
3536         rsurface.array_color4f           = base + rsurface.array_size * 27;
3537         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
3538 }
3539
3540 void RSurf_CleanUp(void)
3541 {
3542         CHECKGLERROR
3543         if (rsurface.mode == RSURFMODE_GLSL)
3544         {
3545                 qglUseProgramObjectARB(0);CHECKGLERROR
3546         }
3547         GL_AlphaTest(false);
3548         rsurface.mode = RSURFMODE_NONE;
3549         rsurface.uselightmaptexture = false;
3550         rsurface.texture = NULL;
3551 }
3552
3553 void RSurf_ActiveWorldEntity(void)
3554 {
3555         model_t *model = r_refdef.worldmodel;
3556         RSurf_CleanUp();
3557         if (rsurface.array_size < model->surfmesh.num_vertices)
3558                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
3559         rsurface.matrix = identitymatrix;
3560         rsurface.inversematrix = identitymatrix;
3561         R_Mesh_Matrix(&identitymatrix);
3562         VectorCopy(r_view.origin, rsurface.modelorg);
3563         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
3564         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
3565         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
3566         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
3567         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
3568         rsurface.frameblend[0].frame = 0;
3569         rsurface.frameblend[0].lerp = 1;
3570         rsurface.frameblend[1].frame = 0;
3571         rsurface.frameblend[1].lerp = 0;
3572         rsurface.frameblend[2].frame = 0;
3573         rsurface.frameblend[2].lerp = 0;
3574         rsurface.frameblend[3].frame = 0;
3575         rsurface.frameblend[3].lerp = 0;
3576         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
3577         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
3578         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
3579         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
3580         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
3581         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
3582         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
3583         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
3584         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
3585         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
3586         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
3587         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
3588         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
3589         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
3590         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
3591         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
3592         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
3593         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
3594         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
3595         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
3596         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
3597         rsurface.modelelement3i = model->surfmesh.data_element3i;
3598         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
3599         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
3600         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
3601         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
3602         rsurface.modelsurfaces = model->data_surfaces;
3603         rsurface.generatedvertex = false;
3604         rsurface.vertex3f  = rsurface.modelvertex3f;
3605         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
3606         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
3607         rsurface.svector3f = rsurface.modelsvector3f;
3608         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
3609         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
3610         rsurface.tvector3f = rsurface.modeltvector3f;
3611         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
3612         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
3613         rsurface.normal3f  = rsurface.modelnormal3f;
3614         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
3615         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
3616         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
3617 }
3618
3619 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3620 {
3621         model_t *model = ent->model;
3622         RSurf_CleanUp();
3623         if (rsurface.array_size < model->surfmesh.num_vertices)
3624                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
3625         rsurface.matrix = ent->matrix;
3626         rsurface.inversematrix = ent->inversematrix;
3627         R_Mesh_Matrix(&rsurface.matrix);
3628         Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
3629         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
3630         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
3631         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
3632         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
3633         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
3634         rsurface.frameblend[0] = ent->frameblend[0];
3635         rsurface.frameblend[1] = ent->frameblend[1];
3636         rsurface.frameblend[2] = ent->frameblend[2];
3637         rsurface.frameblend[3] = ent->frameblend[3];
3638         if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
3639         {
3640                 if (wanttangents)
3641                 {
3642                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
3643                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
3644 &nb