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