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