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