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