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