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