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