]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
eliminated calls to Matrix4x4_CreateIdentity (now copies from the already existing...
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "r_shadow.h"
24 #include "polygon.h"
25
26 // used for dlight push checking and other things
27 int r_framecount;
28
29 mplane_t frustum[5];
30
31 matrix4x4_t identitymatrix;
32
33 renderstats_t renderstats;
34
35 // true during envmap command capture
36 qboolean envmap;
37
38 // maximum visible distance (recalculated from world box each frame)
39 float r_farclip;
40 // brightness of world lightmaps and related lighting
41 // (often reduced when world rtlights are enabled)
42 float r_lightmapintensity;
43 // whether to draw world lights realtime, dlights realtime, and their shadows
44 qboolean r_rtworld;
45 qboolean r_rtworldshadows;
46 qboolean r_rtdlight;
47 qboolean r_rtdlightshadows;
48
49
50 // forces all rendering to draw triangle outlines
51 int r_showtrispass;
52
53 // view origin
54 vec3_t r_vieworigin;
55 vec3_t r_viewforward;
56 vec3_t r_viewleft;
57 vec3_t r_viewright;
58 vec3_t r_viewup;
59 int r_view_x;
60 int r_view_y;
61 int r_view_z;
62 int r_view_width;
63 int r_view_height;
64 int r_view_depth;
65 matrix4x4_t r_view_matrix;
66
67 //
68 // screen size info
69 //
70 refdef_t r_refdef;
71
72 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
73 cvar_t r_showtris_polygonoffset = {0, "r_showtris_polygonoffset", "-10", "nudges triangle outlines in hardware depth units, used to make outlines appear infront of walls"};
74 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
75 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"};
76 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"};
77 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
78 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"};
79 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"};
80 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"};
81 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
82 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
83 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
84 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
85 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
86 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
87 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
88
89 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
90 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
91 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
92 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
93 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
94 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
95 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
96
97 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)"};
98
99 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
100 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
101 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
102
103 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
104 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
105 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
106 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
107 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
108
109 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"};
110
111 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"};
112
113 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
114
115 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
116
117 rtexturepool_t *r_main_texturepool;
118 rtexture_t *r_bloom_texture_screen;
119 rtexture_t *r_bloom_texture_bloom;
120 rtexture_t *r_texture_blanknormalmap;
121 rtexture_t *r_texture_white;
122 rtexture_t *r_texture_black;
123 rtexture_t *r_texture_notexture;
124 rtexture_t *r_texture_whitecube;
125 rtexture_t *r_texture_normalizationcube;
126 rtexture_t *r_texture_fogattenuation;
127 rtexture_t *r_texture_fogintensity;
128
129 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
130 {
131         int i;
132         for (i = 0;i < verts;i++)
133         {
134                 out[0] = in[0] * r;
135                 out[1] = in[1] * g;
136                 out[2] = in[2] * b;
137                 out[3] = in[3];
138                 in += 4;
139                 out += 4;
140         }
141 }
142
143 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
144 {
145         int i;
146         for (i = 0;i < verts;i++)
147         {
148                 out[0] = r;
149                 out[1] = g;
150                 out[2] = b;
151                 out[3] = a;
152                 out += 4;
153         }
154 }
155
156 vec3_t fogcolor;
157 vec_t fogdensity;
158 vec_t fogrange;
159 vec_t fograngerecip;
160 int fogtableindex;
161 vec_t fogtabledistmultiplier;
162 float fogtable[FOGTABLEWIDTH];
163 float fog_density, fog_red, fog_green, fog_blue;
164 qboolean fogenabled;
165 qboolean oldgl_fogenable;
166 void R_UpdateFog(void)
167 {
168         if (gamemode == GAME_NEHAHRA)
169         {
170                 if (gl_fogenable.integer)
171                 {
172                         oldgl_fogenable = true;
173                         fog_density = gl_fogdensity.value;
174                         fog_red = gl_fogred.value;
175                         fog_green = gl_foggreen.value;
176                         fog_blue = gl_fogblue.value;
177                 }
178                 else if (oldgl_fogenable)
179                 {
180                         oldgl_fogenable = false;
181                         fog_density = 0;
182                         fog_red = 0;
183                         fog_green = 0;
184                         fog_blue = 0;
185                 }
186         }
187         if (fog_density)
188         {
189                 fogcolor[0] = fog_red   = bound(0.0f, fog_red  , 1.0f);
190                 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
191                 fogcolor[2] = fog_blue  = bound(0.0f, fog_blue , 1.0f);
192         }
193         if (fog_density)
194         {
195                 fogenabled = true;
196                 fogdensity = -4000.0f / (fog_density * fog_density);
197                 // this is the point where the fog reaches 0.9986 alpha, which we
198                 // consider a good enough cutoff point for the texture
199                 // (0.9986 * 256 == 255.6)
200                 fogrange = 400 / fog_density;
201                 fograngerecip = 1.0f / fogrange;
202                 fogtabledistmultiplier = FOGTABLEWIDTH * fograngerecip;
203                 // fog color was already set
204         }
205         else
206                 fogenabled = false;
207 }
208
209 // FIXME: move this to client?
210 void FOG_clear(void)
211 {
212         if (gamemode == GAME_NEHAHRA)
213         {
214                 Cvar_Set("gl_fogenable", "0");
215                 Cvar_Set("gl_fogdensity", "0.2");
216                 Cvar_Set("gl_fogred", "0.3");
217                 Cvar_Set("gl_foggreen", "0.3");
218                 Cvar_Set("gl_fogblue", "0.3");
219         }
220         fog_density = fog_red = fog_green = fog_blue = 0.0f;
221 }
222
223 // FIXME: move this to client?
224 void FOG_registercvars(void)
225 {
226         int x;
227         double r, alpha;
228
229         if (gamemode == GAME_NEHAHRA)
230         {
231                 Cvar_RegisterVariable (&gl_fogenable);
232                 Cvar_RegisterVariable (&gl_fogdensity);
233                 Cvar_RegisterVariable (&gl_fogred);
234                 Cvar_RegisterVariable (&gl_foggreen);
235                 Cvar_RegisterVariable (&gl_fogblue);
236                 Cvar_RegisterVariable (&gl_fogstart);
237                 Cvar_RegisterVariable (&gl_fogend);
238         }
239
240         r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
241         for (x = 0;x < FOGTABLEWIDTH;x++)
242         {
243                 alpha = exp(r / ((double)x*(double)x));
244                 if (x == FOGTABLEWIDTH - 1)
245                         alpha = 1;
246                 fogtable[x] = bound(0, alpha, 1);
247         }
248 }
249
250 static void R_BuildBlankTextures(void)
251 {
252         unsigned char data[4];
253         data[0] = 128; // normal X
254         data[1] = 128; // normal Y
255         data[2] = 255; // normal Z
256         data[3] = 128; // height
257         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
258         data[0] = 255;
259         data[1] = 255;
260         data[2] = 255;
261         data[3] = 255;
262         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
263         data[0] = 0;
264         data[1] = 0;
265         data[2] = 0;
266         data[3] = 255;
267         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
268 }
269
270 static void R_BuildNoTexture(void)
271 {
272         int x, y;
273         unsigned char pix[16][16][4];
274         // this makes a light grey/dark grey checkerboard texture
275         for (y = 0;y < 16;y++)
276         {
277                 for (x = 0;x < 16;x++)
278                 {
279                         if ((y < 8) ^ (x < 8))
280                         {
281                                 pix[y][x][0] = 128;
282                                 pix[y][x][1] = 128;
283                                 pix[y][x][2] = 128;
284                                 pix[y][x][3] = 255;
285                         }
286                         else
287                         {
288                                 pix[y][x][0] = 64;
289                                 pix[y][x][1] = 64;
290                                 pix[y][x][2] = 64;
291                                 pix[y][x][3] = 255;
292                         }
293                 }
294         }
295         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
296 }
297
298 static void R_BuildWhiteCube(void)
299 {
300         unsigned char data[6*1*1*4];
301         data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
302         data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
303         data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
304         data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
305         data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
306         data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
307         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
308 }
309
310 static void R_BuildNormalizationCube(void)
311 {
312         int x, y, side;
313         vec3_t v;
314         vec_t s, t, intensity;
315 #define NORMSIZE 64
316         unsigned char data[6][NORMSIZE][NORMSIZE][4];
317         for (side = 0;side < 6;side++)
318         {
319                 for (y = 0;y < NORMSIZE;y++)
320                 {
321                         for (x = 0;x < NORMSIZE;x++)
322                         {
323                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
324                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
325                                 switch(side)
326                                 {
327                                 default:
328                                 case 0:
329                                         v[0] = 1;
330                                         v[1] = -t;
331                                         v[2] = -s;
332                                         break;
333                                 case 1:
334                                         v[0] = -1;
335                                         v[1] = -t;
336                                         v[2] = s;
337                                         break;
338                                 case 2:
339                                         v[0] = s;
340                                         v[1] = 1;
341                                         v[2] = t;
342                                         break;
343                                 case 3:
344                                         v[0] = s;
345                                         v[1] = -1;
346                                         v[2] = -t;
347                                         break;
348                                 case 4:
349                                         v[0] = s;
350                                         v[1] = -t;
351                                         v[2] = 1;
352                                         break;
353                                 case 5:
354                                         v[0] = -s;
355                                         v[1] = -t;
356                                         v[2] = -1;
357                                         break;
358                                 }
359                                 intensity = 127.0f / sqrt(DotProduct(v, v));
360                                 data[side][y][x][0] = 128.0f + intensity * v[0];
361                                 data[side][y][x][1] = 128.0f + intensity * v[1];
362                                 data[side][y][x][2] = 128.0f + intensity * v[2];
363                                 data[side][y][x][3] = 255;
364                         }
365                 }
366         }
367         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
368 }
369
370 static void R_BuildFogTexture(void)
371 {
372         int x, b;
373         double r, alpha;
374 #define FOGWIDTH 64
375         unsigned char data1[FOGWIDTH][4];
376         unsigned char data2[FOGWIDTH][4];
377         r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
378         for (x = 0;x < FOGWIDTH;x++)
379         {
380                 alpha = exp(r / ((double)x*(double)x));
381                 if (x == FOGWIDTH - 1)
382                         alpha = 1;
383                 b = (int)(256.0 * alpha);
384                 b = bound(0, b, 255);
385                 data1[x][0] = 255 - b;
386                 data1[x][1] = 255 - b;
387                 data1[x][2] = 255 - b;
388                 data1[x][3] = 255;
389                 data2[x][0] = b;
390                 data2[x][1] = b;
391                 data2[x][2] = b;
392                 data2[x][3] = 255;
393         }
394         r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
395         r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
396 }
397
398 void gl_main_start(void)
399 {
400         r_main_texturepool = R_AllocTexturePool();
401         r_bloom_texture_screen = NULL;
402         r_bloom_texture_bloom = NULL;
403         R_BuildBlankTextures();
404         R_BuildNoTexture();
405         if (gl_texturecubemap)
406         {
407                 R_BuildWhiteCube();
408                 R_BuildNormalizationCube();
409         }
410         R_BuildFogTexture();
411 }
412
413 void gl_main_shutdown(void)
414 {
415         R_FreeTexturePool(&r_main_texturepool);
416         r_bloom_texture_screen = NULL;
417         r_bloom_texture_bloom = NULL;
418         r_texture_blanknormalmap = NULL;
419         r_texture_white = NULL;
420         r_texture_black = NULL;
421         r_texture_whitecube = NULL;
422         r_texture_normalizationcube = NULL;
423 }
424
425 extern void CL_ParseEntityLump(char *entitystring);
426 void gl_main_newmap(void)
427 {
428         // FIXME: move this code to client
429         int l;
430         char *entities, entname[MAX_QPATH];
431         r_framecount = 1;
432         if (cl.worldmodel)
433         {
434                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
435                 l = (int)strlen(entname) - 4;
436                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
437                 {
438                         strcpy(entname + l, ".ent");
439                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
440                         {
441                                 CL_ParseEntityLump(entities);
442                                 Mem_Free(entities);
443                                 return;
444                         }
445                 }
446                 if (cl.worldmodel->brush.entities)
447                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
448         }
449 }
450
451 void GL_Main_Init(void)
452 {
453 // FIXME: move this to client?
454         FOG_registercvars();
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 = 1.0;
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) + 1.0f;
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) + 1.0f;
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         // don't let sound skip if going slow
1170         if (r_refdef.extraupdate)
1171                 S_ExtraUpdate ();
1172
1173         r_framecount++;
1174
1175         R_MeshQueue_BeginScene();
1176
1177         R_SetFrustum();
1178
1179         r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1180         if (r_rtworldshadows || r_rtdlightshadows)
1181                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, 1.0f);
1182         else
1183                 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, 1.0f, r_farclip);
1184
1185         GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1186
1187         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);
1188
1189         R_SkyStartFrame();
1190
1191         R_WorldVisibility();
1192         if (r_timereport_active)
1193                 R_TimeReport("worldvis");
1194
1195         R_MarkEntities();
1196         if (r_timereport_active)
1197                 R_TimeReport("markentity");
1198
1199         R_Shadow_UpdateWorldLightSelection();
1200
1201         for (r_showtrispass = 0;r_showtrispass <= (r_showtris.value > 0);r_showtrispass++)
1202         {
1203                 if (r_showtrispass)
1204                 {
1205                         rmeshstate_t m;
1206                         r_showtrispass = 0;
1207                         GL_BlendFunc(GL_ONE, GL_ONE);
1208                         GL_DepthTest(!r_showdisabledepthtest.integer);
1209                         GL_DepthMask(GL_FALSE);
1210                         memset(&m, 0, sizeof(m));
1211                         R_Mesh_State(&m);
1212                         //qglEnable(GL_LINE_SMOOTH);
1213                         qglEnable(GL_POLYGON_OFFSET_LINE);
1214                         qglPolygonOffset(0, r_showtris_polygonoffset.value);
1215                         r_showtrispass = 1;
1216                 }
1217
1218                 if (cl.csqc_vidvars.drawworld)
1219                 {
1220                         // don't let sound skip if going slow
1221                         if (r_refdef.extraupdate)
1222                                 S_ExtraUpdate ();
1223
1224                         if (r_showtrispass)
1225                                 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1226                         if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1227                         {
1228                                 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1229                                 if (r_timereport_active)
1230                                         R_TimeReport("worldsky");
1231                         }
1232
1233                         if (R_DrawBrushModelsSky() && r_timereport_active)
1234                                 R_TimeReport("bmodelsky");
1235
1236                         if (r_showtrispass)
1237                                 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1238                         if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1239                         {
1240                                 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1241                                 if (r_timereport_active)
1242                                         R_TimeReport("world");
1243                         }
1244                 }
1245
1246                 // don't let sound skip if going slow
1247                 if (r_refdef.extraupdate)
1248                         S_ExtraUpdate ();
1249
1250                 if (r_showtrispass)
1251                         GL_ShowTrisColor(0, 0.015, 0, 1);
1252
1253                 R_DrawModels();
1254                 if (r_timereport_active)
1255                         R_TimeReport("models");
1256
1257                 // don't let sound skip if going slow
1258                 if (r_refdef.extraupdate)
1259                         S_ExtraUpdate ();
1260
1261                 if (r_showtrispass)
1262                         GL_ShowTrisColor(0, 0, 0.033, 1);
1263                 R_ShadowVolumeLighting(false);
1264                 if (r_timereport_active)
1265                         R_TimeReport("rtlights");
1266
1267                 // don't let sound skip if going slow
1268                 if (r_refdef.extraupdate)
1269                         S_ExtraUpdate ();
1270
1271                 if (r_showtrispass)
1272                         GL_ShowTrisColor(0.1, 0, 0, 1);
1273
1274                 if (cl.csqc_vidvars.drawworld)
1275                 {
1276                         R_DrawLightningBeams();
1277                         if (r_timereport_active)
1278                                 R_TimeReport("lightning");
1279
1280                         R_DrawParticles();
1281                         if (r_timereport_active)
1282                                 R_TimeReport("particles");
1283
1284                         R_DrawExplosions();
1285                         if (r_timereport_active)
1286                                 R_TimeReport("explosions");
1287                 }
1288
1289                 R_MeshQueue_RenderTransparent();
1290                 if (r_timereport_active)
1291                         R_TimeReport("drawtrans");
1292
1293                 if (cl.csqc_vidvars.drawworld)
1294                 {
1295                         R_DrawCoronas();
1296                         if (r_timereport_active)
1297                                 R_TimeReport("coronas");
1298                 }
1299                 if(cl.csqc_vidvars.drawcrosshair)
1300                 {
1301                         R_DrawWorldCrosshair();
1302                         if (r_timereport_active)
1303                                 R_TimeReport("crosshair");
1304                 }
1305
1306                 VM_AddPolygonsToMeshQueue();
1307
1308                 R_MeshQueue_Render();
1309
1310                 if (r_showtrispass)
1311                 {
1312                         //qglDisable(GL_LINE_SMOOTH);
1313                         qglDisable(GL_POLYGON_OFFSET_LINE);
1314                 }
1315         }
1316
1317         r_showtrispass = 0;
1318
1319         R_MeshQueue_EndScene();
1320
1321         // don't let sound skip if going slow
1322         if (r_refdef.extraupdate)
1323                 S_ExtraUpdate ();
1324 }
1325
1326 /*
1327 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1328 {
1329         int i;
1330         float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1331         rmeshstate_t m;
1332         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1333         GL_DepthMask(false);
1334         GL_DepthTest(true);
1335         R_Mesh_Matrix(&identitymatrix);
1336
1337         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1338         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1339         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1340         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1341         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1342         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1343         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1344         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1345         R_FillColors(color, 8, cr, cg, cb, ca);
1346         if (fogenabled)
1347         {
1348                 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1349                 {
1350                         f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
1351                         f1 = 1 - f2;
1352                         c[0] = c[0] * f1 + fogcolor[0] * f2;
1353                         c[1] = c[1] * f1 + fogcolor[1] * f2;
1354                         c[2] = c[2] * f1 + fogcolor[2] * f2;
1355                 }
1356         }
1357         memset(&m, 0, sizeof(m));
1358         m.pointer_vertex = vertex3f;
1359         m.pointer_color = color;
1360         R_Mesh_State(&m);
1361         R_Mesh_Draw(8, 12);
1362 }
1363 */
1364
1365 int nomodelelements[24] =
1366 {
1367         5, 2, 0,
1368         5, 1, 2,
1369         5, 0, 3,
1370         5, 3, 1,
1371         0, 2, 4,
1372         2, 1, 4,
1373         3, 0, 4,
1374         1, 3, 4
1375 };
1376
1377 float nomodelvertex3f[6*3] =
1378 {
1379         -16,   0,   0,
1380          16,   0,   0,
1381           0, -16,   0,
1382           0,  16,   0,
1383           0,   0, -16,
1384           0,   0,  16
1385 };
1386
1387 float nomodelcolor4f[6*4] =
1388 {
1389         0.0f, 0.0f, 0.5f, 1.0f,
1390         0.0f, 0.0f, 0.5f, 1.0f,
1391         0.0f, 0.5f, 0.0f, 1.0f,
1392         0.0f, 0.5f, 0.0f, 1.0f,
1393         0.5f, 0.0f, 0.0f, 1.0f,
1394         0.5f, 0.0f, 0.0f, 1.0f
1395 };
1396
1397 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
1398 {
1399         int i;
1400         float f1, f2, *c;
1401         float color4f[6*4];
1402         rmeshstate_t m;
1403         R_Mesh_Matrix(&ent->matrix);
1404
1405         memset(&m, 0, sizeof(m));
1406         m.pointer_vertex = nomodelvertex3f;
1407
1408         if (ent->flags & EF_ADDITIVE)
1409         {
1410                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1411                 GL_DepthMask(false);
1412         }
1413         else if (ent->alpha < 1)
1414         {
1415                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1416                 GL_DepthMask(false);
1417         }
1418         else
1419         {
1420                 GL_BlendFunc(GL_ONE, GL_ZERO);
1421                 GL_DepthMask(true);
1422         }
1423         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1424         if (fogenabled)
1425         {
1426                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1427                 m.pointer_color = color4f;
1428                 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
1429                 f1 = 1 - f2;
1430                 for (i = 0, c = color4f;i < 6;i++, c += 4)
1431                 {
1432                         c[0] = (c[0] * f1 + fogcolor[0] * f2);
1433                         c[1] = (c[1] * f1 + fogcolor[1] * f2);
1434                         c[2] = (c[2] * f1 + fogcolor[2] * f2);
1435                         c[3] *= ent->alpha;
1436                 }
1437         }
1438         else if (ent->alpha != 1)
1439         {
1440                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1441                 m.pointer_color = color4f;
1442                 for (i = 0, c = color4f;i < 6;i++, c += 4)
1443                         c[3] *= ent->alpha;
1444         }
1445         else
1446                 m.pointer_color = nomodelcolor4f;
1447         R_Mesh_State(&m);
1448         R_Mesh_Draw(0, 6, 8, nomodelelements);
1449 }
1450
1451 void R_DrawNoModel(entity_render_t *ent)
1452 {
1453         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1454                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
1455         //else
1456         //      R_DrawNoModelCallback(ent, 0);
1457 }
1458
1459 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1460 {
1461         vec3_t right1, right2, diff, normal;
1462
1463         VectorSubtract (org2, org1, normal);
1464
1465         // calculate 'right' vector for start
1466         VectorSubtract (r_vieworigin, org1, diff);
1467         CrossProduct (normal, diff, right1);
1468         VectorNormalize (right1);
1469
1470         // calculate 'right' vector for end
1471         VectorSubtract (r_vieworigin, org2, diff);
1472         CrossProduct (normal, diff, right2);
1473         VectorNormalize (right2);
1474
1475         vert[ 0] = org1[0] + width * right1[0];
1476         vert[ 1] = org1[1] + width * right1[1];
1477         vert[ 2] = org1[2] + width * right1[2];
1478         vert[ 3] = org1[0] - width * right1[0];
1479         vert[ 4] = org1[1] - width * right1[1];
1480         vert[ 5] = org1[2] - width * right1[2];
1481         vert[ 6] = org2[0] - width * right2[0];
1482         vert[ 7] = org2[1] - width * right2[1];
1483         vert[ 8] = org2[2] - width * right2[2];
1484         vert[ 9] = org2[0] + width * right2[0];
1485         vert[10] = org2[1] + width * right2[1];
1486         vert[11] = org2[2] + width * right2[2];
1487 }
1488
1489 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1490
1491 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)
1492 {
1493         float fog = 0.0f, ifog;
1494         rmeshstate_t m;
1495
1496         if (fogenabled)
1497                 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
1498         ifog = 1 - fog;
1499
1500         R_Mesh_Matrix(&identitymatrix);
1501         GL_BlendFunc(blendfunc1, blendfunc2);
1502         GL_DepthMask(false);
1503         GL_DepthTest(!depthdisable);
1504
1505         varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1506         varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1507         varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1508         varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1509         varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1510         varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1511         varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1512         varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1513         varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1514         varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1515         varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1516         varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1517
1518         memset(&m, 0, sizeof(m));
1519         m.tex[0] = R_GetTexture(texture);
1520         m.pointer_texcoord[0] = spritetexcoord2f;
1521         m.pointer_vertex = varray_vertex3f;
1522         R_Mesh_State(&m);
1523         GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
1524         R_Mesh_Draw(0, 4, 2, polygonelements);
1525
1526         if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
1527         {
1528                 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
1529                 GL_BlendFunc(blendfunc1, GL_ONE);
1530                 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
1531                 R_Mesh_Draw(0, 4, 2, polygonelements);
1532         }
1533 }
1534
1535 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1536 {
1537         int i;
1538         float *vertex3f;
1539         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1540                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1541                         break;
1542         if (i == mesh->numvertices)
1543         {
1544                 if (mesh->numvertices < mesh->maxvertices)
1545                 {
1546                         VectorCopy(v, vertex3f);
1547                         mesh->numvertices++;
1548                 }
1549                 return mesh->numvertices;
1550         }
1551         else
1552                 return i;
1553 }
1554
1555 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1556 {
1557         int i;
1558         int *e, element[3];
1559         element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1560         element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1561         e = mesh->element3i + mesh->numtriangles * 3;
1562         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1563         {
1564                 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1565                 if (mesh->numtriangles < mesh->maxtriangles)
1566                 {
1567                         *e++ = element[0];
1568                         *e++ = element[1];
1569                         *e++ = element[2];
1570                         mesh->numtriangles++;
1571                 }
1572                 element[1] = element[2];
1573         }
1574 }
1575
1576 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1577 {
1578         int planenum, planenum2;
1579         int w;
1580         int tempnumpoints;
1581         mplane_t *plane, *plane2;
1582         float temppoints[2][256*3];
1583         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1584         {
1585                 w = 0;
1586                 tempnumpoints = 4;
1587                 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1588                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1589                 {
1590                         if (planenum2 == planenum)
1591                                 continue;
1592                         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);
1593                         w = !w;
1594                 }
1595                 if (tempnumpoints < 3)
1596                         continue;
1597                 // generate elements forming a triangle fan for this polygon
1598                 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1599         }
1600 }
1601
1602 void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, matrix4x4_t *matrix, float r, float g, float b, float a)
1603 {
1604         texturelayer_t *layer;
1605         layer = t->currentlayers + t->currentnumlayers++;
1606         layer->type = type;
1607         layer->depthmask = depthmask;
1608         layer->blendfunc1 = blendfunc1;
1609         layer->blendfunc2 = blendfunc2;
1610         layer->texture = texture;
1611         layer->texmatrix = *matrix;
1612         layer->color[0] = r;
1613         layer->color[1] = g;
1614         layer->color[2] = b;
1615         layer->color[3] = a;
1616 }
1617
1618 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1619 {
1620         // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1621         //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1622
1623         {
1624                 texture_t *texture = t;
1625                 model_t *model = ent->model;
1626                 int s = ent->skinnum;
1627                 if ((unsigned int)s >= (unsigned int)model->numskins)
1628                         s = 0;
1629                 if (model->skinscenes)
1630                 {
1631                         if (model->skinscenes[s].framecount > 1)
1632                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1633                         else
1634                                 s = model->skinscenes[s].firstframe;
1635                 }
1636                 if (s > 0)
1637                         t = t + s * model->num_surfaces;
1638                 if (t->animated)
1639                         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];
1640                 texture->currentframe = t;
1641         }
1642
1643         t->currentmaterialflags = t->basematerialflags;
1644         t->currentalpha = ent->alpha;
1645         if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1646                 t->currentalpha *= r_wateralpha.value;
1647         if (!(ent->flags & RENDER_LIGHT))
1648                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1649         if (ent->effects & EF_ADDITIVE)
1650                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1651         else if (t->currentalpha < 1)
1652                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1653         if (ent->effects & EF_NODEPTHTEST)
1654                 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1655         if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1656                 t->currenttexmatrix = r_waterscrollmatrix;
1657         else
1658                 t->currenttexmatrix = identitymatrix;
1659         t->currentnumlayers = 0;
1660         if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
1661         {
1662                 if (gl_lightmaps.integer)
1663                         R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
1664                 else if (t->currentmaterialflags & MATERIALFLAG_SKY)
1665                 {
1666                         // transparent sky would be ridiculous
1667                         if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1668                                 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
1669                 }
1670                 else
1671                 {
1672                         int blendfunc1, blendfunc2, depthmask;
1673                         if (t->currentmaterialflags & MATERIALFLAG_ADD)
1674                         {
1675                                 blendfunc1 = GL_SRC_ALPHA;
1676                                 blendfunc2 = GL_ONE;
1677                                 depthmask = false;
1678                         }
1679                         else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
1680                         {
1681                                 blendfunc1 = GL_SRC_ALPHA;
1682                                 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1683                                 depthmask = false;
1684                         }
1685                         else
1686                         {
1687                                 blendfunc1 = GL_ONE;
1688                                 blendfunc2 = GL_ZERO;
1689                                 depthmask = true;
1690                         }
1691                         if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1692                         {
1693                                 rtexture_t *currentbasetexture;
1694                                 int layerflags = 0;
1695                                 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1696                                         layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
1697                                 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
1698                                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1699                                 {
1700                                         // fullbright is not affected by r_lightmapintensity
1701                                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
1702                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
1703                                                 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);
1704                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
1705                                                 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);
1706                                 }
1707                                 else
1708                                 {
1709                                         float colorscale;
1710                                         colorscale = 2;
1711                                         // q3bsp has no lightmap updates, so the lightstylevalue that
1712                                         // would normally be baked into the lightmaptexture must be
1713                                         // applied to the color
1714                                         if (ent->model->type == mod_brushq3)
1715                                                 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
1716                                         colorscale *= r_lightmapintensity;
1717                                         if (r_textureunits.integer >= 2 && gl_combine.integer)
1718                                                 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);
1719                                         else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
1720                                                 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);
1721                                         else
1722                                                 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);
1723                                         if (r_ambient.value >= (1.0f/64.0f))
1724                                                 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);
1725                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
1726                                         {
1727                                                 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);
1728                                                 if (r_ambient.value >= (1.0f/64.0f))
1729                                                         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);
1730                                         }
1731                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
1732                                         {
1733                                                 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);
1734                                                 if (r_ambient.value >= (1.0f/64.0f))
1735                                                         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);
1736                                         }
1737                                 }
1738                                 if (t->skin.glow != NULL)
1739                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
1740                                 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
1741                                 {
1742                                         // if this is opaque use alpha blend which will darken the earlier
1743                                         // passes cheaply.
1744                                         //
1745                                         // if this is an alpha blended material, all the earlier passes
1746                                         // were darkened by fog already, so we only need to add the fog
1747                                         // color ontop through the fog mask texture
1748                                         //
1749                                         // if this is an additive blended material, all the earlier passes
1750                                         // were darkened by fog already, and we should not add fog color
1751                                         // (because the background was not darkened, there is no fog color
1752                                         // that was lost behind it).
1753                                         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);
1754                                 }
1755                         }
1756                 }
1757         }
1758 }
1759
1760 void R_UpdateAllTextureInfo(entity_render_t *ent)
1761 {
1762         int i;
1763         if (ent->model)
1764                 for (i = 0;i < ent->model->num_textures;i++)
1765                         R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1766 }
1767
1768 float *rsurface_vertex3f;
1769 float *rsurface_svector3f;
1770 float *rsurface_tvector3f;
1771 float *rsurface_normal3f;
1772 float *rsurface_lightmapcolor4f;
1773
1774 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1775 {
1776         int i, j;
1777         float center[3], forward[3], right[3], up[3], v[4][3];
1778         matrix4x4_t matrix1, imatrix1;
1779         if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1780         {
1781                 rsurface_vertex3f = varray_vertex3f;
1782                 rsurface_svector3f = NULL;
1783                 rsurface_tvector3f = NULL;
1784                 rsurface_normal3f = NULL;
1785                 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1786         }
1787         else
1788         {
1789                 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1790                 rsurface_svector3f = surface->groupmesh->data_svector3f;
1791                 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1792                 rsurface_normal3f = surface->groupmesh->data_normal3f;
1793         }
1794         if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1795         {
1796                 if (!rsurface_svector3f)
1797                 {
1798                         rsurface_svector3f = varray_svector3f;
1799                         rsurface_tvector3f = varray_tvector3f;
1800                         rsurface_normal3f = varray_normal3f;
1801                         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);
1802                 }
1803                 // a single autosprite surface can contain multiple sprites...
1804                 VectorClear(forward);
1805                 VectorClear(right);
1806                 VectorSet(up, 0, 0, 1);
1807                 for (j = 0;j < surface->num_vertices - 3;j += 4)
1808                 {
1809                         VectorClear(center);
1810                         for (i = 0;i < 4;i++)
1811                                 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1812                         VectorScale(center, 0.25f, center);
1813                         // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1814                         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);
1815                         Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1816                         for (i = 0;i < 4;i++)
1817                                 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1818                         forward[0] = modelorg[0] - center[0];
1819                         forward[1] = modelorg[1] - center[1];
1820                         VectorNormalize(forward);
1821                         right[0] = forward[1];
1822                         right[1] = -forward[0];
1823                         for (i = 0;i < 4;i++)
1824                                 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1825                 }
1826                 rsurface_vertex3f = varray_vertex3f;
1827                 rsurface_svector3f = NULL;
1828                 rsurface_tvector3f = NULL;
1829                 rsurface_normal3f = NULL;
1830         }
1831         else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1832         {
1833                 if (!rsurface_svector3f)
1834                 {
1835                         rsurface_svector3f = varray_svector3f;
1836                         rsurface_tvector3f = varray_tvector3f;
1837                         rsurface_normal3f = varray_normal3f;
1838                         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);
1839                 }
1840                 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1841                 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1842                 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1843                 // a single autosprite surface can contain multiple sprites...
1844                 for (j = 0;j < surface->num_vertices - 3;j += 4)
1845                 {
1846                         VectorClear(center);
1847                         for (i = 0;i < 4;i++)
1848                                 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1849                         VectorScale(center, 0.25f, center);
1850                         // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1851                         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);
1852                         Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1853                         for (i = 0;i < 4;i++)
1854                                 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1855                         for (i = 0;i < 4;i++)
1856                                 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1857                 }
1858                 rsurface_vertex3f = varray_vertex3f;
1859                 rsurface_svector3f = NULL;
1860                 rsurface_tvector3f = NULL;
1861                 rsurface_normal3f = NULL;
1862         }
1863         R_Mesh_VertexPointer(rsurface_vertex3f);
1864 }
1865
1866 void RSurf_SetColorPointer(const entity_render_t *ent, const msurface_t *surface, const vec3_t modelorg, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
1867 {
1868         int i;
1869         float f;
1870         float *v, *c, *c2;
1871         if (lightmode >= 2)
1872         {
1873                 // model lighting
1874                 vec4_t ambientcolor4f;
1875                 vec3_t diffusecolor;
1876                 vec3_t diffusenormal;
1877                 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1878                 {
1879                         rsurface_lightmapcolor4f = varray_color4f;
1880                         if (rsurface_normal3f == NULL)
1881                         {
1882                                 rsurface_normal3f = varray_normal3f;
1883                                 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);
1884                         }
1885                         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);
1886                         r = 1;
1887                         g = 1;
1888                         b = 1;
1889                         a = 1;
1890                         applycolor = false;
1891                 }
1892                 else
1893                 {
1894                         r = ambientcolor4f[0];
1895                         g = ambientcolor4f[1];
1896                         b = ambientcolor4f[2];
1897                         a = ambientcolor4f[3];
1898                         rsurface_lightmapcolor4f = NULL;
1899                 }
1900         }
1901         else if (lightmode >= 1)
1902         {
1903                 if (surface->lightmapinfo)
1904                 {
1905                         for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1906                         {
1907                                 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1908                                 if (lm)
1909                                 {
1910                                         float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1911                                         VectorScale(lm, scale, c);
1912                                         if (surface->lightmapinfo->styles[1] != 255)
1913                                         {
1914                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1915                                                 lm += size3;
1916                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1917                                                 VectorMA(c, scale, lm, c);
1918                                                 if (surface->lightmapinfo->styles[2] != 255)
1919                                                 {
1920                                                         lm += size3;
1921                                                         scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1922                                                         VectorMA(c, scale, lm, c);
1923                                                         if (surface->lightmapinfo->styles[3] != 255)
1924                                                         {
1925                                                                 lm += size3;
1926                                                                 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1927                                                                 VectorMA(c, scale, lm, c);
1928                                                         }
1929                                                 }
1930                                         }
1931                                 }
1932                                 else
1933                                         VectorClear(c);
1934                         }
1935                         rsurface_lightmapcolor4f = varray_color4f;
1936                 }
1937                 else
1938                         rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1939         }
1940         else
1941                 rsurface_lightmapcolor4f = NULL;
1942         if (applyfog)
1943         {
1944                 if (rsurface_lightmapcolor4f)
1945                 {
1946                         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)
1947                         {
1948                                 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1949                                 c2[0] = c[0] * f;
1950                                 c2[1] = c[1] * f;
1951                                 c2[2] = c[2] * f;
1952                                 c2[3] = c[3];
1953                         }
1954                 }
1955                 else
1956                 {
1957                         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)
1958                         {
1959                                 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1960                                 c2[0] = f;
1961                                 c2[1] = f;
1962                                 c2[2] = f;
1963                                 c2[3] = 1;
1964                         }
1965                 }
1966                 rsurface_lightmapcolor4f = varray_color4f;
1967         }
1968         if (applycolor && rsurface_lightmapcolor4f)
1969         {
1970                 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)
1971                 {
1972                         c2[0] = c[0] * r;
1973                         c2[1] = c[1] * g;
1974                         c2[2] = c[2] * b;
1975                         c2[3] = c[3] * a;
1976                 }
1977                 rsurface_lightmapcolor4f = varray_color4f;
1978         }
1979         R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1980         GL_Color(r, g, b, a);
1981 }
1982
1983 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1984 {
1985         int texturesurfaceindex;
1986         int lightmode;
1987         const msurface_t *surface;
1988         qboolean applycolor;
1989         rmeshstate_t m;
1990         if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1991                 return;
1992         renderstats.entities_surfaces += texturenumsurfaces;
1993         // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1994         lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1995         GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1996         if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
1997                 qglDisable(GL_CULL_FACE);
1998         if (texture->currentnumlayers)
1999         {
2000                 int layerindex;
2001                 texturelayer_t *layer;
2002                 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
2003                 {
2004                         vec4_t layercolor;
2005                         int layertexrgbscale;
2006                         GL_DepthMask(layer->depthmask);
2007                         GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2008                         if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2009                         {
2010                                 layertexrgbscale = 4;
2011                                 VectorScale(layer->color, 0.25f, layercolor);
2012                         }
2013                         else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2014                         {
2015                                 layertexrgbscale = 2;
2016                                 VectorScale(layer->color, 0.5f, layercolor);
2017                         }
2018                         else
2019                         {
2020                                 layertexrgbscale = 1;
2021                                 VectorScale(layer->color, 1.0f, layercolor);
2022                         }
2023                         layercolor[3] = layer->color[3];
2024                         GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2025                         applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2026                         switch (layer->type)
2027                         {
2028                         case TEXTURELAYERTYPE_SKY:
2029                                 if (skyrendernow)
2030                                 {
2031                                         skyrendernow = false;
2032                                         if (skyrendermasked)
2033                                         {
2034                                                 R_Sky();
2035                                                 // restore entity matrix and GL_Color
2036                                                 R_Mesh_Matrix(&ent->matrix);
2037                                                 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2038                                         }
2039                                 }
2040                                 // LordHavoc: HalfLife maps have freaky skypolys...
2041                                 //if (!ent->model->brush.ishlbsp)
2042                                 {
2043                                         if (skyrendermasked)
2044                                         {
2045                                                 // depth-only (masking)
2046                                                 GL_ColorMask(0,0,0,0);
2047                                                 // just to make sure that braindead drivers don't draw anything
2048                                                 // despite that colormask...
2049                                                 GL_BlendFunc(GL_ZERO, GL_ONE);
2050                                         }
2051                                         else
2052                                         {
2053                                                 // fog sky
2054                                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2055                                         }
2056                                         memset(&m, 0, sizeof(m));
2057                                         R_Mesh_State(&m);
2058                                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2059                                         {
2060                                                 surface = texturesurfacelist[texturesurfaceindex];
2061                                                 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2062                                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2063                                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2064                                                 GL_LockArrays(0, 0);
2065                                         }
2066                                         if (skyrendermasked)
2067                                                 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2068                                 }
2069                                 break;
2070                         case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2071                                 memset(&m, 0, sizeof(m));
2072                                 m.tex[1] = R_GetTexture(layer->texture);
2073                                 m.texmatrix[1] = layer->texmatrix;
2074                                 m.texrgbscale[1] = layertexrgbscale;
2075                                 m.pointer_color = varray_color4f;
2076                                 R_Mesh_State(&m);
2077                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2078                                 {
2079                                         surface = texturesurfacelist[texturesurfaceindex];
2080                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2081                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2082                                         R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2083                                         if (lightmode == 2)
2084                                         {
2085                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2086                                                 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2087                                         }
2088                                         else if (surface->lightmaptexture)
2089                                         {
2090                                                 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2091                                                 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2092                                         }
2093                                         else
2094                                         {
2095                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2096                                                 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2097                                         }
2098                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2099                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2100                                         GL_LockArrays(0, 0);
2101                                 }
2102                                 break;
2103                         case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2104                                 memset(&m, 0, sizeof(m));
2105                                 m.tex[0] = R_GetTexture(layer->texture);
2106                                 m.texmatrix[0] = layer->texmatrix;
2107                                 m.pointer_color = varray_color4f;
2108                                 m.texrgbscale[0] = layertexrgbscale;
2109                                 R_Mesh_State(&m);
2110                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2111                                 {
2112                                         surface = texturesurfacelist[texturesurfaceindex];
2113                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2114                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2115                                         if (lightmode == 2)
2116                                         {
2117                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2118                                                 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 2, false, false);
2119                                         }
2120                                         else if (surface->lightmaptexture)
2121                                         {
2122                                                 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2123                                                 R_Mesh_ColorPointer(NULL);
2124                                         }
2125                                         else
2126                                         {
2127                                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2128                                                 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 1, false, false);
2129                                         }
2130                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2131                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2132                                         GL_LockArrays(0, 0);
2133                                 }
2134                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2135                                 memset(&m, 0, sizeof(m));
2136                                 m.tex[0] = R_GetTexture(layer->texture);
2137                                 m.texmatrix[0] = layer->texmatrix;
2138                                 m.pointer_color = varray_color4f;
2139                                 m.texrgbscale[0] = layertexrgbscale;
2140                                 R_Mesh_State(&m);
2141                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2142                                 {
2143                                         surface = texturesurfacelist[texturesurfaceindex];
2144                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2145                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2146                                         RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2147                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2148                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2149                                         GL_LockArrays(0, 0);
2150                                 }
2151                                 break;
2152                         case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
2153                                 memset(&m, 0, sizeof(m));
2154                                 m.tex[0] = R_GetTexture(layer->texture);
2155                                 m.texmatrix[0] = layer->texmatrix;
2156                                 m.texrgbscale[0] = layertexrgbscale;
2157                                 m.pointer_color = varray_color4f;
2158                                 R_Mesh_State(&m);
2159                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2160                                 {
2161                                         surface = texturesurfacelist[texturesurfaceindex];
2162                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2163                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2164                                         RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode ? lightmode : 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2165                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2166                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2167                                         GL_LockArrays(0, 0);
2168                                 }
2169                                 break;
2170                         case TEXTURELAYERTYPE_TEXTURE:
2171                                 memset(&m, 0, sizeof(m));
2172                                 m.tex[0] = R_GetTexture(layer->texture);
2173                                 m.texmatrix[0] = layer->texmatrix;
2174                                 m.pointer_color = varray_color4f;
2175                                 m.texrgbscale[0] = layertexrgbscale;
2176                                 R_Mesh_State(&m);
2177                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2178                                 {
2179                                         surface = texturesurfacelist[texturesurfaceindex];
2180                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2181                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2182                                         RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2183                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2184                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2185                                         GL_LockArrays(0, 0);
2186                                 }
2187                                 break;
2188                         case TEXTURELAYERTYPE_FOG:
2189                                 memset(&m, 0, sizeof(m));
2190                                 if (layer->texture)
2191                                 {
2192                                         m.tex[0] = R_GetTexture(layer->texture);
2193                                         m.texmatrix[0] = layer->texmatrix;
2194                                 }
2195                                 R_Mesh_State(&m);
2196                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2197                                 {
2198                                         int i;
2199                                         float f, *v, *c;
2200                                         surface = texturesurfacelist[texturesurfaceindex];
2201                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2202                                         if (layer->texture)
2203                                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2204                                         R_Mesh_ColorPointer(varray_color4f);
2205                                         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)
2206                                         {
2207                                                 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
2208                                                 c[0] = layercolor[0];
2209                                                 c[1] = layercolor[1];
2210                                                 c[2] = layercolor[2];
2211                                                 c[3] = f * layercolor[3];
2212                                         }
2213                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2214                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2215                                         GL_LockArrays(0, 0);
2216                                 }
2217                                 break;
2218                         default:
2219                                 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2220                         }
2221                         // if trying to do overbright on first pass of an opaque surface
2222                         // when combine is not supported, brighten as a post process
2223                         if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
2224                         {
2225                                 int scale;
2226                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2227                                 GL_Color(1, 1, 1, 1);
2228                                 memset(&m, 0, sizeof(m));
2229                                 R_Mesh_State(&m);
2230                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2231                                 {
2232                                         surface = texturesurfacelist[texturesurfaceindex];
2233                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2234                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2235                                         for (scale = 1;scale < layertexrgbscale;scale <<= 1)
2236                                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2237                                         GL_LockArrays(0, 0);
2238                                 }
2239                         }
2240                 }
2241                 if (r_shownormals.integer && !r_showtrispass)
2242                 {
2243                         int j, k;
2244                         float v[3];
2245                         GL_DepthTest(!r_showdisabledepthtest.integer);
2246                         GL_DepthMask(texture->currentlayers->depthmask);
2247                         GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
2248                         memset(&m, 0, sizeof(m));
2249                         R_Mesh_State(&m);
2250                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2251                         {
2252                                 surface = texturesurfacelist[texturesurfaceindex];
2253                                 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2254                                 if (!rsurface_svector3f)
2255                                 {
2256                                         rsurface_svector3f = varray_svector3f;
2257                                         rsurface_tvector3f = varray_tvector3f;
2258                                         rsurface_normal3f = varray_normal3f;
2259                                         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);
2260                                 }
2261                                 GL_Color(1, 0, 0, 1);
2262                                 qglBegin(GL_LINES);
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_svector3f + k * 3, v);
2268                                         qglVertex3f(v[0], v[1], v[2]);
2269                                 }
2270                                 GL_Color(0, 0, 1, 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_tvector3f + k * 3, v);
2276                                         qglVertex3f(v[0], v[1], v[2]);
2277                                 }
2278                                 GL_Color(0, 1, 0, 1);
2279                                 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2280                                 {
2281                                         VectorCopy(rsurface_vertex3f + k * 3, v);
2282                                         qglVertex3f(v[0], v[1], v[2]);
2283                                         VectorMA(v, 8, rsurface_normal3f + k * 3, v);
2284                                         qglVertex3f(v[0], v[1], v[2]);
2285                                 }
2286                                 qglEnd();
2287                         }
2288                 }
2289         }
2290         if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2291                 qglEnable(GL_CULL_FACE);
2292 }
2293
2294 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2295 {
2296         const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
2297         vec3_t modelorg;
2298         texture_t *texture;
2299
2300         texture = surface->texture;
2301         if (texture->basematerialflags & MATERIALFLAG_SKY)
2302                 return; // transparent sky is too difficult
2303         R_UpdateTextureInfo(ent, texture);
2304
2305         R_Mesh_Matrix(&ent->matrix);
2306         Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2307         R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2308 }
2309
2310 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2311 {
2312         int texturesurfaceindex;
2313         const msurface_t *surface;
2314         vec3_t tempcenter, center;
2315         if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2316         {
2317                 // drawing sky transparently would be too difficult
2318                 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2319                 {
2320                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2321                         {
2322                                 surface = texturesurfacelist[texturesurfaceindex];
2323                                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2324                                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2325                                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2326                                 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2327                                 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
2328                         }
2329                 }
2330         }
2331         else
2332                 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2333 }
2334
2335 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2336 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2337 {
2338         int i, j, f, flagsmask;
2339         int counttriangles = 0;
2340         msurface_t *surface, **surfacechain;
2341         texture_t *t, *texture;
2342         model_t *model = ent->model;
2343         vec3_t modelorg;
2344         const int maxsurfacelist = 1024;
2345         int numsurfacelist = 0;
2346         const msurface_t *surfacelist[1024];
2347         if (model == NULL)
2348                 return;
2349         R_Mesh_Matrix(&ent->matrix);
2350         Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2351
2352         // update light styles
2353         if (!skysurfaces && model->brushq1.light_styleupdatechains)
2354         {
2355                 for (i = 0;i < model->brushq1.light_styles;i++)
2356                 {
2357                         if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
2358                         {
2359                                 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
2360                                 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2361                                         for (;(surface = *surfacechain);surfacechain++)
2362                                                 surface->cached_dlight = true;
2363                         }
2364                 }
2365         }
2366
2367         R_UpdateAllTextureInfo(ent);
2368         flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2369         f = 0;
2370         t = NULL;
2371         texture = NULL;
2372         numsurfacelist = 0;
2373         if (ent == r_refdef.worldentity)
2374         {
2375                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2376                 {
2377                         if (!r_worldsurfacevisible[j])
2378                                 continue;
2379                         if (t != surface->texture)
2380                         {
2381                                 if (numsurfacelist)
2382                                 {
2383                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2384                                         numsurfacelist = 0;
2385                                 }
2386                                 t = surface->texture;
2387                                 texture = t->currentframe;
2388                                 f = texture->currentmaterialflags & flagsmask;
2389                         }
2390                         if (f && surface->num_triangles)
2391                         {
2392                                 // if lightmap parameters changed, rebuild lightmap texture
2393                                 if (surface->cached_dlight && surface->lightmapinfo->samples)
2394                                         R_BuildLightMap(ent, surface);
2395                                 // add face to draw list
2396                                 surfacelist[numsurfacelist++] = surface;
2397                                 counttriangles += surface->num_triangles;
2398                                 if (numsurfacelist >= maxsurfacelist)
2399                                 {
2400                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2401                                         numsurfacelist = 0;
2402                                 }
2403                         }
2404                 }
2405         }
2406         else
2407         {
2408                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2409                 {
2410                         if (t != surface->texture)
2411                         {
2412                                 if (numsurfacelist)
2413                                 {
2414                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2415                                         numsurfacelist = 0;
2416                                 }
2417                                 t = surface->texture;
2418                                 texture = t->currentframe;
2419                                 f = texture->currentmaterialflags & flagsmask;
2420                         }
2421                         if (f && surface->num_triangles)
2422                         {
2423                                 // if lightmap parameters changed, rebuild lightmap texture
2424                                 if (surface->cached_dlight && surface->lightmapinfo->samples)
2425                                         R_BuildLightMap(ent, surface);
2426                                 // add face to draw list
2427                                 surfacelist[numsurfacelist++] = surface;
2428                                 counttriangles += surface->num_triangles;
2429                                 if (numsurfacelist >= maxsurfacelist)
2430                                 {
2431                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2432                                         numsurfacelist = 0;
2433                                 }
2434                         }
2435                 }
2436         }
2437         if (numsurfacelist)
2438                 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2439         if (!r_showtrispass)
2440                 renderstats.entities_triangles += counttriangles;
2441 }
2442