]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
375 (-1)
[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 // used for dlight push checking and other things
27 int r_framecount;
28
29 mplane_t frustum[5];
30
31 matrix4x4_t r_identitymatrix;
32
33 int c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights, c_meshs, c_meshelements, c_rt_lights, c_rt_clears, c_rt_scissored, c_rt_shadowmeshes, c_rt_shadowtris, c_rt_lightmeshes, c_rt_lighttris, c_rtcached_shadowmeshes, c_rtcached_shadowtris, c_bloom, c_bloomcopies, c_bloomcopypixels, c_bloomdraws, c_bloomdrawpixels;
34
35 // true during envmap command capture
36 qboolean envmap;
37
38 // maximum visible distance (recalculated from world box each frame)
39 float r_farclip;
40 // brightness of world lightmaps and related lighting
41 // (often reduced when world rtlights are enabled)
42 float r_lightmapintensity;
43 // whether to draw world lights realtime, dlights realtime, and their shadows
44 qboolean r_rtworld;
45 qboolean r_rtworldshadows;
46 qboolean r_rtdlight;
47 qboolean r_rtdlightshadows;
48
49
50 // forces all rendering to draw triangle outlines
51 int r_showtrispass;
52
53 // view origin
54 vec3_t r_vieworigin;
55 vec3_t r_viewforward;
56 vec3_t r_viewleft;
57 vec3_t r_viewright;
58 vec3_t r_viewup;
59 int r_view_x;
60 int r_view_y;
61 int r_view_z;
62 int r_view_width;
63 int r_view_height;
64 int r_view_depth;
65 float r_view_fov_x;
66 float r_view_fov_y;
67 matrix4x4_t r_view_matrix;
68
69 //
70 // screen size info
71 //
72 refdef_t r_refdef;
73
74 // 8.8 fraction of base light value
75 unsigned short d_lightstylevalue[256];
76
77 cvar_t r_showtris = {0, "r_showtris", "0"};
78 cvar_t r_drawentities = {0, "r_drawentities","1"};
79 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
80 cvar_t r_speeds = {0, "r_speeds","0"};
81 cvar_t r_fullbright = {0, "r_fullbright","0"};
82 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
83 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
84 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
85 cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0"};
86
87 cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
88 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"};
89 cvar_t gl_fogred = {0, "gl_fogred","0.3"};
90 cvar_t gl_foggreen = {0, "gl_foggreen","0.3"};
91 cvar_t gl_fogblue = {0, "gl_fogblue","0.3"};
92 cvar_t gl_fogstart = {0, "gl_fogstart", "0"};
93 cvar_t gl_fogend = {0, "gl_fogend","0"};
94
95 cvar_t r_textureunits = {0, "r_textureunits", "32"};
96
97 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"};
98 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"};
99 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"};
100 cvar_t r_watershader = {CVAR_SAVE, "r_watershader", "1"};
101
102 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0"};
103 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "2"};
104 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "8"};
105 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320"};
106 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "4"};
107
108 cvar_t developer_texturelogging = {0, "developer_texturelogging", "1"};
109
110 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0"};
111
112 rtexturepool_t *r_main_texturepool;
113 rtexture_t *r_bloom_texture_screen;
114 rtexture_t *r_bloom_texture_bloom;
115 rtexture_t *r_texture_blanknormalmap;
116 rtexture_t *r_texture_white;
117 rtexture_t *r_texture_black;
118 rtexture_t *r_texture_notexture;
119 rtexture_t *r_texture_whitecube;
120 rtexture_t *r_texture_normalizationcube;
121 rtexture_t *r_texture_detailtextures[NUM_DETAILTEXTURES];
122 rtexture_t *r_texture_distorttexture[64];
123
124 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
125 {
126         int i;
127         for (i = 0;i < verts;i++)
128         {
129                 out[0] = in[0] * r;
130                 out[1] = in[1] * g;
131                 out[2] = in[2] * b;
132                 out[3] = in[3];
133                 in += 4;
134                 out += 4;
135         }
136 }
137
138 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
139 {
140         int i;
141         for (i = 0;i < verts;i++)
142         {
143                 out[0] = r;
144                 out[1] = g;
145                 out[2] = b;
146                 out[3] = a;
147                 out += 4;
148         }
149 }
150
151 vec3_t fogcolor;
152 vec_t fogdensity;
153 float fog_density, fog_red, fog_green, fog_blue;
154 qboolean fogenabled;
155 qboolean oldgl_fogenable;
156 void R_UpdateFog(void)
157 {
158         if (gamemode == GAME_NEHAHRA)
159         {
160                 if (gl_fogenable.integer)
161                 {
162                         oldgl_fogenable = true;
163                         fog_density = gl_fogdensity.value;
164                         fog_red = gl_fogred.value;
165                         fog_green = gl_foggreen.value;
166                         fog_blue = gl_fogblue.value;
167                 }
168                 else if (oldgl_fogenable)
169                 {
170                         oldgl_fogenable = false;
171                         fog_density = 0;
172                         fog_red = 0;
173                         fog_green = 0;
174                         fog_blue = 0;
175                 }
176         }
177         if (fog_density)
178         {
179                 fogcolor[0] = fog_red   = bound(0.0f, fog_red  , 1.0f);
180                 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
181                 fogcolor[2] = fog_blue  = bound(0.0f, fog_blue , 1.0f);
182         }
183         if (fog_density)
184         {
185                 fogenabled = true;
186                 fogdensity = -4000.0f / (fog_density * fog_density);
187                 // fog color was already set
188         }
189         else
190                 fogenabled = false;
191 }
192
193 // FIXME: move this to client?
194 void FOG_clear(void)
195 {
196         if (gamemode == GAME_NEHAHRA)
197         {
198                 Cvar_Set("gl_fogenable", "0");
199                 Cvar_Set("gl_fogdensity", "0.2");
200                 Cvar_Set("gl_fogred", "0.3");
201                 Cvar_Set("gl_foggreen", "0.3");
202                 Cvar_Set("gl_fogblue", "0.3");
203         }
204         fog_density = fog_red = fog_green = fog_blue = 0.0f;
205 }
206
207 // FIXME: move this to client?
208 void FOG_registercvars(void)
209 {
210         if (gamemode == GAME_NEHAHRA)
211         {
212                 Cvar_RegisterVariable (&gl_fogenable);
213                 Cvar_RegisterVariable (&gl_fogdensity);
214                 Cvar_RegisterVariable (&gl_fogred);
215                 Cvar_RegisterVariable (&gl_foggreen);
216                 Cvar_RegisterVariable (&gl_fogblue);
217                 Cvar_RegisterVariable (&gl_fogstart);
218                 Cvar_RegisterVariable (&gl_fogend);
219         }
220 }
221
222 static void R_BuildDetailTextures (void)
223 {
224         int i, x, y, light;
225         float vc[3], vx[3], vy[3], vn[3], lightdir[3];
226 #define DETAILRESOLUTION 256
227         qbyte (*data)[DETAILRESOLUTION][4];
228         qbyte (*noise)[DETAILRESOLUTION];
229
230         // Allocate the buffers dynamically to avoid having such big guys on the stack
231         data = Mem_Alloc(tempmempool, DETAILRESOLUTION * sizeof(*data));
232         noise = Mem_Alloc(tempmempool, DETAILRESOLUTION * sizeof(*noise));
233
234         lightdir[0] = 0.5;
235         lightdir[1] = 1;
236         lightdir[2] = -0.25;
237         VectorNormalize(lightdir);
238         for (i = 0;i < NUM_DETAILTEXTURES;i++)
239         {
240                 fractalnoise(&noise[0][0], DETAILRESOLUTION, DETAILRESOLUTION >> 4);
241                 for (y = 0;y < DETAILRESOLUTION;y++)
242                 {
243                         for (x = 0;x < DETAILRESOLUTION;x++)
244                         {
245                                 vc[0] = x;
246                                 vc[1] = y;
247                                 vc[2] = noise[y][x] * (1.0f / 32.0f);
248                                 vx[0] = x + 1;
249                                 vx[1] = y;
250                                 vx[2] = noise[y][(x + 1) % DETAILRESOLUTION] * (1.0f / 32.0f);
251                                 vy[0] = x;
252                                 vy[1] = y + 1;
253                                 vy[2] = noise[(y + 1) % DETAILRESOLUTION][x] * (1.0f / 32.0f);
254                                 VectorSubtract(vx, vc, vx);
255                                 VectorSubtract(vy, vc, vy);
256                                 CrossProduct(vx, vy, vn);
257                                 VectorNormalize(vn);
258                                 light = 128 - DotProduct(vn, lightdir) * 128;
259                                 light = bound(0, light, 255);
260                                 data[y][x][0] = data[y][x][1] = data[y][x][2] = light;
261                                 data[y][x][3] = 255;
262                         }
263                 }
264                 r_texture_detailtextures[i] = R_LoadTexture2D(r_main_texturepool, va("detailtexture%i", i), DETAILRESOLUTION, DETAILRESOLUTION, &data[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_PRECACHE, NULL);
265         }
266
267         Mem_Free(noise);
268         Mem_Free(data);
269 }
270
271 static qbyte R_MorphDistortTexture (double y0, double y1, double y2, double y3, double morph)
272 {
273         int m = (int)(((y1 + y3 - (y0 + y2)) * morph * morph * morph) +
274                         ((2 * (y0 - y1) + y2 - y3) * morph * morph) +
275                         ((y2 - y0) * morph) +
276                         (y1));
277         return (qbyte)bound(0, m, 255);
278 }
279
280 static void R_BuildDistortTexture (void)
281 {
282         int x, y, i, j;
283 #define DISTORTRESOLUTION 32
284         qbyte data[5][DISTORTRESOLUTION][DISTORTRESOLUTION][2];
285
286         for (i=0; i<4; i++)
287         {
288                 for (y=0; y<DISTORTRESOLUTION; y++)
289                 {
290                         for (x=0; x<DISTORTRESOLUTION; x++)
291                         {
292                                 data[i][y][x][0] = rand () & 255;
293                                 data[i][y][x][1] = rand () & 255;
294                         }
295                 }
296         }
297
298         for (i=0; i<4; i++)
299         {
300                 for (j=0; j<16; j++)
301                 {
302                         r_texture_distorttexture[i*16+j] = NULL;
303                         if (gl_textureshader)
304                         {
305                                 for (y=0; y<DISTORTRESOLUTION; y++)
306                                 {
307                                         for (x=0; x<DISTORTRESOLUTION; x++)
308                                         {
309                                                 data[4][y][x][0] = R_MorphDistortTexture (data[(i-1)&3][y][x][0], data[i][y][x][0], data[(i+1)&3][y][x][0], data[(i+2)&3][y][x][0], 0.0625*j);
310                                                 data[4][y][x][1] = R_MorphDistortTexture (data[(i-1)&3][y][x][1], data[i][y][x][1], data[(i+1)&3][y][x][1], data[(i+2)&3][y][x][1], 0.0625*j);
311                                         }
312                                 }
313                                 r_texture_distorttexture[i*16+j] = R_LoadTexture2D(r_main_texturepool, va("distorttexture%i", i*16+j), DISTORTRESOLUTION, DISTORTRESOLUTION, &data[4][0][0][0], TEXTYPE_DSDT, TEXF_PRECACHE, NULL);
314                         }
315                 }
316         }
317 }
318
319 static void R_BuildBlankTextures(void)
320 {
321         qbyte data[4];
322         data[0] = 128; // normal X
323         data[1] = 128; // normal Y
324         data[2] = 255; // normal Z
325         data[3] = 128; // height
326         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
327         data[0] = 255;
328         data[1] = 255;
329         data[2] = 255;
330         data[3] = 255;
331         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
332         data[0] = 0;
333         data[1] = 0;
334         data[2] = 0;
335         data[3] = 255;
336         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
337 }
338
339 static void R_BuildNoTexture(void)
340 {
341         int x, y;
342         qbyte pix[16][16][4];
343         // this makes a light grey/dark grey checkerboard texture
344         for (y = 0;y < 16;y++)
345         {
346                 for (x = 0;x < 16;x++)
347                 {
348                         if ((y < 8) ^ (x < 8))
349                         {
350                                 pix[y][x][0] = 128;
351                                 pix[y][x][1] = 128;
352                                 pix[y][x][2] = 128;
353                                 pix[y][x][3] = 255;
354                         }
355                         else
356                         {
357                                 pix[y][x][0] = 64;
358                                 pix[y][x][1] = 64;
359                                 pix[y][x][2] = 64;
360                                 pix[y][x][3] = 255;
361                         }
362                 }
363         }
364         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
365 }
366
367 static void R_BuildWhiteCube(void)
368 {
369         qbyte data[6*1*1*4];
370         data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
371         data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
372         data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
373         data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
374         data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
375         data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
376         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
377 }
378
379 static void R_BuildNormalizationCube(void)
380 {
381         int x, y, side;
382         vec3_t v;
383         vec_t s, t, intensity;
384 #define NORMSIZE 64
385         qbyte data[6][NORMSIZE][NORMSIZE][4];
386         for (side = 0;side < 6;side++)
387         {
388                 for (y = 0;y < NORMSIZE;y++)
389                 {
390                         for (x = 0;x < NORMSIZE;x++)
391                         {
392                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
393                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
394                                 switch(side)
395                                 {
396                                 case 0:
397                                         v[0] = 1;
398                                         v[1] = -t;
399                                         v[2] = -s;
400                                         break;
401                                 case 1:
402                                         v[0] = -1;
403                                         v[1] = -t;
404                                         v[2] = s;
405                                         break;
406                                 case 2:
407                                         v[0] = s;
408                                         v[1] = 1;
409                                         v[2] = t;
410                                         break;
411                                 case 3:
412                                         v[0] = s;
413                                         v[1] = -1;
414                                         v[2] = -t;
415                                         break;
416                                 case 4:
417                                         v[0] = s;
418                                         v[1] = -t;
419                                         v[2] = 1;
420                                         break;
421                                 case 5:
422                                         v[0] = -s;
423                                         v[1] = -t;
424                                         v[2] = -1;
425                                         break;
426                                 }
427                                 intensity = 127.0f / sqrt(DotProduct(v, v));
428                                 data[side][y][x][0] = 128.0f + intensity * v[0];
429                                 data[side][y][x][1] = 128.0f + intensity * v[1];
430                                 data[side][y][x][2] = 128.0f + intensity * v[2];
431                                 data[side][y][x][3] = 255;
432                         }
433                 }
434         }
435         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
436 }
437
438 void gl_main_start(void)
439 {
440         r_main_texturepool = R_AllocTexturePool();
441         r_bloom_texture_screen = NULL;
442         r_bloom_texture_bloom = NULL;
443         R_BuildBlankTextures();
444         R_BuildNoTexture();
445         R_BuildDetailTextures();
446         R_BuildDistortTexture();
447         if (gl_texturecubemap)
448         {
449                 R_BuildWhiteCube();
450                 R_BuildNormalizationCube();
451         }
452 }
453
454 void gl_main_shutdown(void)
455 {
456         R_FreeTexturePool(&r_main_texturepool);
457         r_bloom_texture_screen = NULL;
458         r_bloom_texture_bloom = NULL;
459         r_texture_blanknormalmap = NULL;
460         r_texture_white = NULL;
461         r_texture_black = NULL;
462         r_texture_whitecube = NULL;
463         r_texture_normalizationcube = NULL;
464 }
465
466 extern void CL_ParseEntityLump(char *entitystring);
467 void gl_main_newmap(void)
468 {
469         // FIXME: move this code to client
470         int l;
471         char *entities, entname[MAX_QPATH];
472         r_framecount = 1;
473         if (cl.worldmodel)
474         {
475                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
476                 l = strlen(entname) - 4;
477                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
478                 {
479                         strcpy(entname + l, ".ent");
480                         if ((entities = FS_LoadFile(entname, tempmempool, true)))
481                         {
482                                 CL_ParseEntityLump(entities);
483                                 Mem_Free(entities);
484                                 return;
485                         }
486                 }
487                 if (cl.worldmodel->brush.entities)
488                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
489         }
490 }
491
492 void GL_Main_Init(void)
493 {
494         Matrix4x4_CreateIdentity(&r_identitymatrix);
495 // FIXME: move this to client?
496         FOG_registercvars();
497         Cvar_RegisterVariable(&r_showtris);
498         Cvar_RegisterVariable(&r_drawentities);
499         Cvar_RegisterVariable(&r_drawviewmodel);
500         Cvar_RegisterVariable(&r_speeds);
501         Cvar_RegisterVariable(&r_fullbrights);
502         Cvar_RegisterVariable(&r_wateralpha);
503         Cvar_RegisterVariable(&r_dynamic);
504         Cvar_RegisterVariable(&r_fullbright);
505         Cvar_RegisterVariable(&r_textureunits);
506         Cvar_RegisterVariable(&r_lerpsprites);
507         Cvar_RegisterVariable(&r_lerpmodels);
508         Cvar_RegisterVariable(&r_waterscroll);
509         Cvar_RegisterVariable(&r_watershader);
510         Cvar_RegisterVariable(&r_drawcollisionbrushes);
511         Cvar_RegisterVariable(&r_bloom);
512         Cvar_RegisterVariable(&r_bloom_intensity);
513         Cvar_RegisterVariable(&r_bloom_blur);
514         Cvar_RegisterVariable(&r_bloom_resolution);
515         Cvar_RegisterVariable(&r_bloom_power);
516         Cvar_RegisterVariable(&developer_texturelogging);
517         Cvar_RegisterVariable(&gl_lightmaps);
518         if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
519                 Cvar_SetValue("r_fullbrights", 0);
520         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
521 }
522
523 static vec3_t r_farclip_origin;
524 static vec3_t r_farclip_direction;
525 static vec_t r_farclip_directiondist;
526 static vec_t r_farclip_meshfarclip;
527 static int r_farclip_directionbit0;
528 static int r_farclip_directionbit1;
529 static int r_farclip_directionbit2;
530
531 // enlarge farclip to accomodate box
532 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
533 {
534         float d;
535         d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
536           + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
537           + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
538         if (r_farclip_meshfarclip < d)
539                 r_farclip_meshfarclip = d;
540 }
541
542 // return farclip value
543 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
544 {
545         int i;
546
547         VectorCopy(origin, r_farclip_origin);
548         VectorCopy(direction, r_farclip_direction);
549         r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
550         r_farclip_directionbit0 = r_farclip_direction[0] < 0;
551         r_farclip_directionbit1 = r_farclip_direction[1] < 0;
552         r_farclip_directionbit2 = r_farclip_direction[2] < 0;
553         r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
554
555         if (r_refdef.worldmodel)
556                 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
557         for (i = 0;i < r_refdef.numentities;i++)
558                 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
559
560         return r_farclip_meshfarclip - r_farclip_directiondist;
561 }
562
563 extern void R_Textures_Init(void);
564 extern void GL_Draw_Init(void);
565 extern void GL_Main_Init(void);
566 extern void R_Shadow_Init(void);
567 extern void R_Sky_Init(void);
568 extern void GL_Surf_Init(void);
569 extern void R_Crosshairs_Init(void);
570 extern void R_Light_Init(void);
571 extern void R_Particles_Init(void);
572 extern void R_Explosion_Init(void);
573 extern void gl_backend_init(void);
574 extern void Sbar_Init(void);
575 extern void R_LightningBeams_Init(void);
576 extern void Mod_RenderInit(void);
577
578 void Render_Init(void)
579 {
580         gl_backend_init();
581         R_Textures_Init();
582         Mod_RenderInit();
583         R_MeshQueue_Init();
584         GL_Main_Init();
585         GL_Draw_Init();
586         R_Shadow_Init();
587         R_Sky_Init();
588         GL_Surf_Init();
589         R_Crosshairs_Init();
590         R_Light_Init();
591         R_Particles_Init();
592         R_Explosion_Init();
593         UI_Init();
594         Sbar_Init();
595         R_LightningBeams_Init();
596 }
597
598 /*
599 ===============
600 GL_Init
601 ===============
602 */
603 extern char *ENGINE_EXTENSIONS;
604 void GL_Init (void)
605 {
606         VID_CheckExtensions();
607
608         // LordHavoc: report supported extensions
609         Con_DPrintf("\nengine extensions: %s\n", ENGINE_EXTENSIONS);
610
611         // clear to black (loading plaque will be seen over this)
612         qglClearColor(0,0,0,1);
613         qglClear(GL_COLOR_BUFFER_BIT);
614 }
615
616 int R_CullBox(const vec3_t mins, const vec3_t maxs)
617 {
618         int i;
619         mplane_t *p;
620         for (i = 0;i < 4;i++)
621         {
622                 p = frustum + i;
623                 switch(p->signbits)
624                 {
625                 default:
626                 case 0:
627                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
628                                 return true;
629                         break;
630                 case 1:
631                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
632                                 return true;
633                         break;
634                 case 2:
635                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
636                                 return true;
637                         break;
638                 case 3:
639                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
640                                 return true;
641                         break;
642                 case 4:
643                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
644                                 return true;
645                         break;
646                 case 5:
647                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
648                                 return true;
649                         break;
650                 case 6:
651                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
652                                 return true;
653                         break;
654                 case 7:
655                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
656                                 return true;
657                         break;
658                 }
659         }
660         return false;
661 }
662
663 //==================================================================================
664
665 static void R_MarkEntities (void)
666 {
667         int i, renderimask;
668         entity_render_t *ent;
669
670         if (!r_drawentities.integer)
671                 return;
672
673         r_refdef.worldentity->visframe = r_framecount;
674         renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
675         if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
676         {
677                 // worldmodel can check visibility
678                 for (i = 0;i < r_refdef.numentities;i++)
679                 {
680                         ent = r_refdef.entities[i];
681                         Mod_CheckLoaded(ent->model);
682                         // some of the renderer still relies on origin...
683                         Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
684                         // some of the renderer still relies on scale...
685                         ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
686                         if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_worldleafvisible, ent->mins, ent->maxs)))
687                         {
688                                 R_UpdateEntLights(ent);
689                                 ent->visframe = r_framecount;
690                         }
691                 }
692         }
693         else
694         {
695                 // no worldmodel or it can't check visibility
696                 for (i = 0;i < r_refdef.numentities;i++)
697                 {
698                         ent = r_refdef.entities[i];
699                         Mod_CheckLoaded(ent->model);
700                         // some of the renderer still relies on origin...
701                         Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
702                         // some of the renderer still relies on scale...
703                         ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
704                         if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
705                         {
706                                 R_UpdateEntLights(ent);
707                                 ent->visframe = r_framecount;
708                         }
709                 }
710         }
711 }
712
713 // only used if skyrendermasked, and normally returns false
714 int R_DrawBrushModelsSky (void)
715 {
716         int i, sky;
717         entity_render_t *ent;
718
719         if (!r_drawentities.integer)
720                 return false;
721
722         sky = false;
723         for (i = 0;i < r_refdef.numentities;i++)
724         {
725                 ent = r_refdef.entities[i];
726                 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
727                 {
728                         ent->model->DrawSky(ent);
729                         sky = true;
730                 }
731         }
732         return sky;
733 }
734
735 void R_DrawNoModel(entity_render_t *ent);
736 void R_DrawModels(void)
737 {
738         int i;
739         entity_render_t *ent;
740
741         if (!r_drawentities.integer)
742                 return;
743
744         for (i = 0;i < r_refdef.numentities;i++)
745         {
746                 ent = r_refdef.entities[i];
747                 if (ent->visframe == r_framecount)
748                 {
749                         if (ent->model && ent->model->Draw != NULL)
750                                 ent->model->Draw(ent);
751                         else
752                                 R_DrawNoModel(ent);
753                 }
754         }
755 }
756
757 static void R_SetFrustum(void)
758 {
759         // break apart the view matrix into vectors for various purposes
760         Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
761         VectorNegate(r_viewleft, r_viewright);
762
763         // LordHavoc: note to all quake engine coders, the special case for 90
764         // degrees assumed a square view (wrong), so I removed it, Quake2 has it
765         // disabled as well.
766
767         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
768         RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_view_fov_x / 2));
769         frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
770         PlaneClassify(&frustum[0]);
771
772         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
773         RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_view_fov_x / 2));
774         frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
775         PlaneClassify(&frustum[1]);
776
777         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
778         RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_view_fov_y / 2));
779         frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
780         PlaneClassify(&frustum[2]);
781
782         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
783         RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_view_fov_y / 2));
784         frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
785         PlaneClassify(&frustum[3]);
786
787         // nearclip plane
788         VectorCopy(r_viewforward, frustum[4].normal);
789         frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
790         PlaneClassify(&frustum[4]);
791 }
792
793 static void R_BlendView(void)
794 {
795         rmeshstate_t m;
796
797         if (r_refdef.viewblend[3] < 0.01f && !r_bloom.integer)
798                 return;
799
800         GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
801         GL_DepthMask(true);
802         GL_DepthTest(false);
803         R_Mesh_Matrix(&r_identitymatrix);
804         // vertex coordinates for a quad that covers the screen exactly
805         varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
806         varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
807         varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
808         varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
809         if (r_bloom.integer && 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)
810         {
811                 int screenwidth, screenheight, bloomwidth, bloomheight, x, dobloomblend, range;
812                 float xoffset, yoffset, r;
813                 c_bloom++;
814                 // set the (poorly named) screenwidth and screenheight variables to
815                 // a power of 2 at least as large as the screen, these will define the
816                 // size of the texture to allocate
817                 for (screenwidth = 1;screenwidth < vid.realwidth;screenwidth *= 2);
818                 for (screenheight = 1;screenheight < vid.realheight;screenheight *= 2);
819                 // allocate textures as needed
820                 if (!r_bloom_texture_screen)
821                         r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
822                 if (!r_bloom_texture_bloom)
823                         r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
824                 // set bloomwidth and bloomheight to the bloom resolution that will be
825                 // used (often less than the screen resolution for faster rendering)
826                 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
827                 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
828                 // set up a texcoord array for the full resolution screen image
829                 // (we have to keep this around to copy back during final render)
830                 varray_texcoord2f[0][0] = 0;
831                 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
832                 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
833                 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
834                 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
835                 varray_texcoord2f[0][5] = 0;
836                 varray_texcoord2f[0][6] = 0;
837                 varray_texcoord2f[0][7] = 0;
838                 // set up a texcoord array for the reduced resolution bloom image
839                 // (which will be additive blended over the screen image)
840                 varray_texcoord2f[1][0] = 0;
841                 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
842                 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
843                 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
844                 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
845                 varray_texcoord2f[1][5] = 0;
846                 varray_texcoord2f[1][6] = 0;
847                 varray_texcoord2f[1][7] = 0;
848                 memset(&m, 0, sizeof(m));
849                 m.pointer_vertex = varray_vertex3f;
850                 m.pointer_texcoord[0] = varray_texcoord2f[0];
851                 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
852                 R_Mesh_State(&m);
853                 // copy view into the full resolution screen image texture
854                 GL_ActiveTexture(0);
855                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.realheight - (r_view_y + r_view_height), r_view_width, r_view_height);
856                 c_bloomcopies++;
857                 c_bloomcopypixels += r_view_width * r_view_height;
858                 // now scale it down to the bloom size and raise to a power of itself
859                 // to darken it (this leaves the really bright stuff bright, and
860                 // everything else becomes very dark)
861                 // TODO: optimize with multitexture or GLSL
862                 qglViewport(r_view_x, vid.realheight - (r_view_y + bloomheight), bloomwidth, bloomheight);
863                 GL_BlendFunc(GL_ONE, GL_ZERO);
864                 GL_Color(1, 1, 1, 1);
865                 R_Mesh_Draw(0, 4, 2, polygonelements);
866                 c_bloomdraws++;
867                 c_bloomdrawpixels += bloomwidth * bloomheight;
868                 // render multiple times with a multiply blendfunc to raise to a power
869                 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
870                 for (x = 1;x < r_bloom_power.integer;x++)
871                 {
872                         R_Mesh_Draw(0, 4, 2, polygonelements);
873                         c_bloomdraws++;
874                         c_bloomdrawpixels += bloomwidth * bloomheight;
875                 }
876                 // we now have a darkened bloom image in the framebuffer, copy it into
877                 // the bloom image texture for more processing
878                 memset(&m, 0, sizeof(m));
879                 m.pointer_vertex = varray_vertex3f;
880                 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
881                 m.pointer_texcoord[0] = varray_texcoord2f[2];
882                 R_Mesh_State(&m);
883                 GL_ActiveTexture(0);
884                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.realheight - (r_view_y + bloomheight), bloomwidth, bloomheight);
885                 c_bloomcopies++;
886                 c_bloomcopypixels += bloomwidth * bloomheight;
887                 // blend on at multiple vertical offsets to achieve a vertical blur
888                 // TODO: do offset blends using GLSL
889                 range = r_bloom_blur.integer * bloomwidth / 320;
890                 GL_BlendFunc(GL_ONE, GL_ZERO);
891                 for (x = -range;x <= range;x++)
892                 {
893                         xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
894                         yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
895                         // compute a texcoord array with the specified x and y offset
896                         varray_texcoord2f[2][0] = xoffset+0;
897                         varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
898                         varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
899                         varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
900                         varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
901                         varray_texcoord2f[2][5] = yoffset+0;
902                         varray_texcoord2f[2][6] = xoffset+0;
903                         varray_texcoord2f[2][7] = yoffset+0;
904                         // this r value looks like a 'dot' particle, fading sharply to
905                         // black at the edges
906                         // (probably not realistic but looks good enough)
907                         r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
908                         if (r < 0.01f)
909                                 continue;
910                         GL_Color(r, r, r, 1);
911                         R_Mesh_Draw(0, 4, 2, polygonelements);
912                         c_bloomdraws++;
913                         c_bloomdrawpixels += bloomwidth * bloomheight;
914                         GL_BlendFunc(GL_ONE, GL_ONE);
915                 }
916                 // copy the vertically blurred bloom view to a texture
917                 GL_ActiveTexture(0);
918                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.realheight - (r_view_y + bloomheight), bloomwidth, bloomheight);
919                 c_bloomcopies++;
920                 c_bloomcopypixels += bloomwidth * bloomheight;
921                 // blend the vertically blurred image at multiple offsets horizontally
922                 // to finish the blur effect
923                 // TODO: do offset blends using GLSL
924                 range = r_bloom_blur.integer * bloomwidth / 320;
925                 GL_BlendFunc(GL_ONE, GL_ZERO);
926                 for (x = -range;x <= range;x++)
927                 {
928                         xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
929                         yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
930                         // compute a texcoord array with the specified x and y offset
931                         varray_texcoord2f[2][0] = xoffset+0;
932                         varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
933                         varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
934                         varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
935                         varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
936                         varray_texcoord2f[2][5] = yoffset+0;
937                         varray_texcoord2f[2][6] = xoffset+0;
938                         varray_texcoord2f[2][7] = yoffset+0;
939                         // this r value looks like a 'dot' particle, fading sharply to
940                         // black at the edges
941                         // (probably not realistic but looks good enough)
942                         r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
943                         if (r < 0.01f)
944                                 continue;
945                         GL_Color(r, r, r, 1);
946                         R_Mesh_Draw(0, 4, 2, polygonelements);
947                         c_bloomdraws++;
948                         c_bloomdrawpixels += bloomwidth * bloomheight;
949                         GL_BlendFunc(GL_ONE, GL_ONE);
950                 }
951                 // copy the blurred bloom view to a texture
952                 GL_ActiveTexture(0);
953                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.realheight - (r_view_y + bloomheight), bloomwidth, bloomheight);
954                 c_bloomcopies++;
955                 c_bloomcopypixels += bloomwidth * bloomheight;
956                 // go back to full view area
957                 qglViewport(r_view_x, vid.realheight - (r_view_y + r_view_height), r_view_width, r_view_height);
958                 // put the original screen image back in place and blend the bloom
959                 // texture on it
960                 memset(&m, 0, sizeof(m));
961                 m.pointer_vertex = varray_vertex3f;
962                 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
963                 m.pointer_texcoord[0] = varray_texcoord2f[0];
964 #if 0
965                 dobloomblend = false;
966 #else
967                 // do both in one pass if possible
968                 if (r_textureunits.integer >= 2 && gl_combine.integer)
969                 {
970                         dobloomblend = false;
971                         m.texcombinergb[1] = GL_ADD;
972                         m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
973                         m.pointer_texcoord[1] = varray_texcoord2f[1];
974                 }
975                 else
976                         dobloomblend = true;
977 #endif
978                 R_Mesh_State(&m);
979                 GL_BlendFunc(GL_ONE, GL_ZERO);
980                 GL_Color(1,1,1,1);
981                 R_Mesh_Draw(0, 4, 2, polygonelements);
982                 c_bloomdraws++;
983                 c_bloomdrawpixels += r_view_width * r_view_height;
984                 // now blend on the bloom texture if multipass
985                 if (dobloomblend)
986                 {
987                         memset(&m, 0, sizeof(m));
988                         m.pointer_vertex = varray_vertex3f;
989                         m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
990                         m.pointer_texcoord[0] = varray_texcoord2f[1];
991                         R_Mesh_State(&m);
992                         GL_BlendFunc(GL_ONE, GL_ONE);
993                         GL_Color(1,1,1,1);
994                         R_Mesh_Draw(0, 4, 2, polygonelements);
995                         c_bloomdraws++;
996                         c_bloomdrawpixels += r_view_width * r_view_height;
997                 }
998         }
999         if (r_refdef.viewblend[3] >= 0.01f)
1000         {
1001                 // apply a color tint to the whole view
1002                 memset(&m, 0, sizeof(m));
1003                 m.pointer_vertex = varray_vertex3f;
1004                 R_Mesh_State(&m);
1005                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1006                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1007                 R_Mesh_Draw(0, 4, 2, polygonelements);
1008         }
1009 }
1010
1011 void R_RenderScene(void);
1012
1013 matrix4x4_t r_waterscrollmatrix;
1014
1015 /*
1016 ================
1017 R_RenderView
1018 ================
1019 */
1020 void R_RenderView(void)
1021 {
1022         if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1023                 return; //Host_Error ("R_RenderView: NULL worldmodel");
1024
1025         r_view_width = bound(0, r_refdef.width, vid.realwidth);
1026         r_view_height = bound(0, r_refdef.height, vid.realheight);
1027         r_view_depth = 1;
1028         r_view_x = bound(0, r_refdef.x, vid.realwidth - r_refdef.width);
1029         r_view_y = bound(0, r_refdef.y, vid.realheight - r_refdef.height);
1030         r_view_z = 0;
1031         r_view_fov_x = bound(1, r_refdef.fov_x, 170);
1032         r_view_fov_y = bound(1, r_refdef.fov_y, 170);
1033         r_view_matrix = r_refdef.viewentitymatrix;
1034         GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1035         r_rtworld = r_shadow_realtime_world.integer;
1036         r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1037         r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1038         r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1039         r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1040
1041         // GL is weird because it's bottom to top, r_view_y is top to bottom
1042         qglViewport(r_view_x, vid.realheight - (r_view_y + r_view_height), r_view_width, r_view_height);
1043         GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1044         GL_ScissorTest(true);
1045         GL_DepthMask(true);
1046         R_ClearScreen();
1047         R_Textures_Frame();
1048         R_UpdateFog();
1049         R_UpdateLights();
1050         R_TimeReport("setup");
1051
1052         qglDepthFunc(GL_LEQUAL);
1053         qglPolygonOffset(0, 0);
1054         qglEnable(GL_POLYGON_OFFSET_FILL);
1055
1056         R_RenderScene();
1057
1058         qglPolygonOffset(0, 0);
1059         qglDisable(GL_POLYGON_OFFSET_FILL);
1060
1061         R_BlendView();
1062         R_TimeReport("blendview");
1063
1064         GL_Scissor(0, 0, vid.realwidth, vid.realheight);
1065         GL_ScissorTest(false);
1066 }
1067
1068 extern void R_DrawLightningBeams (void);
1069 void R_RenderScene(void)
1070 {
1071         // don't let sound skip if going slow
1072         if (r_refdef.extraupdate)
1073                 S_ExtraUpdate ();
1074
1075         r_framecount++;
1076
1077         R_MeshQueue_BeginScene();
1078
1079         GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1080
1081         R_SetFrustum();
1082
1083         r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1084         if (r_rtworldshadows || r_rtdlightshadows)
1085                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f);
1086         else
1087                 GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip);
1088
1089         GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1090
1091         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);
1092
1093         R_SkyStartFrame();
1094
1095         R_WorldVisibility();
1096         R_TimeReport("worldvis");
1097
1098         R_MarkEntities();
1099         R_TimeReport("markentity");
1100
1101         R_Shadow_UpdateWorldLightSelection();
1102
1103         // don't let sound skip if going slow
1104         if (r_refdef.extraupdate)
1105                 S_ExtraUpdate ();
1106
1107         GL_ShowTrisColor(0.025, 0.025, 0, 1);
1108         if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1109         {
1110                 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1111                 R_TimeReport("worldsky");
1112         }
1113
1114         if (R_DrawBrushModelsSky())
1115                 R_TimeReport("bmodelsky");
1116
1117         GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1118         if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1119         {
1120                 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1121                 R_TimeReport("world");
1122         }
1123
1124         // don't let sound skip if going slow
1125         if (r_refdef.extraupdate)
1126                 S_ExtraUpdate ();
1127
1128         GL_ShowTrisColor(0, 0.015, 0, 1);
1129
1130         R_DrawModels();
1131         R_TimeReport("models");
1132
1133         // don't let sound skip if going slow
1134         if (r_refdef.extraupdate)
1135                 S_ExtraUpdate ();
1136
1137         GL_ShowTrisColor(0, 0, 0.033, 1);
1138         R_ShadowVolumeLighting(false);
1139         R_TimeReport("rtlights");
1140
1141         // don't let sound skip if going slow
1142         if (r_refdef.extraupdate)
1143                 S_ExtraUpdate ();
1144
1145         GL_ShowTrisColor(0.1, 0, 0, 1);
1146
1147         R_DrawLightningBeams();
1148         R_TimeReport("lightning");
1149
1150         R_DrawParticles();
1151         R_TimeReport("particles");
1152
1153         R_DrawExplosions();
1154         R_TimeReport("explosions");
1155
1156         R_MeshQueue_RenderTransparent();
1157         R_TimeReport("drawtrans");
1158
1159         R_DrawCoronas();
1160         R_TimeReport("coronas");
1161
1162         R_DrawWorldCrosshair();
1163         R_TimeReport("crosshair");
1164
1165         R_MeshQueue_Render();
1166         R_MeshQueue_EndScene();
1167
1168         if ((r_shadow_visiblelighting.integer || r_shadow_visiblevolumes.integer) && !r_showtrispass)
1169         {
1170                 R_ShadowVolumeLighting(true);
1171                 R_TimeReport("visiblevolume");
1172         }
1173
1174         GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1175
1176         // don't let sound skip if going slow
1177         if (r_refdef.extraupdate)
1178                 S_ExtraUpdate ();
1179 }
1180
1181 /*
1182 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1183 {
1184         int i;
1185         float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1186         rmeshstate_t m;
1187         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1188         GL_DepthMask(false);
1189         GL_DepthTest(true);
1190         R_Mesh_Matrix(&r_identitymatrix);
1191
1192         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1193         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1194         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1195         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1196         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1197         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1198         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1199         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1200         R_FillColors(color, 8, cr, cg, cb, ca);
1201         if (fogenabled)
1202         {
1203                 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1204                 {
1205                         VectorSubtract(v, r_vieworigin, diff);
1206                         f2 = exp(fogdensity/DotProduct(diff, diff));
1207                         f1 = 1 - f2;
1208                         c[0] = c[0] * f1 + fogcolor[0] * f2;
1209                         c[1] = c[1] * f1 + fogcolor[1] * f2;
1210                         c[2] = c[2] * f1 + fogcolor[2] * f2;
1211                 }
1212         }
1213         memset(&m, 0, sizeof(m));
1214         m.pointer_vertex = vertex3f;
1215         m.pointer_color = color;
1216         R_Mesh_State(&m);
1217         R_Mesh_Draw(8, 12);
1218 }
1219 */
1220
1221 int nomodelelements[24] =
1222 {
1223         5, 2, 0,
1224         5, 1, 2,
1225         5, 0, 3,
1226         5, 3, 1,
1227         0, 2, 4,
1228         2, 1, 4,
1229         3, 0, 4,
1230         1, 3, 4
1231 };
1232
1233 float nomodelvertex3f[6*3] =
1234 {
1235         -16,   0,   0,
1236          16,   0,   0,
1237           0, -16,   0,
1238           0,  16,   0,
1239           0,   0, -16,
1240           0,   0,  16
1241 };
1242
1243 float nomodelcolor4f[6*4] =
1244 {
1245         0.0f, 0.0f, 0.5f, 1.0f,
1246         0.0f, 0.0f, 0.5f, 1.0f,
1247         0.0f, 0.5f, 0.0f, 1.0f,
1248         0.0f, 0.5f, 0.0f, 1.0f,
1249         0.5f, 0.0f, 0.0f, 1.0f,
1250         0.5f, 0.0f, 0.0f, 1.0f
1251 };
1252
1253 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1254 {
1255         const entity_render_t *ent = calldata1;
1256         int i;
1257         float f1, f2, *c, diff[3];
1258         float color4f[6*4];
1259         rmeshstate_t m;
1260         R_Mesh_Matrix(&ent->matrix);
1261
1262         memset(&m, 0, sizeof(m));
1263         m.pointer_vertex = nomodelvertex3f;
1264
1265         if (ent->flags & EF_ADDITIVE)
1266         {
1267                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1268                 GL_DepthMask(false);
1269         }
1270         else if (ent->alpha < 1)
1271         {
1272                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1273                 GL_DepthMask(false);
1274         }
1275         else
1276         {
1277                 GL_BlendFunc(GL_ONE, GL_ZERO);
1278                 GL_DepthMask(true);
1279         }
1280         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1281         if (fogenabled)
1282         {
1283                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1284                 m.pointer_color = color4f;
1285                 VectorSubtract(ent->origin, r_vieworigin, diff);
1286                 f2 = exp(fogdensity/DotProduct(diff, diff));
1287                 f1 = 1 - f2;
1288                 for (i = 0, c = color4f;i < 6;i++, c += 4)
1289                 {
1290                         c[0] = (c[0] * f1 + fogcolor[0] * f2);
1291                         c[1] = (c[1] * f1 + fogcolor[1] * f2);
1292                         c[2] = (c[2] * f1 + fogcolor[2] * f2);
1293                         c[3] *= ent->alpha;
1294                 }
1295         }
1296         else if (ent->alpha != 1)
1297         {
1298                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1299                 m.pointer_color = color4f;
1300                 for (i = 0, c = color4f;i < 6;i++, c += 4)
1301                         c[3] *= ent->alpha;
1302         }
1303         else
1304                 m.pointer_color = nomodelcolor4f;
1305         R_Mesh_State(&m);
1306         R_Mesh_Draw(0, 6, 8, nomodelelements);
1307 }
1308
1309 void R_DrawNoModel(entity_render_t *ent)
1310 {
1311         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1312                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModelCallback, ent, 0);
1313         //else
1314         //      R_DrawNoModelCallback(ent, 0);
1315 }
1316
1317 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1318 {
1319         vec3_t right1, right2, diff, normal;
1320
1321         VectorSubtract (org2, org1, normal);
1322
1323         // calculate 'right' vector for start
1324         VectorSubtract (r_vieworigin, org1, diff);
1325         CrossProduct (normal, diff, right1);
1326         VectorNormalize (right1);
1327
1328         // calculate 'right' vector for end
1329         VectorSubtract (r_vieworigin, org2, diff);
1330         CrossProduct (normal, diff, right2);
1331         VectorNormalize (right2);
1332
1333         vert[ 0] = org1[0] + width * right1[0];
1334         vert[ 1] = org1[1] + width * right1[1];
1335         vert[ 2] = org1[2] + width * right1[2];
1336         vert[ 3] = org1[0] - width * right1[0];
1337         vert[ 4] = org1[1] - width * right1[1];
1338         vert[ 5] = org1[2] - width * right1[2];
1339         vert[ 6] = org2[0] - width * right2[0];
1340         vert[ 7] = org2[1] - width * right2[1];
1341         vert[ 8] = org2[2] - width * right2[2];
1342         vert[ 9] = org2[0] + width * right2[0];
1343         vert[10] = org2[1] + width * right2[1];
1344         vert[11] = org2[2] + width * right2[2];
1345 }
1346
1347 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1348
1349 void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, 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)
1350 {
1351         float diff[3];
1352         rmeshstate_t m;
1353
1354         if (fogenabled)
1355         {
1356                 VectorSubtract(origin, r_vieworigin, diff);
1357                 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1358         }
1359
1360         R_Mesh_Matrix(&r_identitymatrix);
1361         GL_BlendFunc(blendfunc1, blendfunc2);
1362         GL_DepthMask(false);
1363         GL_DepthTest(!depthdisable);
1364
1365         varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1366         varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1367         varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1368         varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1369         varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1370         varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1371         varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1372         varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1373         varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1374         varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1375         varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1376         varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1377
1378         memset(&m, 0, sizeof(m));
1379         m.tex[0] = R_GetTexture(texture);
1380         m.pointer_texcoord[0] = spritetexcoord2f;
1381         m.pointer_vertex = varray_vertex3f;
1382         R_Mesh_State(&m);
1383         GL_Color(cr, cg, cb, ca);
1384         R_Mesh_Draw(0, 4, 2, polygonelements);
1385 }
1386
1387 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1388 {
1389         int i;
1390         float *vertex3f;
1391         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1392                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1393                         break;
1394         if (i == mesh->numvertices)
1395         {
1396                 if (mesh->numvertices < mesh->maxvertices)
1397                 {
1398                         VectorCopy(v, vertex3f);
1399                         mesh->numvertices++;
1400                 }
1401                 return mesh->numvertices;
1402         }
1403         else
1404                 return i;
1405 }
1406
1407 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1408 {
1409         int i;
1410         int *e, element[3];
1411         element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1412         element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1413         e = mesh->element3i + mesh->numtriangles * 3;
1414         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1415         {
1416                 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1417                 if (mesh->numtriangles < mesh->maxtriangles)
1418                 {
1419                         *e++ = element[0];
1420                         *e++ = element[1];
1421                         *e++ = element[2];
1422                         mesh->numtriangles++;
1423                 }
1424                 element[1] = element[2];
1425         }
1426 }
1427
1428 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1429 {
1430         int planenum, planenum2;
1431         int w;
1432         int tempnumpoints;
1433         mplane_t *plane, *plane2;
1434         float temppoints[2][256*3];
1435         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1436         {
1437                 w = 0;
1438                 tempnumpoints = 4;
1439                 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1440                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1441                 {
1442                         if (planenum2 == planenum)
1443                                 continue;
1444                         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);
1445                         w = !w;
1446                 }
1447                 if (tempnumpoints < 3)
1448                         continue;
1449                 // generate elements forming a triangle fan for this polygon
1450                 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1451         }
1452 }
1453
1454 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1455 {
1456         // we don't need to set currentframe if t->animated is false because
1457         // it was already set up by the texture loader for non-animating
1458         if (t->animated)
1459         {
1460                 t->currentframe = t->anim_frames[ent->frame != 0][(t->anim_total[ent->frame != 0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[ent->frame != 0]) : 0];
1461                 t = t->currentframe;
1462         }
1463         t->currentmaterialflags = t->basematerialflags;
1464         t->currentalpha = ent->alpha;
1465         if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1466                 t->currentalpha *= r_wateralpha.value;
1467         if (!(ent->flags & RENDER_LIGHT))
1468                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1469         if (ent->effects & EF_ADDITIVE)
1470                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1471         else if (t->currentalpha < 1)
1472                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1473 }
1474
1475 void R_UpdateAllTextureInfo(entity_render_t *ent)
1476 {
1477         int i;
1478         if (ent->model)
1479                 for (i = 0;i < ent->model->num_textures;i++)
1480                         R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1481 }
1482
1483 static void RSurf_DeformVertices(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1484 {
1485         int i, j;
1486         float center[3], forward[3], right[3], up[3], v[4][3];
1487         matrix4x4_t matrix1, imatrix1;
1488         if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1489         {
1490                 // a single autosprite surface can contain multiple sprites...
1491                 VectorClear(forward);
1492                 VectorClear(right);
1493                 VectorSet(up, 0, 0, 1);
1494                 for (j = 0;j < surface->num_vertices - 3;j += 4)
1495                 {
1496                         VectorClear(center);
1497                         for (i = 0;i < 4;i++)
1498                                 VectorAdd(center, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1499                         VectorScale(center, 0.25f, center);
1500                         // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1501                         Matrix4x4_FromVectors(&matrix1, (surface->groupmesh->data_normal3f + 3 * surface->num_firstvertex) + j*3, (surface->groupmesh->data_svector3f + 3 * surface->num_firstvertex) + j*3, (surface->groupmesh->data_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
1502                         Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1503                         for (i = 0;i < 4;i++)
1504                                 Matrix4x4_Transform(&imatrix1, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1505                         forward[0] = modelorg[0] - center[0];
1506                         forward[1] = modelorg[1] - center[1];
1507                         VectorNormalize(forward);
1508                         right[0] = forward[1];
1509                         right[1] = -forward[0];
1510                         for (i = 0;i < 4;i++)
1511                                 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1512                 }
1513         }
1514         else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1515         {
1516                 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1517                 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1518                 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1519                 // a single autosprite surface can contain multiple sprites...
1520                 for (j = 0;j < surface->num_vertices - 3;j += 4)
1521                 {
1522                         VectorClear(center);
1523                         for (i = 0;i < 4;i++)
1524                                 VectorAdd(center, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1525                         VectorScale(center, 0.25f, center);
1526                         // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1527                         Matrix4x4_FromVectors(&matrix1, (surface->groupmesh->data_normal3f + 3 * surface->num_firstvertex) + j*3, (surface->groupmesh->data_svector3f + 3 * surface->num_firstvertex) + j*3, (surface->groupmesh->data_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
1528                         Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1529                         for (i = 0;i < 4;i++)
1530                                 Matrix4x4_Transform(&imatrix1, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1531                         for (i = 0;i < 4;i++)
1532                                 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1533                 }
1534         }
1535         else
1536                 memcpy((varray_vertex3f + 3 * surface->num_firstvertex), (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), sizeof(float[3]) * surface->num_vertices);
1537 }
1538
1539 // any sort of deformvertices call is *VERY* rare, so this must be optimized
1540 // to skip deformvertices quickly!
1541 #if 1
1542 #define RSurf_GetVertexPointer(ent, texture, surface, modelorg) ((texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)) ? (RSurf_DeformVertices(ent, texture, surface, modelorg), varray_vertex3f) : surface->groupmesh->data_vertex3f)
1543 #else
1544 static float *RSurf_GetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1545 {
1546         if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
1547         {
1548                 RSurf_DeformVertices(ent, texture, surface, modelorg);
1549                 return varray_vertex3f;
1550         }
1551         else
1552                 return surface->groupmesh->data_vertex3f;
1553 }
1554 #endif
1555
1556 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1557 {
1558         int i;
1559         int texturesurfaceindex;
1560         const float *v, *vertex3f;
1561         float *c;
1562         float diff[3];
1563         float f, r, g, b, a, base, colorscale;
1564         const msurface_t *surface;
1565         qboolean dolightmap;
1566         qboolean dobase;
1567         qboolean doambient;
1568         qboolean dodetail;
1569         qboolean doglow;
1570         qboolean dofogpass;
1571         qboolean fogallpasses;
1572         qboolean waterscrolling;
1573         surfmesh_t *groupmesh;
1574         rtexture_t *lightmaptexture;
1575         rmeshstate_t m;
1576         texture = texture->currentframe;
1577         if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1578                 return;
1579         c_faces += texturenumsurfaces;
1580         // gl_lightmaps debugging mode skips normal texturing
1581         if (gl_lightmaps.integer)
1582         {
1583                 GL_BlendFunc(GL_ONE, GL_ZERO);
1584                 GL_DepthMask(true);
1585                 GL_DepthTest(true);
1586                 qglDisable(GL_CULL_FACE);
1587                 GL_Color(1, 1, 1, 1);
1588                 memset(&m, 0, sizeof(m));
1589                 R_Mesh_State(&m);
1590                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1591                 {
1592                         surface = texturesurfacelist[texturesurfaceindex];
1593                         R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1594                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1595                         R_Mesh_ColorPointer(surface->lightmaptexture ? NULL : surface->groupmesh->data_lightmapcolor4f);
1596                         R_Mesh_VertexPointer(surface->groupmesh->data_vertex3f);
1597                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1598                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1599                         GL_LockArrays(0, 0);
1600                 }
1601                 qglEnable(GL_CULL_FACE);
1602                 return;
1603         }
1604         GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1605         GL_DepthMask(!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT));
1606         if (texture->currentmaterialflags & MATERIALFLAG_ADD)
1607                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1608         else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
1609                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1610         else
1611                 GL_BlendFunc(GL_ONE, GL_ZERO);
1612         // water waterscrolling in texture matrix
1613         waterscrolling = (texture->currentmaterialflags & MATERIALFLAG_WATER) && r_waterscroll.value != 0;
1614         if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1615                 qglDisable(GL_CULL_FACE);
1616         if (texture->currentmaterialflags & MATERIALFLAG_SKY)
1617         {
1618                 if (skyrendernow)
1619                 {
1620                         skyrendernow = false;
1621                         if (skyrendermasked)
1622                                 R_Sky();
1623                 }
1624                 // LordHavoc: HalfLife maps have freaky skypolys...
1625                 //if (!ent->model->brush.ishlbsp)
1626                 {
1627                         R_Mesh_Matrix(&ent->matrix);
1628                         GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
1629                         if (skyrendermasked)
1630                         {
1631                                 // depth-only (masking)
1632                                 GL_ColorMask(0,0,0,0);
1633                                 // just to make sure that braindead drivers don't draw anything
1634                                 // despite that colormask...
1635                                 GL_BlendFunc(GL_ZERO, GL_ONE);
1636                         }
1637                         else
1638                         {
1639                                 // fog sky
1640                                 GL_BlendFunc(GL_ONE, GL_ZERO);
1641                         }
1642                         GL_DepthMask(true);
1643                         GL_DepthTest(true);
1644                         memset(&m, 0, sizeof(m));
1645                         R_Mesh_State(&m);
1646                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1647                         {
1648                                 surface = texturesurfacelist[texturesurfaceindex];
1649                                 R_Mesh_VertexPointer(surface->groupmesh->data_vertex3f);
1650                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1651                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1652                                 GL_LockArrays(0, 0);
1653                         }
1654                         GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1655                 }
1656         }
1657         else if ((texture->currentmaterialflags & MATERIALFLAG_WATER) && r_watershader.value && gl_textureshader && !texture->skin.glow && !fogenabled && ent->colormod[0] == 1 && ent->colormod[1] == 1 && ent->colormod[2] == 1)
1658         {
1659                 // NVIDIA Geforce3 distortion texture shader on water
1660                 float args[4] = {0.05f,0,0,0.04f};
1661                 memset(&m, 0, sizeof(m));
1662                 m.tex[0] = R_GetTexture(r_texture_distorttexture[(int)(r_refdef.time * 16)&63]);
1663                 m.tex[1] = R_GetTexture(texture->skin.base);
1664                 m.texcombinergb[0] = GL_REPLACE;
1665                 m.texcombinergb[1] = GL_REPLACE;
1666                 Matrix4x4_CreateFromQuakeEntity(&m.texmatrix[0], 0, 0, 0, 0, 0, 0, r_watershader.value);
1667                 m.texmatrix[1] = r_waterscrollmatrix;
1668                 R_Mesh_State(&m);
1669
1670                 GL_Color(1, 1, 1, texture->currentalpha);
1671                 GL_ActiveTexture(0);
1672                 qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
1673                 GL_ActiveTexture(1);
1674                 qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_OFFSET_TEXTURE_2D_NV);
1675                 qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB);
1676                 qglTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, &args[0]);
1677                 qglEnable(GL_TEXTURE_SHADER_NV);
1678
1679                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1680                 {
1681                         surface = texturesurfacelist[texturesurfaceindex];
1682                         R_Mesh_VertexPointer(RSurf_GetVertexPointer(ent, texture, surface, modelorg));
1683                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1684                         R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
1685                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1686                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1687                         GL_LockArrays(0, 0);
1688                 }
1689
1690                 qglDisable(GL_TEXTURE_SHADER_NV);
1691                 qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
1692                 GL_ActiveTexture(0);
1693         }
1694         else if (texture->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1695         {
1696                 // normal surface (wall or water)
1697                 dobase = true;
1698                 dolightmap = !(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT);
1699                 doambient = r_ambient.value >= (1/64.0f);
1700                 dodetail = r_detailtextures.integer && texture->skin.detail != NULL && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT);
1701                 doglow = texture->skin.glow != NULL;
1702                 dofogpass = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_ADD);
1703                 fogallpasses = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT);
1704                 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
1705                 {
1706                         if (dobase && dolightmap && gl_combine.integer)
1707                         {
1708                                 dobase = false;
1709                                 memset(&m, 0, sizeof(m));
1710                                 m.tex[1] = R_GetTexture(texture->skin.base);
1711                                 if (waterscrolling)
1712                                         m.texmatrix[1] = r_waterscrollmatrix;
1713                                 m.texrgbscale[1] = 2;
1714                                 m.pointer_color = varray_color4f;
1715                                 R_Mesh_State(&m);
1716                                 colorscale = 1;
1717                                 r = ent->colormod[0] * colorscale;
1718                                 g = ent->colormod[1] * colorscale;
1719                                 b = ent->colormod[2] * colorscale;
1720                                 a = texture->currentalpha;
1721                                 base = r_ambient.value * (1.0f / 64.0f);
1722                                 // q3bsp has no lightmap updates, so the lightstylevalue that
1723                                 // would normally be baked into the lightmaptexture must be
1724                                 // applied to the color
1725                                 if (ent->model->brushq1.lightdata)
1726                                 {
1727                                         float scale = d_lightstylevalue[0] * (1.0f / 128.0f);
1728                                         r *= scale;
1729                                         g *= scale;
1730                                         b *= scale;
1731                                 }
1732                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1733                                 {
1734                                         surface = texturesurfacelist[texturesurfaceindex];
1735                                         vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
1736                                         R_Mesh_VertexPointer(vertex3f);
1737                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1738                                         R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
1739                                         if (surface->lightmaptexture)
1740                                         {
1741                                                 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1742                                                 if (fogallpasses)
1743                                                 {
1744                                                         R_Mesh_ColorPointer(varray_color4f);
1745                                                         for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
1746                                                         {
1747                                                                 VectorSubtract(v, modelorg, diff);
1748                                                                 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1749                                                                 c[0] = f * r;
1750                                                                 c[1] = f * g;
1751                                                                 c[2] = f * b;
1752                                                                 c[3] = a;
1753                                                         }
1754                                                 }
1755                                                 else
1756                                                 {
1757                                                         R_Mesh_ColorPointer(NULL);
1758                                                         GL_Color(r, g, b, a);
1759                                                 }
1760                                         }
1761                                         else
1762                                         {
1763                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1764                                                 R_Mesh_ColorPointer(varray_color4f);
1765                                                 if (!surface->lightmaptexture)
1766                                                 {
1767                                                         for (i = 0, c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4)
1768                                                         {
1769                                                                 c[0] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+0] * r;
1770                                                                 c[1] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+1] * g;
1771                                                                 c[2] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+2] * b;
1772                                                                 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
1773                                                         }
1774                                                         if (fogallpasses)
1775                                                         {
1776                                                                 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
1777                                                                 {
1778                                                                         VectorSubtract(v, modelorg, diff);
1779                                                                         f = 1 - exp(fogdensity/DotProduct(diff, diff));
1780                                                                         VectorScale(c, f, c);
1781                                                                 }
1782                                                         }
1783                                                 }
1784                                                 else
1785                                                 {
1786                                                         R_Mesh_ColorPointer(NULL);
1787                                                         GL_Color(0, 0, 0, a);
1788                                                 }
1789                                         }
1790                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1791                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1792                                         GL_LockArrays(0, 0);
1793                                 }
1794                         }
1795                         if (dobase)
1796                         {
1797                                 dobase = false;
1798                                 memset(&m, 0, sizeof(m));
1799                                 m.tex[0] = R_GetTexture(texture->skin.base);
1800                                 if (waterscrolling)
1801                                         m.texmatrix[0] = r_waterscrollmatrix;
1802                                 m.pointer_color = varray_color4f;
1803                                 colorscale = 1;
1804                                 if (gl_combine.integer)
1805                                 {
1806                                         m.texrgbscale[0] = 4;
1807                                         colorscale *= 0.25f;
1808                                 }
1809                                 R_Mesh_State(&m);
1810                                 r = ent->colormod[0] * colorscale;
1811                                 g = ent->colormod[1] * colorscale;
1812                                 b = ent->colormod[2] * colorscale;
1813                                 a = texture->currentalpha;
1814                                 if (dolightmap)
1815                                 {
1816                                         // q3bsp has no lightmap updates, so the lightstylevalue that
1817                                         // would normally be baked into the lightmaptexture must be
1818                                         // applied to the color
1819                                         if (!ent->model->brushq1.lightdata)
1820                                         {
1821                                                 float scale = d_lightstylevalue[0] * (1.0f / 128.0f);
1822                                                 r *= scale;
1823                                                 g *= scale;
1824                                                 b *= scale;
1825                                         }
1826                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1827                                         {
1828                                                 surface = texturesurfacelist[texturesurfaceindex];
1829                                                 vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
1830                                                 R_Mesh_VertexPointer(vertex3f);
1831                                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1832                                                 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
1833                                                 {
1834                                                         c[0] = 0;
1835                                                         c[1] = 0;
1836                                                         c[2] = 0;
1837                                                         if (!surface->lightmapinfo)
1838                                                                 VectorCopy((surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex) + i*4, c);
1839                                                         else //if (surface->lightmapinfo)
1840                                                         {
1841                                                                 const qbyte *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1842                                                                 float scale = d_lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1843                                                                 VectorMA(c, scale, lm, c);
1844                                                                 if (surface->lightmapinfo->styles[1] != 255)
1845                                                                 {
1846                                                                         int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1847                                                                         lm += size3;
1848                                                                         scale = d_lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1849                                                                         VectorMA(c, scale, lm, c);
1850                                                                         if (surface->lightmapinfo->styles[2] != 255)
1851                                                                         {
1852                                                                                 lm += size3;
1853                                                                                 scale = d_lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1854                                                                                 VectorMA(c, scale, lm, c);
1855                                                                                 if (surface->lightmapinfo->styles[3] != 255)
1856                                                                                 {
1857                                                                                         lm += size3;
1858                                                                                         scale = d_lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1859                                                                                         VectorMA(c, scale, lm, c);
1860                                                                                 }
1861                                                                         }
1862                                                                 }
1863                                                         }
1864                                                         c[0] *= r;
1865                                                         c[1] *= g;
1866                                                         c[2] *= b;
1867                                                         if (fogallpasses)
1868                                                         {
1869                                                                 VectorSubtract(v, modelorg, diff);
1870                                                                 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1871                                                                 VectorScale(c, f, c);
1872                                                         }
1873                                                         if (!surface->lightmapinfo && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1874                                                                 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
1875                                                         else
1876                                                                 c[3] = a;
1877                                                 }
1878                                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1879                                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1880                                                 GL_LockArrays(0, 0);
1881                                         }
1882                                 }
1883                                 else
1884                                 {
1885                                         if (fogallpasses)
1886                                         {
1887                                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1888                                                 {
1889                                                         surface = texturesurfacelist[texturesurfaceindex];
1890                                                         vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
1891                                                         R_Mesh_VertexPointer(vertex3f);
1892                                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1893                                                         if (!surface->lightmapinfo && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1894                                                         {
1895                                                                 R_Mesh_ColorPointer(varray_color4f);
1896                                                                 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
1897                                                                 {
1898                                                                         VectorSubtract(v, modelorg, diff);
1899                                                                         f = 1 - exp(fogdensity/DotProduct(diff, diff));
1900                                                                         c[0] = r * f;
1901                                                                         c[1] = g * f;
1902                                                                         c[2] = b * f;
1903                                                                         c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
1904                                                                 }
1905                                                         }
1906                                                         else
1907                                                         {
1908                                                                 R_Mesh_ColorPointer(varray_color4f);
1909                                                                 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
1910                                                                 {
1911                                                                         VectorSubtract(v, modelorg, diff);
1912                                                                         f = 1 - exp(fogdensity/DotProduct(diff, diff));
1913                                                                         c[0] = r * f;
1914                                                                         c[1] = g * f;
1915                                                                         c[2] = b * f;
1916                                                                         c[3] = a;
1917                                                                 }
1918                                                         }
1919                                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1920                                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1921                                                         GL_LockArrays(0, 0);
1922                                                 }
1923                                         }
1924                                         else
1925                                         {
1926                                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1927                                                 {
1928                                                         surface = texturesurfacelist[texturesurfaceindex];
1929                                                         vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
1930                                                         R_Mesh_VertexPointer(vertex3f);
1931                                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1932                                                         if (!surface->lightmaptexture && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1933                                                         {
1934                                                                 R_Mesh_ColorPointer(varray_color4f);
1935                                                                 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
1936                                                                 {
1937                                                                         c[0] = r;
1938                                                                         c[1] = g;
1939                                                                         c[2] = b;
1940                                                                         c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
1941                                                                 }
1942                                                         }
1943                                                         else
1944                                                         {
1945                                                                 R_Mesh_ColorPointer(NULL);
1946                                                                 GL_Color(r, g, b, a);
1947                                                         }
1948                                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1949                                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1950                                                         GL_LockArrays(0, 0);
1951                                                 }
1952                                         }
1953                                 }
1954                         }
1955                 }
1956                 else
1957                 {
1958                         if (!dolightmap && dobase)
1959                         {
1960                                 dolightmap = false;
1961                                 dobase = false;
1962                                 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], 1);
1963                                 memset(&m, 0, sizeof(m));
1964                                 m.tex[0] = R_GetTexture(texture->skin.base);
1965                                 if (waterscrolling)
1966                                         m.texmatrix[0] = r_waterscrollmatrix;
1967                                 R_Mesh_State(&m);
1968                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1969                                 {
1970                                         surface = texturesurfacelist[texturesurfaceindex];
1971                                         R_Mesh_VertexPointer(RSurf_GetVertexPointer(ent, texture, surface, modelorg));
1972                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1973                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1974                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1975                                         GL_LockArrays(0, 0);
1976                                 }
1977                         }
1978                         if (r_lightmapintensity <= 0 && dolightmap && dobase)
1979                         {
1980                                 dolightmap = false;
1981                                 dobase = false;
1982                                 GL_Color(0, 0, 0, 1);
1983                                 memset(&m, 0, sizeof(m));
1984                                 R_Mesh_State(&m);
1985                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1986                                 {
1987                                         surface = texturesurfacelist[texturesurfaceindex];
1988                                         R_Mesh_VertexPointer(RSurf_GetVertexPointer(ent, texture, surface, modelorg));
1989                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1990                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1991                                         GL_LockArrays(0, 0);
1992                                 }
1993                         }
1994                         if (r_textureunits.integer >= 2 && gl_combine.integer && dolightmap && dobase)
1995                         {
1996                                 // dualtexture combine
1997                                 GL_BlendFunc(GL_ONE, GL_ZERO);
1998                                 GL_DepthMask(true);
1999                                 dolightmap = false;
2000                                 dobase = false;
2001                                 memset(&m, 0, sizeof(m));
2002                                 m.tex[1] = R_GetTexture(texture->skin.base);
2003                                 if (waterscrolling)
2004                                         m.texmatrix[1] = r_waterscrollmatrix;
2005                                 m.texrgbscale[1] = 2;
2006                                 R_Mesh_State(&m);
2007                                 r = ent->colormod[0] * r_lightmapintensity;
2008                                 g = ent->colormod[1] * r_lightmapintensity;
2009                                 b = ent->colormod[2] * r_lightmapintensity;
2010                                 GL_Color(r, g, b, 1);
2011                                 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2012                                 {
2013                                         R_Mesh_VertexPointer(varray_vertex3f);
2014                                         if (r == 1 && g == 1 && b == 1)
2015                                         {
2016                                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2017                                                 {
2018                                                         surface = texturesurfacelist[texturesurfaceindex];
2019                                                         RSurf_DeformVertices(ent, texture, surface, modelorg);
2020                                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2021                                                         R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2022                                                         if (surface->lightmaptexture)
2023                                                         {
2024                                                                 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2025                                                                 R_Mesh_ColorPointer(NULL);
2026                                                         }
2027                                                         else //if (r == 1 && g == 1 && b == 1)
2028                                                         {
2029                                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2030                                                                 R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
2031                                                         }
2032                                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2033                                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2034                                                         GL_LockArrays(0, 0);
2035                                                 }
2036                                         }
2037                                         else
2038                                         {
2039                                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2040                                                 {
2041                                                         surface = texturesurfacelist[texturesurfaceindex];
2042                                                         RSurf_DeformVertices(ent, texture, surface, modelorg);
2043                                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2044                                                         R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2045                                                         if (surface->lightmaptexture)
2046                                                         {
2047                                                                 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2048                                                                 R_Mesh_ColorPointer(NULL);
2049                                                         }
2050                                                         else
2051                                                         {
2052                                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2053                                                                 R_Mesh_ColorPointer(varray_color4f);
2054                                                                 for (i = 0, c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4)
2055                                                                 {
2056                                                                         c[0] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+0] * r;
2057                                                                         c[1] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+1] * g;
2058                                                                         c[2] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+2] * b;
2059                                                                         c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3];
2060                                                                 }
2061                                                         }
2062                                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2063                                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2064                                                         GL_LockArrays(0, 0);
2065                                                 }
2066                                         }
2067                                 }
2068                                 else
2069                                 {
2070                                         if (r == 1 && g == 1 && b == 1)
2071                                         {
2072 #if 0
2073                                                 // experimental direct state calls for measuring
2074                                                 // R_Mesh_ call overhead, do not use!
2075                                                 R_Mesh_VertexPointer(varray_vertex3f);
2076                                                 R_Mesh_TexCoordPointer(0, 2, varray_texcoord2f[0]);
2077                                                 R_Mesh_TexCoordPointer(1, 2, varray_texcoord2f[1]);
2078                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2079                                                 R_Mesh_ColorPointer(varray_color4f);
2080                                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2081                                                 {
2082                                                         surface = texturesurfacelist[texturesurfaceindex];
2083                                                         qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), surface->groupmesh->data_vertex3f);
2084                                                         qglClientActiveTexture(GL_TEXTURE0_ARB);
2085                                                         qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), surface->groupmesh->data_texcoordlightmap2f);
2086                                                         qglClientActiveTexture(GL_TEXTURE1_ARB);
2087                                                         qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), surface->groupmesh->data_texcoordtexture2f);
2088                                                         if (surface->lightmaptexture)
2089                                                         {
2090                                                                 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2091                                                                 qglDisableClientState(GL_COLOR_ARRAY);
2092                                                                 qglColor4f(r, g, b, 1);
2093                                                         }
2094                                                         else //if (r == 1 && g == 1 && b == 1)
2095                                                         {
2096                                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2097                                                                 qglEnableClientState(GL_COLOR_ARRAY);
2098                                                                 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), surface->groupmesh->data_lightmapcolor4f);
2099                                                         }
2100                                                         qglLockArraysEXT(0, surface->num_vertices);
2101                                                         qglDrawRangeElements(GL_TRIANGLES, surface->num_firstvertex, surface->num_firstvertex + surface->num_vertices, surface->num_triangles * 3, GL_UNSIGNED_INT, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2102                                                         qglUnlockArraysEXT();
2103                                                 }
2104 #else
2105                                                 groupmesh = NULL;
2106                                                 lightmaptexture = NULL;
2107                                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2108                                                 {
2109                                                         surface = texturesurfacelist[texturesurfaceindex];
2110                                                         if (groupmesh != surface->groupmesh)
2111                                                         {
2112                                                                 groupmesh = surface->groupmesh;
2113                                                                 R_Mesh_VertexPointer(groupmesh->data_vertex3f);
2114                                                                 R_Mesh_TexCoordPointer(0, 2, groupmesh->data_texcoordlightmap2f);
2115                                                                 R_Mesh_TexCoordPointer(1, 2, groupmesh->data_texcoordtexture2f);
2116                                                                 if (!lightmaptexture)
2117                                                                         R_Mesh_ColorPointer(groupmesh->data_lightmapcolor4f);
2118                                                         }
2119                                                         if (lightmaptexture != surface->lightmaptexture)
2120                                                         {
2121                                                                 lightmaptexture = surface->lightmaptexture;
2122                                                                 if (lightmaptexture)
2123                                                                 {
2124                                                                         R_Mesh_TexBind(0, R_GetTexture(lightmaptexture));
2125                                                                         R_Mesh_ColorPointer(NULL);
2126                                                                 }
2127                                                                 else //if (r == 1 && g == 1 && b == 1)
2128                                                                 {
2129                                                                         R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2130                                                                         R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
2131                                                                 }
2132                                                         }
2133                                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2134                                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2135                                                         GL_LockArrays(0, 0);
2136                                                 }
2137 #endif
2138                                         }
2139                                         else
2140                                         {
2141                                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2142                                                 {
2143                                                         surface = texturesurfacelist[texturesurfaceindex];
2144                                                         R_Mesh_VertexPointer(surface->groupmesh->data_vertex3f);
2145                                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2146                                                         R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2147                                                         if (surface->lightmaptexture)
2148                                                         {
2149                                                                 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2150                                                                 R_Mesh_ColorPointer(NULL);
2151                                                         }
2152                                                         else
2153                                                         {
2154                                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2155                                                                 R_Mesh_ColorPointer(varray_color4f);
2156                                                                 for (i = 0, c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4)
2157                                                                 {
2158                                                                         c[0] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+0] * r;
2159                                                                         c[1] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+1] * g;
2160                                                                         c[2] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+2] * b;
2161                                                                         c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3];
2162                                                                 }
2163                                                         }
2164                                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2165                                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2166                                                         GL_LockArrays(0, 0);
2167                                                 }
2168                                         }
2169                                 }
2170                         }
2171                         // single texture
2172                         if (dolightmap)
2173                         {
2174                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2175                                 GL_DepthMask(true);
2176                                 GL_Color(1, 1, 1, 1);
2177                                 memset(&m, 0, sizeof(m));
2178                                 R_Mesh_State(&m);
2179                                 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2180                                 {
2181                                         R_Mesh_VertexPointer(varray_vertex3f);
2182                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2183                                         {
2184                                                 surface = texturesurfacelist[texturesurfaceindex];
2185                                                 RSurf_DeformVertices(ent, texture, surface, modelorg);
2186                                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2187                                                 if (surface->lightmaptexture)
2188                                                 {
2189                                                         R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2190                                                         R_Mesh_ColorPointer(NULL);
2191                                                 }
2192                                                 else //if (r == 1 && g == 1 && b == 1)
2193                                                 {
2194                                                         R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2195                                                         R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
2196                                                 }
2197                                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2198                                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2199                                                 GL_LockArrays(0, 0);
2200                                         }
2201                                 }
2202                                 else
2203                                 {
2204                                         groupmesh = NULL;
2205                                         lightmaptexture = NULL;
2206                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2207                                         {
2208                                                 surface = texturesurfacelist[texturesurfaceindex];
2209                                                 if (groupmesh != surface->groupmesh)
2210                                                 {
2211                                                         groupmesh = surface->groupmesh;
2212                                                         R_Mesh_VertexPointer(groupmesh->data_vertex3f);
2213                                                         R_Mesh_TexCoordPointer(0, 2, groupmesh->data_texcoordlightmap2f);
2214                                                         if (!lightmaptexture)
2215                                                                 R_Mesh_ColorPointer(groupmesh->data_lightmapcolor4f);
2216                                                 }
2217                                                 if (lightmaptexture != surface->lightmaptexture)
2218                                                 {
2219                                                         lightmaptexture = surface->lightmaptexture;
2220                                                         if (lightmaptexture)
2221                                                         {
2222                                                                 R_Mesh_TexBind(0, R_GetTexture(lightmaptexture));
2223                                                                 R_Mesh_ColorPointer(NULL);
2224                                                         }
2225                                                         else //if (r == 1 && g == 1 && b == 1)
2226                                                         {
2227                                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2228                                                                 R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
2229                                                         }
2230                                                 }
2231                                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2232                                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2233                                                 GL_LockArrays(0, 0);
2234                                         }
2235                                 }
2236                         }
2237                         if (dobase)
2238                         {
2239                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2240                                 GL_DepthMask(false);
2241                                 GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1);
2242                                 memset(&m, 0, sizeof(m));
2243                                 m.tex[0] = R_GetTexture(texture->skin.base);
2244                                 if (waterscrolling)
2245                                         m.texmatrix[0] = r_waterscrollmatrix;
2246                                 R_Mesh_State(&m);
2247                                 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2248                                 {
2249                                         R_Mesh_VertexPointer(varray_vertex3f);
2250                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2251                                         {
2252                                                 surface = texturesurfacelist[texturesurfaceindex];
2253                                                 RSurf_DeformVertices(ent, texture, surface, modelorg);
2254                                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2255                                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2256                                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2257                                                 GL_LockArrays(0, 0);
2258                                         }
2259                                 }
2260                                 else
2261                                 {
2262                                         groupmesh = NULL;
2263                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2264                                         {
2265                                                 surface = texturesurfacelist[texturesurfaceindex];
2266                                                 if (groupmesh != surface->groupmesh)
2267                                                 {
2268                                                         groupmesh = surface->groupmesh;
2269                                                         R_Mesh_VertexPointer(groupmesh->data_vertex3f);
2270                                                         R_Mesh_TexCoordPointer(0, 2, groupmesh->data_texcoordtexture2f);
2271                                                 }
2272                                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2273                                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2274                                                 GL_LockArrays(0, 0);
2275                                         }
2276                                 }
2277                         }
2278                 }
2279                 if (doambient)
2280                 {
2281                         doambient = false;
2282                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2283                         GL_DepthMask(false);
2284                         memset(&m, 0, sizeof(m));
2285                         m.tex[0] = R_GetTexture(texture->skin.base);
2286                         if (waterscrolling)
2287                                 m.texmatrix[0] = r_waterscrollmatrix;
2288                         m.pointer_color = varray_color4f;
2289                         colorscale = 1;
2290                         if (gl_combine.integer)
2291                         {
2292                                 m.texrgbscale[0] = 4;
2293                                 colorscale *= 0.25f;
2294                         }
2295                         R_Mesh_State(&m);
2296                         base = r_ambient.value * (1.0f / 64.0f);
2297                         r = ent->colormod[0] * colorscale * base;
2298                         g = ent->colormod[1] * colorscale * base;
2299                         b = ent->colormod[2] * colorscale * base;
2300                         a = texture->currentalpha;
2301                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2302                         {
2303                                 surface = texturesurfacelist[texturesurfaceindex];
2304                                 vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
2305                                 R_Mesh_VertexPointer(vertex3f);
2306                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2307                                 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
2308                                 {
2309                                         c[0] = r;
2310                                         c[1] = g;
2311                                         c[2] = b;
2312                                         if (fogallpasses)
2313                                         {
2314                                                 VectorSubtract(v, modelorg, diff);
2315                                                 f = 1 - exp(fogdensity/DotProduct(diff, diff));
2316                                                 VectorScale(c, f, c);
2317                                         }
2318                                         if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2319                                                 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
2320                                         else
2321                                                 c[3] = a;
2322                                 }
2323                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2324                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2325                                 GL_LockArrays(0, 0);
2326                         }
2327                 }
2328                 if (dodetail)
2329                 {
2330                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2331                         GL_DepthMask(false);
2332                         GL_Color(1, 1, 1, 1);
2333                         memset(&m, 0, sizeof(m));
2334                         m.tex[0] = R_GetTexture(texture->skin.detail);
2335                         R_Mesh_State(&m);
2336                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2337                         {
2338                                 surface = texturesurfacelist[texturesurfaceindex];
2339                                 R_Mesh_VertexPointer(RSurf_GetVertexPointer(ent, texture, surface, modelorg));
2340                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoorddetail2f);
2341                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2342                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2343                                 GL_LockArrays(0, 0);
2344                         }
2345                 }
2346                 if (doglow)
2347                 {
2348                         // if glow was not already done using multitexture, do it now.
2349                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2350                         GL_DepthMask(false);
2351                         memset(&m, 0, sizeof(m));
2352                         m.tex[0] = R_GetTexture(texture->skin.glow);
2353                         if (waterscrolling)
2354                                 m.texmatrix[0] = r_waterscrollmatrix;
2355                         m.pointer_color = varray_color4f;
2356                         R_Mesh_State(&m);
2357                         colorscale = 1;
2358                         r = ent->colormod[0] * colorscale;
2359                         g = ent->colormod[1] * colorscale;
2360                         b = ent->colormod[2] * colorscale;
2361                         a = texture->currentalpha;
2362                         if (fogallpasses)
2363                         {
2364                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2365                                 {
2366                                         surface = texturesurfacelist[texturesurfaceindex];
2367                                         vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
2368                                         R_Mesh_VertexPointer(vertex3f);
2369                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2370                                         R_Mesh_ColorPointer(varray_color4f);
2371                                         if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2372                                         {
2373                                                 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
2374                                                 {
2375                                                         VectorSubtract(v, modelorg, diff);
2376                                                         f = 1 - exp(fogdensity/DotProduct(diff, diff));
2377                                                         c[0] = f * r;
2378                                                         c[1] = f * g;
2379                                                         c[2] = f * b;
2380                                                         c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
2381                                                 }
2382                                         }
2383                                         else
2384                                         {
2385                                                 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
2386                                                 {
2387                                                         VectorSubtract(v, modelorg, diff);
2388                                                         f = 1 - exp(fogdensity/DotProduct(diff, diff));
2389                                                         c[0] = f * r;
2390                                                         c[1] = f * g;
2391                                                         c[2] = f * b;
2392                                                         c[3] = a;
2393                                                 }
2394                                         }
2395                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2396                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2397                                         GL_LockArrays(0, 0);
2398                                 }
2399                         }
2400                         else
2401                         {
2402                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2403                                 {
2404                                         surface = texturesurfacelist[texturesurfaceindex];
2405                                         vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
2406                                         R_Mesh_VertexPointer(vertex3f);
2407                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2408                                         if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2409                                         {
2410                                                 R_Mesh_ColorPointer(varray_color4f);
2411                                                 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
2412                                                 {
2413                                                         c[0] = r;
2414                                                         c[1] = g;
2415                                                         c[2] = b;
2416                                                         c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
2417                                                 }
2418                                         }
2419                                         else
2420                                         {
2421                                                 R_Mesh_ColorPointer(NULL);
2422                                                 GL_Color(r, g, b, a);
2423                                         }
2424                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2425                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2426                                         GL_LockArrays(0, 0);
2427                                 }
2428                         }
2429                 }
2430                 if (dofogpass)
2431                 {
2432                         // if this is opaque use alpha blend which will darken the earlier
2433                         // passes cheaply.
2434                         //
2435                         // if this is an alpha blended material, all the earlier passes
2436                         // were darkened by fog already, so we only need to add the fog
2437                         // color ontop through the fog mask texture
2438                         //
2439                         // if this is an additive blended material, all the earlier passes
2440                         // were darkened by fog already, and we should not add fog color
2441                         // (because the background was not darkened, there is no fog color
2442                         // that was lost behind it).
2443                         if (!fogallpasses)
2444                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2445                         else
2446                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2447                         GL_DepthMask(false);
2448                         memset(&m, 0, sizeof(m));
2449                         m.tex[0] = R_GetTexture(texture->skin.fog);
2450                         if (waterscrolling)
2451                                 m.texmatrix[0] = r_waterscrollmatrix;
2452                         R_Mesh_State(&m);
2453                         r = fogcolor[0];
2454                         g = fogcolor[1];
2455                         b = fogcolor[2];
2456                         a = texture->currentalpha;
2457                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2458                         {
2459                                 surface = texturesurfacelist[texturesurfaceindex];
2460                                 vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
2461                                 R_Mesh_VertexPointer(vertex3f);
2462                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2463                                 R_Mesh_ColorPointer(varray_color4f);
2464                                 //RSurf_FogPassColors_Vertex3f_Color4f((surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], texture->currentalpha, 1, surface->num_vertices, modelorg);
2465                                 if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2466                                 {
2467                                         for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
2468                                         {
2469                                                 VectorSubtract(v, modelorg, diff);
2470                                                 f = exp(fogdensity/DotProduct(diff, diff));
2471                                                 c[0] = r;
2472                                                 c[1] = g;
2473                                                 c[2] = b;
2474                                                 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * f * a;
2475                                         }
2476                                 }
2477                                 else
2478                                 {
2479                                         for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
2480                                         {
2481                                                 VectorSubtract(v, modelorg, diff);
2482                                                 f = exp(fogdensity/DotProduct(diff, diff));
2483                                                 c[0] = r;
2484                                                 c[1] = g;
2485                                                 c[2] = b;
2486                                                 c[3] = f * a;
2487                                         }
2488                                 }
2489                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2490                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2491                                 GL_LockArrays(0, 0);
2492                         }
2493                 }
2494         }
2495         if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
2496                 qglEnable(GL_CULL_FACE);
2497 }
2498
2499 static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
2500 {
2501         const entity_render_t *ent = calldata1;
2502         const msurface_t *surface = ent->model->data_surfaces + calldata2;
2503         vec3_t modelorg;
2504         texture_t *texture;
2505
2506         texture = surface->texture;
2507         if (texture->basematerialflags & MATERIALFLAG_SKY)
2508                 return; // transparent sky is too difficult
2509         R_UpdateTextureInfo(ent, texture);
2510
2511         R_Mesh_Matrix(&ent->matrix);
2512         Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2513         R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2514 }
2515
2516 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2517 {
2518         int texturesurfaceindex;
2519         const msurface_t *surface;
2520         vec3_t tempcenter, center;
2521         if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2522         {
2523                 // drawing sky transparently would be too difficult
2524                 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2525                 {
2526                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2527                         {
2528                                 surface = texturesurfacelist[texturesurfaceindex];
2529                                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2530                                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2531                                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2532                                 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2533                                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->data_surfaces);
2534                         }
2535                 }
2536         }
2537         else
2538                 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2539 }
2540
2541 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2542 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2543 {
2544         int i, j, f, flagsmask;
2545         msurface_t *surface, **surfacechain;
2546         texture_t *t, *texture;
2547         model_t *model = ent->model;
2548         vec3_t modelorg;
2549         const int maxsurfacelist = 1024;
2550         int numsurfacelist = 0;
2551         const msurface_t *surfacelist[1024];
2552         if (model == NULL)
2553                 return;
2554         R_Mesh_Matrix(&ent->matrix);
2555         Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2556
2557         // update light styles
2558         if (!skysurfaces && model->brushq1.light_styleupdatechains)
2559         {
2560                 for (i = 0;i < model->brushq1.light_styles;i++)
2561                 {
2562                         if (model->brushq1.light_stylevalue[i] != d_lightstylevalue[model->brushq1.light_style[i]])
2563                         {
2564                                 model->brushq1.light_stylevalue[i] = d_lightstylevalue[model->brushq1.light_style[i]];
2565                                 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2566                                         for (;(surface = *surfacechain);surfacechain++)
2567                                                 surface->cached_dlight = true;
2568                         }
2569                 }
2570         }
2571
2572         R_UpdateAllTextureInfo(ent);
2573         flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2574         f = 0;
2575         t = NULL;
2576         texture = NULL;
2577         numsurfacelist = 0;
2578         if (ent == r_refdef.worldentity)
2579         {
2580                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2581                 {
2582                         if (!r_worldsurfacevisible[j])
2583                                 continue;
2584                         if (t != surface->texture)
2585                         {
2586                                 if (numsurfacelist)
2587                                 {
2588                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2589                                         numsurfacelist = 0;
2590                                 }
2591                                 t = surface->texture;
2592                                 f = t->currentmaterialflags & flagsmask;
2593                                 texture = t->currentframe;
2594                         }
2595                         if (f && surface->num_triangles)
2596                         {
2597                                 // if lightmap parameters changed, rebuild lightmap texture
2598                                 if (surface->cached_dlight && surface->lightmapinfo->samples)
2599                                         R_BuildLightMap(ent, surface);
2600                                 // add face to draw list
2601                                 surfacelist[numsurfacelist++] = surface;
2602                                 if (numsurfacelist >= maxsurfacelist)
2603                                 {
2604                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2605                                         numsurfacelist = 0;
2606                                 }
2607                         }
2608                 }
2609         }
2610         else
2611         {
2612                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2613                 {
2614                         if (t != surface->texture)
2615                         {
2616                                 if (numsurfacelist)
2617                                 {
2618                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2619                                         numsurfacelist = 0;
2620                                 }
2621                                 t = surface->texture;
2622                                 f = t->currentmaterialflags & flagsmask;
2623                                 texture = t->currentframe;
2624                         }
2625                         if (f && surface->num_triangles)
2626                         {
2627                                 // if lightmap parameters changed, rebuild lightmap texture
2628                                 if (surface->cached_dlight && surface->lightmapinfo->samples)
2629                                         R_BuildLightMap(ent, surface);
2630                                 // add face to draw list
2631                                 surfacelist[numsurfacelist++] = surface;
2632                                 if (numsurfacelist >= maxsurfacelist)
2633                                 {
2634                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2635                                         numsurfacelist = 0;
2636                                 }
2637                         }
2638                 }
2639         }
2640         if (numsurfacelist)
2641                 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2642 }
2643