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