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