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