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