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