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