]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
eliminated RENDER_NOCULLFACE (now uses MATERIALFLAG_NOCULLFACE on a texture)
[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->effects & EF_DOUBLESIDED) ? 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->effects & EF_DOUBLESIDED)
2657                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
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_ActiveWorldEntity(void)
2855 {
2856         RSurf_CleanUp();
2857         rsurface_entity = r_refdef.worldentity;
2858         rsurface_model = r_refdef.worldmodel;
2859         if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2860                 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2861         R_Mesh_Matrix(&identitymatrix);
2862         VectorCopy(r_view.origin, rsurface_modelorg);
2863         rsurface_modelvertex3f  = rsurface_model->surfmesh.data_vertex3f;
2864         rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2865         rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2866         rsurface_modelnormal3f  = rsurface_model->surfmesh.data_normal3f;
2867         rsurface_generatedvertex = false;
2868         rsurface_vertex3f  = rsurface_modelvertex3f;
2869         rsurface_svector3f = rsurface_modelsvector3f;
2870         rsurface_tvector3f = rsurface_modeltvector3f;
2871         rsurface_normal3f  = rsurface_modelnormal3f;
2872 }
2873
2874 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2875 {
2876         RSurf_CleanUp();
2877         rsurface_entity = ent;
2878         rsurface_model = ent->model;
2879         if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2880                 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2881         R_Mesh_Matrix(&ent->matrix);
2882         Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2883         if (rsurface_model->surfmesh.isanimated && (rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0))
2884         {
2885                 if (wanttangents)
2886                 {
2887                         rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2888                         rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2889                         rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2890                         rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2891                         Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2892                 }
2893                 else if (wantnormals)
2894                 {
2895                         rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2896                         rsurface_modelsvector3f = NULL;
2897                         rsurface_modeltvector3f = NULL;
2898                         rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2899                         Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2900                 }
2901                 else
2902                 {
2903                         rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2904                         rsurface_modelsvector3f = NULL;
2905                         rsurface_modeltvector3f = NULL;
2906                         rsurface_modelnormal3f = NULL;
2907                         Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2908                 }
2909                 rsurface_generatedvertex = true;
2910         }
2911         else
2912         {
2913                 rsurface_modelvertex3f  = rsurface_model->surfmesh.data_vertex3f;
2914                 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2915                 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2916                 rsurface_modelnormal3f  = rsurface_model->surfmesh.data_normal3f;
2917                 rsurface_generatedvertex = false;
2918         }
2919         rsurface_vertex3f  = rsurface_modelvertex3f;
2920         rsurface_svector3f = rsurface_modelsvector3f;
2921         rsurface_tvector3f = rsurface_modeltvector3f;
2922         rsurface_normal3f  = rsurface_modelnormal3f;
2923 }
2924
2925 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2926 {
2927         // 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
2928         if (rsurface_generatedvertex)
2929         {
2930                 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2931                         generatetangents = true;
2932                 if (generatetangents)
2933                         generatenormals = true;
2934                 if (generatenormals && !rsurface_modelnormal3f)
2935                 {
2936                         rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2937                         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);
2938                 }
2939                 if (generatetangents && !rsurface_modelsvector3f)
2940                 {
2941                         rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2942                         rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2943                         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);
2944                 }
2945         }
2946         // 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)
2947         if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2948         {
2949                 int texturesurfaceindex;
2950                 float center[3], forward[3], right[3], up[3], v[4][3];
2951                 matrix4x4_t matrix1, imatrix1;
2952                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
2953                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
2954                 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
2955                 // make deformed versions of only the model vertices used by the specified surfaces
2956                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2957                 {
2958                         int i, j;
2959                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2960                         // a single autosprite surface can contain multiple sprites...
2961                         for (j = 0;j < surface->num_vertices - 3;j += 4)
2962                         {
2963                                 VectorClear(center);
2964                                 for (i = 0;i < 4;i++)
2965                                         VectorAdd(center, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2966                                 VectorScale(center, 0.25f, center);
2967                                 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2968                                 {
2969                                         forward[0] = rsurface_modelorg[0] - center[0];
2970                                         forward[1] = rsurface_modelorg[1] - center[1];
2971                                         forward[2] = 0;
2972                                         VectorNormalize(forward);
2973                                         right[0] = forward[1];
2974                                         right[1] = -forward[0];
2975                                         right[2] = 0;
2976                                         VectorSet(up, 0, 0, 1);
2977                                 }
2978                                 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2979                                 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);
2980                                 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2981                                 for (i = 0;i < 4;i++)
2982                                         Matrix4x4_Transform(&imatrix1, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2983                                 for (i = 0;i < 4;i++)
2984                                         VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
2985                         }
2986                         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);
2987                         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);
2988                 }
2989                 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2990                 rsurface_svector3f = rsurface_array_deformedsvector3f;
2991                 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2992                 rsurface_normal3f = rsurface_array_deformednormal3f;
2993         }
2994         else
2995         {
2996                 rsurface_vertex3f = rsurface_modelvertex3f;
2997                 rsurface_svector3f = rsurface_modelsvector3f;
2998                 rsurface_tvector3f = rsurface_modeltvector3f;
2999                 rsurface_normal3f = rsurface_modelnormal3f;
3000         }
3001         R_Mesh_VertexPointer(rsurface_vertex3f);
3002 }
3003
3004 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
3005 {
3006         int i, j;
3007         const msurface_t *surface = texturesurfacelist[0];
3008         const msurface_t *surface2;
3009         int firstvertex;
3010         int endvertex;
3011         int numvertices;
3012         int numtriangles;
3013         // TODO: lock all array ranges before render, rather than on each surface
3014         if (texturenumsurfaces == 1)
3015         {
3016                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3017                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3018         }
3019         else if (r_batchmode.integer == 2)
3020         {
3021                 #define MAXBATCHTRIANGLES 4096
3022                 int batchtriangles = 0;
3023                 int batchelements[MAXBATCHTRIANGLES*3];
3024                 for (i = 0;i < texturenumsurfaces;i = j)
3025                 {
3026                         surface = texturesurfacelist[i];
3027                         j = i + 1;
3028                         if (surface->num_triangles > MAXBATCHTRIANGLES)
3029                         {
3030                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3031                                 continue;
3032                         }
3033                         memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
3034                         batchtriangles = surface->num_triangles;
3035                         firstvertex = surface->num_firstvertex;
3036                         endvertex = surface->num_firstvertex + surface->num_vertices;
3037                         for (;j < texturenumsurfaces;j++)
3038                         {
3039                                 surface2 = texturesurfacelist[j];
3040                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
3041                                         break;
3042                                 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
3043                                 batchtriangles += surface2->num_triangles;
3044                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
3045                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
3046                         }
3047                         surface2 = texturesurfacelist[j-1];
3048                         numvertices = endvertex - firstvertex;
3049                         R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements);
3050                 }
3051         }
3052         else if (r_batchmode.integer == 1)
3053         {
3054                 for (i = 0;i < texturenumsurfaces;i = j)
3055                 {
3056                         surface = texturesurfacelist[i];
3057                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3058                                 if (texturesurfacelist[j] != surface2)
3059                                         break;
3060                         surface2 = texturesurfacelist[j-1];
3061                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3062                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3063                         GL_LockArrays(surface->num_firstvertex, numvertices);
3064                         R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3065                 }
3066         }
3067         else
3068         {
3069                 for (i = 0;i < texturenumsurfaces;i++)
3070                 {
3071                         surface = texturesurfacelist[i];
3072                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3073                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3074                 }
3075         }
3076 }
3077
3078 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
3079 {
3080         int i;
3081         int j;
3082         const msurface_t *surface = texturesurfacelist[0];
3083         const msurface_t *surface2;
3084         int firstvertex;
3085         int endvertex;
3086         int numvertices;
3087         int numtriangles;
3088         // TODO: lock all array ranges before render, rather than on each surface
3089         if (texturenumsurfaces == 1)
3090         {
3091                 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3092                 if (deluxemaptexunit >= 0)
3093                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3094                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3095                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3096         }
3097         else if (r_batchmode.integer == 2)
3098         {
3099                 #define MAXBATCHTRIANGLES 4096
3100                 int batchtriangles = 0;
3101                 int batchelements[MAXBATCHTRIANGLES*3];
3102                 for (i = 0;i < texturenumsurfaces;i = j)
3103                 {
3104                         surface = texturesurfacelist[i];
3105                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3106                         if (deluxemaptexunit >= 0)
3107                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3108                         j = i + 1;
3109                         if (surface->num_triangles > MAXBATCHTRIANGLES)
3110                         {
3111                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3112                                 continue;
3113                         }
3114                         memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
3115                         batchtriangles = surface->num_triangles;
3116                         firstvertex = surface->num_firstvertex;
3117                         endvertex = surface->num_firstvertex + surface->num_vertices;
3118                         for (;j < texturenumsurfaces;j++)
3119                         {
3120                                 surface2 = texturesurfacelist[j];
3121                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
3122                                         break;
3123                                 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
3124                                 batchtriangles += surface2->num_triangles;
3125                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
3126                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
3127                         }
3128                         surface2 = texturesurfacelist[j-1];
3129                         numvertices = endvertex - firstvertex;
3130                         R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements);
3131                 }
3132         }
3133         else if (r_batchmode.integer == 1)
3134         {
3135 #if 0
3136                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface_texture->name);
3137                 for (i = 0;i < texturenumsurfaces;i = j)
3138                 {
3139                         surface = texturesurfacelist[i];
3140                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3141                                 if (texturesurfacelist[j] != surface2)
3142                                         break;
3143                         Con_Printf(" %i", j - i);
3144                 }
3145                 Con_Printf("\n");
3146                 Con_Printf("%s batch sizes honoring lightmap:", rsurface_texture->name);
3147 #endif
3148                 for (i = 0;i < texturenumsurfaces;i = j)
3149                 {
3150                         surface = texturesurfacelist[i];
3151                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3152                         if (deluxemaptexunit >= 0)
3153                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3154                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3155                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
3156                                         break;
3157 #if 0
3158                         Con_Printf(" %i", j - i);
3159 #endif
3160                         surface2 = texturesurfacelist[j-1];
3161                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3162                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3163                         GL_LockArrays(surface->num_firstvertex, numvertices);
3164                         R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3165                 }
3166 #if 0
3167                 Con_Printf("\n");
3168 #endif
3169         }
3170         else
3171         {
3172                 for (i = 0;i < texturenumsurfaces;i++)
3173                 {
3174                         surface = texturesurfacelist[i];
3175                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3176                         if (deluxemaptexunit >= 0)
3177                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3178                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3179                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3180                 }
3181         }
3182 }
3183
3184 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3185 {
3186         int j;
3187         int texturesurfaceindex;
3188         if (r_showsurfaces.integer == 2)
3189         {
3190                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3191                 {
3192                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3193                         for (j = 0;j < surface->num_triangles;j++)
3194                         {
3195                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
3196                                 GL_Color(f, f, f, 1);
3197                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, 1, (rsurface_model->surfmesh.data_element3i + 3 * (j + surface->num_firsttriangle)));
3198                         }
3199                 }
3200         }
3201         else
3202         {
3203                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3204                 {
3205                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3206                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
3207                         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);
3208                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3209                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3210                 }
3211         }
3212 }
3213
3214 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
3215 {
3216         int texturesurfaceindex;
3217         int i;
3218         float f;
3219         float *v, *c, *c2;
3220         if (rsurface_lightmapcolor4f)
3221         {
3222                 // generate color arrays for the surfaces in this list
3223                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3224                 {
3225                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3226                         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)
3227                         {
3228                                 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3229                                 c2[0] = c[0] * f;
3230                                 c2[1] = c[1] * f;
3231                                 c2[2] = c[2] * f;
3232                                 c2[3] = c[3];
3233                         }
3234                 }
3235         }
3236         else
3237         {
3238                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3239                 {
3240                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3241                         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)
3242                         {
3243                                 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3244                                 c2[0] = f;
3245                                 c2[1] = f;
3246                                 c2[2] = f;
3247                                 c2[3] = 1;
3248                         }
3249                 }
3250         }
3251         rsurface_lightmapcolor4f = rsurface_array_color4f;
3252 }
3253
3254 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
3255 {
3256         int texturesurfaceindex;
3257         int i;
3258         float *c, *c2;
3259         if (!rsurface_lightmapcolor4f)
3260                 return;
3261         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3262         {
3263                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3264                 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)
3265                 {
3266                         c2[0] = c[0] * r;
3267                         c2[1] = c[1] * g;
3268                         c2[2] = c[2] * b;
3269                         c2[3] = c[3] * a;
3270                 }
3271         }
3272         rsurface_lightmapcolor4f = rsurface_array_color4f;
3273 }
3274
3275 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3276 {
3277         // TODO: optimize
3278         rsurface_lightmapcolor4f = NULL;
3279         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3280         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3281         R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3282         GL_Color(r, g, b, a);
3283         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
3284 }
3285
3286 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3287 {
3288         // TODO: optimize applyfog && applycolor case
3289         // just apply fog if necessary, and tint the fog color array if necessary
3290         rsurface_lightmapcolor4f = NULL;
3291         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3292         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3293         R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3294         GL_Color(r, g, b, a);
3295         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3296 }
3297
3298 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3299 {
3300         int texturesurfaceindex;
3301         int i;
3302         float *c;
3303         // TODO: optimize
3304         if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
3305         {
3306                 // generate color arrays for the surfaces in this list
3307                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3308                 {
3309                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3310                         for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
3311                         {
3312                                 if (surface->lightmapinfo->samples)
3313                                 {
3314                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
3315                                         float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
3316                                         VectorScale(lm, scale, c);
3317                                         if (surface->lightmapinfo->styles[1] != 255)
3318                                         {
3319                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
3320                                                 lm += size3;
3321                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
3322                                                 VectorMA(c, scale, lm, c);
3323                                                 if (surface->lightmapinfo->styles[2] != 255)
3324                                                 {
3325                                                         lm += size3;
3326                                                         scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
3327                                                         VectorMA(c, scale, lm, c);
3328                                                         if (surface->lightmapinfo->styles[3] != 255)
3329                                                         {
3330                                                                 lm += size3;
3331                                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
3332                                                                 VectorMA(c, scale, lm, c);
3333                                                         }
3334                                                 }
3335                                         }
3336                                 }
3337                                 else
3338                                         VectorClear(c);
3339                                 c[3] = 1;
3340                         }
3341                 }
3342                 rsurface_lightmapcolor4f = rsurface_array_color4f;
3343         }
3344         else
3345                 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
3346         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3347         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3348         R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3349         GL_Color(r, g, b, a);
3350         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3351 }
3352
3353 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3354 {
3355         int texturesurfaceindex;
3356         int i;
3357         float f;
3358         float *v, *c, *c2;
3359         vec3_t ambientcolor;
3360         vec3_t diffusecolor;
3361         vec3_t lightdir;
3362         // TODO: optimize
3363         // model lighting
3364         VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
3365         ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
3366         ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
3367         ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
3368         diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
3369         diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
3370         diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
3371         if (VectorLength2(diffusecolor) > 0)
3372         {
3373                 // generate color arrays for the surfaces in this list
3374                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3375                 {
3376                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3377                         int numverts = surface->num_vertices;
3378                         v = rsurface_vertex3f + 3 * surface->num_firstvertex;
3379                         c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
3380                         c = rsurface_array_color4f + 4 * surface->num_firstvertex;
3381                         // q3-style directional shading
3382                         for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
3383                         {
3384                                 if ((f = DotProduct(c2, lightdir)) > 0)
3385                                         VectorMA(ambientcolor, f, diffusecolor, c);
3386                                 else
3387                                         VectorCopy(ambientcolor, c);
3388                                 c[3] = a;
3389                         }
3390                 }
3391                 r = 1;
3392                 g = 1;
3393                 b = 1;
3394                 a = 1;
3395                 applycolor = false;
3396                 rsurface_lightmapcolor4f = rsurface_array_color4f;
3397         }
3398         else
3399         {
3400                 r = ambientcolor[0];
3401                 g = ambientcolor[1];
3402                 b = ambientcolor[2];
3403                 rsurface_lightmapcolor4f = NULL;
3404         }
3405         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3406         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3407         R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3408         GL_Color(r, g, b, a);
3409         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3410 }
3411
3412 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3413 {
3414         GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3415         GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3416         if (rsurface_mode != RSURFMODE_SHOWSURFACES)
3417         {
3418                 rsurface_mode = RSURFMODE_SHOWSURFACES;
3419                 GL_DepthMask(true);
3420                 GL_BlendFunc(GL_ONE, GL_ZERO);
3421                 R_Mesh_ColorPointer(NULL);
3422                 R_Mesh_ResetTextureState();
3423         }
3424         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3425         RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3426 }
3427
3428 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
3429 {
3430         // transparent sky would be ridiculous
3431         if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
3432                 return;
3433         if (rsurface_mode != RSURFMODE_SKY)
3434         {
3435                 if (rsurface_mode == RSURFMODE_GLSL)
3436                 {
3437                         qglUseProgramObjectARB(0);CHECKGLERROR
3438                 }
3439                 rsurface_mode = RSURFMODE_SKY;
3440         }
3441         if (skyrendernow)
3442         {
3443                 skyrendernow = false;
3444                 R_Sky();
3445                 // restore entity matrix
3446                 R_Mesh_Matrix(&rsurface_entity->matrix);
3447         }
3448         GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3449         GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3450         GL_DepthMask(true);
3451         // LordHavoc: HalfLife maps have freaky skypolys so don't use
3452         // skymasking on them, and Quake3 never did sky masking (unlike
3453         // software Quake and software Quake2), so disable the sky masking
3454         // in Quake3 maps as it causes problems with q3map2 sky tricks,
3455         // and skymasking also looks very bad when noclipping outside the
3456         // level, so don't use it then either.
3457         if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
3458         {
3459                 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
3460                 R_Mesh_ColorPointer(NULL);
3461                 R_Mesh_ResetTextureState();
3462                 if (skyrendermasked)
3463                 {
3464                         // depth-only (masking)
3465                         GL_ColorMask(0,0,0,0);
3466                         // just to make sure that braindead drivers don't draw
3467                         // anything despite that colormask...
3468                         GL_BlendFunc(GL_ZERO, GL_ONE);
3469                 }
3470                 else
3471                 {
3472                         // fog sky
3473                         GL_BlendFunc(GL_ONE, GL_ZERO);
3474                 }
3475                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3476                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3477                 if (skyrendermasked)
3478                         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
3479         }
3480 }
3481
3482 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
3483 {
3484         if (rsurface_mode != RSURFMODE_GLSL)
3485         {
3486                 rsurface_mode = RSURFMODE_GLSL;
3487                 R_Mesh_ResetTextureState();
3488         }
3489
3490         R_SetupSurfaceShader(vec3_origin, rsurface_lightmode == 2);
3491         if (!r_glsl_permutation)
3492                 return;
3493
3494         if (rsurface_lightmode == 2)
3495                 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3496         else
3497                 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3498         R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
3499         R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
3500         R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
3501         R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
3502         R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
3503
3504         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3505         {
3506                 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3507                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3508                         R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3509                 R_Mesh_ColorPointer(NULL);
3510         }
3511         else if (rsurface_uselightmaptexture)
3512         {
3513                 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
3514                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3515                         R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
3516                 R_Mesh_ColorPointer(NULL);
3517         }
3518         else
3519         {
3520                 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3521                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3522                         R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3523                 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
3524         }
3525
3526         if (rsurface_uselightmaptexture && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
3527                 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
3528         else
3529                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3530         if (rsurface_texture->backgroundnumskinframes && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
3531         {
3532         }
3533 }
3534
3535 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
3536 {
3537         // OpenGL 1.3 path - anything not completely ancient
3538         int texturesurfaceindex;
3539         qboolean applycolor;
3540         qboolean applyfog;
3541         rmeshstate_t m;
3542         int layerindex;
3543         const texturelayer_t *layer;
3544         if (rsurface_mode != RSURFMODE_MULTIPASS)
3545                 rsurface_mode = RSURFMODE_MULTIPASS;
3546         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3547         for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3548         {
3549                 vec4_t layercolor;
3550                 int layertexrgbscale;
3551                 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3552                 {
3553                         if (layerindex == 0)
3554                                 GL_AlphaTest(true);
3555                         else
3556                         {
3557                                 GL_AlphaTest(false);
3558                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3559                         }
3560                 }
3561                 GL_DepthMask(layer->depthmask);
3562                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3563                 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
3564                 {
3565                         layertexrgbscale = 4;
3566                         VectorScale(layer->color, 0.25f, layercolor);
3567                 }
3568                 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
3569                 {
3570                         layertexrgbscale = 2;
3571                         VectorScale(layer->color, 0.5f, layercolor);
3572                 }
3573                 else
3574                 {
3575                         layertexrgbscale = 1;
3576                         VectorScale(layer->color, 1.0f, layercolor);
3577                 }
3578                 layercolor[3] = layer->color[3];
3579                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
3580                 R_Mesh_ColorPointer(NULL);
3581                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3582                 switch (layer->type)
3583                 {
3584                 case TEXTURELAYERTYPE_LITTEXTURE:
3585                         memset(&m, 0, sizeof(m));
3586                         m.tex[0] = R_GetTexture(r_texture_white);
3587                         m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3588                         m.tex[1] = R_GetTexture(layer->texture);
3589                         m.texmatrix[1] = layer->texmatrix;
3590                         m.texrgbscale[1] = layertexrgbscale;
3591                         m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
3592                         R_Mesh_TextureState(&m);
3593                         if (rsurface_lightmode == 2)
3594                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3595                         else if (rsurface_uselightmaptexture)
3596                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3597                         else
3598                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3599                         break;
3600                 case TEXTURELAYERTYPE_TEXTURE:
3601                         memset(&m, 0, sizeof(m));
3602                         m.tex[0] = R_GetTexture(layer->texture);
3603                         m.texmatrix[0] = layer->texmatrix;
3604                         m.texrgbscale[0] = layertexrgbscale;
3605                         m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3606                         R_Mesh_TextureState(&m);
3607                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3608                         break;
3609                 case TEXTURELAYERTYPE_FOG:
3610                         memset(&m, 0, sizeof(m));
3611                         m.texrgbscale[0] = layertexrgbscale;
3612                         if (layer->texture)
3613                         {
3614                                 m.tex[0] = R_GetTexture(layer->texture);
3615                                 m.texmatrix[0] = layer->texmatrix;
3616                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3617                         }
3618                         R_Mesh_TextureState(&m);
3619                         // generate a color array for the fog pass
3620                         R_Mesh_ColorPointer(rsurface_array_color4f);
3621                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3622                         {
3623                                 int i;
3624                                 float f, *v, *c;
3625                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3626                                 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)
3627                                 {
3628                                         f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3629                                         c[0] = layercolor[0];
3630                                         c[1] = layercolor[1];
3631                                         c[2] = layercolor[2];
3632                                         c[3] = f * layercolor[3];
3633                                 }
3634                         }
3635                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3636                         break;
3637                 default:
3638                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3639                 }
3640                 GL_LockArrays(0, 0);
3641         }
3642         CHECKGLERROR
3643         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3644         {
3645                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3646                 GL_AlphaTest(false);
3647         }
3648 }
3649
3650 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3651 {
3652         // OpenGL 1.1 - crusty old voodoo path
3653         int texturesurfaceindex;
3654         qboolean applyfog;
3655         rmeshstate_t m;
3656         int layerindex;
3657         const texturelayer_t *layer;
3658         if (rsurface_mode != RSURFMODE_MULTIPASS)
3659                 rsurface_mode = RSURFMODE_MULTIPASS;
3660         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3661         for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3662         {
3663                 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3664                 {
3665                         if (layerindex == 0)
3666                                 GL_AlphaTest(true);
3667                         else
3668                         {
3669                                 GL_AlphaTest(false);
3670                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3671                         }
3672                 }
3673                 GL_DepthMask(layer->depthmask);
3674                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3675                 R_Mesh_ColorPointer(NULL);
3676                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3677                 switch (layer->type)
3678                 {
3679                 case TEXTURELAYERTYPE_LITTEXTURE:
3680                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3681                         {
3682                                 // two-pass lit texture with 2x rgbscale
3683                                 // first the lightmap pass
3684                                 memset(&m, 0, sizeof(m));
3685                                 m.tex[0] = R_GetTexture(r_texture_white);
3686                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3687                                 R_Mesh_TextureState(&m);
3688                                 if (rsurface_lightmode == 2)
3689                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3690                                 else if (rsurface_uselightmaptexture)
3691                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3692                                 else
3693                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3694                                 GL_LockArrays(0, 0);
3695                                 // then apply the texture to it
3696                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3697                                 memset(&m, 0, sizeof(m));
3698                                 m.tex[0] = R_GetTexture(layer->texture);
3699                                 m.texmatrix[0] = layer->texmatrix;
3700                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3701                                 R_Mesh_TextureState(&m);
3702                                 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);
3703                         }
3704                         else
3705                         {
3706                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3707                                 memset(&m, 0, sizeof(m));
3708                                 m.tex[0] = R_GetTexture(layer->texture);
3709                                 m.texmatrix[0] = layer->texmatrix;
3710                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3711                                 R_Mesh_TextureState(&m);
3712                                 if (rsurface_lightmode == 2)
3713                                         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);
3714                                 else
3715                                         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);
3716                         }
3717                         break;
3718                 case TEXTURELAYERTYPE_TEXTURE:
3719                         // singletexture unlit texture with transparency support
3720                         memset(&m, 0, sizeof(m));
3721                         m.tex[0] = R_GetTexture(layer->texture);
3722                         m.texmatrix[0] = layer->texmatrix;
3723                         m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3724                         R_Mesh_TextureState(&m);
3725                         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);
3726                         break;
3727                 case TEXTURELAYERTYPE_FOG:
3728                         // singletexture fogging
3729                         R_Mesh_ColorPointer(rsurface_array_color4f);
3730                         if (layer->texture)
3731                         {
3732                                 memset(&m, 0, sizeof(m));
3733                                 m.tex[0] = R_GetTexture(layer->texture);
3734                                 m.texmatrix[0] = layer->texmatrix;
3735                                 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3736                                 R_Mesh_TextureState(&m);
3737                         }
3738                         else
3739                                 R_Mesh_ResetTextureState();
3740                         // generate a color array for the fog pass
3741                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3742                         {
3743                                 int i;
3744                                 float f, *v, *c;
3745                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3746                                 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)
3747                                 {
3748                                         f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3749                                         c[0] = layer->color[0];
3750                                         c[1] = layer->color[1];
3751                                         c[2] = layer->color[2];
3752                                         c[3] = f * layer->color[3];
3753                                 }
3754                         }
3755                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3756                         break;
3757                 default:
3758                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3759                 }
3760                 GL_LockArrays(0, 0);
3761         }
3762         CHECKGLERROR
3763         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3764         {
3765                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3766                 GL_AlphaTest(false);
3767         }
3768 }
3769
3770 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3771 {
3772         if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3773                 return;
3774         r_shadow_rtlight = NULL;
3775         r_refdef.stats.entities_surfaces += texturenumsurfaces;
3776         CHECKGLERROR
3777         if (r_showsurfaces.integer)
3778                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3779         else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3780                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3781         else if (rsurface_texture->currentnumlayers)
3782         {
3783                 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3784                 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3785                 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
3786                 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
3787                 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
3788                 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
3789                 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3790                 rsurface_lightmode = ((rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3791                 if (r_glsl.integer && gl_support_fragment_shader)
3792                         R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3793                 else if (gl_combine.integer && r_textureunits.integer >= 2)
3794                         R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3795                 else
3796                         R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3797         }
3798         CHECKGLERROR
3799         GL_LockArrays(0, 0);
3800 }
3801
3802 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3803 {
3804         int i, j;
3805         int texturenumsurfaces, endsurface;
3806         texture_t *texture;
3807         msurface_t *surface;
3808         msurface_t *texturesurfacelist[1024];
3809
3810         // if the model is static it doesn't matter what value we give for
3811         // wantnormals and wanttangents, so this logic uses only rules applicable
3812         // to a model, knowing that they are meaningless otherwise
3813         if (ent == r_refdef.worldentity)
3814                 RSurf_ActiveWorldEntity();
3815         else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3816                 RSurf_ActiveModelEntity(ent, false, false);
3817         else
3818                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3819
3820         for (i = 0;i < numsurfaces;i = j)
3821         {
3822                 j = i + 1;
3823                 surface = rsurface_model->data_surfaces + surfacelist[i];
3824                 texture = surface->texture;
3825                 rsurface_texture = texture->currentframe;
3826                 rsurface_uselightmaptexture = surface->lightmaptexture != NULL;
3827                 // scan ahead until we find a different texture
3828                 endsurface = min(i + 1024, numsurfaces);
3829                 texturenumsurfaces = 0;
3830                 texturesurfacelist[texturenumsurfaces++] = surface;
3831                 for (;j < endsurface;j++)
3832                 {
3833                         surface = rsurface_model->data_surfaces + surfacelist[j];
3834                         if (texture != surface->texture || rsurface_uselightmaptexture != (surface->lightmaptexture != NULL))
3835                                 break;
3836                         texturesurfacelist[texturenumsurfaces++] = surface;
3837                 }
3838                 // render the range of surfaces
3839                 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3840         }
3841
3842         RSurf_CleanUp();
3843 }
3844
3845 void R_QueueSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask)
3846 {
3847         int i, j;
3848         vec3_t tempcenter, center;
3849         texture_t *texture;
3850         // break the surface list down into batches by texture and use of lightmapping
3851         for (i = 0;i < numsurfaces;i = j)
3852         {
3853                 j = i + 1;
3854                 // texture is the base texture pointer, rsurface_texture is the
3855                 // current frame/skin the texture is directing us to use (for example
3856                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
3857                 // use skin 1 instead)
3858                 texture = surfacelist[i]->texture;
3859                 rsurface_texture = texture->currentframe;
3860                 rsurface_uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
3861                 if (!(rsurface_texture->currentmaterialflags & flagsmask))
3862                 {
3863                         // if this texture is not the kind we want, skip ahead to the next one
3864                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
3865                                 ;
3866                         continue;
3867                 }
3868                 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3869                 {
3870                         // transparent surfaces get pushed off into the transparent queue
3871                         const msurface_t *surface = surfacelist[i];
3872                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3873                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3874                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3875                         Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3876                         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);
3877                 }
3878                 else
3879                 {
3880                         // simply scan ahead until we find a different texture or lightmap state
3881                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface_uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
3882                                 ;
3883                         // render the range of surfaces
3884                         R_DrawTextureSurfaceList(j - i, surfacelist + i);
3885                 }
3886         }
3887 }
3888
3889 void R_DrawCollisionBrushes(entity_render_t *ent)
3890 {
3891         int i;
3892         q3mbrush_t *brush;
3893         msurface_t *surface;
3894         model_t *model = ent->model;
3895         if (!model->brush.num_brushes)
3896                 return;
3897         CHECKGLERROR
3898         R_Mesh_ColorPointer(NULL);
3899         R_Mesh_ResetTextureState();
3900         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3901         GL_DepthMask(false);
3902         GL_DepthTest(!r_showdisabledepthtest.integer);
3903         qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3904         for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3905                 if (brush->colbrushf && brush->colbrushf->numtriangles)
3906                         R_DrawCollisionBrush(brush->colbrushf);
3907         for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3908                 if (surface->num_collisiontriangles)
3909                         R_DrawCollisionSurface(ent, surface);
3910         qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
3911 }
3912
3913 void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
3914 {
3915         int i, j, k, l;
3916         const int *elements;
3917         msurface_t *surface;
3918         model_t *model = ent->model;
3919         vec3_t v;
3920         CHECKGLERROR
3921         GL_DepthTest(!r_showdisabledepthtest.integer);
3922         GL_DepthMask(true);
3923         GL_BlendFunc(GL_ONE, GL_ZERO);
3924         R_Mesh_ColorPointer(NULL);
3925         R_Mesh_ResetTextureState();
3926         for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3927         {
3928                 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
3929                         continue;
3930                 rsurface_texture = surface->texture->currentframe;
3931                 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3932                 {
3933                         RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3934                         if (drawtris)
3935                         {
3936                                 if (!rsurface_texture->currentlayers->depthmask)
3937                                         GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
3938                                 else if (ent == r_refdef.worldentity)
3939                                         GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
3940                                 else
3941                                         GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
3942                                 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3943                                 CHECKGLERROR
3944                                 qglBegin(GL_LINES);
3945                                 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3946                                 {
3947                                         qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3948                                         qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3949                                         qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3950                                 }
3951                                 qglEnd();
3952                                 CHECKGLERROR
3953                         }
3954                         if (drawnormals)
3955                         {
3956                                 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
3957                                 qglBegin(GL_LINES);
3958                                 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3959                                 {
3960                                         VectorCopy(rsurface_vertex3f + l * 3, v);
3961                                         qglVertex3f(v[0], v[1], v[2]);
3962                                         VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3963                                         qglVertex3f(v[0], v[1], v[2]);
3964                                 }
3965                                 qglEnd();
3966                                 CHECKGLERROR
3967                                 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
3968                                 qglBegin(GL_LINES);
3969                                 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3970                                 {
3971                                         VectorCopy(rsurface_vertex3f + l * 3, v);
3972                                         qglVertex3f(v[0], v[1], v[2]);
3973                                         VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3974                                         qglVertex3f(v[0], v[1], v[2]);
3975                                 }
3976                                 qglEnd();
3977                                 CHECKGLERROR
3978                                 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
3979                                 qglBegin(GL_LINES);
3980                                 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3981                                 {
3982                                         VectorCopy(rsurface_vertex3f + l * 3, v);
3983                                         qglVertex3f(v[0], v[1], v[2]);
3984                                         VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3985                                         qglVertex3f(v[0], v[1], v[2]);
3986                                 }
3987                                 qglEnd();
3988                                 CHECKGLERROR
3989                         }
3990                 }
3991         }
3992         rsurface_texture = NULL;
3993 }
3994
3995 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3996 void R_DrawWorldSurfaces(qboolean skysurfaces)
3997 {
3998         int i, j, endj, f, flagsmask;
3999         int counttriangles = 0;
4000         msurface_t *surface, **surfacechain;
4001         texture_t *t;
4002         model_t *model = r_refdef.worldmodel;
4003         const int maxsurfacelist = 1024;
4004         int numsurfacelist = 0;
4005         msurface_t *surfacelist[1024];
4006         if (model == NULL)
4007                 return;
4008
4009         RSurf_ActiveWorldEntity();
4010
4011         // update light styles
4012         if (!skysurfaces && model->brushq1.light_styleupdatechains)
4013         {
4014                 for (i = 0;i < model->brushq1.light_styles;i++)
4015                 {
4016                         if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
4017                         {
4018                                 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
4019                                 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
4020                                         for (;(surface = *surfacechain);surfacechain++)
4021                                                 surface->cached_dlight = true;
4022                         }
4023                 }
4024         }
4025
4026         R_UpdateAllTextureInfo(r_refdef.worldentity);
4027         flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
4028         f = 0;
4029         t = NULL;
4030         rsurface_uselightmaptexture = false;
4031         rsurface_texture = NULL;
4032         numsurfacelist = 0;
4033         j = model->firstmodelsurface;
4034         endj = j + model->nummodelsurfaces;
4035         while (j < endj)
4036         {
4037                 // quickly skip over non-visible surfaces
4038                 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
4039                         ;
4040                 // quickly iterate over visible surfaces
4041                 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
4042                 {
4043                         // process this surface
4044                         surface = model->data_surfaces + j;
4045                         // if this surface fits the criteria, add it to the list
4046                         if (surface->num_triangles)
4047                         {
4048                                 // if lightmap parameters changed, rebuild lightmap texture
4049                                 if (surface->cached_dlight)
4050                                         R_BuildLightMap(r_refdef.worldentity, surface);
4051                                 // add face to draw list
4052                                 surfacelist[numsurfacelist++] = surface;
4053                                 counttriangles += surface->num_triangles;
4054                                 if (numsurfacelist >= maxsurfacelist)
4055                                 {
4056                                         R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4057                                         numsurfacelist = 0;
4058                                 }
4059                         }
4060                 }
4061         }
4062         if (numsurfacelist)
4063                 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4064         r_refdef.stats.entities_triangles += counttriangles;
4065         RSurf_CleanUp();
4066
4067         if (r_showcollisionbrushes.integer && !skysurfaces)
4068                 R_DrawCollisionBrushes(r_refdef.worldentity);
4069
4070         if (r_showtris.integer || r_shownormals.integer)
4071                 R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
4072 }
4073
4074 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces)
4075 {
4076         int i, f, flagsmask;
4077         int counttriangles = 0;
4078         msurface_t *surface, *endsurface, **surfacechain;
4079         texture_t *t;
4080         model_t *model = ent->model;
4081         const int maxsurfacelist = 1024;
4082         int numsurfacelist = 0;
4083         msurface_t *surfacelist[1024];
4084         if (model == NULL)
4085                 return;
4086
4087         // if the model is static it doesn't matter what value we give for
4088         // wantnormals and wanttangents, so this logic uses only rules applicable
4089         // to a model, knowing that they are meaningless otherwise
4090         if (ent == r_refdef.worldentity)
4091                 RSurf_ActiveWorldEntity();
4092         else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
4093                 RSurf_ActiveModelEntity(ent, false, false);
4094         else
4095                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
4096
4097         // update light styles
4098         if (!skysurfaces && model->brushq1.light_styleupdatechains)
4099         {
4100                 for (i = 0;i < model->brushq1.light_styles;i++)
4101                 {
4102                         if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
4103                         {
4104                                 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
4105                                 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
4106                                         for (;(surface = *surfacechain);surfacechain++)
4107                                                 surface->cached_dlight = true;
4108                         }
4109                 }
4110         }
4111
4112         R_UpdateAllTextureInfo(ent);
4113         flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
4114         f = 0;
4115         t = NULL;
4116         rsurface_uselightmaptexture = false;
4117         rsurface_texture = NULL;
4118         numsurfacelist = 0;
4119         surface = model->data_surfaces + model->firstmodelsurface;
4120         endsurface = surface + model->nummodelsurfaces;
4121         for (;surface < endsurface;surface++)
4122         {
4123                 // if this surface fits the criteria, add it to the list
4124                 if (surface->num_triangles)
4125                 {
4126                         // if lightmap parameters changed, rebuild lightmap texture
4127                         if (surface->cached_dlight)
4128                                 R_BuildLightMap(ent, surface);
4129                         // add face to draw list
4130                         surfacelist[numsurfacelist++] = surface;
4131                         counttriangles += surface->num_triangles;
4132                         if (numsurfacelist >= maxsurfacelist)
4133                         {
4134                                 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4135                                 numsurfacelist = 0;
4136                         }
4137                 }
4138         }
4139         if (numsurfacelist)
4140                 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4141         r_refdef.stats.entities_triangles += counttriangles;
4142         RSurf_CleanUp();
4143
4144         if (r_showcollisionbrushes.integer && !skysurfaces)
4145                 R_DrawCollisionBrushes(ent);
4146
4147         if (r_showtris.integer || r_shownormals.integer)
4148                 R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);
4149 }