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