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