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