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