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